diff --git a/pom.xml b/pom.xml index f0a66b601..d4ea069f1 100644 --- a/pom.xml +++ b/pom.xml @@ -542,16 +542,6 @@ jar true - - - - org.bukkit - craftbukkit - 1.7.9-R0.1-SNAPSHOT - compile - jar - true - @@ -578,11 +568,11 @@ - nmsblocks/ + . false - ${basedir}/src/bukkit/resources/nmsblocks/ + ${basedir}/src/bukkit/resources/ - *.class + **/*.class diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java index 579ea88ae..7de20172b 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java @@ -98,6 +98,21 @@ final class BukkitAdapter { (float) Math.toDegrees(location.getPitch())); } + /** + * Create a Bukkit location from a WorldEdit position with a Bukkit world. + * + * @param world the Bukkit world + * @param position the WorldEdit position + * @return a Bukkit location + */ + public static org.bukkit.Location adapt(org.bukkit.World world, Vector position) { + checkNotNull(world); + checkNotNull(position); + return new org.bukkit.Location( + world, + position.getX(), position.getY(), position.getZ()); + } + /** * Create a WorldEdit entity from a Bukkit entity. * diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index e693f18ea..29648289d 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -31,36 +31,23 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.blocks.BlockID; -import com.sk89q.worldedit.blocks.ContainerBlock; -import com.sk89q.worldedit.blocks.FurnaceBlock; import com.sk89q.worldedit.blocks.LazyBlock; -import com.sk89q.worldedit.blocks.MobSpawnerBlock; -import com.sk89q.worldedit.blocks.NoteBlock; -import com.sk89q.worldedit.blocks.SignBlock; -import com.sk89q.worldedit.blocks.SkullBlock; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Enums; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.registry.LegacyWorldData; import com.sk89q.worldedit.world.registry.WorldData; -import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.SkullType; import org.bukkit.TreeType; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.Chest; -import org.bukkit.block.CreatureSpawner; -import org.bukkit.block.Furnace; -import org.bukkit.block.Sign; -import org.bukkit.block.Skull; -import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Ambient; import org.bukkit.entity.Animals; import org.bukkit.entity.Boat; @@ -82,15 +69,9 @@ import org.bukkit.entity.Villager; import org.bukkit.inventory.DoubleChestInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; import javax.annotation.Nullable; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.InputStream; import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.net.URL; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -107,118 +88,26 @@ import static com.google.common.base.Preconditions.checkNotNull; public class BukkitWorld extends LocalWorld { private static final Logger logger = WorldEdit.logger; - private final WeakReference worldRef; - private static boolean skipNmsAccess = false; - private static boolean skipNmsSafeSet = false; - private static boolean skipNmsValidBlockCheck = false; + private static final org.bukkit.entity.EntityType tntMinecartType = + Enums.findByValue(org.bukkit.entity.EntityType.class, "MINECART_TNT"); - /* - * holder for the nmsblock class that we should use - */ - private static Class nmsBlockType; - private static Method nmsSetMethod; - private static Method nmsValidBlockMethod; - private static Method nmsGetMethod; - private static Method nmsSetSafeMethod; - - // copied from WG - private static > T tryEnum(Class enumType, String ... values) { - for (String val : values) { - try { - return Enum.valueOf(enumType, val); - } catch (IllegalArgumentException e) {} + private static final Map effects = new HashMap(); + static { + for (Effect effect : Effect.values()) { + effects.put(effect.getId(), effect); } - return null; } - private static org.bukkit.entity.EntityType tntMinecartType; - private static boolean checkMinecartType = true; + + private final WeakReference worldRef; /** * Construct the object. - * @param world + * + * @param world the world */ @SuppressWarnings("unchecked") public BukkitWorld(World world) { this.worldRef = new WeakReference(world); - - if (checkMinecartType) { - tntMinecartType = tryEnum(org.bukkit.entity.EntityType.class, "MINECART_TNT"); - checkMinecartType = false; - } - // check if we have a class we can use for nms access - - // only run once per server startup - if (nmsBlockType != null || skipNmsAccess || skipNmsSafeSet || skipNmsValidBlockCheck) return; - Plugin plugin = Bukkit.getPluginManager().getPlugin("WorldEdit"); - if (!(plugin instanceof WorldEditPlugin)) return; // hopefully never happens - WorldEditPlugin wePlugin = ((WorldEditPlugin) plugin); - File nmsBlocksDir = new File(wePlugin.getDataFolder() + File.separator + "nmsblocks" + File.separator); - if (nmsBlocksDir.listFiles() == null) { // no files to use - skipNmsAccess = true; skipNmsSafeSet = true; skipNmsValidBlockCheck = true; - return; - } - try { - // make a classloader that can handle our blocks - NmsBlockClassLoader loader = new NmsBlockClassLoader(BukkitWorld.class.getClassLoader(), nmsBlocksDir); - String filename; - for (File f : nmsBlocksDir.listFiles()) { - if (!f.isFile()) continue; - filename = f.getName(); - // load class using magic keyword - Class testBlock = null; - try { - testBlock = loader.loadClass("CL-NMS" + filename); - } catch (Throwable e) { - // someone is putting things where they don't belong - continue; - } - filename = filename.replaceFirst(".class$", ""); // get rid of extension - if (NmsBlock.class.isAssignableFrom(testBlock)) { - // got a NmsBlock, test it now - Class nmsClass = (Class) testBlock; - boolean canUse = false; - try { - canUse = (Boolean) nmsClass.getMethod("verify").invoke(null); - } catch (Throwable e) { - continue; - } - if (!canUse) continue; // not for this server - nmsBlockType = nmsClass; - nmsSetMethod = nmsBlockType.getMethod("set", World.class, Vector.class, BaseBlock.class); - nmsValidBlockMethod = nmsBlockType.getMethod("isValidBlockType", int.class); - nmsGetMethod = nmsBlockType.getMethod("get", World.class, Vector.class, int.class, int.class); - nmsSetSafeMethod = nmsBlockType.getMethod("setSafely", - BukkitWorld.class, Vector.class, com.sk89q.worldedit.foundation.Block.class, boolean.class); - // phew - break; - } - } - if (nmsBlockType != null) { - logger.info("[WorldEdit] Using external NmsBlock for this version: " + nmsBlockType.getName()); - } else { - // try our default - try { - nmsBlockType = (Class) Class.forName("com.sk89q.worldedit.bukkit.DefaultNmsBlock"); - boolean canUse = (Boolean) nmsBlockType.getMethod("verify").invoke(null); - if (canUse) { - nmsSetMethod = nmsBlockType.getMethod("set", World.class, Vector.class, BaseBlock.class); - nmsValidBlockMethod = nmsBlockType.getMethod("isValidBlockType", int.class); - nmsGetMethod = nmsBlockType.getMethod("get", World.class, Vector.class, int.class, int.class); - nmsSetSafeMethod = nmsBlockType.getMethod("setSafely", - BukkitWorld.class, Vector.class, com.sk89q.worldedit.foundation.Block.class, boolean.class); - logger.info("[WorldEdit] Using inbuilt NmsBlock for this version."); - } - } catch (Throwable e) { - // OMG DEVS WAI U NO SUPPORT SERVER - skipNmsAccess = true; skipNmsSafeSet = true; skipNmsValidBlockCheck = true; - logger.warning("[WorldEdit] No compatible nms block class found."); - } - } - } catch (Throwable e) { - logger.warning("[WorldEdit] Unable to load NmsBlock classes, make sure they are installed correctly."); - e.printStackTrace(); - skipNmsAccess = true; skipNmsSafeSet = true; skipNmsValidBlockCheck = true; - } } @Override @@ -256,41 +145,6 @@ public class BukkitWorld extends LocalWorld { throw new UnsupportedOperationException("Not implemented yet"); } - private class NmsBlockClassLoader extends ClassLoader { - public File searchDir; - public NmsBlockClassLoader(ClassLoader parent, File searchDir) { - super(parent); - this.searchDir = searchDir; - } - - @Override - public Class loadClass(String name) throws ClassNotFoundException { - if (!name.startsWith("CL-NMS")) { - return super.loadClass(name); - } else { - name = name.replace("CL-NMS", ""); // hacky lol - } - try { - URL url = new File(searchDir, name).toURI().toURL(); - InputStream input = url.openConnection().getInputStream(); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - int data = input.read(); - while (data != -1) { - buffer.write(data); - data = input.read(); - } - input.close(); - - byte[] classData = buffer.toByteArray(); - - return defineClass(name.replaceFirst(".class$", ""), classData, 0, classData.length); - } catch (Throwable e) { - throw new ClassNotFoundException(); - } - } - } - /** * Get the world handle. * @@ -318,66 +172,6 @@ public class BukkitWorld extends LocalWorld { return getWorld().getName(); } - /** - * Set block type. - * - * @param pt - * @param type - * @return - */ - @Override - public boolean setBlockType(Vector pt, int type) { - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type); - } - - /** - * Set block type. - * - * @param pt - * @param type - * @return - */ - @Override - public boolean setBlockTypeFast(Vector pt, int type) { - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeId(type, false); - } - - @Override - public boolean setTypeIdAndData(Vector pt, int type, int data) { - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeIdAndData(type, (byte) data, true); - } - - @Override - public boolean setTypeIdAndDataFast(Vector pt, int type, int data) { - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setTypeIdAndData(type, (byte) data, false); - } - - /** - * Get block type. - * - * @param pt - * @return - */ - @Override - public int getBlockType(Vector pt) { - return getWorld().getBlockTypeIdAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - } - - @Override - public void setBlockData(Vector pt, int data) { - getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setData((byte) data); - } - - @Override - public void setBlockDataFast(Vector pt, int data) { - getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).setData((byte) data, false); - } - - @Override - public int getBlockData(Vector pt) { - return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getData(); - } - @Override public int getBlockLightLevel(Vector pt) { return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); @@ -423,7 +217,7 @@ public class BukkitWorld extends LocalWorld { try { getWorld().regenerateChunk(chunk.getBlockX(), chunk.getBlockZ()); } catch (Throwable t) { - t.printStackTrace(); + logger.log(Level.WARNING, "Chunk generation via Bukkit raised an error", t); } // Then restore @@ -448,303 +242,6 @@ public class BukkitWorld extends LocalWorld { return true; } - @Override - public boolean copyToWorld(Vector pt, BaseBlock block) { - World world = getWorld(); - - if (block instanceof SignBlock) { - // Signs - setSignText(pt, ((SignBlock) block).getText()); - return true; - } - - if (block instanceof FurnaceBlock) { - // Furnaces - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof Furnace)) return false; - Furnace bukkit = (Furnace) state; - FurnaceBlock we = (FurnaceBlock) block; - bukkit.setBurnTime(we.getBurnTime()); - bukkit.setCookTime(we.getCookTime()); - return setContainerBlockContents(pt, ((ContainerBlock) block).getItems()); - } - - if (block instanceof ContainerBlock) { - // Chests/dispenser - return setContainerBlockContents(pt, ((ContainerBlock) block).getItems()); - } - - if (block instanceof MobSpawnerBlock) { - // Mob spawners - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof CreatureSpawner)) return false; - CreatureSpawner bukkit = (CreatureSpawner) state; - MobSpawnerBlock we = (MobSpawnerBlock) block; - bukkit.setCreatureTypeByName(we.getMobType()); - bukkit.setDelay(we.getDelay()); - return true; - } - - if (block instanceof NoteBlock) { - // Note block - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof org.bukkit.block.NoteBlock)) return false; - org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state; - NoteBlock we = (NoteBlock) block; - bukkit.setRawNote(we.getNote()); - return true; - } - - if (block instanceof SkullBlock) { - // Skull block - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof org.bukkit.block.Skull)) return false; - Skull bukkit = (Skull) state; - SkullBlock we = (SkullBlock) block; - // this is dumb - SkullType skullType = SkullType.SKELETON; - switch (we.getSkullType()) { - case 0: - skullType = SkullType.SKELETON; - break; - case 1: - skullType = SkullType.WITHER; - break; - case 2: - skullType = SkullType.ZOMBIE; - break; - case 3: - skullType = SkullType.PLAYER; - break; - case 4: - skullType = SkullType.CREEPER; - break; - } - bukkit.setSkullType(skullType); - BlockFace rotation; - switch (we.getRot()) { - // soooo dumb - case 0: - rotation = BlockFace.NORTH; - break; - case 1: - rotation = BlockFace.NORTH_NORTH_EAST; - break; - case 2: - rotation = BlockFace.NORTH_EAST; - break; - case 3: - rotation = BlockFace.EAST_NORTH_EAST; - break; - case 4: - rotation = BlockFace.EAST; - break; - case 5: - rotation = BlockFace.EAST_SOUTH_EAST; - break; - case 6: - rotation = BlockFace.SOUTH_EAST; - break; - case 7: - rotation = BlockFace.SOUTH_SOUTH_EAST; - break; - case 8: - rotation = BlockFace.SOUTH; - break; - case 9: - rotation = BlockFace.SOUTH_SOUTH_WEST; - break; - case 10: - rotation = BlockFace.SOUTH_WEST; - break; - case 11: - rotation = BlockFace.WEST_SOUTH_WEST; - break; - case 12: - rotation = BlockFace.WEST; - break; - case 13: - rotation = BlockFace.WEST_NORTH_WEST; - break; - case 14: - rotation = BlockFace.NORTH_WEST; - break; - case 15: - rotation = BlockFace.NORTH_NORTH_WEST; - break; - default: - rotation = BlockFace.NORTH; - break; - } - bukkit.setRotation(rotation); - if (we.getOwner() != null && !we.getOwner().isEmpty()) bukkit.setOwner(we.getOwner()); - bukkit.update(true); - return true; - } - - if (!skipNmsAccess) { - try { - return (Boolean) nmsSetMethod.invoke(null, world, pt, block); - } catch (Throwable t) { - logger.log(Level.WARNING, "WorldEdit: Failed to do NMS access for direct NBT data copy", t); - skipNmsAccess = true; - } - } - - return false; - } - - @Override - public boolean copyFromWorld(Vector pt, BaseBlock block) { - World world = getWorld(); - - if (block instanceof SignBlock) { - // Signs - ((SignBlock) block).setText(getSignText(pt)); - return true; - } - - if (block instanceof FurnaceBlock) { - // Furnaces - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof Furnace)) return false; - Furnace bukkit = (Furnace) state; - FurnaceBlock we = (FurnaceBlock) block; - we.setBurnTime(bukkit.getBurnTime()); - we.setCookTime(bukkit.getCookTime()); - ((ContainerBlock) block).setItems(getContainerBlockContents(pt)); - return true; - } - - if (block instanceof ContainerBlock) { - // Chests/dispenser - ((ContainerBlock) block).setItems(getContainerBlockContents(pt)); - return true; - } - - if (block instanceof MobSpawnerBlock) { - // Mob spawners - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof CreatureSpawner)) return false; - CreatureSpawner bukkit = (CreatureSpawner) state; - MobSpawnerBlock we = (MobSpawnerBlock) block; - we.setMobType(bukkit.getCreatureTypeName()); - we.setDelay((short) bukkit.getDelay()); - return true; - } - - if (block instanceof NoteBlock) { - // Note block - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof org.bukkit.block.NoteBlock)) return false; - org.bukkit.block.NoteBlock bukkit = (org.bukkit.block.NoteBlock) state; - NoteBlock we = (NoteBlock) block; - we.setNote(bukkit.getRawNote()); - return true; - } - - if (block instanceof SkullBlock) { - // Skull block - Block bukkitBlock = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (bukkitBlock == null) return false; - BlockState state = bukkitBlock.getState(); - if (!(state instanceof org.bukkit.block.Skull)) return false; - Skull bukkit = (Skull) state; - SkullBlock we = (SkullBlock) block; - byte skullType = 0; - switch (bukkit.getSkullType()) { - // this is dumb but whoever wrote the class is stupid - case SKELETON: - skullType = 0; - break; - case WITHER: - skullType = 1; - break; - case ZOMBIE: - skullType = 2; - break; - case PLAYER: - skullType = 3; - break; - case CREEPER: - skullType = 4; - break; - } - we.setSkullType(skullType); - byte rot = 0; - switch (bukkit.getRotation()) { - // this is even more dumb, hurray for copy/paste - case NORTH: - rot = (byte) 0; - break; - case NORTH_NORTH_EAST: - rot = (byte) 1; - break; - case NORTH_EAST: - rot = (byte) 2; - break; - case EAST_NORTH_EAST: - rot = (byte) 3; - break; - case EAST: - rot = (byte) 4; - break; - case EAST_SOUTH_EAST: - rot = (byte) 5; - break; - case SOUTH_EAST: - rot = (byte) 6; - break; - case SOUTH_SOUTH_EAST: - rot = (byte) 7; - break; - case SOUTH: - rot = (byte) 8; - break; - case SOUTH_SOUTH_WEST: - rot = (byte) 9; - break; - case SOUTH_WEST: - rot = (byte) 10; - break; - case WEST_SOUTH_WEST: - rot = (byte) 11; - break; - case WEST: - rot = (byte) 12; - break; - case WEST_NORTH_WEST: - rot = (byte) 13; - break; - case NORTH_WEST: - rot = (byte) 14; - break; - case NORTH_NORTH_WEST: - rot = (byte) 15; - break; - } - we.setRot(rot); - we.setOwner(bukkit.hasOwner() ? bukkit.getOwner() : ""); - return true; - } - - return false; - } - /** * Gets the single block inventory for a potentially double chest. * Handles people who have an old version of Bukkit. @@ -1032,159 +529,9 @@ public class BukkitWorld extends LocalWorld { return num; } - /** - * Set a sign's text. - * - * @param pt - * @param text - * @return - */ - private boolean setSignText(Vector pt, String[] text) { - World world = getWorld(); - - Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (block == null) return false; - BlockState state = block.getState(); - if (state == null || !(state instanceof Sign)) return false; - Sign sign = (Sign) state; - sign.setLine(0, text[0]); - sign.setLine(1, text[1]); - sign.setLine(2, text[2]); - sign.setLine(3, text[3]); - sign.update(); - return true; - } - - /** - * Get a sign's text. - * - * @param pt - * @return - */ - private String[] getSignText(Vector pt) { - World world = getWorld(); - - Block block = world.getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (block == null) return new String[] { "", "", "", "" }; - BlockState state = block.getState(); - if (state == null || !(state instanceof Sign)) return new String[] { "", "", "", "" }; - Sign sign = (Sign) state; - String line0 = sign.getLine(0); - String line1 = sign.getLine(1); - String line2 = sign.getLine(2); - String line3 = sign.getLine(3); - return new String[] { - line0 != null ? line0 : "", - line1 != null ? line1 : "", - line2 != null ? line2 : "", - line3 != null ? line3 : "", - }; - } - - /** - * Get a container block's contents. - * - * @param pt - * @return - */ - private BaseItemStack[] getContainerBlockContents(Vector pt) { - Block block = getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (block == null) { - return new BaseItemStack[0]; - } - BlockState state = block.getState(); - if (!(state instanceof org.bukkit.inventory.InventoryHolder)) { - return new BaseItemStack[0]; - } - - org.bukkit.inventory.InventoryHolder container = (org.bukkit.inventory.InventoryHolder) state; - Inventory inven = container.getInventory(); - if (container instanceof Chest) { - inven = getBlockInventory((Chest) container); - } - int size = inven.getSize(); - BaseItemStack[] contents = new BaseItemStack[size]; - - for (int i = 0; i < size; ++i) { - ItemStack bukkitStack = inven.getItem(i); - if (bukkitStack != null && bukkitStack.getTypeId() > 0) { - contents[i] = new BaseItemStack( - bukkitStack.getTypeId(), - bukkitStack.getAmount(), - bukkitStack.getDurability()); - try { - for (Map.Entry entry : bukkitStack.getEnchantments().entrySet()) { - contents[i].getEnchantments().put(entry.getKey().getId(), entry.getValue()); - } - } catch (Throwable ignore) {} - } - } - - return contents; - } - - /** - * Set a container block's contents. - * - * @param pt - * @param contents - * @return - */ - private boolean setContainerBlockContents(Vector pt, BaseItemStack[] contents) { - Block block = getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()); - if (block == null) { - return false; - } - BlockState state = block.getState(); - if (!(state instanceof org.bukkit.inventory.InventoryHolder)) { - return false; - } - - org.bukkit.inventory.InventoryHolder chest = (org.bukkit.inventory.InventoryHolder) state; - Inventory inven = chest.getInventory(); - if (chest instanceof Chest) { - inven = getBlockInventory((Chest) chest); - } - int size = inven.getSize(); - - for (int i = 0; i < size; ++i) { - if (i >= contents.length) { - break; - } - - if (contents[i] != null) { - ItemStack toAdd = new ItemStack(contents[i].getType(), - contents[i].getAmount(), - contents[i].getData()); - try { - for (Map.Entry entry : contents[i].getEnchantments().entrySet()) { - toAdd.addEnchantment(Enchantment.getById(entry.getKey()), entry.getValue()); - } - } catch (Throwable ignore) {} - inven.setItem(i, toAdd); - } else { - inven.setItem(i, null); - } - } - - return true; - } - - /** - * Returns whether a block has a valid ID. - * - * @param type - * @return - */ + @SuppressWarnings("deprecation") @Override public boolean isValidBlockType(int type) { - if (!skipNmsValidBlockCheck) { - try { - return (Boolean) nmsValidBlockMethod.invoke(null, type); - } catch (Throwable e) { - skipNmsValidBlockCheck = true; - } - } return Material.getMaterial(type) != null && Material.getMaterial(type).isBlock(); } @@ -1228,13 +575,6 @@ public class BukkitWorld extends LocalWorld { } } - private static final Map effects = new HashMap(); - static { - for (Effect effect : Effect.values()) { - effects.put(effect.getId(), effect); - } - } - @Override public boolean playEffect(Vector position, int type, int data) { World world = getWorld(); @@ -1278,38 +618,25 @@ public class BukkitWorld extends LocalWorld { } @Override - public BaseBlock getBlock(Vector pt) { - int type = getBlockType(pt); - int data = getBlockData(pt); - - switch (type) { - case BlockID.WALL_SIGN: - case BlockID.SIGN_POST: - //case BlockID.CHEST: // Prevent data loss for now - //case BlockID.FURNACE: - //case BlockID.BURNING_FURNACE: - //case BlockID.DISPENSER: - //case BlockID.MOB_SPAWNER: - case BlockID.NOTE_BLOCK: - case BlockID.HEAD: - return super.getBlock(pt); - default: - if (!skipNmsAccess) { - try { - NmsBlock block = null; - block = (NmsBlock) nmsGetMethod.invoke(null, getWorld(), pt, type, data); - if (block != null) { - return block; - } - } catch (Throwable t) { - logger.log(Level.WARNING, - "WorldEdit: Failed to do NMS access for direct NBT data copy", t); - skipNmsAccess = true; - } - } + public BaseBlock getBlock(Vector position) { + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + return adapter.getBlock(BukkitAdapter.adapt(getWorld(), position)); + } else { + Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData()); } + } - return super.getBlock(pt); + @Override + public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException { + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, notifyAndLight); + } else { + Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + return bukkitBlock.setTypeIdAndData(block.getType(), (byte) block.getData(), notifyAndLight); + } } @SuppressWarnings("deprecation") @@ -1320,20 +647,6 @@ public class BukkitWorld extends LocalWorld { return new LazyBlock(bukkitBlock.getTypeId(), bukkitBlock.getData(), this, position); } - @Override - public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) throws WorldEditException { - if (!skipNmsSafeSet) { - try { - return (Boolean) nmsSetSafeMethod.invoke(null, this, pt, block, notifyAdjacent); - } catch (Throwable t) { - logger.log(Level.WARNING, "WorldEdit: Failed to do NMS safe block set", t); - skipNmsSafeSet = true; - } - } - - return super.setBlock(pt, block, notifyAdjacent); - } - /** * @deprecated Use {@link #setBlock(Vector, BaseBlock, boolean)} */ diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java deleted file mode 100644 index 8b738923b..000000000 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * 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 . - */ - -package com.sk89q.worldedit.bukkit; -import com.sk89q.jnbt.*; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.blocks.TileEntityBlock; -import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.foundation.Block; -import net.minecraft.server.v1_7_R3.*; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_7_R3.CraftWorld; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.*; -import java.util.logging.Logger; - -/** - * A blind handler of blocks with TileEntity data that directly access Minecraft's - * classes through CraftBukkit. - *

