From f033d87098efb5ed717d7a456db003f03a1bd5fb Mon Sep 17 00:00:00 2001
From: sk89q
Date: Mon, 14 Jul 2014 12:10:38 -0700
Subject: [PATCH] Add new Bukkit implementation adapter system to access MC
internals.
Replaces the old NMSBlocks.
---
pom.xml | 16 +-
.../sk89q/worldedit/bukkit/BukkitAdapter.java | 15 +
.../sk89q/worldedit/bukkit/BukkitWorld.java | 749 +-----------------
.../worldedit/bukkit/DefaultNmsBlock.java | 472 -----------
.../com/sk89q/worldedit/bukkit/NmsBlock.java | 61 --
.../worldedit/bukkit/WorldEditPlugin.java | 194 +++--
.../bukkit/adapter/AdapterLoadException.java | 41 +
.../bukkit/adapter/BukkitImplAdapter.java | 49 ++
.../bukkit/adapter/BukkitImplLoader.java | 197 +++++
.../adapter/impl/CraftBukkit_v1_7_R2.class | Bin 0 -> 12200 bytes
.../adapter/impl/CraftBukkit_v1_7_R3.class | Bin 0 -> 12200 bytes
.../adapter/impl/CraftBukkit_v1_7_R4.class | Bin 0 -> 12210 bytes
.../resources/nmsblocks/CBXNmsBlock_145.class | Bin 12701 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_146.class | Bin 12456 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_147.class | Bin 12528 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_15.class | Bin 12533 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_152.class | Bin 12540 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_161.class | Bin 12540 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_162.class | Bin 12540 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_164.class | Bin 12590 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_172.class | Bin 13807 -> 0 bytes
.../resources/nmsblocks/CBXNmsBlock_175.class | Bin 13808 -> 0 bytes
.../nmsblocks/CBXNmsBlock_prePackage.class | Bin 12484 -> 0 bytes
.../nmsblocks/CBXNmsBlock_v152_2.class | Bin 12552 -> 0 bytes
.../nmsblocks/MCPCPlusXNmsBlock_147.class | Bin 9277 -> 0 bytes
.../nmsblocks/MCPCPlusXNmsBlock_151dv.class | Bin 10513 -> 0 bytes
.../nmsblocks/MCPCPlusXNmsBlock_162.class | Bin 9348 -> 0 bytes
.../nmsblocks/MCPCPlusXNmsBlock_164.class | Bin 9348 -> 0 bytes
.../java/com/sk89q/worldedit/LocalWorld.java | 104 ---
.../worldedit/internal/LocalWorldAdapter.java | 55 --
.../command/WorldEditExceptionConverter.java | 2 +-
.../java/com/sk89q/worldedit/util/Enums.java | 54 ++
.../sk89q/worldedit/world/AbstractWorld.java | 81 +-
.../java/com/sk89q/worldedit/world/World.java | 18 -
34 files changed, 528 insertions(+), 1580 deletions(-)
delete mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/DefaultNmsBlock.java
delete mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/NmsBlock.java
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/AdapterLoadException.java
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java
create mode 100644 src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R2.class
create mode 100644 src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R3.class
create mode 100644 src/bukkit/resources/com/sk89q/worldedit/bukkit/adapter/impl/CraftBukkit_v1_7_R4.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_145.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_146.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_147.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_15.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_152.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_161.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_162.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_164.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_172.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_175.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_prePackage.class
delete mode 100644 src/bukkit/resources/nmsblocks/CBXNmsBlock_v152_2.class
delete mode 100644 src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_147.class
delete mode 100644 src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_151dv.class
delete mode 100644 src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_162.class
delete mode 100644 src/bukkit/resources/nmsblocks/MCPCPlusXNmsBlock_164.class
create mode 100644 src/main/java/com/sk89q/worldedit/util/Enums.java
diff --git a/pom.xml b/pom.xml
index f0a66b601..d4ea069f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -542,16 +542,6 @@
jartrue
-
-
-
- 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 extends NmsBlock> 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 extends NmsBlock> nmsClass = (Class extends NmsBlock>) 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 extends NmsBlock>) 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