diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeEntity.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeEntity.java index 4a55e41bd..750d1a4b1 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgeEntity.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeEntity.java @@ -55,28 +55,9 @@ class ForgeEntity implements Entity { @Override public Location getLocation() { - Vector position; - float pitch; - float yaw; - - if (entity instanceof EntityHanging) { - EntityHanging hanging = (EntityHanging) entity; - - position = new Vector(hanging.xPosition, hanging.yPosition, hanging.zPosition); - - Direction direction = MCDirections.fromHanging(hanging.hangingDirection); - if (direction != null) { - yaw = direction.toVector().toYaw(); - pitch = direction.toVector().toPitch(); - } else { - yaw = (float) Math.toRadians(entity.rotationYaw); - pitch = (float) Math.toRadians(entity.rotationPitch); - } - } else { - position = new Vector(entity.posX, entity.posY, entity.posZ); - yaw = (float) Math.toRadians(entity.rotationYaw); - pitch = (float) Math.toRadians(entity.rotationPitch); - } + Vector position = new Vector(entity.posX, entity.posY, entity.posZ); + float yaw = (float) Math.toRadians(entity.rotationYaw); + float pitch = (float) Math.toRadians(entity.rotationPitch); return new Location(ForgeAdapter.adapt(entity.worldObj), position, yaw, pitch); } diff --git a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java index b7f15e27f..11576145e 100644 --- a/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/src/forge/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -551,16 +551,6 @@ public class ForgeWorld extends AbstractWorld { createdEntity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), (float) Math.toDegrees(location.getYaw()), (float) Math.toDegrees(location.getPitch())); - // Special handling for hanging entities - if (createdEntity instanceof EntityHanging) { - EntityHanging hanging = (EntityHanging) createdEntity; - hanging.xPosition = location.getBlockX(); - hanging.yPosition = location.getBlockY(); - hanging.zPosition = location.getBlockZ(); - Direction direction = Direction.findClosest(location.getDirection(), Flag.CARDINAL); - hanging.setDirection(MCDirections.toHanging(direction)); - } - world.spawnEntityInWorld(createdEntity); return new ForgeEntity(createdEntity); } else { diff --git a/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java b/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java index 2728285fe..d172d10c6 100644 --- a/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java +++ b/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java @@ -19,13 +19,18 @@ package com.sk89q.worldedit.function.entity; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.CompoundTagBuilder; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.EntityFunction; +import com.sk89q.worldedit.internal.helper.MCDirections; import com.sk89q.worldedit.math.transform.Transform; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Direction.Flag; import com.sk89q.worldedit.util.Location; import static com.google.common.base.Preconditions.checkNotNull; @@ -87,6 +92,10 @@ public class ExtentEntityCopy implements EntityFunction { Vector newPosition = transform.apply(location.toVector().subtract(from)); Vector newDirection = transform.apply(location.getDirection()).subtract(transform.apply(Vector.ZERO)).normalize(); Location newLocation = new Location(destination, newPosition.add(to), newDirection); + + // Some entities store their position data in NBT + state = transformNbtData(state); + boolean success = destination.createEntity(newLocation, state) != null; // Remove @@ -100,4 +109,49 @@ public class ExtentEntityCopy implements EntityFunction { } } + /** + * Transform NBT data in the given entity state and return a new instance + * if the NBT data needs to be transformed. + * + * @param state the existing state + * @return a new state or the existing one + */ + private BaseEntity transformNbtData(BaseEntity state) { + CompoundTag tag = state.getNbtData(); + + if (tag != null) { + // Handle hanging entities (paintings, item frames, etc.) + boolean hasTilePosition = tag.containsKey("TileX") && tag.containsKey("TileY") && tag.containsKey("TileZ"); + boolean hasDirection = tag.containsKey("Direction"); + boolean hasLegacyDirection = tag.containsKey("Dir"); + + if (hasTilePosition) { + Vector tilePosition = new Vector(tag.asInt("TileX"), tag.asInt("TileY"), tag.asInt("TileZ")); + Vector newTilePosition = transform.apply(tilePosition.subtract(from)).add(to); + + CompoundTagBuilder builder = tag.createBuilder() + .putInt("TileX", newTilePosition.getBlockX()) + .putInt("TileY", newTilePosition.getBlockY()) + .putInt("TileZ", newTilePosition.getBlockZ()); + + if (hasDirection || hasLegacyDirection) { + int d = hasDirection ? tag.asInt("Direction") : MCDirections.fromLegacyHanging((byte) tag.asInt("Dir")); + Direction direction = MCDirections.fromHanging(d); + + if (direction != null) { + Vector vector = transform.apply(direction.toVector()).subtract(transform.apply(Vector.ZERO)).normalize(); + Direction newDirection = Direction.findClosest(vector, Flag.CARDINAL); + + builder.putByte("Direction", (byte) MCDirections.toHanging(newDirection)); + builder.putByte("Dir", MCDirections.toLegacyHanging(MCDirections.toHanging(newDirection))); + } + } + + return new BaseEntity(state.getTypeId(), builder.build()); + } + } + + return state; + } + } diff --git a/src/main/java/com/sk89q/worldedit/internal/helper/MCDirections.java b/src/main/java/com/sk89q/worldedit/internal/helper/MCDirections.java index 6805196de..d9e75d62f 100644 --- a/src/main/java/com/sk89q/worldedit/internal/helper/MCDirections.java +++ b/src/main/java/com/sk89q/worldedit/internal/helper/MCDirections.java @@ -59,4 +59,22 @@ public final class MCDirections { } } + public static int fromLegacyHanging(byte i) { + switch (i) { + case 0: return 2; + case 1: return 1; + case 2: return 0; + default: return 3; + } + } + + public static byte toLegacyHanging(int i) { + switch (i) { + case 0: return (byte) 2; + case 1: return (byte) 1; + case 2: return (byte) 0; + default: return (byte) 3; + } + } + }