- * Usage of this class may break terribly in the future, and therefore usage should - * be trapped in a handler for {@link Throwable}. - */ -public class DefaultNmsBlock extends NmsBlock { - - private static final Logger logger = WorldEdit.logger; - private static Field compoundMapField; - private static final Field nmsBlock_isTileEntityField; // The field is deobfuscated but the method isn't. No idea why. - private NBTTagCompound nbtData = null; - - static { - Field field; - try { - field = net.minecraft.server.v1_7_R3.Block.class.getDeclaredField("isTileEntity"); - field.setAccessible(true); - } catch (NoSuchFieldException e) { - // logger.severe("Could not find NMS block tile entity field!"); - field = null; - } - nmsBlock_isTileEntityField = field; - } - - public static boolean verify() { - return nmsBlock_isTileEntityField != null; - } - - /** - * Create a new instance with a given type ID, data value, and previous - * {@link TileEntityBlock}-implementing object. - * - * @param type block type ID - * @param data data value - * @param tileEntityBlock tile entity block - */ - public DefaultNmsBlock(int type, int data, TileEntityBlock tileEntityBlock) { - super(type, data); - - nbtData = (NBTTagCompound) fromNative(tileEntityBlock.getNbtData()); - } - - /** - * Create a new instance with a given type ID, data value, and raw - * {@link NBTTagCompound} copy. - * - * @param type block type ID - * @param data data value - * @param nbtData raw NBT data - */ - public DefaultNmsBlock(int type, int data, NBTTagCompound nbtData) { - super(type, data); - - this.nbtData = nbtData; - } - - /** - * Build a {@link NBTTagCompound} that has valid coordinates. - * - * @param pt coordinates to set - * @return the tag compound - */ - private NBTTagCompound getNmsData(Vector pt) { - if (nbtData == null) { - return null; - } - - nbtData.set("x", new NBTTagInt(pt.getBlockX())); - nbtData.set("y", new NBTTagInt(pt.getBlockY())); - nbtData.set("z", new NBTTagInt(pt.getBlockZ())); - - return nbtData; - } - - @Override - public boolean hasNbtData() { - return nbtData != null; - } - - @Override - public String getNbtId() { - if (nbtData == null) { - return ""; - } - - return nbtData.getString("id"); - } - - @Override - public CompoundTag getNbtData() { - if (nbtData == null) { - return new CompoundTag(getNbtId(), - new HashMap()); - } - return (CompoundTag) toNative(nbtData); - } - - @Override - public void setNbtData(CompoundTag tag) { - if (tag == null) { - this.nbtData = null; - } - this.nbtData = (NBTTagCompound) fromNative(tag); - } - - /** - * Build an instance from the given information. - * - * @param world world to get the block from - * @param position position to get the block at - * @param type type ID of block - * @param data data value of block - * @return the block, or null - */ - public static DefaultNmsBlock get(World world, Vector position, int type, int data) { - if (!hasTileEntity(type)) { - return null; - } - - TileEntity te = ((CraftWorld) world).getHandle().getTileEntity( - position.getBlockX(), position.getBlockY(), position.getBlockZ()); - - if (te != null) { - NBTTagCompound tag = new NBTTagCompound(); - te.b(tag); // Load data - return new DefaultNmsBlock(type, data, tag); - } - - return null; - } - - /** - * Set an instance or a {@link TileEntityBlock} to the given position. - * - * @param world world to set the block in - * @param position position to set the block at - * @param block the block to set - * @return true if tile entity data was copied to the world - */ - public static boolean set(World world, Vector position, BaseBlock block) { - NBTTagCompound data = null; - if (!hasTileEntity(world.getBlockTypeIdAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()))) { - return false; - } - - if (block instanceof DefaultNmsBlock) { - DefaultNmsBlock nmsProxyBlock = (DefaultNmsBlock) block; - data = nmsProxyBlock.getNmsData(position); - } else if (block instanceof TileEntityBlock) { - DefaultNmsBlock nmsProxyBlock = new DefaultNmsBlock( - block.getId(), block.getData(), block); - data = nmsProxyBlock.getNmsData(position); - } - - if (data != null) { - TileEntity te = ((CraftWorld) world).getHandle().getTileEntity( - position.getBlockX(), position.getBlockY(), position.getBlockZ()); - if (te != null) { - te.a(data); // Load data - return true; - } - } - - return false; - } - - /** - * Tries to set a block 'safely', as in setting the block data to the location, and - * then triggering physics only at the end. - * - * @param world world to set the block in - * @param position position to set the block at - * @param block the block to set - * @param notifyAdjacent true to notify physics and what not - * @return true if block id or data was changed - */ - public static boolean setSafely(BukkitWorld world, Vector position, - Block block, boolean notifyAdjacent) { - - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - - CraftWorld craftWorld = ((CraftWorld) world.getWorld()); -// TileEntity te = craftWorld.getHandle().getTileEntity(x, y, z); -// craftWorld.getHandle().tileEntityList.remove(te); - - boolean changed = craftWorld.getHandle().setTypeAndData(x, y, z, getNmsBlock(block.getId()), block.getData(), 0); - - if (block instanceof BaseBlock) { - world.copyToWorld(position, (BaseBlock) block); - } - - changed = craftWorld.getHandle().setData(x, y, z, block.getData(), 0) || changed; - if (changed && notifyAdjacent) { - craftWorld.getHandle().notify(x, y, z); - craftWorld.getHandle().update(x, y, z, getNmsBlock(block.getId())); - } - - return changed; - } - - public static boolean hasTileEntity(int type) { - net.minecraft.server.v1_7_R3.Block nmsBlock = getNmsBlock(type); - if (nmsBlock == null) { - return false; - } - - try { - return nmsBlock_isTileEntityField.getBoolean(nmsBlock); // Once we have the field stord, gets are fast - } catch (IllegalAccessException e) { - return false; - } - } - - public static net.minecraft.server.v1_7_R3.Block getNmsBlock(int type) { - return net.minecraft.server.v1_7_R3.Block.e(type); - } - - /** - * Converts from a non-native NMS NBT structure to a native WorldEdit NBT - * structure. - * - * @param foreign non-native NMS NBT structure - * @return native WorldEdit NBT structure - */ - private static Tag toNative(NBTBase foreign) { - // temporary fix since mojang removed names from tags - // our nbt spec will need to be updated to theirs - return toNative(getTagName(foreign.getTypeId()), foreign); - } - - // seriously these two methods are hacky - our jnbt spec needs updating - // copied from NMS 1.7.5- code, since it was removed in 1.7.8 - private static String getTagName(int i) { - switch (i) { - case 0: - return "TAG_End"; - case 1: - return "TAG_Byte"; - case 2: - return "TAG_Short"; - case 3: - return "TAG_Int"; - case 4: - return "TAG_Long"; - case 5: - return "TAG_Float"; - case 6: - return "TAG_Double"; - case 7: - return "TAG_Byte_Array"; - case 8: - return "TAG_String"; - case 9: - return "TAG_List"; - case 10: - return "TAG_Compound"; - case 11: - return "TAG_Int_Array"; - case 99: - return "Any Numeric Tag"; - default: - return "UNKNOWN"; - } - } - - /** - * Converts from a non-native NMS NBT structure to a native WorldEdit NBT - * structure. - * - * @param foreign non-native NMS NBT structure - * @param name name for the tag, if it has one - * @return native WorldEdit NBT structure - */ - @SuppressWarnings("unchecked") - private static Tag toNative(String name, NBTBase foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof NBTTagCompound) { - Map values = new HashMap(); - Collection foreignKeys = null; - - if (compoundMapField == null) { - try { - // Method name may change! - foreignKeys = ((NBTTagCompound) foreign).c(); - } catch (Throwable t) { - try { - logger.warning("WorldEdit: Couldn't get NBTTagCompound.c(), " + - "so we're going to try to get at the 'map' field directly from now on"); - - if (compoundMapField == null) { - compoundMapField = NBTTagCompound.class.getDeclaredField("map"); - compoundMapField.setAccessible(true); - } - } catch (Throwable e) { - // Can't do much beyond this - throw new RuntimeException(e); - } - } - } - - if (compoundMapField != null) { - try { - foreignKeys = ((HashMap) compoundMapField.get(foreign)).keySet(); - } catch (Throwable e) { - // Can't do much beyond this - throw new RuntimeException(e); - } - } - - for (Object obj : foreignKeys) { - String key = (String) obj; - NBTBase base = (NBTBase) ((NBTTagCompound) foreign).get(key); - values.put(key, toNative(key, base)); - } - return new CompoundTag(name, values); - } else if (foreign instanceof NBTTagByte) { - return new ByteTag(name, ((NBTTagByte) foreign).f()); // getByte - } else if (foreign instanceof NBTTagByteArray) { - return new ByteArrayTag(name, - ((NBTTagByteArray) foreign).c()); // data - } else if (foreign instanceof NBTTagDouble) { - return new DoubleTag(name, - ((NBTTagDouble) foreign).g()); // getDouble - } else if (foreign instanceof NBTTagFloat) { - return new FloatTag(name, ((NBTTagFloat) foreign).h()); // getFloat - } else if (foreign instanceof NBTTagInt) { - return new IntTag(name, ((NBTTagInt) foreign).d()); // getInt - } else if (foreign instanceof NBTTagIntArray) { - return new IntArrayTag(name, - ((NBTTagIntArray) foreign).c()); // data - } else if (foreign instanceof NBTTagList) { - try { - return transmorgifyList(name, (NBTTagList) foreign); - } catch (NoSuchFieldException e) { - } catch (SecurityException e) { - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) {} - return new ListTag(name, ByteTag.class, new ArrayList()); - } else if (foreign instanceof NBTTagLong) { - return new LongTag(name, ((NBTTagLong) foreign).c()); // getLong - } else if (foreign instanceof NBTTagShort) { - return new ShortTag(name, ((NBTTagShort) foreign).e()); // getShort - } else if (foreign instanceof NBTTagString) { - return new StringTag(name, - ((NBTTagString) foreign).a_()); // data - } else if (foreign instanceof NBTTagEnd) { - return new EndTag(); - } else { - throw new IllegalArgumentException("Don't know how to make native " - + foreign.getClass().getCanonicalName()); - } - } - - private static ListTag transmorgifyList(String name, NBTTagList foreign) - throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { - List values = new ArrayList(); - int type = foreign.d(); - Field listField = NBTTagList.class.getDeclaredField("list"); - listField.setAccessible(true); - List foreignList; - foreignList = (List) listField.get(foreign); - for (int i = 0; i < foreign.size(); i++) { - NBTBase element = (NBTBase) foreignList.get(i); - values.add(toNative(null, element)); // list elements shouldn't have names - } - Class cls = NBTConstants.getClassFromType(type); - return new ListTag(name, cls, values); - } - - /** - * Converts a WorldEdit-native NBT structure to a NMS structure. - * - * @param foreign structure to convert - * @return non-native structure - */ - private static NBTBase fromNative(Tag foreign) { - if (foreign == null) { - return null; - } - if (foreign instanceof CompoundTag) { - NBTTagCompound tag = new NBTTagCompound(); - for (Map.Entry entry : ((CompoundTag) foreign) - .getValue().entrySet()) { - tag.set(entry.getKey(), fromNative(entry.getValue())); - } - return tag; - } else if (foreign instanceof ByteTag) { - return new NBTTagByte(((ByteTag) foreign).getValue()); - } else if (foreign instanceof ByteArrayTag) { - return new NBTTagByteArray(((ByteArrayTag) foreign).getValue()); - } else if (foreign instanceof DoubleTag) { - return new NBTTagDouble(((DoubleTag) foreign).getValue()); - } else if (foreign instanceof FloatTag) { - return new NBTTagFloat(((FloatTag) foreign).getValue()); - } else if (foreign instanceof IntTag) { - return new NBTTagInt(((IntTag) foreign).getValue()); - } else if (foreign instanceof IntArrayTag) { - return new NBTTagIntArray(((IntArrayTag) foreign).getValue()); - } else if (foreign instanceof ListTag) { - NBTTagList tag = new NBTTagList(); - ListTag foreignList = (ListTag) foreign; - for (Tag t : foreignList.getValue()) { - tag.add(fromNative(t)); - } - return tag; - } else if (foreign instanceof LongTag) { - return new NBTTagLong(((LongTag) foreign).getValue()); - } else if (foreign instanceof ShortTag) { - return new NBTTagShort(((ShortTag) foreign).getValue()); - } else if (foreign instanceof StringTag) { - return new NBTTagString(((StringTag) foreign).getValue()); - } else if (foreign instanceof EndTag) { - try { - Method tagMaker = NBTBase.class.getDeclaredMethod("createTag", byte.class); - tagMaker.setAccessible(true); - return (NBTBase) tagMaker.invoke(null, (byte) 0); - } catch (Exception e) { - return null; - } - } else { - throw new IllegalArgumentException("Don't know how to make NMS " - + foreign.getClass().getCanonicalName()); - } - } - - public static boolean isValidBlockType(int type) throws NoClassDefFoundError { - return type == 0 || (type >= 1 && net.minecraft.server.v1_7_R3.Block.e(type) != null); - } - -} diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/NmsBlock.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/NmsBlock.java deleted file mode 100644 index 088de8547..000000000 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/NmsBlock.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * 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 . - */ - -package com.sk89q.worldedit.bukkit; - -import org.bukkit.World; - -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.foundation.Block; - -public abstract class NmsBlock extends BaseBlock { - - protected NmsBlock(int type) { - super(type); - } - - protected NmsBlock(int type, int data) { - super(type, data); - } - - public static boolean verify() { - return false; - } - - public static NmsBlock get(World world, Vector vector, int type, int data) { - return null; - } - - public static boolean set(World world, Vector vector, Block block) { - return false; - } - - public static boolean setSafely(World world, Vector vector, Block block, boolean notify) { - return false; - } - - public static boolean hasTileEntity(int type) { - return false; - } - - public static boolean isValidBlockType(int type) { - return false; - } -} \ No newline at end of file diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 0cdaf470d..eac26306b 100644 --- a/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -22,7 +22,16 @@ package com.sk89q.worldedit.bukkit; import com.google.common.base.Joiner; import com.sk89q.util.yaml.YAMLProcessor; import com.sk89q.wepif.PermissionsResolverManager; -import com.sk89q.worldedit.*; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.IncompleteRegionException; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.ServerInterface; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditOperation; +import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; import com.sk89q.worldedit.bukkit.selections.CuboidSelection; import com.sk89q.worldedit.bukkit.selections.CylinderSelection; import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection; @@ -32,7 +41,11 @@ import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.inventory.BlockBag; -import com.sk89q.worldedit.regions.*; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.CylinderRegion; +import com.sk89q.worldedit.regions.Polygonal2DRegion; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionSelector; import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -40,13 +53,20 @@ import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; -import java.io.*; -import java.util.Enumeration; +import javax.annotation.Nullable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.List; -import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.zip.ZipEntry; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Plugin for Bukkit. * @@ -54,27 +74,13 @@ import java.util.zip.ZipEntry; */ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { - /** - * The name of the CUI's plugin channel registration - */ + private static final Logger log = Logger.getLogger(WorldEditPlugin.class.getCanonicalName()); public static final String CUI_PLUGIN_CHANNEL = "WECUI"; + private static WorldEditPlugin INSTANCE; - /** - * The server interface that all server-related API goes through. - */ + private BukkitImplAdapter bukkitAdapter; private BukkitServerInterface server; - /** - * Main WorldEdit instance. - */ - private WorldEdit controller; - /** - * Deprecated API. - */ - private WorldEditAPI api; - - /** - * Holds the configuration for WorldEdit. - */ + private final WorldEditAPI api = new WorldEditAPI(this); private BukkitConfiguration config; /** @@ -82,41 +88,27 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { */ @Override public void onEnable() { - final String pluginYmlVersion = getDescription().getVersion(); - final String manifestVersion = WorldEdit.getVersion(); + this.INSTANCE = this; - if (!manifestVersion.equalsIgnoreCase(pluginYmlVersion)) { - WorldEdit.setVersion(manifestVersion + " (" + pluginYmlVersion + ")"); - } + WorldEdit worldEdit = WorldEdit.getInstance(); - // Make the data folders that WorldEdit uses - getDataFolder().mkdirs(); - File targetDir = new File(getDataFolder() + File.separator + "nmsblocks"); - targetDir.mkdir(); - copyNmsBlockClasses(targetDir); + loadAdapter(); // Need an adapter to work with special blocks with NBT data + loadConfig(); // Load configuration + PermissionsResolverManager.initialize(this); // Setup permission resolver - // Create the default configuration file - createDefaultConfiguration("config.yml"); - - // Set up configuration and such, including the permissions - // resolver - config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), this); - PermissionsResolverManager.initialize(this); - - // Load the configuration - config.load(); - - // Setup interfaces + // Setup platform server = new BukkitServerInterface(this, getServer()); - controller = WorldEdit.getInstance(); - controller.getPlatformManager().register(server); - api = new WorldEditAPI(this); + worldEdit.getPlatformManager().register(server); + + // Register CUI getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this)); getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL); - // Now we can register events! + + // Now we can register events getServer().getPluginManager().registerEvents(new WorldEditListener(this), this); - getServer().getScheduler().runTaskTimerAsynchronously(this, new SessionTimer(controller, getServer()), 120, 120); + // Register session timer + getServer().getScheduler().runTaskTimerAsynchronously(this, new SessionTimer(worldEdit, getServer()), 120, 120); // If we are on MCPC+/Cauldron, then Forge will have already loaded // Forge WorldEdit and there's (probably) not going to be any other @@ -124,31 +116,34 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent()); } - private void copyNmsBlockClasses(File target) { + private void loadConfig() { + createDefaultConfiguration("config.yml"); // Create the default configuration file + + config = new BukkitConfiguration(new YAMLProcessor(new File(getDataFolder(), "config.yml"), true), this); + config.load(); + } + + private void loadAdapter() { + // Attempt to load a Bukkit adapter + BukkitImplLoader adapterLoader = new BukkitImplLoader(); + try { - JarFile jar = new JarFile(getFile()); - @SuppressWarnings("rawtypes") - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry jarEntry = (JarEntry) entries.nextElement(); - if (!jarEntry.getName().startsWith("nmsblocks") || jarEntry.isDirectory()) continue; + adapterLoader.addFromPath(getClass().getClassLoader()); + } catch (IOException e) { + log.log(Level.WARNING, "Failed to search path for Bukkit adapters"); + } - File file = new File(target + File.separator + jarEntry.getName().replace("nmsblocks", "")); - if (file.exists()) continue; - - InputStream is = jar.getInputStream(jarEntry); - FileOutputStream fos = new FileOutputStream(file); - - fos = new FileOutputStream(file); - byte[] buf = new byte[8192]; - int length = 0; - while ((length = is.read(buf)) > 0) { - fos.write(buf, 0, length); - } - fos.close(); - is.close(); - } - } catch (Throwable e) {} + try { + adapterLoader.addFromJar(getFile()); + } catch (IOException e) { + log.log(Level.WARNING, "Failed to search " + getFile() + " for Bukkit adapters", e); + } + try { + bukkitAdapter = adapterLoader.loadAdapter(); + log.log(Level.INFO, "Using " + bukkitAdapter.getClass().getCanonicalName() + " as the Bukkit adapter"); + } catch (AdapterLoadException e) { + log.log(Level.WARNING, e.getMessage()); + } } /** @@ -156,10 +151,13 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { */ @Override public void onDisable() { - if (controller != null) { - controller.clearSessions(); - controller.getPlatformManager().unregister(server); + WorldEdit worldEdit = WorldEdit.getInstance(); + worldEdit.clearSessions(); + worldEdit.getPlatformManager().unregister(server); + if (config != null) { config.unload(); + } + if (server != null) { server.unregisterCommands(); } this.getServer().getScheduler().cancelTasks(this); @@ -177,7 +175,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { /** * Create a default configuration file from the .jar. * - * @param name + * @param name the filename */ protected void createDefaultConfiguration(String name) { File actual = new File(getDataFolder(), name); @@ -257,7 +255,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { * @return */ public LocalSession getSession(Player player) { - return controller.getSession(wrapPlayer(player)); + return WorldEdit.getInstance().getSession(wrapPlayer(player)); } /** @@ -268,10 +266,10 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { */ public EditSession createEditSession(Player player) { LocalPlayer wePlayer = wrapPlayer(player); - LocalSession session = controller.getSession(wePlayer); + LocalSession session = WorldEdit.getInstance().getSession(wePlayer); BlockBag blockBag = session.getBlockBag(wePlayer); - EditSession editSession = controller.getEditSessionFactory() + EditSession editSession = WorldEdit.getInstance().getEditSessionFactory() .getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer); editSession.enableQueue(); @@ -286,12 +284,12 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { */ public void remember(Player player, EditSession editSession) { LocalPlayer wePlayer = wrapPlayer(player); - LocalSession session = controller.getSession(wePlayer); + LocalSession session = WorldEdit.getInstance().getSession(wePlayer); session.remember(editSession); editSession.flushQueue(); - controller.flushBlockBag(wePlayer, editSession); + WorldEdit.getInstance().flushBlockBag(wePlayer, editSession); } /** @@ -301,10 +299,9 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { * @param op * @throws Throwable */ - public void perform(Player player, WorldEditOperation op) - throws Throwable { + public void perform(Player player, WorldEditOperation op) throws Throwable { LocalPlayer wePlayer = wrapPlayer(player); - LocalSession session = controller.getSession(wePlayer); + LocalSession session = WorldEdit.getInstance().getSession(wePlayer); EditSession editSession = createEditSession(player); try { @@ -379,7 +376,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { * @return */ public WorldEdit getWorldEdit() { - return controller; + return WorldEdit.getInstance(); } /** @@ -396,7 +393,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { throw new IllegalArgumentException("Offline player not allowed"); } - LocalSession session = controller.getSession(wrapPlayer(player)); + LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player)); RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld())); try { @@ -434,9 +431,30 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { throw new IllegalArgumentException("Null selection not allowed"); } - LocalSession session = controller.getSession(wrapPlayer(player)); + LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player)); RegionSelector sel = selection.getRegionSelector(); session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel); session.dispatchCUISelection(wrapPlayer(player)); } + + /** + * Gets the instance of this plugin. + * + * @return an instance of the plugin + * @throws NullPointerException if the plugin hasn't been enabled + */ + static WorldEditPlugin getInstance() { + return checkNotNull(INSTANCE); + } + + /** + * Get the Bukkit implementation adapter. + * + * @return the adapter + */ + @Nullable + BukkitImplAdapter getBukkitImplAdapter() { + return bukkitAdapter; + } + } diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/AdapterLoadException.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/AdapterLoadException.java new file mode 100644 index 000000000..d8459d691 --- /dev/null +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/AdapterLoadException.java @@ -0,0 +1,41 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.bukkit.adapter; + +/** + * Thrown when no adapter can be found. + */ +public class AdapterLoadException extends Exception { + + public AdapterLoadException() { + } + + public AdapterLoadException(String message) { + super(message); + } + + public AdapterLoadException(String message, Throwable cause) { + super(message, cause); + } + + public AdapterLoadException(Throwable cause) { + super(cause); + } +} diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java new file mode 100644 index 000000000..8de74ce80 --- /dev/null +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -0,0 +1,49 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.bukkit.adapter; + +import com.sk89q.worldedit.blocks.BaseBlock; +import org.bukkit.Location; + +/** + * An interface for adapters of various Bukkit implementations. + */ +public interface BukkitImplAdapter { + + /** + * Get the block at the given location. + * + * @param location the location + * @return the block + */ + BaseBlock getBlock(Location location); + + /** + * Set the block at the given location. + * + * @param location the location + * @param state the block + * @param notifyAndLight notify and light if set + * @return true if a block was likely changed + */ + boolean setBlock(Location location, BaseBlock state, boolean notifyAndLight); + + +} diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java new file mode 100644 index 000000000..28704a8ca --- /dev/null +++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -0,0 +1,197 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.bukkit.adapter; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.util.io.Closer; +import org.bukkit.Bukkit; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Loads Bukkit implementation adapters. + */ +public class BukkitImplLoader { + + private static final Logger log = Logger.getLogger(BukkitImplLoader.class.getCanonicalName()); + private final List adapterCandidates = new ArrayList(); + private String customCandidate; + + private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.bukkit.adapter.impl"; + private static final String SEARCH_PACKAGE_DOT = SEARCH_PACKAGE + "."; + private static final String SEARCH_PATH = SEARCH_PACKAGE.replace(".", "/"); + private static final String CLASS_SUFFIX = ".class"; + + private static final String LOAD_ERROR_MESSAGE = + "Failed to find an adapter for Bukkit!\n\n" + + "This version of WorldEdit (%s) does not fully support your version of Bukkit (%s).\n\n" + + "What this means:\n" + + "1) Block operations will work, but chests will be empty, signs will be blank, and so on.\n" + + "2) You won't be able to save and load chests, signs, etc. with .schematic files.\n" + + "3) You won't be able to work with entities properly.\n" + + "4) Undo will will not be able to restore chests, signs, and etc.\n\n" + + "Possible solutions:\n" + + "1) If this is a new version of Minecraft, please wait for us to update. " + + "You can also put in a ticket at http://youtrack.sk89q.com (check for an existing ticket first).\n" + + "2) If you are using an older version of Minecraft, you may need to downgrade WorldEdit.\n" + + "3) If you are using an older version of WorldEdit, you may need to update your WorldEdit.\n" + + "4) If you are not using CraftBukkit, then report this issue to http://youtrack.sk89q.com " + + "(check for an existing ticket first).\n" + + "5) If you are developing WorldEdit, you can force an adapter with " + + "-Dworldedit.bukkit.adapter=the_class_name.\n\n" + + "Can I ignore this error? Yes! Just be aware of the undo issue.\n" + + "Am I using CraftBukkit? %s.\n"; + + /** + * Create a new instance. + */ + public BukkitImplLoader() { + addDefaults(); + } + + /** + * Add default candidates, such as any defined with + * {@code -Dworldedit.bukkit.adapter}. + */ + private void addDefaults() { + String className = System.getProperty("worldedit.bukkit.adapter"); + if (className != null) { + customCandidate = className; + adapterCandidates.add(className); + log.log(Level.INFO, "-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters"); + } + } + + /** + * Search the given JAR for candidate implementations. + * + * @param file the file + * @throws IOException thrown on I/O error + */ + public void addFromJar(File file) throws IOException { + Closer closer = Closer.create(); + JarFile jar = closer.register(new JarFile(file)); + try { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) entries.nextElement(); + + String className = jarEntry.getName().replaceAll("[/\\\\]+", "."); + + if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory()) continue; + + int beginIndex = 0; + int endIndex = className.length() - CLASS_SUFFIX.length(); + className = className.substring(beginIndex, endIndex); + adapterCandidates.add(className); + } + } finally { + closer.close(); + } + } + + /** + * Search for classes stored as separate files available via the given + * class loader. + * + * @param classLoader the class loader + * @throws IOException thrown on error + */ + public void addFromPath(ClassLoader classLoader) throws IOException { + Enumeration resources = classLoader.getResources(SEARCH_PATH); + while (resources.hasMoreElements()) { + File file = new File(resources.nextElement().getFile()); + addFromPath(file); + } + } + + /** + * Search for classes stored as separate files available via the given + * path. + * + * @param file the path + */ + private void addFromPath(File file) { + String resource = SEARCH_PACKAGE_DOT + file.getName(); + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + addFromPath(child); + } + } + } else if (resource.endsWith(CLASS_SUFFIX)) { + int beginIndex = 0; + int endIndex = resource.length() - CLASS_SUFFIX.length(); + String className = resource.substring(beginIndex, endIndex); + adapterCandidates.add(className); + } + } + + /** + * Iterate through the list of candidates and load an adapter. + * + * @return an adapter + * @throws AdapterLoadException thrown if no adapter could be found + */ + public BukkitImplAdapter loadAdapter() throws AdapterLoadException { + for (String className : adapterCandidates) { + try { + Class cls = Class.forName(className); + if (BukkitImplAdapter.class.isAssignableFrom(cls)) { + return (BukkitImplAdapter) cls.newInstance(); + } else { + log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + + "' because it does not implement " + BukkitImplAdapter.class.getCanonicalName()); + } + } catch (ClassNotFoundException e) { + log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + + "' that is not supposed to be missing", e); + } catch (IllegalAccessException e) { + log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + + "' that is not supposed to be raising this error", e); + } catch (Throwable e) { + if (className.equals(customCandidate)) { + log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + "'", e); + } + } + } + + String weVersion = WorldEdit.getVersion(); + String bukkitVersion = Bukkit.getBukkitVersion() + " implemented by " + Bukkit.getName() + " " + Bukkit.getVersion(); + String usingCraftBukkit = + Bukkit.getName().equals("CraftBukkit") + ? "Probably (if you got it from dl.bukkit.org, then yes)" + : "No! You are using " + Bukkit.getName(); + + throw new AdapterLoadException( + String.format(LOAD_ERROR_MESSAGE, weVersion, bukkitVersion, usingCraftBukkit)); + } + +} diff --git a/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R2.class b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R2.class new file mode 100644 index 000000000..1fbcb3cba Binary files /dev/null and b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R2.class differ diff --git a/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R3.class b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R3.class new file mode 100644 index 000000000..7aa94f9a2 Binary files /dev/null and b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R3.class differ diff --git a/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R4.class b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R4.class new file mode 100644 index 000000000..15c6cc9a3 Binary files /dev/null and b/src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R4.class differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_145.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_145.class deleted file mode 100644 index b8d6c51f3..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_145.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_146.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_146.class deleted file mode 100644 index e89c4a70b..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_146.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_147.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_147.class deleted file mode 100644 index e3c8c20fd..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_147.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_15.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_15.class deleted file mode 100644 index 68781e198..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_15.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_152.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_152.class deleted file mode 100644 index 8dda57ec9..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_152.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_161.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_161.class deleted file mode 100644 index 336c611cb..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_161.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_162.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_162.class deleted file mode 100644 index 2d70cfbcb..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_162.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_164.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_164.class deleted file mode 100644 index 7520a85a1..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_164.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_172.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_172.class deleted file mode 100644 index a7fb7e100..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_172.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_175.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_175.class deleted file mode 100644 index 6afbcdcc5..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_175.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_prePackage.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_prePackage.class deleted file mode 100644 index 07a94b131..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_prePackage.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/CBXNmsBlock_v152_2.class b/src/bukkit/resources/nmsblocks/CBXNmsBlock_v152_2.class deleted file mode 100644 index 2a4acd48e..000000000 Binary files a/src/bukkit/resources/nmsblocks/CBXNmsBlock_v152_2.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_147.class b/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_147.class deleted file mode 100644 index 86da91a7f..000000000 Binary files a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_147.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_151dv.class b/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_151dv.class deleted file mode 100644 index b68088e83..000000000 Binary files a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_151dv.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_162.class b/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_162.class deleted file mode 100644 index 7f1326865..000000000 Binary files a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_162.class and /dev/null differ diff --git a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_164.class b/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_164.class deleted file mode 100644 index ac6c27721..000000000 Binary files a/src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_164.class and /dev/null differ diff --git a/src/main/java/com/sk89q/worldedit/LocalWorld.java b/src/main/java/com/sk89q/worldedit/LocalWorld.java index 9dd3498cb..037e92810 100644 --- a/src/main/java/com/sk89q/worldedit/LocalWorld.java +++ b/src/main/java/com/sk89q/worldedit/LocalWorld.java @@ -60,115 +60,11 @@ public abstract class LocalWorld extends AbstractWorld { @Deprecated protected Random random = new Random(); - @Override - public BaseBlock getBlock(Vector pt) { - checkLoadedChunk(pt); - - @SuppressWarnings("deprecation") int type = getBlockType(pt); - @SuppressWarnings("deprecation") int data = getBlockData(pt); - - switch (type) { - case BlockID.WALL_SIGN: - case BlockID.SIGN_POST: { - SignBlock block = new SignBlock(type, data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.CHEST: { - ChestBlock block = new ChestBlock(data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.FURNACE: - case BlockID.BURNING_FURNACE: { - FurnaceBlock block = new FurnaceBlock(type, data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.DISPENSER: { - DispenserBlock block = new DispenserBlock(data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.MOB_SPAWNER: { - MobSpawnerBlock block = new MobSpawnerBlock(data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.NOTE_BLOCK: { - NoteBlock block = new NoteBlock(data); - copyFromWorld(pt, block); - return block; - } - - case BlockID.HEAD: { - SkullBlock block = new SkullBlock(data); - copyFromWorld(pt, block); - return block; - } - - default: - return new BaseBlock(type, data); - } - } - - /** - * Given a block and a position, copy data from the world to the block - * based on the type of block. - *

- * The provided {@link BaseBlock} should match that of the one in the - * world. - * - * @param position the position - * @param block the block - * @return true if the copy operation succeeded, false otherwise - */ - public abstract boolean copyFromWorld(Vector position, BaseBlock block); - @Override public BaseBlock getLazyBlock(Vector position) { return getBlock(position); } - @Override - public boolean setBlock(Vector pt, BaseBlock block, boolean notifyAdjacent) throws WorldEditException { - boolean successful; - - // Default implementation will call the old deprecated methods - if (notifyAdjacent) { - successful = setTypeIdAndData(pt, block.getId(), block.getData()); - } else { - successful = setTypeIdAndDataFast(pt, block.getId(), block.getData()); - } - - copyToWorld(pt, block); - - return successful; - } - - /** - * Given a block and a position, copy data to the world from the block - * based on the type of block. - *

- * The provided {@link BaseBlock} should match that of the one in the - * world. - * - * @param position the position - * @param block the block - * @return true if the copy operation succeeded, false otherwise - */ - public abstract boolean copyToWorld(Vector position, BaseBlock block); - - @Override - public boolean setBlock(Vector pt, BaseBlock block) throws WorldEditException { - return setBlock(pt, block, true); - } - @Override public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException { switch (type) { diff --git a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java index 2166b506d..eba0423bc 100644 --- a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java +++ b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java @@ -100,42 +100,6 @@ public class LocalWorldAdapter extends LocalWorld { return world.setBlock(position, block, notifyAndLight); } - @Override - @Deprecated - public boolean setBlockType(Vector position, int type) { - return world.setBlockType(position, type); - } - - @Override - @Deprecated - public boolean setBlockTypeFast(Vector position, int type) { - return world.setBlockTypeFast(position, type); - } - - @Override - @Deprecated - public void setBlockData(Vector position, int data) { - world.setBlockData(position, data); - } - - @Override - @Deprecated - public void setBlockDataFast(Vector position, int data) { - world.setBlockDataFast(position, data); - } - - @Override - @Deprecated - public boolean setTypeIdAndData(Vector position, int type, int data) { - return world.setTypeIdAndData(position, type, data); - } - - @Override - @Deprecated - public boolean setTypeIdAndDataFast(Vector position, int type, int data) { - return world.setTypeIdAndDataFast(position, type, data); - } - @Override public int getBlockLightLevel(Vector position) { return world.getBlockLightLevel(position); @@ -298,30 +262,11 @@ public class LocalWorldAdapter extends LocalWorld { return world.getBlock(position); } - @Override - public boolean copyFromWorld(Vector position, BaseBlock block) { - return false; - } - - @Override - public boolean copyToWorld(Vector position, BaseBlock block) { - return false; - } - @Override public BaseBlock getLazyBlock(Vector position) { return world.getLazyBlock(position); } - @Override - public boolean setBlock(Vector position, BaseBlock block) { - try { - return world.setBlock(position, block); - } catch (WorldEditException e) { - throw new RuntimeException(e); - } - } - @Override @Nullable public Operation commit() { diff --git a/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java b/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java index 6b8831d13..393e8c134 100644 --- a/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java +++ b/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java @@ -150,7 +150,7 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { @ExceptionMatch public void convert(WorldEditException e) throws CommandException { - throw new CommandException(e.getMessage()); + throw new CommandException(e.getMessage(), e); } } diff --git a/src/main/java/com/sk89q/worldedit/util/Enums.java b/src/main/java/com/sk89q/worldedit/util/Enums.java new file mode 100644 index 000000000..9f397c127 --- /dev/null +++ b/src/main/java/com/sk89q/worldedit/util/Enums.java @@ -0,0 +1,54 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.util; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Helper methods for enums. + */ +public final class Enums { + + private Enums() { + } + + /** + * Search the given enum for a value that is equal to the one of the + * given values, searching in an ascending manner. + * + * @param enumType the enum type + * @param values the list of values + * @param the type of enum + * @return the found value or null + */ + @Nullable + public static > T findByValue(Class enumType, String... values) { + checkNotNull(enumType); + checkNotNull(values); + for (String val : values) { + try { + return Enum.valueOf(enumType, val); + } catch (IllegalArgumentException ignored) {} + } + return null; + } +} diff --git a/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java b/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java index 6c982cf6a..95917043e 100644 --- a/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java +++ b/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java @@ -47,6 +47,37 @@ public abstract class AbstractWorld implements World { private final PriorityQueue effectQueue = new PriorityQueue(); private int taskId = -1; + @Override + public final boolean setBlockType(Vector position, int type) { + try { + return setBlock(position, new BaseBlock(type)); + } catch (WorldEditException ignored) { + return false; + } + } + + @Override + public final void setBlockData(Vector position, int data) { + try { + setBlock(position, new BaseBlock(getLazyBlock(position).getType(), data)); + } catch (WorldEditException ignored) { + } + } + + @Override + public final boolean setTypeIdAndData(Vector position, int type, int data) { + try { + return setBlock(position, new BaseBlock(type, data)); + } catch (WorldEditException ignored) { + return false; + } + } + + @Override + public final boolean setBlock(Vector pt, BaseBlock block) throws WorldEditException { + return setBlock(pt, block, true); + } + @Override public int getMaxY() { return getMaximumPoint().getBlockY(); @@ -82,56 +113,6 @@ public abstract class AbstractWorld implements World { return getLazyBlock(pt).getData(); } - @Override - public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException { - return setBlock(position, block, true); - } - - @Override - public boolean setBlockType(Vector position, int type) { - try { - return setBlock(position, new BaseBlock(type)); - } catch (WorldEditException e) { - throw new RuntimeException(e); - } - } - - @Override - public void setBlockData(Vector position, int data) { - try { - setBlock(position, new BaseBlock(getLazyBlock(position).getId(), data)); - } catch (WorldEditException e) { - throw new RuntimeException(e); - } - } - - @Override - public void setBlockDataFast(Vector position, int data) { - setBlockData(position, data); - } - - @SuppressWarnings("deprecation") - @Override - public boolean setBlockTypeFast(Vector pt, int type) { - return setBlockType(pt, type); - } - - @SuppressWarnings("deprecation") - @Override - public boolean setTypeIdAndData(Vector pt, int type, int data) { - boolean ret = setBlockType(pt, type); - setBlockData(pt, data); - return ret; - } - - @SuppressWarnings("deprecation") - @Override - public boolean setTypeIdAndDataFast(Vector pt, int type, int data) { - boolean ret = setBlockTypeFast(pt, type); - setBlockDataFast(pt, data); - return ret; - } - @Override public void dropItem(Vector pt, BaseItemStack item, int times) { for (int i = 0; i < times; ++i) { diff --git a/src/main/java/com/sk89q/worldedit/world/World.java b/src/main/java/com/sk89q/worldedit/world/World.java index 1c077d3d2..c11b1bf2d 100644 --- a/src/main/java/com/sk89q/worldedit/world/World.java +++ b/src/main/java/com/sk89q/worldedit/world/World.java @@ -122,36 +122,18 @@ public interface World extends Extent { @Deprecated boolean setBlockType(Vector position, int type); - /** - * @deprecated Use {@link #setBlock(Vector, BaseBlock)} - */ - @Deprecated - boolean setBlockTypeFast(Vector position, int type); - /** * @deprecated Use {@link #setBlock(Vector, BaseBlock)} */ @Deprecated void setBlockData(Vector position, int data); - /** - * @deprecated Use {@link #setBlock(Vector, BaseBlock)} - */ - @Deprecated - void setBlockDataFast(Vector position, int data); - /** * @deprecated Use {@link #setBlock(Vector, BaseBlock)} */ @Deprecated boolean setTypeIdAndData(Vector position, int type, int data); - /** - * @deprecated Use {@link #setBlock(Vector, BaseBlock)} - */ - @Deprecated - boolean setTypeIdAndDataFast(Vector position, int type, int data); - /** * Get the light level at the given block. *