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); + +}