Setup a legacy mapper system. The file does not exist yet.

This commit is contained in:
Matthew Miller 2018-07-01 22:03:22 +10:00
parent 8e09eb3dbe
commit b06937d1c8
31 changed files with 497 additions and 659 deletions

View File

@ -31,8 +31,6 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.LazyBlock; import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.blocks.type.BlockStateHolder; import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockType;
import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.history.change.BlockChange; import com.sk89q.worldedit.history.change.BlockChange;
@ -40,7 +38,7 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.AbstractWorld;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.LegacyMapper;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.TreeType; import org.bukkit.TreeType;
import org.bukkit.World; import org.bukkit.World;
@ -361,10 +359,7 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public com.sk89q.worldedit.blocks.type.BlockState getBlock(Vector position) { public com.sk89q.worldedit.blocks.type.BlockState getBlock(Vector position) {
Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
BlockType blockType = BlockTypes.getBlockType( return LegacyMapper.getInstance().getBlockFromLegacy(bukkitBlock.getTypeId(), bukkitBlock.getData());
BundledBlockData.getInstance().fromLegacyId(bukkitBlock.getTypeId())
);
return blockType.getDefaultState(); // TODO Data
} }
@Override @Override
@ -374,7 +369,11 @@ public class BukkitWorld extends AbstractWorld {
return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, notifyAndLight); return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, notifyAndLight);
} else { } else {
Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
return bukkitBlock.setTypeIdAndData(block.getBlockType().getLegacyId(), (byte) 0, notifyAndLight); // TODO Data int[] datas = LegacyMapper.getInstance().getLegacyFromBlock(block.toImmutableState());
if (datas == null) {
throw new WorldEditException("Unknown block"){}; // TODO Remove.
}
return bukkitBlock.setTypeIdAndData(datas[0], (byte) datas[1], notifyAndLight);
} }
} }

View File

