From 354d819872706ecfa0aa3f0ea261a5473643f98f Mon Sep 17 00:00:00 2001
From: sk89q
Date: Sat, 26 Apr 2014 21:57:45 -0700
Subject: [PATCH] Added a new preliminary mapping + metadata framework.
The eventual goal is to add:
1. Support for mapping block, etc. names (minecraft:stone, etc.)
2. Proper support for entities in WorldEdit
3. Support for querying for metadata about a block, entity, etc.
4. Extent support to biomes, structures, and so on
---
.../sk89q/worldedit/bukkit/BukkitAdapter.java | 61 ++++++
.../sk89q/worldedit/bukkit/BukkitEntity.java | 60 ++++++
.../sk89q/worldedit/bukkit/BukkitWorld.java | 37 ++++
.../worldedit/bukkit/TameableAdapter.java | 40 ++++
.../com/sk89q/worldedit/forge/ForgeWorld.java | 32 +++
.../com/sk89q/worldedit/entity/Entity.java | 182 ------------------
.../com/sk89q/worldedit/entity/Player.java | 181 ++++++++++++++++-
.../worldedit/entity/metadata/Tameable.java | 34 ++++
.../worldedit/internal/LocalWorldAdapter.java | 30 +++
.../internal/util/AbstractAdapter.java | 52 +++++
.../com/sk89q/worldedit/util/TargetBlock.java | 6 +-
.../com/sk89q/worldedit/world/NullWorld.java | 33 ++++
.../java/com/sk89q/worldedit/world/World.java | 3 +-
.../worldedit/world/mapping/Mapping.java | 114 +++++++++++
.../worldedit/world/mapping/NullResolver.java | 44 +++++
.../worldedit/world/mapping/Resolver.java | 56 ++++++
16 files changed, 777 insertions(+), 188 deletions(-)
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitEntity.java
create mode 100644 src/bukkit/java/com/sk89q/worldedit/bukkit/TameableAdapter.java
create mode 100644 src/main/java/com/sk89q/worldedit/entity/metadata/Tameable.java
create mode 100644 src/main/java/com/sk89q/worldedit/internal/util/AbstractAdapter.java
create mode 100644 src/main/java/com/sk89q/worldedit/world/mapping/Mapping.java
create mode 100644 src/main/java/com/sk89q/worldedit/world/mapping/NullResolver.java
create mode 100644 src/main/java/com/sk89q/worldedit/world/mapping/Resolver.java
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java
new file mode 100644
index 000000000..42b3eecbf
--- /dev/null
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java
@@ -0,0 +1,61 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.bukkit;
+
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.util.Location;
+import com.sk89q.worldedit.util.Vectors;
+import com.sk89q.worldedit.world.World;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Adapts between Bukkit and WorldEdit equivalent objects.
+ */
+final class BukkitAdapter {
+
+ private BukkitAdapter() {
+ }
+
+ /**
+ * Create a WorldEdit world from a Bukkit world.
+ *
+ * @param world the Bukkit world
+ * @return a WorldEdit world
+ */
+ public static World adapt(org.bukkit.World world) {
+ checkNotNull(world);
+ return new BukkitWorld(world);
+ }
+
+ /**
+ * Create a WorldEdit location from a Bukkit location.
+ *
+ * @param location the Bukkit location
+ * @return a WorldEdit location
+ */
+ public static Location adapt(org.bukkit.Location location) {
+ checkNotNull(location);
+ Vector position = BukkitUtil.toVector(location);
+ Vector direction = Vectors.fromEulerDeg(location.getYaw(), location.getPitch());
+ return new com.sk89q.worldedit.util.Location(adapt(location.getWorld()), position, direction);
+ }
+
+}
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitEntity.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitEntity.java
new file mode 100644
index 000000000..a2b749248
--- /dev/null
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitEntity.java
@@ -0,0 +1,60 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.bukkit;
+
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.entity.metadata.Tameable;
+import com.sk89q.worldedit.internal.util.AbstractAdapter;
+import com.sk89q.worldedit.util.Location;
+import com.sk89q.worldedit.world.World;
+
+/**
+ * An adapter to adapt a Bukkit entity into a WorldEdit one.
+ */
+class BukkitEntity extends AbstractAdapter implements Entity {
+
+ /**
+ * Create a new instance.
+ *
+ * @param entity the entity
+ */
+ BukkitEntity(org.bukkit.entity.Entity entity) {
+ super(entity);
+ }
+
+ @SuppressWarnings("unchecked")
+ T getMetaData(Class metaDataClass) {
+ if (metaDataClass == Tameable.class && getHandle() instanceof org.bukkit.entity.Tameable) {
+ return (T) new TameableAdapter((org.bukkit.entity.Tameable) getHandle());
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public World getWorld() {
+ return BukkitAdapter.adapt(getHandle().getWorld());
+ }
+
+ @Override
+ public Location getLocation() {
+ return BukkitAdapter.adapt(getHandle().getLocation());
+ }
+}
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
index 3617df143..d8ac86841 100644
--- a/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
@@ -26,8 +26,11 @@ import com.sk89q.worldedit.blocks.*;
import com.sk89q.worldedit.blocks.ContainerBlock;
import com.sk89q.worldedit.blocks.NoteBlock;
import com.sk89q.worldedit.bukkit.entity.BukkitEntity;
+import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
+import com.sk89q.worldedit.world.mapping.NullResolver;
+import com.sk89q.worldedit.world.mapping.Resolver;
import org.bukkit.*;
import org.bukkit.Location;
import org.bukkit.block.*;
@@ -38,6 +41,7 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
+import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
@@ -1248,4 +1252,37 @@ public class BukkitWorld extends LocalWorld {
return super.setBlock(pt, block, notifyAdjacent);
}
+
+ @Override
+ public Resolver getBlockMapping() {
+ return new NullResolver();
+ }
+
+ @Override
+ public Resolver getEntityMapping() {
+ return new NullResolver();
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseBlock block, Class metaDataClass) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(com.sk89q.worldedit.entity.Entity entity, Class metaDataClass) {
+ if (entity instanceof com.sk89q.worldedit.bukkit.BukkitEntity) {
+ return ((com.sk89q.worldedit.bukkit.BukkitEntity) entity).getMetaData(metaDataClass);
+ }
+
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseEntity entity, Class metaDataClass) {
+ return null;
+ }
+
}
diff --git a/src/bukkit/java/com/sk89q/worldedit/bukkit/TameableAdapter.java b/src/bukkit/java/com/sk89q/worldedit/bukkit/TameableAdapter.java
new file mode 100644
index 000000000..b514f1b29
--- /dev/null
+++ b/src/bukkit/java/com/sk89q/worldedit/bukkit/TameableAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.bukkit;
+
+import com.sk89q.worldedit.entity.metadata.Tameable;
+import com.sk89q.worldedit.internal.util.AbstractAdapter;
+
+/**
+ * Adapts a Bukkit {@link org.bukkit.entity.Tameable} into a WorldEdit
+ * equivalent.
+ */
+public class TameableAdapter extends AbstractAdapter implements Tameable {
+
+ TameableAdapter(org.bukkit.entity.Tameable entity) {
+ super(entity);
+ }
+
+ @Override
+ public boolean isTamed() {
+ return getHandle().isTamed();
+ }
+
+}
diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java
index 2f64a1f82..2b3a91eb6 100644
--- a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java
+++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java
@@ -24,9 +24,12 @@ import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.LazyBlock;
+import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.AbstractWorld;
+import com.sk89q.worldedit.world.mapping.NullResolver;
+import com.sk89q.worldedit.world.mapping.Resolver;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityHanging;
@@ -48,6 +51,7 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.ChunkProviderServer;
+import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.List;
@@ -469,6 +473,34 @@ public class ForgeWorld extends AbstractWorld {
}
}
+ @Override
+ public Resolver getBlockMapping() {
+ return new NullResolver();
+ }
+
+ @Override
+ public Resolver getEntityMapping() {
+ return new NullResolver();
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseBlock block, Class metaDataClass) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(com.sk89q.worldedit.entity.Entity entity, Class metaDataClass) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseEntity entity, Class metaDataClass) {
+ return null;
+ }
+
/**
* Thrown when the reference to the world is lost.
*/
diff --git a/src/main/java/com/sk89q/worldedit/entity/Entity.java b/src/main/java/com/sk89q/worldedit/entity/Entity.java
index 950557bc3..8f3c4be73 100644
--- a/src/main/java/com/sk89q/worldedit/entity/Entity.java
+++ b/src/main/java/com/sk89q/worldedit/entity/Entity.java
@@ -19,10 +19,6 @@
package com.sk89q.worldedit.entity;
-import com.sk89q.worldedit.PlayerDirection;
-import com.sk89q.worldedit.Vector;
-import com.sk89q.worldedit.WorldVector;
-import com.sk89q.worldedit.WorldVectorFace;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
@@ -39,137 +35,6 @@ import com.sk89q.worldedit.world.World;
*/
public interface Entity {
- /**
- * Find a position for the actor to stand that is not inside a block.
- * Blocks above the player will be iteratively tested until there is
- * a series of two free blocks. The actor will be teleported to
- * that free position.
- *
- * @param searchPos search position
- */
- void findFreePosition(WorldVector searchPos);
-
- /**
- * Set the actor on the ground.
- *
- * @param searchPos The location to start searching from
- */
- void setOnGround(WorldVector searchPos);
-
- /**
- * Find a position for the player to stand that is not inside a block.
- * Blocks above the player will be iteratively tested until there is
- * a series of two free blocks. The player will be teleported to
- * that free position.
- */
- void findFreePosition();
-
- /**
- * Go up one level to the next free space above.
- *
- * @return true if a spot was found
- */
- boolean ascendLevel();
-
- /**
- * Go up one level to the next free space above.
- *
- * @return true if a spot was found
- */
- boolean descendLevel();
-
- /**
- * Ascend to the ceiling above.
- *
- * @param clearance How many blocks to leave above the player's head
- * @return whether the player was moved
- */
- boolean ascendToCeiling(int clearance);
-
- /**
- * Ascend to the ceiling above.
- *
- * @param clearance How many blocks to leave above the player's head
- * @param alwaysGlass Always put glass under the player
- * @return whether the player was moved
- */
- boolean ascendToCeiling(int clearance, boolean alwaysGlass);
-
- /**
- * Just go up.
- *
- * @param distance How far up to teleport
- * @return whether the player was moved
- */
- boolean ascendUpwards(int distance);
-
- /**
- * Just go up.
- *
- * @param distance How far up to teleport
- * @param alwaysGlass Always put glass under the player
- * @return whether the player was moved
- */
- boolean ascendUpwards(int distance, boolean alwaysGlass);
-
- /**
- * Make the player float in the given blocks.
- *
- * @param x The X coordinate of the block to float in
- * @param y The Y coordinate of the block to float in
- * @param z The Z coordinate of the block to float in
- */
- void floatAt(int x, int y, int z, boolean alwaysGlass);
-
- /**
- * Get the point of the block that is being stood in.
- *
- * @return point
- */
- WorldVector getBlockIn();
-
- /**
- * Get the point of the block that is being stood upon.
- *
- * @return point
- */
- WorldVector getBlockOn();
-
- /**
- * Get the point of the block being looked at. May return null.
- * Will return the farthest away air block if useLastBlock is true and no other block is found.
- *
- * @param range How far to checks for blocks
- * @param useLastBlock Try to return the last valid air block found.
- * @return point
- */
- WorldVector getBlockTrace(int range, boolean useLastBlock);
-
- WorldVectorFace getBlockTraceFace(int range, boolean useLastBlock);
-
- /**
- * Get the point of the block being looked at. May return null.
- *
- * @param range How far to checks for blocks
- * @return point
- */
- WorldVector getBlockTrace(int range);
-
- /**
- * Get the point of the block being looked at. May return null.
- *
- * @param range How far to checks for blocks
- * @return point
- */
- WorldVector getSolidBlockTrace(int range);
-
- /**
- * Get the player's cardinal direction (N, W, NW, etc.). May return null.
- *
- * @return the direction
- */
- PlayerDirection getCardinalDirection();
-
/**
* Get the location of this entity.
*
@@ -177,53 +42,6 @@ public interface Entity {
*/
Location getLocation();
- /**
- * Get the actor's position.
- *
- * If the actor has no permission, then return a dummy location.
- *
- * @return the actor's position
- */
- WorldVector getPosition();
-
- /**
- * Get the player's view pitch.
- *
- * @return pitch
- */
- double getPitch();
-
- /**
- * Get the player's view yaw.
- *
- * @return yaw
- */
- double getYaw();
-
- /**
- * Pass through the wall that you are looking at.
- *
- * @param range How far to checks for blocks
- * @return whether the player was pass through
- */
- boolean passThroughForwardWall(int range);
-
- /**
- * Move the player.
- *
- * @param pos Where to move them
- * @param pitch The pitch (up/down) of the player's view
- * @param yaw The yaw (left/right) of the player's view
- */
- void setPosition(Vector pos, float pitch, float yaw);
-
- /**
- * Move the player.
- *
- * @param pos Where to move them
- */
- void setPosition(Vector pos);
-
/**
* Get the world that this entity is on.
*
diff --git a/src/main/java/com/sk89q/worldedit/entity/Player.java b/src/main/java/com/sk89q/worldedit/entity/Player.java
index 4d5a5b601..175c6617d 100644
--- a/src/main/java/com/sk89q/worldedit/entity/Player.java
+++ b/src/main/java/com/sk89q/worldedit/entity/Player.java
@@ -19,8 +19,7 @@
package com.sk89q.worldedit.entity;
-import com.sk89q.worldedit.PlayerDirection;
-import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.inventory.BlockBag;
@@ -80,4 +79,182 @@ public interface Player extends Entity {
*/
boolean hasCreativeMode();
+ /**
+ * Find a position for the actor to stand that is not inside a block.
+ * Blocks above the player will be iteratively tested until there is
+ * a series of two free blocks. The actor will be teleported to
+ * that free position.
+ *
+ * @param searchPos search position
+ */
+ void findFreePosition(WorldVector searchPos);
+
+ /**
+ * Set the actor on the ground.
+ *
+ * @param searchPos The location to start searching from
+ */
+ void setOnGround(WorldVector searchPos);
+
+ /**
+ * Find a position for the player to stand that is not inside a block.
+ * Blocks above the player will be iteratively tested until there is
+ * a series of two free blocks. The player will be teleported to
+ * that free position.
+ */
+ void findFreePosition();
+
+ /**
+ * Go up one level to the next free space above.
+ *
+ * @return true if a spot was found
+ */
+ boolean ascendLevel();
+
+ /**
+ * Go up one level to the next free space above.
+ *
+ * @return true if a spot was found
+ */
+ boolean descendLevel();
+
+ /**
+ * Ascend to the ceiling above.
+ *
+ * @param clearance How many blocks to leave above the player's head
+ * @return whether the player was moved
+ */
+ boolean ascendToCeiling(int clearance);
+
+ /**
+ * Ascend to the ceiling above.
+ *
+ * @param clearance How many blocks to leave above the player's head
+ * @param alwaysGlass Always put glass under the player
+ * @return whether the player was moved
+ */
+ boolean ascendToCeiling(int clearance, boolean alwaysGlass);
+
+ /**
+ * Just go up.
+ *
+ * @param distance How far up to teleport
+ * @return whether the player was moved
+ */
+ boolean ascendUpwards(int distance);
+
+ /**
+ * Just go up.
+ *
+ * @param distance How far up to teleport
+ * @param alwaysGlass Always put glass under the player
+ * @return whether the player was moved
+ */
+ boolean ascendUpwards(int distance, boolean alwaysGlass);
+
+ /**
+ * Make the player float in the given blocks.
+ *
+ * @param x The X coordinate of the block to float in
+ * @param y The Y coordinate of the block to float in
+ * @param z The Z coordinate of the block to float in
+ */
+ void floatAt(int x, int y, int z, boolean alwaysGlass);
+
+ /**
+ * Get the point of the block that is being stood in.
+ *
+ * @return point
+ */
+ WorldVector getBlockIn();
+
+ /**
+ * Get the point of the block that is being stood upon.
+ *
+ * @return point
+ */
+ WorldVector getBlockOn();
+
+ /**
+ * Get the point of the block being looked at. May return null.
+ * Will return the farthest away air block if useLastBlock is true and no other block is found.
+ *
+ * @param range How far to checks for blocks
+ * @param useLastBlock Try to return the last valid air block found.
+ * @return point
+ */
+ WorldVector getBlockTrace(int range, boolean useLastBlock);
+
+ WorldVectorFace getBlockTraceFace(int range, boolean useLastBlock);
+
+ /**
+ * Get the point of the block being looked at. May return null.
+ *
+ * @param range How far to checks for blocks
+ * @return point
+ */
+ WorldVector getBlockTrace(int range);
+
+ /**
+ * Get the point of the block being looked at. May return null.
+ *
+ * @param range How far to checks for blocks
+ * @return point
+ */
+ WorldVector getSolidBlockTrace(int range);
+
+ /**
+ * Get the player's cardinal direction (N, W, NW, etc.). May return null.
+ *
+ * @return the direction
+ */
+ PlayerDirection getCardinalDirection();
+
+ /**
+ * Get the actor's position.
+ *
+ * If the actor has no permission, then return a dummy location.
+ *
+ * @return the actor's position
+ */
+ WorldVector getPosition();
+
+ /**
+ * Get the player's view pitch.
+ *
+ * @return pitch
+ */
+ double getPitch();
+
+ /**
+ * Get the player's view yaw.
+ *
+ * @return yaw
+ */
+ double getYaw();
+
+ /**
+ * Pass through the wall that you are looking at.
+ *
+ * @param range How far to checks for blocks
+ * @return whether the player was pass through
+ */
+ boolean passThroughForwardWall(int range);
+
+ /**
+ * Move the player.
+ *
+ * @param pos Where to move them
+ * @param pitch The pitch (up/down) of the player's view
+ * @param yaw The yaw (left/right) of the player's view
+ */
+ void setPosition(Vector pos, float pitch, float yaw);
+
+ /**
+ * Move the player.
+ *
+ * @param pos Where to move them
+ */
+ void setPosition(Vector pos);
+
}
diff --git a/src/main/java/com/sk89q/worldedit/entity/metadata/Tameable.java b/src/main/java/com/sk89q/worldedit/entity/metadata/Tameable.java
new file mode 100644
index 000000000..6f288a00f
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/entity/metadata/Tameable.java
@@ -0,0 +1,34 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.entity.metadata;
+
+/**
+ * Indicates a creature that can be tamed.
+ */
+public interface Tameable {
+
+ /**
+ * Returns whether the creature is tamed.
+ *
+ * @return true if the creature is tamed
+ */
+ boolean isTamed();
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java
index 3e061de36..9dc583878 100644
--- a/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java
+++ b/src/main/java/com/sk89q/worldedit/internal/LocalWorldAdapter.java
@@ -22,11 +22,14 @@ package com.sk89q.worldedit.internal;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
+import com.sk89q.worldedit.entity.BaseEntity;
+import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.World;
+import com.sk89q.worldedit.world.mapping.Resolver;
import javax.annotation.Nullable;
@@ -308,6 +311,33 @@ public class LocalWorldAdapter extends LocalWorld {
public Operation commit() {
return world.commit();
}
+ @Override
+ public Resolver getBlockMapping() {
+ return world.getBlockMapping();
+ }
+
+ @Override
+ public Resolver getEntityMapping() {
+ return world.getEntityMapping();
+ }
+
+ @Override
+ @Nullable
+ public T getMetaData(BaseBlock block, Class metaDataClass) {
+ return world.getMetaData(block, metaDataClass);
+ }
+
+ @Override
+ @Nullable
+ public T getMetaData(Entity entity, Class metaDataClass) {
+ return world.getMetaData(entity, metaDataClass);
+ }
+
+ @Override
+ @Nullable
+ public T getMetaData(BaseEntity entity, Class metaDataClass) {
+ return world.getMetaData(entity, metaDataClass);
+ }
public static LocalWorldAdapter wrap(World world) {
return new LocalWorldAdapter(world);
diff --git a/src/main/java/com/sk89q/worldedit/internal/util/AbstractAdapter.java b/src/main/java/com/sk89q/worldedit/internal/util/AbstractAdapter.java
new file mode 100644
index 000000000..c4ab6305e
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/internal/util/AbstractAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.internal.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Abstract class for adapters.
+ *
+ * @param class of adapted objects
+ */
+public abstract class AbstractAdapter {
+
+ private final E object;
+
+ /**
+ * Create a new instance.
+ *
+ * @param object the object to adapt
+ */
+ public AbstractAdapter(E object) {
+ checkNotNull(object);
+ this.object = object;
+ }
+
+ /**
+ * Get the object.
+ *
+ * @return the object
+ */
+ public E getHandle() {
+ return object;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java
index 700dce3f8..e5d474f72 100644
--- a/src/main/java/com/sk89q/worldedit/util/TargetBlock.java
+++ b/src/main/java/com/sk89q/worldedit/util/TargetBlock.java
@@ -22,7 +22,7 @@ package com.sk89q.worldedit.util;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
-import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.internal.LocalWorldAdapter;
/**
@@ -62,7 +62,7 @@ public class TargetBlock {
* @param checkDistance how often to check for blocks, the smaller the more precise
*/
public TargetBlock(LocalPlayer player, int maxDistance, double checkDistance) {
- this((Entity) player, maxDistance, checkDistance);
+ this((Player) player, maxDistance, checkDistance);
}
/**
@@ -72,7 +72,7 @@ public class TargetBlock {
* @param maxDistance how far it checks for blocks
* @param checkDistance how often to check for blocks, the smaller the more precise
*/
- public TargetBlock(Entity player, int maxDistance, double checkDistance) {
+ public TargetBlock(Player player, int maxDistance, double checkDistance) {
this.world = LocalWorldAdapter.wrap(player.getWorld());
this.setValues(player.getPosition(), player.getYaw(), player.getPitch(),
maxDistance, 1.65, checkDistance);
diff --git a/src/main/java/com/sk89q/worldedit/world/NullWorld.java b/src/main/java/com/sk89q/worldedit/world/NullWorld.java
index 62edc3352..ba7b9d0d7 100644
--- a/src/main/java/com/sk89q/worldedit/world/NullWorld.java
+++ b/src/main/java/com/sk89q/worldedit/world/NullWorld.java
@@ -23,8 +23,14 @@ import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID;
+import com.sk89q.worldedit.entity.BaseEntity;
+import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
+import com.sk89q.worldedit.world.mapping.NullResolver;
+import com.sk89q.worldedit.world.mapping.Resolver;
+
+import javax.annotation.Nullable;
/**
* A null implementation of {@link World} that drops all changes and
@@ -95,4 +101,31 @@ public class NullWorld extends AbstractWorld {
return new BaseBlock(BlockID.AIR);
}
+ @Override
+ public Resolver getBlockMapping() {
+ return new NullResolver();
+ }
+
+ @Override
+ public Resolver getEntityMapping() {
+ return new NullResolver();
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseBlock block, Class metaDataClass) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(Entity entity, Class metaDataClass) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public T getMetaData(BaseEntity entity, Class metaDataClass) {
+ return null;
+ }
}
diff --git a/src/main/java/com/sk89q/worldedit/world/World.java b/src/main/java/com/sk89q/worldedit/world/World.java
index 9f69b122e..c711bcdf2 100644
--- a/src/main/java/com/sk89q/worldedit/world/World.java
+++ b/src/main/java/com/sk89q/worldedit/world/World.java
@@ -27,11 +27,12 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
+import com.sk89q.worldedit.world.mapping.Mapping;
/**
* Represents a world (dimension).
*/
-public interface World extends Extent {
+public interface World extends Extent, Mapping {
/**
* Get the name of the world.
diff --git a/src/main/java/com/sk89q/worldedit/world/mapping/Mapping.java b/src/main/java/com/sk89q/worldedit/world/mapping/Mapping.java
new file mode 100644
index 000000000..401ab94a7
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/world/mapping/Mapping.java
@@ -0,0 +1,114 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.world.mapping;
+
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.entity.BaseEntity;
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.entity.metadata.Tameable;
+
+import javax.annotation.Nullable;
+
+/**
+ * A mapping can create state objects (such as {@link BaseBlock})
+ * from implementation-independent identifiers (such as "minecraft.stone"),
+ * as well as perform the opposite task of retrieving
+ * the identifier for a given state object (whenever possible at least, because
+ * a mapping may not be compatible with a set of state objects that may have
+ * come from another implementation). In addition, a mapping may be able to
+ * retrieve a variety of metadata objects (such as {@link Tameable}) to
+ * describe a given state object.
+ *
+ * However, it may be possible that a mapping be "dumb" and not be able to,
+ * for example, return a {@link Tameable} for a "Horse" entity, simply because
+ * it has not be implemented. Any code that queries a mapping must be
+ * aware of this and act accordingly.
+ */
+public interface Mapping {
+
+ /**
+ * Get the mapping for block identifiers.
+ *
+ * @return a block mapping
+ */
+ Resolver getBlockMapping();
+
+ /**
+ * Get the mapping for entity identifiers.
+ *
+ * @return an entity mapping
+ */
+ Resolver getEntityMapping();
+
+ /**
+ * Attempt to return an instance of the given class for the given block.
+ * For example, {@code getMetaData(block, Inventory.class)} might return
+ * an instance if the block happens to contain an inventory.
+ *
+ * If the given block is not of the given class (i.e. a dirt block does
+ * not have an inventory) or if the information is simply not available,
+ * {@code null} will be returned.
+ *
+ * Mutator methods on the returned instance should change the block.
+ *
+ * @param block the block
+ * @param metaDataClass the metadata class for the returned instance
+ * @param the metadata class
+ * @return an instance of the given class, otherwise null
+ */
+ @Nullable T getMetaData(BaseBlock block, Class metaDataClass);
+
+ /**
+ * Attempt to return an instance of the given class for the given entity.
+ * For example, {@code getMetaData(entity, Creature.class)} might return
+ * an instance if the entity happens to be a creature.
+ *
+ * If the given entity is not of the given class (i.e. a painting is
+ * not a creature) or if the information is simply not available,
+ * {@code null} will be returned.
+ *
+ * Mutator methods on the returned instance should change the entity.
+ *
+ * @param entity the entity
+ * @param metaDataClass the metadata class for the returned instance
+ * @param the metadata class
+ * @return an instance of the given class, otherwise null
+ */
+ @Nullable T getMetaData(Entity entity, Class metaDataClass);
+
+ /**
+ * Attempt to return an instance of the given class for the given entity.
+ * For example, {@code getMetaData(entity, Creature.class)} might return
+ * an instance if the entity happens to be a creature.
+ *
+ * If the given entity is not of the given class (i.e. a painting is
+ * not a creature) or if the information is simply not available,
+ * {@code null} will be returned.
+ *
+ * Mutator methods on the returned instance should change the entity.
+ *
+ * @param entity the entity
+ * @param metaDataClass the metadata class for the returned instance
+ * @param the metadata class
+ * @return an instance of the given class, otherwise null
+ */
+ @Nullable T getMetaData(BaseEntity entity, Class metaDataClass);
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/world/mapping/NullResolver.java b/src/main/java/com/sk89q/worldedit/world/mapping/NullResolver.java
new file mode 100644
index 000000000..c59beefdb
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/world/mapping/NullResolver.java
@@ -0,0 +1,44 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.world.mapping;
+
+import javax.annotation.Nullable;
+
+/**
+ * An implementation of a {@link Resolver} that knows nothing and returns
+ * {@code null} in all cases.
+ *
+ * @param the object to resolve
+ */
+public class NullResolver implements Resolver {
+
+ @Nullable
+ @Override
+ public E create(String id) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String getId(E object) {
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/sk89q/worldedit/world/mapping/Resolver.java b/src/main/java/com/sk89q/worldedit/world/mapping/Resolver.java
new file mode 100644
index 000000000..3acd80ab4
--- /dev/null
+++ b/src/main/java/com/sk89q/worldedit/world/mapping/Resolver.java
@@ -0,0 +1,56 @@
+/*
+ * WorldEdit, a Minecraft world manipulation toolkit
+ * Copyright (C) sk89q
+ * Copyright (C) WorldEdit team and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+package com.sk89q.worldedit.world.mapping;
+
+import com.sk89q.worldedit.blocks.BaseBlock;
+
+import javax.annotation.Nullable;
+
+/**
+ * A resolver can create state objects (such as {@link BaseBlock}) from
+ * universal identifiers, but also get the universal identifier for
+ * a given state object (at least when it is known).
+ *
+ * Identifiers may be case-sensitive. Routines that work with IDs should
+ * not make changes to the casing of the IDs or perform case-insensitive
+ * comparisons. Implementations may normalize the casing of IDs if it
+ * is appropriate.
+ *
+ * @param the type of state object
+ */
+public interface Resolver {
+
+ /**
+ * Create an instance of the state object from the given ID.
+ *
+ * @param id the ID
+ * @return an instance, otherwise null if an instance cannot be created
+ */
+ @Nullable E create(String id);
+
+ /**
+ * Get the ID for the given object.
+ *
+ * @param object the object
+ * @return the ID, otherwise null if it is not known
+ */
+ @Nullable String getId(E object);
+
+}