diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index 93f84a1ec4..6d81b20855 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -35,12 +35,14 @@ import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.NbtUtils; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.BitStorage; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BeaconBlockEntity; @@ -736,6 +738,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz syncTasks[1] = () -> { Iterator iterator = entities.iterator(); + Map leashRef = new HashMap<>(); while (iterator.hasNext()) { final CompoundTag nativeTag = iterator.next(); final Map> entityTagMap = nativeTag.getValue(); @@ -759,12 +762,35 @@ public synchronized > T call(IChunkSet set, Runnable finaliz if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( nativeTag); + if (entityTagMap.containsKey("Leash")) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("Leash")); + final LeashFenceKnotEntity leashEntity = leashRef.get(NbtUtils.readBlockPos(leashTag)); + if (leashEntity != null) { + tag.put("Leash", NbtUtils.writeBlockPos(leashEntity.pos)); + } + } + for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(nativeTag.getUUID()); + if (entity instanceof LeashFenceKnotEntity leashFenceKnotEntity) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("OldPos")); + if (leashTag != null) { + leashRef.put( + new BlockPos( + leashTag.getInt("X"), + leashTag.getInt("Y"), + leashTag.getInt("Z") + ), + leashFenceKnotEntity + ); + } + } if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java index d2d18968aa..19d3e16c4b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java @@ -35,12 +35,14 @@ import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.NbtUtils; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.BitStorage; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BeaconBlockEntity; @@ -735,6 +737,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz syncTasks[1] = () -> { Iterator iterator = entities.iterator(); + Map leashRef = new HashMap<>(); while (iterator.hasNext()) { final CompoundTag nativeTag = iterator.next(); final Map> entityTagMap = nativeTag.getValue(); @@ -758,12 +761,35 @@ public synchronized > T call(IChunkSet set, Runnable finaliz if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( nativeTag); + if (entityTagMap.containsKey("Leash")) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("Leash")); + final LeashFenceKnotEntity leashEntity = leashRef.get(NbtUtils.readBlockPos(leashTag)); + if (leashEntity != null) { + tag.put("Leash", NbtUtils.writeBlockPos(leashEntity.pos)); + } + } + for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(nativeTag.getUUID()); + if (entity instanceof LeashFenceKnotEntity leashFenceKnotEntity) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("OldPos")); + if (leashTag != null) { + leashRef.put( + new BlockPos( + leashTag.getInt("X"), + leashTag.getInt("Y"), + leashTag.getInt("Z") + ), + leashFenceKnotEntity + ); + } + } if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java index 47466ac5e7..d8f6a6769e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java @@ -35,6 +35,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.NbtUtils; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; @@ -42,6 +43,7 @@ import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BeaconBlockEntity; @@ -736,6 +738,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz syncTasks[1] = () -> { Iterator iterator = entities.iterator(); + Map leashRef = new HashMap<>(); while (iterator.hasNext()) { final CompoundTag nativeTag = iterator.next(); final Map> entityTagMap = nativeTag.getValue(); @@ -759,12 +762,34 @@ public synchronized > T call(IChunkSet set, Runnable finaliz if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( nativeTag); + if (entityTagMap.containsKey("Leash")) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("Leash")); + final LeashFenceKnotEntity leashEntity = leashRef.get(NbtUtils.readBlockPos(leashTag, "Leash")); + if (leashEntity != null) { + tag.put("Leash", NbtUtils.writeBlockPos(leashEntity.pos)); + } + } for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(nativeTag.getUUID()); + if (entity instanceof LeashFenceKnotEntity leashFenceKnotEntity) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("OldPos")); + if (leashTag != null) { + leashRef.put( + new BlockPos( + leashTag.getInt("X"), + leashTag.getInt("Y"), + leashTag.getInt("Z") + ), + leashFenceKnotEntity + ); + } + } if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java index bdd9d0648c..cba99181e4 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java @@ -36,12 +36,14 @@ import net.minecraft.core.SectionPos; import net.minecraft.nbt.IntTag; import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.nbt.NbtUtils; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.BitStorage; import net.minecraft.util.ZeroBitStorage; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.entity.BeaconBlockEntity; @@ -730,6 +732,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz syncTasks[1] = () -> { Iterator iterator = entities.iterator(); + Map leashRef = new HashMap<>(); while (iterator.hasNext()) { final CompoundTag nativeTag = iterator.next(); final Map> entityTagMap = nativeTag.getValue(); @@ -753,12 +756,29 @@ public synchronized > T call(IChunkSet set, Runnable finaliz if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( nativeTag); + if (entityTagMap.containsKey("Leash")) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("Leash")) ; + final LeashFenceKnotEntity leashEntity = leashRef.get(NbtUtils.readBlockPos(leashTag, "Leash")); + if (leashEntity != null) { + tag.put("Leash", NbtUtils.writeBlockPos(leashEntity.getPos())); + } + } for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(nativeTag.getUUID()); + if (entity instanceof LeashFenceKnotEntity leashFenceKnotEntity) { + var leashTag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( + entityTagMap.get("OldPos")) ; + if (leashTag != null) { + leashRef.put(new BlockPos(leashTag.getInt("X"), leashTag.getInt("Y"), + leashTag.getInt("Z")), + leashFenceKnotEntity); + } + } if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java index 534a96fac9..137775fb95 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java @@ -2,6 +2,8 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.DoubleTag; +import com.sk89q.jnbt.FloatTag; +import com.sk89q.jnbt.IntArrayTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTUtils; import com.sk89q.jnbt.StringTag; @@ -133,6 +135,12 @@ default Entity createEntity(Location location, BaseEntity entity, UUID uuid) { posList.add(new DoubleTag(location.y())); posList.add(new DoubleTag(location.z())); map.put("Pos", new ListTag(DoubleTag.class, posList)); + if (!map.containsKey("Rotation")) { + List rotList = new ArrayList<>(); + rotList.add(new FloatTag(location.getYaw())); + rotList.add(new FloatTag(location.getPitch())); + map.put("Rotation", new ListTag(FloatTag.class, rotList)); + } NBTUtils.addUUIDToMap(map, uuid); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java index cac9f4a7b2..05c04d905f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/Clipboard.java @@ -27,6 +27,9 @@ import com.fastasyncworldedit.core.function.visitor.Order; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.util.MaskTraverser; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSessionBuilder; import com.sk89q.worldedit.WorldEdit; @@ -49,6 +52,7 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.entity.EntityTypes; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -59,6 +63,7 @@ import java.io.IOException; import java.io.OutputStream; import java.net.URI; +import java.util.HashMap; import java.util.Iterator; import java.util.UUID; @@ -428,11 +433,29 @@ default void paste(Extent extent, BlockVector3 to, boolean pasteAir, boolean pas continue; } Location pos = entity.getLocation(); - Location newPos = new Location(pos.getExtent(), pos.x() + entityOffsetX, - pos.y() + entityOffsetY, pos.z() + entityOffsetZ, pos.getYaw(), - pos.getPitch() - ); - extent.createEntity(newPos, entity.getState()); + if (entity.getType().equals(EntityTypes.LEASH_KNOT)) { + var state = entity.getState(); + var nbtData = new HashMap<>(state.getNbtData().getValue()); + var posAsMap = new HashMap>(); + posAsMap.put("X", new IntTag(pos.getBlockX())); + posAsMap.put("Y", new IntTag(pos.getBlockY())); + posAsMap.put("Z", new IntTag(pos.getBlockZ())); + nbtData.put("OldPos", new CompoundTag(posAsMap)); + state.setNbtData(new CompoundTag(nbtData)); + Location newPos = new Location(pos.getExtent(), pos.x() + entityOffsetX, + pos.y() + entityOffsetY, pos.z() + entityOffsetZ, pos.getYaw(), + pos.getPitch() + ); + + extent.createEntity(newPos, state); + } else { + Location newPos = new Location(pos.getExtent(), pos.x() + entityOffsetX, + pos.y() + entityOffsetY, pos.z() + entityOffsetZ, pos.getYaw(), + pos.getPitch() + ); + + extent.createEntity(newPos, entity.getState()); + } } } }