mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Add new Bukkit implementation adapter system to access MC internals.
Replaces the old NMSBlocks.
This commit is contained in:
parent
c535ad8682
commit
f033d87098
16
pom.xml
16
pom.xml
@ -542,16 +542,6 @@
|
|||||||
<type>jar</type>
|
<type>jar</type>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- NMS blocks -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.bukkit</groupId>
|
|
||||||
<artifactId>craftbukkit</artifactId>
|
|
||||||
<version>1.7.9-R0.1-SNAPSHOT</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
<type>jar</type>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -578,11 +568,11 @@
|
|||||||
|
|
||||||
<!-- NMS support in Bukkit -->
|
<!-- NMS support in Bukkit -->
|
||||||
<resource>
|
<resource>
|
||||||
<targetPath>nmsblocks/</targetPath>
|
<targetPath>.</targetPath>
|
||||||
<filtering>false</filtering>
|
<filtering>false</filtering>
|
||||||
<directory>${basedir}/src/bukkit/resources/nmsblocks/</directory>
|
<directory>${basedir}/src/bukkit/resources/</directory>
|
||||||
<includes>
|
<includes>
|
||||||
<include>*.class</include>
|
<include>**/*.class</include>
|
||||||
</includes>
|
</includes>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -98,6 +98,21 @@ final class BukkitAdapter {
|
|||||||
(float) Math.toDegrees(location.getPitch()));
|
(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.
|
* Create a WorldEdit entity from a Bukkit entity.
|
||||||
*
|
*
|
||||||
|
@ -31,36 +31,23 @@ import com.sk89q.worldedit.WorldEdit;
|
|||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
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.LazyBlock;
|
||||||
import com.sk89q.worldedit.blocks.MobSpawnerBlock;
|
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||||
import com.sk89q.worldedit.blocks.NoteBlock;
|
|
||||||
import com.sk89q.worldedit.blocks.SignBlock;
|
|
||||||
import com.sk89q.worldedit.blocks.SkullBlock;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.Enums;
|
||||||
import com.sk89q.worldedit.util.TreeGenerator;
|
import com.sk89q.worldedit.util.TreeGenerator;
|
||||||
import com.sk89q.worldedit.world.registry.LegacyWorldData;
|
import com.sk89q.worldedit.world.registry.LegacyWorldData;
|
||||||
import com.sk89q.worldedit.world.registry.WorldData;
|
import com.sk89q.worldedit.world.registry.WorldData;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.SkullType;
|
|
||||||
import org.bukkit.TreeType;
|
import org.bukkit.TreeType;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.Chest;
|
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.Ambient;
|
||||||
import org.bukkit.entity.Animals;
|
import org.bukkit.entity.Animals;
|
||||||
import org.bukkit.entity.Boat;
|
import org.bukkit.entity.Boat;
|
||||||
@ -82,15 +69,9 @@ import org.bukkit.entity.Villager;
|
|||||||
import org.bukkit.inventory.DoubleChestInventory;
|
import org.bukkit.inventory.DoubleChestInventory;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -107,118 +88,26 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
public class BukkitWorld extends LocalWorld {
|
public class BukkitWorld extends LocalWorld {
|
||||||
|
|
||||||
private static final Logger logger = WorldEdit.logger;
|
private static final Logger logger = WorldEdit.logger;
|
||||||
|
private static final org.bukkit.entity.EntityType tntMinecartType =
|
||||||
|
Enums.findByValue(org.bukkit.entity.EntityType.class, "MINECART_TNT");
|
||||||
|
|
||||||
|
private static final Map<Integer, Effect> effects = new HashMap<Integer, Effect>();
|
||||||
|
static {
|
||||||
|
for (Effect effect : Effect.values()) {
|
||||||
|
effects.put(effect.getId(), effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final WeakReference<World> worldRef;
|
private final WeakReference<World> worldRef;
|
||||||
private static boolean skipNmsAccess = false;
|
|
||||||
private static boolean skipNmsSafeSet = false;
|
|
||||||
private static boolean skipNmsValidBlockCheck = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 extends Enum<T>> T tryEnum(Class<T> enumType, String ... values) {
|
|
||||||
for (String val : values) {
|
|
||||||
try {
|
|
||||||
return Enum.valueOf(enumType, val);
|
|
||||||
} catch (IllegalArgumentException e) {}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private static org.bukkit.entity.EntityType tntMinecartType;
|
|
||||||
private static boolean checkMinecartType = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the object.
|
* Construct the object.
|
||||||
* @param world
|
*
|
||||||
|
* @param world the world
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public BukkitWorld(World world) {
|
public BukkitWorld(World world) {
|
||||||
this.worldRef = new WeakReference<World>(world);
|
this.worldRef = new WeakReference<World>(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 <xyz> 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
|
@Override
|
||||||
@ -256,41 +145,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
throw new UnsupportedOperationException("Not implemented yet");
|
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.
|
* Get the world handle.
|
||||||
*
|
*
|
||||||
@ -318,66 +172,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
return getWorld().getName();
|
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
|
@Override
|
||||||
public int getBlockLightLevel(Vector pt) {
|
public int getBlockLightLevel(Vector pt) {
|
||||||
return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel();
|
return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel();
|
||||||
@ -423,7 +217,7 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
try {
|
try {
|
||||||
getWorld().regenerateChunk(chunk.getBlockX(), chunk.getBlockZ());
|
getWorld().regenerateChunk(chunk.getBlockX(), chunk.getBlockZ());
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
logger.log(Level.WARNING, "Chunk generation via Bukkit raised an error", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then restore
|
// Then restore
|
||||||
@ -448,303 +242,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
return true;
|
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.
|
* Gets the single block inventory for a potentially double chest.
|
||||||
* Handles people who have an old version of Bukkit.
|
* Handles people who have an old version of Bukkit.
|
||||||
@ -1032,159 +529,9 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@SuppressWarnings("deprecation")
|
||||||
* 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<Enchantment, Integer> 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<Integer, Integer> 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
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidBlockType(int type) {
|
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();
|
return Material.getMaterial(type) != null && Material.getMaterial(type).isBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,13 +575,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Map<Integer, Effect> effects = new HashMap<Integer, Effect>();
|
|
||||||
static {
|
|
||||||
for (Effect effect : Effect.values()) {
|
|
||||||
effects.put(effect.getId(), effect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean playEffect(Vector position, int type, int data) {
|
public boolean playEffect(Vector position, int type, int data) {
|
||||||
World world = getWorld();
|
World world = getWorld();
|
||||||
@ -1278,38 +618,25 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock getBlock(Vector pt) {
|
public BaseBlock getBlock(Vector position) {
|
||||||
int type = getBlockType(pt);
|
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
|
||||||
int data = getBlockData(pt);
|
if (adapter != null) {
|
||||||
|
return adapter.getBlock(BukkitAdapter.adapt(getWorld(), position));
|
||||||
switch (type) {
|
} else {
|
||||||
case BlockID.WALL_SIGN:
|
Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||||
case BlockID.SIGN_POST:
|
return new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData());
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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")
|
@SuppressWarnings("deprecation")
|
||||||
@ -1320,20 +647,6 @@ public class BukkitWorld extends LocalWorld {
|
|||||||
return new LazyBlock(bukkitBlock.getTypeId(), bukkitBlock.getData(), this, position);
|
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)}
|
* @deprecated Use {@link #setBlock(Vector, BaseBlock, boolean)}
|
||||||
*/
|
*/
|
||||||
|
@ -1,472 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sk89q.worldedit.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.
|
|
||||||
* </p>
|
|
||||||
* 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<String, Tag>());
|
|
||||||
}
|
|
||||||
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<String, Tag> values = new HashMap<String, Tag>();
|
|
||||||
Collection<Object> 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<Object, Object>) 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<ByteTag>());
|
|
||||||
} 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<Tag> values = new ArrayList<Tag>();
|
|
||||||
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<? extends Tag> 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<String, Tag> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
||||||
* Copyright (C) WorldEdit team and contributors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sk89q.worldedit.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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,7 +22,16 @@ package com.sk89q.worldedit.bukkit;
|
|||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.sk89q.util.yaml.YAMLProcessor;
|
import com.sk89q.util.yaml.YAMLProcessor;
|
||||||
import com.sk89q.wepif.PermissionsResolverManager;
|
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.CuboidSelection;
|
||||||
import com.sk89q.worldedit.bukkit.selections.CylinderSelection;
|
import com.sk89q.worldedit.bukkit.selections.CylinderSelection;
|
||||||
import com.sk89q.worldedit.bukkit.selections.Polygonal2DSelection;
|
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.event.platform.PlatformReadyEvent;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
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.World;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -40,13 +53,20 @@ import org.bukkit.command.TabCompleter;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.*;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Enumeration;
|
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.List;
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin for Bukkit.
|
* Plugin for Bukkit.
|
||||||
*
|
*
|
||||||
@ -54,27 +74,13 @@ import java.util.zip.ZipEntry;
|
|||||||
*/
|
*/
|
||||||
public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
||||||
|
|
||||||
/**
|
private static final Logger log = Logger.getLogger(WorldEditPlugin.class.getCanonicalName());
|
||||||
* The name of the CUI's plugin channel registration
|
|
||||||
*/
|
|
||||||
public static final String CUI_PLUGIN_CHANNEL = "WECUI";
|
public static final String CUI_PLUGIN_CHANNEL = "WECUI";
|
||||||
|
private static WorldEditPlugin INSTANCE;
|
||||||
|
|
||||||
/**
|
private BukkitImplAdapter bukkitAdapter;
|
||||||
* The server interface that all server-related API goes through.
|
|
||||||
*/
|
|
||||||
private BukkitServerInterface server;
|
private BukkitServerInterface server;
|
||||||
/**
|
private final WorldEditAPI api = new WorldEditAPI(this);
|
||||||
* Main WorldEdit instance.
|
|
||||||
*/
|
|
||||||
private WorldEdit controller;
|
|
||||||
/**
|
|
||||||
* Deprecated API.
|
|
||||||
*/
|
|
||||||
private WorldEditAPI api;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds the configuration for WorldEdit.
|
|
||||||
*/
|
|
||||||
private BukkitConfiguration config;
|
private BukkitConfiguration config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,41 +88,27 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
final String pluginYmlVersion = getDescription().getVersion();
|
this.INSTANCE = this;
|
||||||
final String manifestVersion = WorldEdit.getVersion();
|
|
||||||
|
|
||||||
if (!manifestVersion.equalsIgnoreCase(pluginYmlVersion)) {
|
WorldEdit worldEdit = WorldEdit.getInstance();
|
||||||
WorldEdit.setVersion(manifestVersion + " (" + pluginYmlVersion + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the data folders that WorldEdit uses
|
loadAdapter(); // Need an adapter to work with special blocks with NBT data
|
||||||
getDataFolder().mkdirs();
|
loadConfig(); // Load configuration
|
||||||
File targetDir = new File(getDataFolder() + File.separator + "nmsblocks");
|
PermissionsResolverManager.initialize(this); // Setup permission resolver
|
||||||
targetDir.mkdir();
|
|
||||||
copyNmsBlockClasses(targetDir);
|
|
||||||
|
|
||||||
// Create the default configuration file
|
// Setup platform
|
||||||
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
|
|
||||||
server = new BukkitServerInterface(this, getServer());
|
server = new BukkitServerInterface(this, getServer());
|
||||||
controller = WorldEdit.getInstance();
|
worldEdit.getPlatformManager().register(server);
|
||||||
controller.getPlatformManager().register(server);
|
|
||||||
api = new WorldEditAPI(this);
|
// Register CUI
|
||||||
getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
|
getServer().getMessenger().registerIncomingPluginChannel(this, CUI_PLUGIN_CHANNEL, new CUIChannelListener(this));
|
||||||
getServer().getMessenger().registerOutgoingPluginChannel(this, CUI_PLUGIN_CHANNEL);
|
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().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
|
// If we are on MCPC+/Cauldron, then Forge will have already loaded
|
||||||
// Forge WorldEdit and there's (probably) not going to be any other
|
// 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());
|
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 {
|
try {
|
||||||
JarFile jar = new JarFile(getFile());
|
adapterLoader.addFromPath(getClass().getClassLoader());
|
||||||
@SuppressWarnings("rawtypes")
|
} catch (IOException e) {
|
||||||
Enumeration entries = jar.entries();
|
log.log(Level.WARNING, "Failed to search path for Bukkit adapters");
|
||||||
while (entries.hasMoreElements()) {
|
|
||||||
JarEntry jarEntry = (JarEntry) entries.nextElement();
|
|
||||||
if (!jarEntry.getName().startsWith("nmsblocks") || jarEntry.isDirectory()) continue;
|
|
||||||
|
|
||||||
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();
|
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());
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,10 +151,13 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
if (controller != null) {
|
WorldEdit worldEdit = WorldEdit.getInstance();
|
||||||
controller.clearSessions();
|
worldEdit.clearSessions();
|
||||||
controller.getPlatformManager().unregister(server);
|
worldEdit.getPlatformManager().unregister(server);
|
||||||
|
if (config != null) {
|
||||||
config.unload();
|
config.unload();
|
||||||
|
}
|
||||||
|
if (server != null) {
|
||||||
server.unregisterCommands();
|
server.unregisterCommands();
|
||||||
}
|
}
|
||||||
this.getServer().getScheduler().cancelTasks(this);
|
this.getServer().getScheduler().cancelTasks(this);
|
||||||
@ -177,7 +175,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
/**
|
/**
|
||||||
* Create a default configuration file from the .jar.
|
* Create a default configuration file from the .jar.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name the filename
|
||||||
*/
|
*/
|
||||||
protected void createDefaultConfiguration(String name) {
|
protected void createDefaultConfiguration(String name) {
|
||||||
File actual = new File(getDataFolder(), name);
|
File actual = new File(getDataFolder(), name);
|
||||||
@ -257,7 +255,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public LocalSession getSession(Player player) {
|
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) {
|
public EditSession createEditSession(Player player) {
|
||||||
LocalPlayer wePlayer = wrapPlayer(player);
|
LocalPlayer wePlayer = wrapPlayer(player);
|
||||||
LocalSession session = controller.getSession(wePlayer);
|
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
|
||||||
BlockBag blockBag = session.getBlockBag(wePlayer);
|
BlockBag blockBag = session.getBlockBag(wePlayer);
|
||||||
|
|
||||||
EditSession editSession = controller.getEditSessionFactory()
|
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory()
|
||||||
.getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer);
|
.getEditSession(wePlayer.getWorld(), session.getBlockChangeLimit(), blockBag, wePlayer);
|
||||||
editSession.enableQueue();
|
editSession.enableQueue();
|
||||||
|
|
||||||
@ -286,12 +284,12 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
*/
|
*/
|
||||||
public void remember(Player player, EditSession editSession) {
|
public void remember(Player player, EditSession editSession) {
|
||||||
LocalPlayer wePlayer = wrapPlayer(player);
|
LocalPlayer wePlayer = wrapPlayer(player);
|
||||||
LocalSession session = controller.getSession(wePlayer);
|
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
|
||||||
|
|
||||||
session.remember(editSession);
|
session.remember(editSession);
|
||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
|
|
||||||
controller.flushBlockBag(wePlayer, editSession);
|
WorldEdit.getInstance().flushBlockBag(wePlayer, editSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,10 +299,9 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
* @param op
|
* @param op
|
||||||
* @throws Throwable
|
* @throws Throwable
|
||||||
*/
|
*/
|
||||||
public void perform(Player player, WorldEditOperation op)
|
public void perform(Player player, WorldEditOperation op) throws Throwable {
|
||||||
throws Throwable {
|
|
||||||
LocalPlayer wePlayer = wrapPlayer(player);
|
LocalPlayer wePlayer = wrapPlayer(player);
|
||||||
LocalSession session = controller.getSession(wePlayer);
|
LocalSession session = WorldEdit.getInstance().getSession(wePlayer);
|
||||||
|
|
||||||
EditSession editSession = createEditSession(player);
|
EditSession editSession = createEditSession(player);
|
||||||
try {
|
try {
|
||||||
@ -379,7 +376,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WorldEdit getWorldEdit() {
|
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");
|
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()));
|
RegionSelector selector = session.getRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -434,9 +431,30 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
|
|||||||
throw new IllegalArgumentException("Null selection not allowed");
|
throw new IllegalArgumentException("Null selection not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalSession session = controller.getSession(wrapPlayer(player));
|
LocalSession session = WorldEdit.getInstance().getSession(wrapPlayer(player));
|
||||||
RegionSelector sel = selection.getRegionSelector();
|
RegionSelector sel = selection.getRegionSelector();
|
||||||
session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel);
|
session.setRegionSelector(BukkitUtil.getLocalWorld(player.getWorld()), sel);
|
||||||
session.dispatchCUISelection(wrapPlayer(player));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.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);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.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<String> adapterCandidates = new ArrayList<String>();
|
||||||
|
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<URL> 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -60,115 +60,11 @@ public abstract class LocalWorld extends AbstractWorld {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
protected Random random = new Random();
|
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.
|
|
||||||
* </p>
|
|
||||||
* 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
|
@Override
|
||||||
public BaseBlock getLazyBlock(Vector position) {
|
public BaseBlock getLazyBlock(Vector position) {
|
||||||
return getBlock(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.
|
|
||||||
* </p>
|
|
||||||
* 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
|
@Override
|
||||||
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException {
|
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, Vector pt) throws MaxChangedBlocksException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -100,42 +100,6 @@ public class LocalWorldAdapter extends LocalWorld {
|
|||||||
return world.setBlock(position, block, notifyAndLight);
|
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
|
@Override
|
||||||
public int getBlockLightLevel(Vector position) {
|
public int getBlockLightLevel(Vector position) {
|
||||||
return world.getBlockLightLevel(position);
|
return world.getBlockLightLevel(position);
|
||||||
@ -298,30 +262,11 @@ public class LocalWorldAdapter extends LocalWorld {
|
|||||||
return world.getBlock(position);
|
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
|
@Override
|
||||||
public BaseBlock getLazyBlock(Vector position) {
|
public BaseBlock getLazyBlock(Vector position) {
|
||||||
return world.getLazyBlock(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
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Operation commit() {
|
public Operation commit() {
|
||||||
|
@ -150,7 +150,7 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper {
|
|||||||
|
|
||||||
@ExceptionMatch
|
@ExceptionMatch
|
||||||
public void convert(WorldEditException e) throws CommandException {
|
public void convert(WorldEditException e) throws CommandException {
|
||||||
throw new CommandException(e.getMessage());
|
throw new CommandException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
54
src/main/java/com/sk89q/worldedit/util/Enums.java
Normal file
54
src/main/java/com/sk89q/worldedit/util/Enums.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.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 <T> the type of enum
|
||||||
|
* @return the found value or null
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static <T extends Enum<T>> T findByValue(Class<T> enumType, String... values) {
|
||||||
|
checkNotNull(enumType);
|
||||||
|
checkNotNull(values);
|
||||||
|
for (String val : values) {
|
||||||
|
try {
|
||||||
|
return Enum.valueOf(enumType, val);
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -47,6 +47,37 @@ public abstract class AbstractWorld implements World {
|
|||||||
private final PriorityQueue<QueuedEffect> effectQueue = new PriorityQueue<QueuedEffect>();
|
private final PriorityQueue<QueuedEffect> effectQueue = new PriorityQueue<QueuedEffect>();
|
||||||
private int taskId = -1;
|
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
|
@Override
|
||||||
public int getMaxY() {
|
public int getMaxY() {
|
||||||
return getMaximumPoint().getBlockY();
|
return getMaximumPoint().getBlockY();
|
||||||
@ -82,56 +113,6 @@ public abstract class AbstractWorld implements World {
|
|||||||
return getLazyBlock(pt).getData();
|
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
|
@Override
|
||||||
public void dropItem(Vector pt, BaseItemStack item, int times) {
|
public void dropItem(Vector pt, BaseItemStack item, int times) {
|
||||||
for (int i = 0; i < times; ++i) {
|
for (int i = 0; i < times; ++i) {
|
||||||
|
@ -122,36 +122,18 @@ public interface World extends Extent {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
boolean setBlockType(Vector position, int type);
|
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 Use {@link #setBlock(Vector, BaseBlock)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
void setBlockData(Vector position, int data);
|
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 Use {@link #setBlock(Vector, BaseBlock)}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
boolean setTypeIdAndData(Vector position, int type, int data);
|
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.
|
* Get the light level at the given block.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user