@ -19,13 +19,12 @@
package com.sk89q.worldedit.bukkit; package com.sk89q.worldedit.bukkit;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.type.BlockTypes; import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import org.bukkit.BlockChangeDelegate; import org.bukkit.BlockChangeDelegate;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.blocks.BaseBlock;
/** /**
* Proxy class to catch calls to set blocks. * Proxy class to catch calls to set blocks.
@ -41,7 +40,7 @@ public class EditSessionBlockChangeDelegate implements BlockChangeDelegate {
@Override @Override
public boolean setRawTypeId(int x, int y, int z, int typeId) { public boolean setRawTypeId(int x, int y, int z, int typeId) {
try { try {
return editSession.setBlock(new Vector(x, y, z), new BaseBlock(typeId)); return editSession.setBlock(new Vector(x, y, z), LegacyMapper.getInstance().getBlockFromLegacy(typeId));
} catch (MaxChangedBlocksException ex) { } catch (MaxChangedBlocksException ex) {
return false; return false;
} }
@ -50,7 +49,7 @@ public class EditSessionBlockChangeDelegate implements BlockChangeDelegate {
@Override @Override
public boolean setRawTypeIdAndData(int x, int y, int z, int typeId, int data) { public boolean setRawTypeIdAndData(int x, int y, int z, int typeId, int data) {
try { try {
return editSession.setBlock(new Vector(x, y, z), new BaseBlock(typeId, data)); return editSession.setBlock(new Vector(x, y, z), LegacyMapper.getInstance().getBlockFromLegacy(typeId, data));
} catch (MaxChangedBlocksException ex) { } catch (MaxChangedBlocksException ex) {
return false; return false;
} }
@ -68,7 +67,8 @@ public class EditSessionBlockChangeDelegate implements BlockChangeDelegate {
@Override @Override
public int getTypeId(int x, int y, int z) { public int getTypeId(int x, int y, int z) {
return editSession.getBlock(new Vector(x, y, z)).getBlockType().getLegacyId(); int[] datas = LegacyMapper.getInstance().getLegacyFromBlock(editSession.getBlock(new Vector(x, y, z)));
return datas[0];
} }
@Override @Override

View File

@ -108,6 +108,7 @@ import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -440,10 +441,9 @@ public class EditSession implements Extent {
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, boolean naturalOnly) { public int getHighestTerrainBlock(int x, int z, int minY, int maxY, boolean naturalOnly) {
for (int y = maxY; y >= minY; --y) { for (int y = maxY; y >= minY; --y) {
Vector pt = new Vector(x, y, z); Vector pt = new Vector(x, y, z);
BaseBlock block = getLazyBlock(pt); BlockState block = getBlock(pt);
int id = block.getId(); int[] datas = LegacyMapper.getInstance().getLegacyFromBlock(block);
int data = block.getData(); if (naturalOnly ? BlockType.isNaturalTerrainBlock(datas[0], datas[1]) : !BlockType.canPassThrough(datas[0], datas[1])) {
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
return y; return y;
} }
} }
@ -2115,8 +2115,9 @@ public class EditSession implements Extent {
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
final BlockVector current = queue.removeFirst(); final BlockVector current = queue.removeFirst();
final BaseBlock block = getLazyBlock(current); final BlockState block = getBlock(current);
if (!BlockType.canPassThrough(block.getId(), block.getData())) { int[] datas = LegacyMapper.getInstance().getLegacyFromBlock(block);
if (!BlockType.canPassThrough(datas[0], datas[1])) {
continue; continue;
} }

View File

@ -53,6 +53,7 @@ import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler; import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.BundledItemData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.File; import java.io.File;
@ -101,6 +102,7 @@ public class WorldEdit {
getVersion(); getVersion();
BundledBlockData.getInstance(); // Load block registry BundledBlockData.getInstance(); // Load block registry
BundledItemData.getInstance(); // Load item registry BundledItemData.getInstance(); // Load item registry
LegacyMapper.getInstance(); // Load item registry
} }
private WorldEdit() { private WorldEdit() {

View File

@ -27,7 +27,7 @@ import com.sk89q.worldedit.blocks.type.BlockStateHolder;
import com.sk89q.worldedit.blocks.type.BlockType; import com.sk89q.worldedit.blocks.type.BlockType;
import com.sk89q.worldedit.blocks.type.BlockTypes; import com.sk89q.worldedit.blocks.type.BlockTypes;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.registry.state.State; import com.sk89q.worldedit.world.registry.state.State;
import com.sk89q.worldedit.world.registry.state.value.StateValue; import com.sk89q.worldedit.world.registry.state.value.StateValue;
@ -52,9 +52,6 @@ import javax.annotation.Nullable;
*/ */
public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock { public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
// Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object.
private BlockState blockState; private BlockState blockState;
@Nullable @Nullable
private CompoundTag nbtData; private CompoundTag nbtData;
@ -67,10 +64,12 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
@Deprecated @Deprecated
public BaseBlock(int id) { public BaseBlock(int id) {
try { try {
this.blockState = BlockTypes.getBlockType(BundledBlockData.getInstance().fromLegacyId(id)).getDefaultState(); this.blockState = LegacyMapper.getInstance().getBlockFromLegacy(id);
if (this.blockState == null) {
this.blockState = BlockTypes.AIR.getDefaultState();
}
} catch (Exception e) { } catch (Exception e) {
System.out.println(id); System.out.println(id);
System.out.println(BundledBlockData.getInstance().fromLegacyId(id));
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -134,16 +133,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
* @param other the other block * @param other the other block
*/ */
public BaseBlock(BaseBlock other) { public BaseBlock(BaseBlock other) {
this(other.getState(), other.getNbtData()); this(other.toImmutableState(), other.getNbtData());
}
/**
* Get the block state
*
* @return The block state
*/
public BlockState getState() {
return this.blockState;
} }
/** /**
@ -240,7 +230,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
final BaseBlock otherBlock = (BaseBlock) o; final BaseBlock otherBlock = (BaseBlock) o;
return this.getState().equals(otherBlock.getState()) && Objects.equals(getNbtData(), otherBlock.getNbtData()); return this.toImmutableState().equals(otherBlock.toImmutableState()) && Objects.equals(getNbtData(), otherBlock.getNbtData());
} }
@ -252,12 +242,17 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
*/ */
@Override @Override
public boolean equalsFuzzy(BlockStateHolder o) { public boolean equalsFuzzy(BlockStateHolder o) {
return this.getState().equalsFuzzy(o); return this.toImmutableState().equalsFuzzy(o);
}
@Override
public BlockState toImmutableState() {
return this.blockState;
} }
@Override @Override
public int hashCode() { public int hashCode() {
int ret = getState().hashCode() << 3; int ret = toImmutableState().hashCode() << 3;
if (hasNbtData()) { if (hasNbtData()) {
ret += getNbtData().hashCode(); ret += getNbtData().hashCode();
} }
@ -266,7 +261,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
@Override @Override
public String toString() { public String toString() {
return "Block{State: " + this.getState().toString() + ", NBT: " + String.valueOf(getNbtData()) + "}"; return "Block{State: " + this.toImmutableState().toString() + ", NBT: " + String.valueOf(getNbtData()) + "}";
} }
} }

View File

@ -23,7 +23,7 @@ import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.type.ItemType; import com.sk89q.worldedit.blocks.type.ItemType;
import com.sk89q.worldedit.blocks.type.ItemTypes; import com.sk89q.worldedit.blocks.type.ItemTypes;
import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.NbtValued;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -46,7 +46,11 @@ public class BaseItem implements NbtValued {
*/ */
@Deprecated @Deprecated
public BaseItem(int id) { public BaseItem(int id) {
this(ItemTypes.getItemType(BundledItemData.getInstance().fromLegacyId(id))); ItemType type = LegacyMapper.getInstance().getItemFromLegacy(id);
if (type == null) {
type = ItemTypes.AIR;
}
this.itemType = type;
} }
/** /**

View File

@ -855,246 +855,188 @@ public final class BlockData {
* @return the new data value for the block * @return the new data value for the block
*/ */
public static int cycle(int type, int data, int increment) { public static int cycle(int type, int data, int increment) {
if (increment != -1 && increment != 1) { return data + increment;
throw new IllegalArgumentException("Increment must be 1 or -1."); // TODO Fix
} // if (increment != -1 && increment != 1) {
// throw new IllegalArgumentException("Increment must be 1 or -1.");
int store; // }
switch (type) { //
// int store;
// special case here, going to use "forward" for type and "backward" for orientation // switch (type) {
case BlockID.LOG: //
case BlockID.LOG2: // // special case here, going to use "forward" for type and "backward" for orientation
if (increment == -1) { // case BlockID.LOG:
store = data & 0x3; // copy bottom (type) bits // case BlockID.LOG2:
return mod((data & ~0x3) + 4, 16) | store; // switch orientation with top bits and reapply bottom bits; // if (increment == -1) {
} else { // store = data & 0x3; // copy bottom (type) bits
store = data & ~0x3; // copy top (orientation) bits // return mod((data & ~0x3) + 4, 16) | store; // switch orientation with top bits and reapply bottom bits;
return mod((data & 0x3) + 1, 4) | store; // switch type with bottom bits and reapply top bits // } else {
} // store = data & ~0x3; // copy top (orientation) bits
// return mod((data & 0x3) + 1, 4) | store; // switch type with bottom bits and reapply top bits
// <del>same here</del> - screw you unit tests // }
/*case BlockID.QUARTZ_BLOCK: //
if (increment == -1 && data > 2) { // // <del>same here</del> - screw you unit tests
switch (data) { // /*case BlockID.QUARTZ_BLOCK:
case 2: return 3; // if (increment == -1 && data > 2) {
case 3: return 4; // switch (data) {
case 4: return 2; // case 2: return 3;
} // case 3: return 4;
} else if (increment == 1) { // case 4: return 2;
switch (data) { // }
case 0: // } else if (increment == 1) {
return 1; // switch (data) {
case 1: // case 0:
return 2; // return 1;
case 2: // case 1:
case 3: // return 2;
case 4: // case 2:
return 0; // case 3:
} // case 4:
} else { // return 0;
return -1; // }
}*/ // } else {
// return -1;
case BlockID.LONG_GRASS: // }*/
case BlockID.SANDSTONE: //
case BlockID.DIRT: // case BlockID.LONG_GRASS:
if (data > 2) return -1; // case BlockID.SANDSTONE:
return mod((data + increment), 3); // case BlockID.DIRT:
// if (data > 2) return -1;
case BlockID.TORCH: // return mod((data + increment), 3);
case BlockID.REDSTONE_TORCH_ON: //
case BlockID.REDSTONE_TORCH_OFF: // case BlockID.TORCH:
if (data < 1 || data > 4) return -1; // case BlockID.REDSTONE_TORCH_ON:
return mod((data - 1 + increment), 4) + 1; // case BlockID.REDSTONE_TORCH_OFF:
// if (data < 1 || data > 4) return -1;
case BlockID.OAK_WOOD_STAIRS: // return mod((data - 1 + increment), 4) + 1;
case BlockID.COBBLESTONE_STAIRS: //
case BlockID.BRICK_STAIRS: // case BlockID.OAK_WOOD_STAIRS:
case BlockID.STONE_BRICK_STAIRS: // case BlockID.COBBLESTONE_STAIRS:
case BlockID.NETHER_BRICK_STAIRS: // case BlockID.BRICK_STAIRS:
case BlockID.SANDSTONE_STAIRS: // case BlockID.STONE_BRICK_STAIRS:
case BlockID.SPRUCE_WOOD_STAIRS: // case BlockID.NETHER_BRICK_STAIRS:
case BlockID.BIRCH_WOOD_STAIRS: // case BlockID.SANDSTONE_STAIRS:
case BlockID.JUNGLE_WOOD_STAIRS: // case BlockID.SPRUCE_WOOD_STAIRS:
case BlockID.QUARTZ_STAIRS: // case BlockID.BIRCH_WOOD_STAIRS:
case BlockID.ACACIA_STAIRS: // case BlockID.JUNGLE_WOOD_STAIRS:
case BlockID.DARK_OAK_STAIRS: // case BlockID.QUARTZ_STAIRS:
if (data > 7) return -1; // case BlockID.ACACIA_STAIRS:
return mod((data + increment), 8); // case BlockID.DARK_OAK_STAIRS:
// if (data > 7) return -1;
case BlockID.STONE_BRICK: // return mod((data + increment), 8);
case BlockID.QUARTZ_BLOCK: //
case BlockID.PUMPKIN: // case BlockID.STONE_BRICK:
case BlockID.JACKOLANTERN: // case BlockID.QUARTZ_BLOCK:
case BlockID.NETHER_WART: // case BlockID.PUMPKIN:
case BlockID.CAULDRON: // case BlockID.JACKOLANTERN:
case BlockID.WOODEN_STEP: // case BlockID.NETHER_WART:
case BlockID.DOUBLE_WOODEN_STEP: // case BlockID.CAULDRON:
case BlockID.HAY_BLOCK: // case BlockID.WOODEN_STEP:
if (data > 3) return -1; // case BlockID.DOUBLE_WOODEN_STEP:
return mod((data + increment), 4); // case BlockID.HAY_BLOCK:
// if (data > 3) return -1;
case BlockID.STEP: // return mod((data + increment), 4);
case BlockID.DOUBLE_STEP: //
case BlockID.CAKE_BLOCK: // case BlockID.STEP:
case BlockID.PISTON_BASE: // case BlockID.DOUBLE_STEP:
case BlockID.PISTON_STICKY_BASE: // case BlockID.CAKE_BLOCK:
case BlockID.SILVERFISH_BLOCK: // case BlockID.PISTON_BASE:
if (data > 5) return -1; // case BlockID.PISTON_STICKY_BASE:
return mod((data + increment), 6); // case BlockID.SILVERFISH_BLOCK:
// if (data > 5) return -1;
case BlockID.DOUBLE_PLANT: // return mod((data + increment), 6);
store = data & 0x8; // top half flag //
data &= ~0x8; // case BlockID.DOUBLE_PLANT:
if (data > 5) return -1; // store = data & 0x8; // top half flag
return mod((data + increment), 6) | store; // data &= ~0x8;
// if (data > 5) return -1;
case BlockID.CROPS: // return mod((data + increment), 6) | store;
case BlockID.PUMPKIN_STEM: //
case BlockID.MELON_STEM: // case BlockID.CROPS:
if (data > 6) return -1; // case BlockID.PUMPKIN_STEM:
return mod((data + increment), 7); // case BlockID.MELON_STEM:
// if (data > 6) return -1;
case BlockID.SOIL: // return mod((data + increment), 7);
case BlockID.RED_FLOWER: //
if (data > 8) return -1; // case BlockID.SOIL:
return mod((data + increment), 9); // case BlockID.RED_FLOWER:
// if (data > 8) return -1;
case BlockID.RED_MUSHROOM_CAP: // return mod((data + increment), 9);
case BlockID.BROWN_MUSHROOM_CAP: //
if (data > 10) return -1; // case BlockID.RED_MUSHROOM_CAP:
return mod((data + increment), 11); // case BlockID.BROWN_MUSHROOM_CAP:
// if (data > 10) return -1;
case BlockID.CACTUS: // return mod((data + increment), 11);
case BlockID.REED: //
case BlockID.SIGN_POST: // case BlockID.CACTUS:
case BlockID.VINE: // case BlockID.REED:
case BlockID.SNOW: // case BlockID.SIGN_POST:
case BlockID.COCOA_PLANT: // case BlockID.VINE:
if (data > 15) return -1; // case BlockID.SNOW:
return mod((data + increment), 16); // case BlockID.COCOA_PLANT:
// if (data > 15) return -1;
case BlockID.FURNACE: // return mod((data + increment), 16);
case BlockID.BURNING_FURNACE: //
case BlockID.WALL_SIGN: // case BlockID.FURNACE:
case BlockID.LADDER: // case BlockID.BURNING_FURNACE:
case BlockID.CHEST: // case BlockID.WALL_SIGN:
case BlockID.ENDER_CHEST: // case BlockID.LADDER:
case BlockID.TRAPPED_CHEST: // case BlockID.CHEST:
case BlockID.HOPPER: // case BlockID.ENDER_CHEST:
int extra = data & 0x8; // case BlockID.TRAPPED_CHEST:
int withoutFlags = data & ~0x8; // case BlockID.HOPPER:
if (withoutFlags < 2 || withoutFlags > 5) return -1; // int extra = data & 0x8;
return (mod((withoutFlags - 2 + increment), 4) + 2) | extra; // int withoutFlags = data & ~0x8;
// if (withoutFlags < 2 || withoutFlags > 5) return -1;
case BlockID.DISPENSER: // return (mod((withoutFlags - 2 + increment), 4) + 2) | extra;
case BlockID.DROPPER: //
store = data & 0x8; // case BlockID.DISPENSER:
data &= ~0x8; // case BlockID.DROPPER:
if (data > 5) return -1; // store = data & 0x8;
return mod((data + increment), 6) | store; // data &= ~0x8;
// if (data > 5) return -1;
case BlockID.REDSTONE_REPEATER_OFF: // return mod((data + increment), 6) | store;
case BlockID.REDSTONE_REPEATER_ON: //
case BlockID.COMPARATOR_OFF: // case BlockID.REDSTONE_REPEATER_OFF:
case BlockID.COMPARATOR_ON: // case BlockID.REDSTONE_REPEATER_ON:
case BlockID.TRAP_DOOR: // case BlockID.COMPARATOR_OFF:
case BlockID.FENCE_GATE: // case BlockID.COMPARATOR_ON:
case BlockID.LEAVES: // case BlockID.TRAP_DOOR:
case BlockID.LEAVES2: // case BlockID.FENCE_GATE:
if (data > 7) return -1; // case BlockID.LEAVES:
store = data & ~0x3; // case BlockID.LEAVES2:
return mod(((data & 0x3) + increment), 4) | store; // if (data > 7) return -1;
// store = data & ~0x3;
case BlockID.MINECART_TRACKS: // return mod(((data & 0x3) + increment), 4) | store;
if (data < 6 || data > 9) return -1; //
return mod((data - 6 + increment), 4) + 6; // case BlockID.MINECART_TRACKS:
// if (data < 6 || data > 9) return -1;
case BlockID.SAPLING: // return mod((data - 6 + increment), 4) + 6;
if ((data & 0x3) == 3 || data > 15) return -1; //
store = data & ~0x3; // case BlockID.SAPLING:
return mod(((data & 0x3) + increment), 3) | store; // if ((data & 0x3) == 3 || data > 15) return -1;
// store = data & ~0x3;
case BlockID.FLOWER_POT: // return mod(((data & 0x3) + increment), 3) | store;
if (data > 13) return -1; //
return mod((data + increment), 14); // case BlockID.FLOWER_POT:
// if (data > 13) return -1;
case BlockID.CLOTH: // return mod((data + increment), 14);
case BlockID.STAINED_CLAY: //
case BlockID.CARPET: // case BlockID.CLOTH:
case BlockID.STAINED_GLASS: // case BlockID.STAINED_CLAY:
case BlockID.STAINED_GLASS_PANE: // case BlockID.CARPET:
if (increment == 1) { // case BlockID.STAINED_GLASS:
data = nextClothColor(data); // case BlockID.STAINED_GLASS_PANE:
} else if (increment == -1) { // if (increment == 1) {
data = prevClothColor(data); // data = nextClothColor(data);
} // } else if (increment == -1) {
return data; // data = prevClothColor(data);
// }
default: // return data;
return -1; //
} // default:
} // return -1;
// }
/**
* Returns the data value for the next color of cloth in the rainbow. This
* should not be used if you want to just increment the data value.
*
* @param data the data value
* @return the next data value
*/
public static int nextClothColor(int data) {
switch (data) {
case ClothColor.ID.WHITE: return ClothColor.ID.LIGHT_GRAY;
case ClothColor.ID.LIGHT_GRAY: return ClothColor.ID.GRAY;
case ClothColor.ID.GRAY: return ClothColor.ID.BLACK;
case ClothColor.ID.BLACK: return ClothColor.ID.BROWN;
case ClothColor.ID.BROWN: return ClothColor.ID.RED;
case ClothColor.ID.RED: return ClothColor.ID.ORANGE;
case ClothColor.ID.ORANGE: return ClothColor.ID.YELLOW;
case ClothColor.ID.YELLOW: return ClothColor.ID.LIGHT_GREEN;
case ClothColor.ID.LIGHT_GREEN: return ClothColor.ID.DARK_GREEN;
case ClothColor.ID.DARK_GREEN: return ClothColor.ID.CYAN;
case ClothColor.ID.CYAN: return ClothColor.ID.LIGHT_BLUE;
case ClothColor.ID.LIGHT_BLUE: return ClothColor.ID.BLUE;
case ClothColor.ID.BLUE: return ClothColor.ID.PURPLE;
case ClothColor.ID.PURPLE: return ClothColor.ID.MAGENTA;
case ClothColor.ID.MAGENTA: return ClothColor.ID.PINK;
case ClothColor.ID.PINK: return ClothColor.ID.WHITE;
}
return ClothColor.ID.WHITE;
}
/**
* Returns the data value for the previous ext color of cloth in the rainbow.
* This should not be used if you want to just increment the data value.
*
* @param data the data value
* @return the new data value
*/
public static int prevClothColor(int data) {
switch (data) {
case ClothColor.ID.LIGHT_GRAY: return ClothColor.ID.WHITE;
case ClothColor.ID.GRAY: return ClothColor.ID.LIGHT_GRAY;
case ClothColor.ID.BLACK: return ClothColor.ID.GRAY;
case ClothColor.ID.BROWN: return ClothColor.ID.BLACK;
case ClothColor.ID.RED: return ClothColor.ID.BROWN;
case ClothColor.ID.ORANGE: return ClothColor.ID.RED;
case ClothColor.ID.YELLOW: return ClothColor.ID.ORANGE;
case ClothColor.ID.LIGHT_GREEN: return ClothColor.ID.YELLOW;
case ClothColor.ID.DARK_GREEN: return ClothColor.ID.LIGHT_GREEN;
case ClothColor.ID.CYAN: return ClothColor.ID.DARK_GREEN;
case ClothColor.ID.LIGHT_BLUE: return ClothColor.ID.CYAN;
case ClothColor.ID.BLUE: return ClothColor.ID.LIGHT_BLUE;
case ClothColor.ID.PURPLE: return ClothColor.ID.BLUE;
case ClothColor.ID.MAGENTA: return ClothColor.ID.PURPLE;
case ClothColor.ID.PINK: return ClothColor.ID.MAGENTA;
case ClothColor.ID.WHITE: return ClothColor.ID.PINK;
}
return ClothColor.ID.WHITE;
} }
/** /**

View File

@ -1194,25 +1194,6 @@ public enum BlockType {
return isNaturalTerrainBlock.contains(-16*id-data) || isNaturalTerrainBlock.contains(id); return isNaturalTerrainBlock.contains(-16*id-data) || isNaturalTerrainBlock.contains(id);
} }
/**
* Checks if the block type is naturally occurring
*
* @param block the block
* @return true if the block type is naturally occurring
*/
public static boolean isNaturalTerrainBlock(BaseBlock block) {
return isNaturalTerrainBlock(block.getId(), block.getData());
}
/**
* Checks if the block type is naturally occurring
*
* @return true if the block type is naturally occurring
*/
public boolean isNaturalTerrainBlock() {
return isNaturalTerrainBlock.contains(id);
}
/** /**
* HashSet for emitsLight. * HashSet for emitsLight.
*/ */

View File

@ -31,61 +31,32 @@ import java.util.EnumSet;
*/ */
public enum ClothColor { public enum ClothColor {
WHITE(ID.WHITE, "White", "white"), WHITE("White", "white"),
ORANGE(ID.ORANGE, "Orange", "orange"), ORANGE("Orange", "orange"),
MAGENTA(ID.MAGENTA, "Magenta", "magenta"), MAGENTA("Magenta", "magenta"),
LIGHT_BLUE(ID.LIGHT_BLUE, "Light blue", "lightblue"), LIGHT_BLUE("Light blue", "lightblue"),
YELLOW(ID.YELLOW, "Yellow", "yellow"), YELLOW("Yellow", "yellow"),
LIGHT_GREEN(ID.LIGHT_GREEN, "Light green", "lightgreen"), LIGHT_GREEN("Light green", "lightgreen"),
PINK(ID.PINK, "Pink", new String[] { "pink", "lightred" }), PINK("Pink", "pink", "lightred"),
GRAY(ID.GRAY, "Gray", new String[] { "grey", "gray" }), GRAY("Gray", "grey", "gray"),
LIGHT_GRAY(ID.LIGHT_GRAY, "Light gray", new String[] { "lightgrey", "lightgray" }), LIGHT_GRAY("Light gray", "lightgrey", "lightgray"),
CYAN(ID.CYAN, "Cyan", new String[] { "cyan", "turquoise" }), CYAN("Cyan", "cyan", "turquoise"),
PURPLE(ID.PURPLE, "Purple", new String[] { "purple", "violet" }), PURPLE("Purple", "purple", "violet"),
BLUE(ID.BLUE, "Blue", "blue"), BLUE("Blue", "blue"),
BROWN(ID.BROWN, "Brown", new String[] { "brown", "cocoa", "coffee" }), BROWN("Brown", "brown", "cocoa", "coffee"),
DARK_GREEN(ID.DARK_GREEN, "Dark green", new String[] { "green", "darkgreen", "cactusgreen", "cactigreen" }), DARK_GREEN("Dark green", "green", "darkgreen", "cactusgreen", "cactigreen"),
RED(ID.RED, "Red", "red"), RED("Red", "red"),
BLACK(ID.BLACK, "Black", "black"); BLACK("Black", "black");
public static final class ID {
public static final int WHITE = 0;
public static final int ORANGE = 1;
public static final int MAGENTA = 2;
public static final int LIGHT_BLUE = 3;
public static final int YELLOW = 4;
public static final int LIGHT_GREEN = 5;
public static final int PINK = 6;
public static final int GRAY = 7;
public static final int LIGHT_GRAY = 8;
public static final int CYAN = 9;
public static final int PURPLE = 10;
public static final int BLUE = 11;
public static final int BROWN = 12;
public static final int DARK_GREEN = 13;
public static final int RED = 14;
public static final int BLACK = 15;
private ID() {
}
}
/**
* Stores a map of the IDs for fast access.
*/
private static final Map<Integer, ClothColor> ids = new HashMap<>();
/** /**
* Stores a map of the names for fast access. * Stores a map of the names for fast access.
*/ */
private static final Map<String, ClothColor> lookup = new HashMap<>(); private static final Map<String, ClothColor> lookup = new HashMap<>();
private final int id;
private final String name; private final String name;
private final String[] lookupKeys; private final String[] lookupKeys;
static { static {
for (ClothColor type : EnumSet.allOf(ClothColor.class)) { for (ClothColor type : EnumSet.allOf(ClothColor.class)) {
ids.put(type.id, type);
for (String key : type.lookupKeys) { for (String key : type.lookupKeys) {
lookup.put(key, type); lookup.put(key, type);
} }
@ -96,40 +67,14 @@ public enum ClothColor {
/** /**
* Construct the type. * Construct the type.
* *
* @param id the ID of the color
* @param name the name of the color * @param name the name of the color
* @param lookupKey a name to refer to the color by * @param lookupKeys a name to refer to the color by
*/ */
ClothColor(int id, String name, String lookupKey) { ClothColor(String name, String ... lookupKeys) {
this.id = id;
this.name = name;
this.lookupKeys = new String[] { lookupKey };
}
/**
* Construct the type.
*
* @param id the ID of the color
* @param name the name of the color
* @param lookupKeys an array of lookup keys
*/
ClothColor(int id, String name, String[] lookupKeys) {
this.id = id;
this.name = name; this.name = name;
this.lookupKeys = lookupKeys; this.lookupKeys = lookupKeys;
} }
/**
* Return type from ID. May return null.
*
* @param id the ID
* @return a color or null
*/
@Nullable
public static ClothColor fromID(int id) {
return ids.get(id);
}
/** /**
* Return type from name. May return null. * Return type from name. May return null.
* *
@ -141,15 +86,6 @@ public enum ClothColor {
return lookup.get(name.toLowerCase()); return lookup.get(name.toLowerCase());
} }
/**
* Get item numeric ID.
*
* @return the ID
*/
public int getID() {
return id;
}
/** /**
* Get user-friendly item name. * Get user-friendly item name.
* *

View File

@ -141,6 +141,11 @@ public class BlockState implements BlockStateHolder<BlockState> {
return true; return true;
} }
@Override
public BlockState toImmutableState() {
return this;
}
/** /**
* Internal method used for creating the initial BlockState. * Internal method used for creating the initial BlockState.
* *

View File

@ -64,4 +64,11 @@ public interface BlockStateHolder<T extends BlockStateHolder> {
* @return true if equal * @return true if equal
*/ */
boolean equalsFuzzy(BlockStateHolder o); boolean equalsFuzzy(BlockStateHolder o);
/**
* Returns an immutable BlockState from this BlockStateHolder.
*
* @return A BlockState
*/
BlockState toImmutableState();
} }

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.blocks.type; package com.sk89q.worldedit.blocks.type;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.function.Function; import java.util.function.Function;
@ -85,9 +86,9 @@ public class BlockType {
*/ */
@Deprecated @Deprecated
public int getLegacyId() { public int getLegacyId() {
Integer id = BundledBlockData.getInstance().toLegacyId(this.id); int[] id = LegacyMapper.getInstance().getLegacyFromBlock(this.getDefaultState());
if (id != null) { if (id != null) {
return id; return id[0];
} else { } else {
return 0; return 0;
} }

View File

@ -19,8 +19,8 @@
package com.sk89q.worldedit.blocks.type; package com.sk89q.worldedit.blocks.type;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.BundledItemData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
public class ItemType { public class ItemType {
@ -61,9 +61,9 @@ public class ItemType {
*/ */
@Deprecated @Deprecated
public int getLegacyId() { public int getLegacyId() {
Integer id = BundledItemData.getInstance().toLegacyId(this.id); int ids[] = LegacyMapper.getInstance().getLegacyFromItem(this);
if (id != null) { if (ids != null) {
return id; return ids[0];
} else { } else {
return 0; return 0;
} }

View File

@ -25,11 +25,13 @@ import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockData; import com.sk89q.worldedit.blocks.BlockData;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.registry.LegacyMapper;
/** /**
* A mode that cycles the data values of supported blocks. * A mode that cycles the data values of supported blocks.
@ -46,9 +48,10 @@ public class BlockDataCyler implements DoubleActionBlockTool {
World world = (World) clicked.getExtent(); World world = (World) clicked.getExtent();
BaseBlock block = world.getLazyBlock(clicked.toVector()); BlockState block = world.getBlock(clicked.toVector());
int type = block.getId(); int[] datas = LegacyMapper.getInstance().getLegacyFromBlock(block);
int data = block.getData(); int type = datas[0];
int data = datas[1];
if (!config.allowedDataCycleBlocks.isEmpty() if (!config.allowedDataCycleBlocks.isEmpty()
&& !player.hasPermission("worldedit.override.data-cycler") && !player.hasPermission("worldedit.override.data-cycler")

View File

@ -153,6 +153,37 @@ class DefaultBlockParser extends InputParser<BlockStateHolder> {
} }
} }
private static BlockState applyProperties(BlockState state, String[] stateProperties) throws NoMatchException {
if (stateProperties.length > 0) { // Block data not yet detected
// Parse the block data (optional)
for (String parseableData : stateProperties) {
try {
String[] parts = parseableData.split("=");
if (parts.length != 2) {
throw new NoMatchException("Bad state format in " + parseableData);
}
State stateKey = BundledBlockData.getInstance().findById(state.getBlockType().getId()).states.get(parts[0]);
if (stateKey == null) {
throw new NoMatchException("Unknown state " + parts[0] + " for block " + state.getBlockType().getName());
}
StateValue value = stateKey.getValueFor(parts[1]);
if (value == null) {
throw new NoMatchException("Unknown value " + parts[1] + " for state " + parts[0]);
}
state = state.with(stateKey, value);
} catch (NoMatchException e) {
throw e; // Pass-through
} catch (Exception e) {
throw new NoMatchException("Unknown state '" + parseableData + "'");
}
}
}
return state;
}
private BlockStateHolder parseLogic(String input, ParserContext context) throws InputParseException { private BlockStateHolder parseLogic(String input, ParserContext context) throws InputParseException {
BlockType blockType; BlockType blockType;
Map<State, StateValue> blockStates = new HashMap<>(); Map<State, StateValue> blockStates = new HashMap<>();
@ -217,39 +248,16 @@ class DefaultBlockParser extends InputParser<BlockStateHolder> {
state = new BlockState(blockType, blockStates); state = new BlockState(blockType, blockStates);
} }
if (stateProperties.length > 0) { // Block data not yet detected state = applyProperties(state, stateProperties);
// Parse the block data (optional)
for (String parseableData : stateProperties) {
try {
String[] parts = parseableData.split("=");
if (parts.length != 2) {
throw new NoMatchException("Bad state format in " + parseableData);
}
State stateKey = BundledBlockData.getInstance().findById(blockType.getId()).states.get(parts[0]);
if (stateKey == null) {
throw new NoMatchException("Unknown state " + parts[0] + " for block " + blockType.getName());
}
StateValue value = stateKey.getValueFor(parts[1]);
if (value == null) {
throw new NoMatchException("Unknown value " + parts[1] + " for state " + parts[0]);
}
state = state.with(stateKey, value);
} catch (NoMatchException e) {
throw e; // Pass-through
} catch (Exception e) {
throw new NoMatchException("Unknown state '" + parseableData + "'");
}
}
}
// Check if the item is allowed // Check if the item is allowed
if (context.isRestricted()) {
Actor actor = context.requireActor(); Actor actor = context.requireActor();
if (context.isRestricted() && actor != null && !actor.hasPermission("worldedit.anyblock") if (actor != null && !actor.hasPermission("worldedit.anyblock")
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) { && worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) {
throw new DisallowedUsageException("You are not allowed to use '" + input + "'"); throw new DisallowedUsageException("You are not allowed to use '" + input + "'");
} }
}
if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN) { if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN) {
// Allow special sign text syntax // Allow special sign text syntax

View File

@ -128,11 +128,7 @@ public class BlockArrayClipboard implements Clipboard {
Vector v = position.subtract(region.getMinimumPoint()); Vector v = position.subtract(region.getMinimumPoint());
BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()]; BlockStateHolder block = blocks[v.getBlockX()][v.getBlockY()][v.getBlockZ()];
if (block != null) { if (block != null) {
if (block instanceof BlockState) { return block.toImmutableState();
return (BlockState) block;
} else if (block instanceof BaseBlock) {
return ((BaseBlock) block).getState();
}
} }
} }

View File

@ -105,7 +105,7 @@ public class ExtentBlockCopy implements RegionFunction {
builder.putByte("Rot", (byte) MCDirections.toRotation(newDirection)); builder.putByte("Rot", (byte) MCDirections.toRotation(newDirection));
return new BaseBlock(state.getState(), builder.build()); return new BaseBlock(state.toImmutableState(), builder.build());
} }
} }
} }

View File

@ -24,7 +24,7 @@ package com.sk89q.worldedit.util;
import com.sk89q.util.StringUtil; import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.snapshot.SnapshotRepository; import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
import java.io.File; import java.io.File;
@ -92,7 +92,7 @@ public class PropertiesConfiguration extends LocalConfiguration {
registerHelp = getBool("register-help", registerHelp); registerHelp = getBool("register-help", registerHelp);
wandItem = getString("wand-item", wandItem); wandItem = getString("wand-item", wandItem);
try { try {
wandItem = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(wandItem)); wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop); superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop);
@ -103,7 +103,7 @@ public class PropertiesConfiguration extends LocalConfiguration {
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride); useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
navigationWand = getString("nav-wand-item", navigationWand); navigationWand = getString("nav-wand-item", navigationWand);
try { try {
navigationWand = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(navigationWand)); navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance); navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.BundledItemData;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.snapshot.SnapshotRepository; import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
import java.io.IOException; import java.io.IOException;
@ -57,7 +58,7 @@ public class YAMLConfiguration extends LocalConfiguration {
profile = config.getBoolean("debug", profile); profile = config.getBoolean("debug", profile);
wandItem = config.getString("wand-item", wandItem); wandItem = config.getString("wand-item", wandItem);
try { try {
wandItem = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(wandItem)); wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
@ -105,7 +106,7 @@ public class YAMLConfiguration extends LocalConfiguration {
navigationWand = config.getString("navigation-wand.item", navigationWand); navigationWand = config.getString("navigation-wand.item", navigationWand);
try { try {
navigationWand = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(navigationWand)); navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance); navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);

View File

@ -42,16 +42,6 @@ public interface BlockRegistry {
@Nullable @Nullable
BlockState createFromId(String id); BlockState createFromId(String id);
/**
* Create a new block using its legacy numeric ID.
*
* @param id the id
* @return the block, which may be null if no block exists
*/
@Nullable
@Deprecated
BlockState createFromId(int id);
/** /**
* Get the material for the given block. * Get the material for the given block.
* *

View File

@ -56,7 +56,6 @@ public class BundledBlockData {
private static final BundledBlockData INSTANCE = new BundledBlockData(); private static final BundledBlockData INSTANCE = new BundledBlockData();
private final Map<String, BlockEntry> idMap = new HashMap<>(); private final Map<String, BlockEntry> idMap = new HashMap<>();
private final Map<Integer, BlockEntry> legacyMap = new HashMap<>(); // Trove usage removed temporarily
/** /**
* Create a new instance. * Create a new instance.
@ -87,7 +86,7 @@ public class BundledBlockData {
for (BlockEntry entry : entries) { for (BlockEntry entry : entries) {
idMap.put(entry.id, entry); idMap.put(entry.id, entry);
legacyMap.put(entry.legacyId, entry); entry.postDeserialization();
} }
} }
@ -106,49 +105,6 @@ public class BundledBlockData {
return idMap.get(id); return idMap.get(id);
} }
/**
* Return the entry for the given block legacy numeric ID.
*
* @param id the ID
* @return the entry, or null
*/
@Nullable
private BlockEntry findById(int id) {
return legacyMap.get(id);
}
/**
* Convert the given string ID to a legacy numeric ID.
*
* @param id the ID
* @return the legacy ID, which may be null if the block does not have a legacy ID
*/
@Nullable
public Integer toLegacyId(String id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.legacyId;
} else {
return null;
}
}
/**
* Convert the given legacy numeric ID to a string ID.
*
* @param id the legacy ID
* @return the ID, which may be null if the block does not have a ID
*/
@Nullable
public String fromLegacyId(Integer id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.id;
} else {
return null;
}
}
/** /**
* Get the material properties for the given block. * Get the material properties for the given block.
* *
@ -191,13 +147,18 @@ public class BundledBlockData {
} }
public static class BlockEntry { public static class BlockEntry {
private int legacyId;
private String id; private String id;
private String unlocalizedName; private String unlocalizedName;
public String localizedName; public String localizedName;
private List<String> aliases; private List<String> aliases;
public Map<String, SimpleState> states = new HashMap<>(); public Map<String, SimpleState> states = new HashMap<>();
private SimpleBlockMaterial material = new SimpleBlockMaterial(); private SimpleBlockMaterial material = new SimpleBlockMaterial();
void postDeserialization() {
for (Map.Entry<String, SimpleState> state : states.entrySet()) {
state.getValue().setName(state.getKey());
}
}
} }
} }

View File

@ -41,17 +41,6 @@ public class BundledBlockRegistry implements BlockRegistry {
return BlockTypes.getBlockType(id).getDefaultState(); return BlockTypes.getBlockType(id).getDefaultState();
} }
@Nullable
@Override
public BlockState createFromId(int legacyId) {
String id = BundledBlockData.getInstance().fromLegacyId(legacyId);
if (id != null) {
return createFromId(id);
} else {
return null;
}
}
@Nullable @Nullable
@Override @Override
public BlockMaterial getMaterial(BaseBlock block) { public BlockMaterial getMaterial(BaseBlock block) {

View File

@ -54,7 +54,6 @@ public class BundledItemData {
private static final BundledItemData INSTANCE = new BundledItemData(); private static final BundledItemData INSTANCE = new BundledItemData();
private final Map<String, ItemEntry> idMap = new HashMap<>(); private final Map<String, ItemEntry> idMap = new HashMap<>();
private final Map<Integer, ItemEntry> legacyMap = new HashMap<>(); // Trove usage removed temporarily
/** /**
* Create a new instance. * Create a new instance.
@ -85,9 +84,6 @@ public class BundledItemData {
for (ItemEntry entry : entries) { for (ItemEntry entry : entries) {
idMap.put(entry.id, entry); idMap.put(entry.id, entry);
if (entry.legacyId >= 0) {
legacyMap.put(entry.legacyId, entry);
}
} }
} }
@ -97,7 +93,8 @@ public class BundledItemData {
* @param id the ID * @param id the ID
* @return the entry, or null * @return the entry, or null
*/ */
@Nullable public ItemEntry findById(String id) { @Nullable
public ItemEntry findById(String id) {
// If it has no namespace, assume minecraft. // If it has no namespace, assume minecraft.
if (!id.contains(":")) { if (!id.contains(":")) {
id = "minecraft:" + id; id = "minecraft:" + id;
@ -105,49 +102,6 @@ public class BundledItemData {
return idMap.get(id); return idMap.get(id);
} }
/**
* Return the entry for the given item legacy numeric ID.
*
* @param id the ID
* @return the entry, or null
*/
@Nullable
private ItemEntry findById(int id) {
return legacyMap.get(id);
}
/**
* Convert the given string ID to a legacy numeric ID.
*
* @param id the ID
* @return the legacy ID, which may be null if the item does not have a legacy ID
*/
@Nullable
public Integer toLegacyId(String id) {
ItemEntry entry = findById(id);
if (entry != null) {
return entry.legacyId;
} else {
return null;
}
}
/**
* Convert the given legacy numeric ID to a string ID.
*
* @param id the legacy ID
* @return the ID, which may be null if the item does not have a ID
*/
@Nullable
public String fromLegacyId(Integer id) {
ItemEntry entry = findById(id);
if (entry != null) {
return entry.id;
} else {
return null;
}
}
/** /**
* Get a singleton instance of this object. * Get a singleton instance of this object.
* *
@ -158,8 +112,6 @@ public class BundledItemData {
} }
public static class ItemEntry { public static class ItemEntry {
private int legacyId; // -1 for items without legacy IDs.
private short legacyData;
private String id; private String id;
private String unlocalizedName; private String unlocalizedName;
public String localizedName; public String localizedName;

View File

@ -35,15 +35,4 @@ public class BundledItemRegistry implements ItemRegistry {
public BaseItem createFromId(String id) { public BaseItem createFromId(String id) {
return new BaseItem(ItemTypes.getItemType(id)); return new BaseItem(ItemTypes.getItemType(id));
} }
@Nullable
@Override
public BaseItem createFromId(int legacyId) {
String id = BundledItemData.getInstance().fromLegacyId(legacyId);
if (id != null) {
return createFromId(id);
} else {
return null;
}
}
} }

View File

@ -34,13 +34,4 @@ public interface ItemRegistry {
@Nullable @Nullable
BaseItem createFromId(String id); BaseItem createFromId(String id);
/**
* Create a new item using its legacy numeric ID.
*
* @param id the id
* @return the item, which may be null if no item exists
*/
@Nullable
BaseItem createFromId(int id);
} }

View File

@ -0,0 +1,152 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.world.registry;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.type.BlockState;
import com.sk89q.worldedit.blocks.type.ItemType;
import com.sk89q.worldedit.blocks.type.ItemTypes;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.util.gson.VectorAdapter;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
public class LegacyMapper {
private static final Logger log = Logger.getLogger(LegacyMapper.class.getCanonicalName());
private static final LegacyMapper INSTANCE = new LegacyMapper();
private BiMap<String, BlockState> blockMap = HashBiMap.create();
private BiMap<String, ItemType> itemMap = HashBiMap.create();
/**
* Create a new instance.
*/
private LegacyMapper() {
try {
loadFromResource();
} catch (IOException e) {
log.log(Level.WARNING, "Failed to load the built-in legacy id registry", e);
}
}
/**
* Attempt to load the data from file.
*
* @throws IOException thrown on I/O error
*/
private void loadFromResource() throws IOException {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Vector.class, new VectorAdapter());
Gson gson = gsonBuilder.disableHtmlEscaping().create();
URL url = LegacyMapper.class.getResource("legacy.json");
if (url == null) {
throw new IOException("Could not find legacy.json");
}
String data = Resources.toString(url, Charset.defaultCharset());
LegacyDataFile dataFile = gson.fromJson(data, new TypeToken<LegacyDataFile>() {}.getType());
ParserContext parserContext = new ParserContext();
parserContext.setPreferringWildcard(false);
parserContext.setRestricted(false);
for (Map.Entry<String, String> blockEntry : dataFile.blocks.entrySet()) {
try {
blockMap.put(blockEntry.getKey(),
(BlockState) WorldEdit.getInstance().getBlockFactory().parseFromInput(blockEntry.getValue(), parserContext));
} catch (Exception e) {
log.warning("Unknown block: " + blockEntry.getValue());
}
}
for (Map.Entry<String, String> itemEntry : dataFile.items.entrySet()) {
try {
itemMap.put(itemEntry.getKey(), ItemTypes.getItemType(itemEntry.getValue()));
} catch (Exception e) {
log.warning("Unknown item: " + itemEntry.getValue());
}
}
}
@Nullable
public ItemType getItemFromLegacy(int legacyId) {
return itemMap.get(legacyId + ":0");
}
@Nullable
public ItemType getItemFromLegacy(int legacyId, int data) {
return itemMap.get(legacyId + ":" + data);
}
@Nullable
public int[] getLegacyFromItem(ItemType itemType) {
if (!itemMap.inverse().containsKey(itemType)) {
return null;
} else {
String value = itemMap.inverse().get(itemType);
return Arrays.stream(value.split(":")).mapToInt(Integer::parseInt).toArray();
}
}
@Nullable
public BlockState getBlockFromLegacy(int legacyId) {
return blockMap.get(legacyId + ":0");
}
@Nullable
public BlockState getBlockFromLegacy(int legacyId, int data) {
return blockMap.get(legacyId + ":" + data);
}
@Nullable
public int[] getLegacyFromBlock(BlockState blockState) {
if (!blockMap.inverse().containsKey(blockState)) {
return null;
} else {
String value = blockMap.inverse().get(blockState);
return Arrays.stream(value.split(":")).mapToInt(Integer::parseInt).toArray();
}
}
public static LegacyMapper getInstance() {
return INSTANCE;
}
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"})
private static class LegacyDataFile {
private Map<String, String> blocks;
private Map<String, String> items;
}
}

View File

@ -29,6 +29,7 @@ import javax.annotation.Nullable;
public class SimpleState<T extends SimpleStateValue> implements State<T> { public class SimpleState<T extends SimpleStateValue> implements State<T> {
private String name;
private List<T> values; private List<T> values;
/** /**
@ -37,9 +38,21 @@ public class SimpleState<T extends SimpleStateValue> implements State<T> {
* @param values The values * @param values The values
*/ */
public SimpleState(List<T> values) { public SimpleState(List<T> values) {
this.name = "Unknown";
this.values = values; this.values = values;
} }
/**
* Internal method for name setting post-deserialise. Do not use.
*/
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
@Override @Override
public List<T> getValues() { public List<T> getValues() {
return Collections.unmodifiableList(values); return Collections.unmodifiableList(values);

View File

@ -33,6 +33,13 @@ import javax.annotation.Nullable;
*/ */
public interface State<T extends SimpleStateValue> { public interface State<T extends SimpleStateValue> {
/**
* Returns the name of this state.
*
* @return The state name
*/
String getName();
/** /**
* Return a list of available values for this state. * Return a list of available values for this state.
* *

View File

@ -61,80 +61,4 @@ public class BlockDataTest {
} }
} }
} }
private static final TreeSet<Integer> datasTemplate = new TreeSet<Integer>();
static {
for (int data = 0; data < 16; ++data) {
datasTemplate.add(data);
}
}
@Test
public void testCycle() {
// Test monotony and continuity
for (int type = 0; type < 256; ++type) {
// Cloth isn't monotonous, and thus excluded.
if (type == BlockID.CLOTH
|| type == BlockID.STAINED_CLAY
|| type == BlockID.STAINED_GLASS
|| type == BlockID.STAINED_GLASS_PANE
|| type == BlockID.CARPET) {
continue;
}
for (int data = 0; data < 16; ++data) {
final String message = type + "/" + data;
final int cycled = BlockData.cycle(type, data, 1);
// If the cycle goes back (including -1), everything is ok.
if (cycled <= data) {
continue;
}
// If there's a gap in the cycle, there's a problem.
assertEquals(message, data + 1, cycled);
}
}
// Test cyclicity forwards
testCycle(1);
// ...and backwards
testCycle(-1);
}
private static void testCycle(final int increment) {
// Iterate each block type and data value that wasn't part of a cycle yet.
for (int type = 0; type < 256; ++type) {
@SuppressWarnings("unchecked")
final TreeSet<Integer> datas = (TreeSet<Integer>) datasTemplate.clone();
while (!datas.isEmpty()) {
final int start = datas.pollFirst();
String message = type + "/" + start;
int current = start;
boolean first = true;
while (true) {
current = BlockData.cycle(type, current, increment);
// If the cycle immediately goes to -1, everything is ok.
if (first && current == -1) break;
first = false;
message += "->" + current;
// If the cycle goes off limits (including -1), there's a problem.
assertTrue(message, current >= 0);
assertTrue(message, current < 16);
// The cycle completes, everything is ok.
if (current == start) break;
// Mark the current element as walked.
assertTrue(message, datas.remove(current));
}
}
}
}
} }

View File

@ -37,14 +37,4 @@ public class ForgeItemRegistry implements ItemRegistry {
return null; return null;
} }
} }
@Nullable
@Override
public BaseItem createFromId(int id) {
if (Item.REGISTRY.getObjectById(id) != null) {
return new BaseItem(id);
} else {
return null;
}
}
} }

View File

@ -22,9 +22,8 @@ package com.sk89q.worldedit.sponge.config;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.blocks.type.ItemTypes;
import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.world.registry.BundledItemData; import com.sk89q.worldedit.world.registry.LegacyMapper;
import com.sk89q.worldedit.world.snapshot.SnapshotRepository; import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
import ninja.leaping.configurate.ConfigurationOptions; import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode; import ninja.leaping.configurate.commented.CommentedConfigurationNode;
@ -61,7 +60,7 @@ public class ConfigurateConfiguration extends LocalConfiguration {
profile = node.getNode("debug").getBoolean(profile); profile = node.getNode("debug").getBoolean(profile);
wandItem = node.getNode("wand-item").getString(wandItem); wandItem = node.getNode("wand-item").getString(wandItem);
try { try {
wandItem = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(wandItem)); wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
@ -105,7 +104,7 @@ public class ConfigurateConfiguration extends LocalConfiguration {
navigationWand = node.getNode("navigation-wand", "item").getString(navigationWand); navigationWand = node.getNode("navigation-wand", "item").getString(navigationWand);
try { try {
navigationWand = BundledItemData.getInstance().fromLegacyId(Integer.parseInt(navigationWand)); navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
} catch (Throwable e) { } catch (Throwable e) {
} }
navigationWandMaxDistance = node.getNode("navigation-wand", "max-distance").getInt(navigationWandMaxDistance); navigationWandMaxDistance = node.getNode("navigation-wand", "max-distance").getInt(navigationWandMaxDistance);