diff --git a/paper-server/nms-patches/net/minecraft/server/commands/PlaceCommand.patch b/paper-server/nms-patches/net/minecraft/server/commands/PlaceCommand.patch new file mode 100644 index 0000000000..2b96dcd0c8 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/server/commands/PlaceCommand.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/server/commands/PlaceCommand.java ++++ b/net/minecraft/server/commands/PlaceCommand.java +@@ -130,6 +130,7 @@ + if (!structurestart.isValid()) { + throw PlaceCommand.ERROR_STRUCTURE_FAILED.create(); + } else { ++ structurestart.generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.COMMAND; // CraftBukkit - set AsyncStructureGenerateEvent.Cause.COMMAND as generation cause + StructureBoundingBox structureboundingbox = structurestart.getBoundingBox(); + ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(SectionPosition.blockToSectionCoord(structureboundingbox.minX()), SectionPosition.blockToSectionCoord(structureboundingbox.minZ())); + ChunkCoordIntPair chunkcoordintpair1 = new ChunkCoordIntPair(SectionPosition.blockToSectionCoord(structureboundingbox.maxX()), SectionPosition.blockToSectionCoord(structureboundingbox.maxZ())); diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructurePiece.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructurePiece.patch new file mode 100644 index 0000000000..4518405ac6 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructurePiece.patch @@ -0,0 +1,151 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java ++++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java +@@ -50,7 +50,7 @@ + private EnumBlockRotation rotation; + protected int genDepth; + private final WorldGenFeatureStructurePieceType type; +- private static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); ++ public static final Set SHAPE_CHECK_BLOCKS = ImmutableSet.builder().add(Blocks.NETHER_BRICK_FENCE).add(Blocks.TORCH).add(Blocks.WALL_TORCH).add(Blocks.OAK_FENCE).add(Blocks.SPRUCE_FENCE).add(Blocks.DARK_OAK_FENCE).add(Blocks.ACACIA_FENCE).add(Blocks.BIRCH_FENCE).add(Blocks.JUNGLE_FENCE).add(Blocks.LADDER).add(Blocks.IRON_BARS).build(); // CraftBukkit - decompile error / PAIL private -> public + + protected StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, int i, StructureBoundingBox structureboundingbox) { + this.type = worldgenfeaturestructurepiecetype; +@@ -59,14 +59,11 @@ + } + + public StructurePiece(WorldGenFeatureStructurePieceType worldgenfeaturestructurepiecetype, NBTTagCompound nbttagcompound) { +- int i = nbttagcompound.getInt("GD"); +- DataResult dataresult = StructureBoundingBox.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("BB")); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- this(worldgenfeaturestructurepiecetype, i, (StructureBoundingBox) dataresult.resultOrPartial(logger::error).orElseThrow(() -> { ++ // CraftBukkit start - decompile error ++ this(worldgenfeaturestructurepiecetype, nbttagcompound.getInt("GD"), (StructureBoundingBox) StructureBoundingBox.CODEC.parse(DynamicOpsNBT.INSTANCE, nbttagcompound.get("BB")).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).orElseThrow(() -> { + return new IllegalArgumentException("Invalid boundingbox"); + })); ++ // CraftBukkit end + int j = nbttagcompound.getInt("O"); + + this.setOrientation(j == -1 ? null : EnumDirection.from2DDataValue(j)); +@@ -84,13 +81,11 @@ + NBTTagCompound nbttagcompound = new NBTTagCompound(); + + nbttagcompound.putString("id", BuiltInRegistries.STRUCTURE_PIECE.getKey(this.getType()).toString()); +- DataResult dataresult = StructureBoundingBox.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.boundingBox); +- Logger logger = StructurePiece.LOGGER; +- +- Objects.requireNonNull(logger); +- dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { +- nbttagcompound.put("BB", nbtbase); ++ // CraftBukkit start - decompile error ++ StructureBoundingBox.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, this.boundingBox).resultOrPartial(Objects.requireNonNull(StructurePiece.LOGGER)::error).ifPresent((nbtbase) -> { ++ nbttagcompound.put("BB", nbtbase); + }); ++ // CraftBukkit end + EnumDirection enumdirection = this.getOrientation(); + + nbttagcompound.putInt("O", enumdirection == null ? -1 : enumdirection.get2DDataValue()); +@@ -190,6 +185,11 @@ + } + + generatoraccessseed.setBlock(blockposition_mutableblockposition, iblockdata, 2); ++ // CraftBukkit start - fluid handling is already done if we have a transformer generator access ++ if (generatoraccessseed instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) { ++ return; ++ } ++ // CraftBukkit end + Fluid fluid = generatoraccessseed.getFluidState(blockposition_mutableblockposition); + + if (!fluid.isEmpty()) { +@@ -204,6 +204,38 @@ + } + } + ++ // CraftBukkit start ++ protected boolean placeCraftBlockEntity(WorldAccess worldAccess, BlockPosition position, org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState, int i) { ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ return transformerAccess.setCraftBlock(position, craftBlockEntityState, i); ++ } ++ boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); ++ TileEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity != null) { ++ tileEntity.load(craftBlockEntityState.getSnapshotNBT()); ++ } ++ return result; ++ } ++ ++ protected void placeCraftSpawner(WorldAccess worldAccess, BlockPosition position, org.bukkit.entity.EntityType entityType, int i) { ++ // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information ++ org.bukkit.craftbukkit.block.CraftCreatureSpawner spawner = (org.bukkit.craftbukkit.block.CraftCreatureSpawner) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); ++ spawner.setSpawnedType(entityType); ++ placeCraftBlockEntity(worldAccess, position, spawner, i); ++ } ++ ++ protected void setCraftLootTable(WorldAccess worldAccess, BlockPosition position, RandomSource randomSource, net.minecraft.resources.MinecraftKey loottableKey) { ++ // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. ++ net.minecraft.world.level.block.entity.TileEntity tileEntity = worldAccess.getBlockEntity(position); ++ if (tileEntity instanceof net.minecraft.world.level.block.entity.TileEntityLootable tileEntityLootable) { ++ tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); ++ if (worldAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ transformerAccess.setCraftBlock(position, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); ++ } ++ } ++ } ++ // CraftBukkit end ++ + protected boolean canBeReplaced(IWorldReader iworldreader, int i, int j, int k, StructureBoundingBox structureboundingbox) { + return true; + } +@@ -397,12 +429,20 @@ + iblockdata = reorient(worldaccess, blockposition, Blocks.CHEST.defaultBlockState()); + } + ++ // CraftBukkit start ++ /* + worldaccess.setBlock(blockposition, iblockdata, 2); + TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, iblockdata, null); ++ chestState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(minecraftkey))); ++ chestState.setSeed(randomsource.nextLong()); ++ placeCraftBlockEntity(worldaccess, blockposition, chestState, 2); ++ // CraftBukkit end + + return true; + } else { +@@ -414,12 +454,31 @@ + BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getWorldPos(i, j, k); + + if (structureboundingbox.isInside(blockposition_mutableblockposition) && !generatoraccessseed.getBlockState(blockposition_mutableblockposition).is(Blocks.DISPENSER)) { ++ // CraftBukkit start ++ /* + this.placeBlock(generatoraccessseed, (IBlockData) Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection), i, j, k, structureboundingbox); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + + if (tileentity instanceof TileEntityDispenser) { + ((TileEntityDispenser) tileentity).setLootTable(minecraftkey, randomsource.nextLong()); + } ++ */ ++ if (!this.canBeReplaced(generatoraccessseed, i, j, k, structureboundingbox)) { ++ return true; ++ } ++ IBlockData iblockdata = Blocks.DISPENSER.defaultBlockState().setValue(BlockDispenser.FACING, enumdirection); ++ if (this.mirror != EnumBlockMirror.NONE) { ++ iblockdata = iblockdata.mirror(this.mirror); ++ } ++ if (this.rotation != EnumBlockRotation.NONE) { ++ iblockdata = iblockdata.rotate(this.rotation); ++ } ++ ++ org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition_mutableblockposition, iblockdata, null); ++ dispenserState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(minecraftkey))); ++ dispenserState.setSeed(randomsource.nextLong()); ++ placeCraftBlockEntity(generatoraccessseed, blockposition_mutableblockposition, dispenserState, 2); ++ // CraftBukkit end + + return true; + } else { diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructureStart.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructureStart.patch new file mode 100644 index 0000000000..f94fcf5193 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/StructureStart.patch @@ -0,0 +1,38 @@ +--- a/net/minecraft/world/level/levelgen/structure/StructureStart.java ++++ b/net/minecraft/world/level/levelgen/structure/StructureStart.java +@@ -31,6 +31,7 @@ + private int references; + @Nullable + private volatile StructureBoundingBox cachedBoundingBox; ++ public org.bukkit.event.world.AsyncStructureGenerateEvent.Cause generationEventCause = org.bukkit.event.world.AsyncStructureGenerateEvent.Cause.WORLD_GENERATION; // CraftBukkit + + public StructureStart(Structure structure, ChunkCoordIntPair chunkcoordintpair, int i, PiecesContainer piecescontainer) { + this.structure = structure; +@@ -91,6 +92,8 @@ + StructureBoundingBox structureboundingbox1 = ((StructurePiece) list.get(0)).boundingBox; + BlockPosition blockposition = structureboundingbox1.getCenter(); + BlockPosition blockposition1 = new BlockPosition(blockposition.getX(), structureboundingbox1.minY(), blockposition.getZ()); ++ // CraftBukkit start ++ /* + Iterator iterator = list.iterator(); + + while (iterator.hasNext()) { +@@ -100,6 +103,18 @@ + structurepiece.postProcess(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); + } + } ++ */ ++ List pieces = list.stream().filter(piece -> piece.getBoundingBox().intersects(structureboundingbox)).toList(); ++ if (!pieces.isEmpty()) { ++ org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess = new org.bukkit.craftbukkit.util.TransformerGeneratorAccess(); ++ transformerAccess.setHandle(generatoraccessseed); ++ transformerAccess.setStructureTransformer(new org.bukkit.craftbukkit.util.CraftStructureTransformer(generationEventCause, generatoraccessseed, structuremanager, structure, structureboundingbox, chunkcoordintpair)); ++ for (StructurePiece piece : pieces) { ++ piece.postProcess(transformerAccess, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, blockposition1); ++ } ++ transformerAccess.getStructureTransformer().discard(); ++ } ++ // CraftBukkit end + + this.structure.afterPlace(generatoraccessseed, structuremanager, chunkgenerator, randomsource, structureboundingbox, chunkcoordintpair, this.pieceContainer); + } diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch new file mode 100644 index 0000000000..a015136b4f --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/DesertPyramidStructure.java +@@ -70,6 +70,15 @@ + + private static void placeSuspiciousSand(StructureBoundingBox structureboundingbox, GeneratorAccessSeed generatoraccessseed, BlockPosition blockposition) { + if (structureboundingbox.isInside(blockposition)) { ++ // CraftBukkit start ++ if (generatoraccessseed instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ org.bukkit.craftbukkit.block.CraftBrushableBlock brushableState = (org.bukkit.craftbukkit.block.CraftBrushableBlock) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, Blocks.SUSPICIOUS_SAND.defaultBlockState(), null); ++ brushableState.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(LootTables.DESERT_PYRAMID_ARCHAEOLOGY))); ++ brushableState.setSeed(blockposition.asLong()); ++ transformerAccess.setCraftBlock(blockposition, brushableState, 2); ++ return; ++ } ++ // CraftBukkit end + generatoraccessseed.setBlock(blockposition, Blocks.SUSPICIOUS_SAND.defaultBlockState(), 2); + generatoraccessseed.getBlockEntity(blockposition, TileEntityTypes.BRUSHABLE_BLOCK).ifPresent((brushableblockentity) -> { + brushableblockentity.setLootTable(LootTables.DESERT_PYRAMID_ARCHAEOLOGY, blockposition.asLong()); diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch new file mode 100644 index 0000000000..9d77b58621 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/EndCityPieces.java +@@ -284,7 +284,12 @@ + BlockPosition blockposition1 = blockposition.below(); + + if (structureboundingbox.isInside(blockposition1)) { ++ // CraftBukkit start - ensure block transformation ++ /* + TileEntityLootable.setLootTable(worldaccess, randomsource, blockposition1, LootTables.END_CITY_TREASURE); ++ */ ++ setCraftLootTable(worldaccess, blockposition1, randomsource, LootTables.END_CITY_TREASURE); ++ // CraftBukkit end + } + } else if (structureboundingbox.isInside(blockposition) && World.isInSpawnableBounds(blockposition)) { + if (s.startsWith("Sentry")) { diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch new file mode 100644 index 0000000000..5d607215b4 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/IglooPieces.java +@@ -85,11 +85,16 @@ + protected void handleDataMarker(String s, BlockPosition blockposition, WorldAccess worldaccess, RandomSource randomsource, StructureBoundingBox structureboundingbox) { + if ("chest".equals(s)) { + worldaccess.setBlock(blockposition, Blocks.AIR.defaultBlockState(), 3); ++ // CraftBukkit start - ensure block transformation ++ /* + TileEntity tileentity = worldaccess.getBlockEntity(blockposition.below()); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(LootTables.IGLOO_CHEST, randomsource.nextLong()); + } ++ */ ++ setCraftLootTable(worldaccess, blockposition.below(), randomsource, LootTables.IGLOO_CHEST); ++ // CraftBukkit end + + } + } diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch new file mode 100644 index 0000000000..2cedb04da6 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.patch @@ -0,0 +1,55 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/MineshaftPieces.java +@@ -42,6 +42,10 @@ + import net.minecraft.world.level.storage.loot.LootTables; + import org.slf4j.Logger; + ++// CraftBukkit start - imports ++import net.minecraft.nbt.NBTBase; ++// CraftBukkit end ++ + public class MineshaftPieces { + + static final Logger LOGGER = LogUtils.getLogger(); +@@ -514,6 +518,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition) && this.isInterior(generatoraccessseed, 1, 0, l, structureboundingbox)) { + this.hasPlacedSpider = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -522,6 +528,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.CAVE_SPIDER, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.CAVE_SPIDER, 2); ++ // CraftBukkit end + } + } + } +@@ -813,11 +822,11 @@ + + public d(NBTTagCompound nbttagcompound) { + super(WorldGenFeatureStructurePieceType.MINE_SHAFT_ROOM, nbttagcompound); +- DataResult dataresult = StructureBoundingBox.CODEC.listOf().parse(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("Entrances", 11)); ++ DataResult> dataresult = StructureBoundingBox.CODEC.listOf().parse(DynamicOpsNBT.INSTANCE, nbttagcompound.getList("Entrances", 11)); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); +- Optional optional = dataresult.resultOrPartial(logger::error); ++ Optional> optional = dataresult.resultOrPartial(logger::error); // CraftBukkit - decompile error + List list = this.childEntranceBoxes; + + Objects.requireNonNull(this.childEntranceBoxes); +@@ -923,7 +932,7 @@ + @Override + protected void addAdditionalSaveData(StructurePieceSerializationContext structurepieceserializationcontext, NBTTagCompound nbttagcompound) { + super.addAdditionalSaveData(structurepieceserializationcontext, nbttagcompound); +- DataResult dataresult = StructureBoundingBox.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.childEntranceBoxes); ++ DataResult dataresult = StructureBoundingBox.CODEC.listOf().encodeStart(DynamicOpsNBT.INSTANCE, this.childEntranceBoxes); // CraftBukkit - decompile error + Logger logger = MineshaftPieces.LOGGER; + + Objects.requireNonNull(logger); diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch new file mode 100644 index 0000000000..ab12d63ae0 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.patch @@ -0,0 +1,21 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/NetherFortressPieces.java +@@ -428,6 +428,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -436,6 +438,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.BLAZE, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.BLAZE, 2); ++ // CraftBukkit end + } + } + diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch new file mode 100644 index 0000000000..f73431b188 --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.patch @@ -0,0 +1,23 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java +@@ -198,12 +198,20 @@ + @Override + protected void handleDataMarker(String s, BlockPosition blockposition, WorldAccess worldaccess, RandomSource randomsource, StructureBoundingBox structureboundingbox) { + if ("chest".equals(s)) { ++ // CraftBukkit start - transform block to ensure loot table is accessible ++ /* + worldaccess.setBlock(blockposition, (IBlockData) Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), 2); + TileEntity tileentity = worldaccess.getBlockEntity(blockposition); + + if (tileentity instanceof TileEntityChest) { + ((TileEntityChest) tileentity).setLootTable(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL, randomsource.nextLong()); + } ++ */ ++ org.bukkit.craftbukkit.block.CraftChest craftChest = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition, Blocks.CHEST.defaultBlockState().setValue(BlockChest.WATERLOGGED, worldaccess.getFluidState(blockposition).is(TagsFluid.WATER)), null); ++ craftChest.setSeed(randomsource.nextLong()); ++ craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? LootTables.UNDERWATER_RUIN_BIG : LootTables.UNDERWATER_RUIN_SMALL))); ++ placeCraftBlockEntity(worldaccess, blockposition, craftChest, 2); ++ // CraftBukkit end + } else if ("drowned".equals(s)) { + EntityDrowned entitydrowned = (EntityDrowned) EntityTypes.DROWNED.create(worldaccess.getLevel()); + diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch new file mode 100644 index 0000000000..b1409167ea --- /dev/null +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java ++++ b/net/minecraft/world/level/levelgen/structure/structures/StrongholdPieces.java +@@ -53,7 +53,7 @@ + public boolean doPlace(int i) { + return super.doPlace(i) && i > 5; + } +- }}; ++ } }; // CraftBukkit - fix decompile styling + private static List currentPieces; + static Class imposedPiece; + private static int totalWeight; +@@ -1136,6 +1136,8 @@ + + if (structureboundingbox.isInside(blockposition_mutableblockposition)) { + this.hasPlacedSpawner = true; ++ // CraftBukkit start ++ /* + generatoraccessseed.setBlock(blockposition_mutableblockposition, Blocks.SPAWNER.defaultBlockState(), 2); + TileEntity tileentity = generatoraccessseed.getBlockEntity(blockposition_mutableblockposition); + +@@ -1144,6 +1146,9 @@ + + tileentitymobspawner.setEntityId(EntityTypes.SILVERFISH, randomsource); + } ++ */ ++ placeCraftSpawner(generatoraccessseed, blockposition_mutableblockposition, org.bukkit.entity.EntityType.SILVERFISH, 2); ++ // CraftBukkit end + } + } + diff --git a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch index 82b39ab1e4..b32090b827 100644 --- a/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch +++ b/paper-server/nms-patches/net/minecraft/world/level/levelgen/structure/templatesystem/DefinedStructure.patch @@ -34,7 +34,66 @@ return definedstructure_blockinfo.pos.getY(); }).thenComparingInt((definedstructure_blockinfo) -> { return definedstructure_blockinfo.pos.getX(); -@@ -472,11 +483,13 @@ +@@ -229,6 +240,19 @@ + if (this.palettes.isEmpty()) { + return false; + } else { ++ // CraftBukkit start ++ // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed ++ WorldAccess wrappedAccess = worldaccess; ++ org.bukkit.craftbukkit.util.CraftStructureTransformer structureTransformer = null; ++ if (wrappedAccess instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) { ++ worldaccess = transformerAccess.getHandle(); ++ structureTransformer = transformerAccess.getStructureTransformer(); ++ // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this ++ if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { ++ structureTransformer = null; ++ } ++ } ++ // CraftBukkit end + List list = definedstructureinfo.getRandomPalette(this.palettes, blockposition).blocks(); + + if ((!list.isEmpty() || !definedstructureinfo.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { +@@ -260,6 +284,20 @@ + Clearable.tryClear(tileentity); + worldaccess.setBlock(blockposition2, Blocks.BARRIER.defaultBlockState(), 20); + } ++ // CraftBukkit start ++ if (structureTransformer != null) { ++ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockposition2, iblockdata, null); ++ if (definedstructure_blockinfo.nbt != null && craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState entityState) { ++ entityState.loadData(definedstructure_blockinfo.nbt); ++ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftLootable craftLootable) { ++ craftLootable.setSeed(randomsource.nextLong()); ++ } ++ } ++ craftBlockState = structureTransformer.transformCraftState(craftBlockState); ++ iblockdata = craftBlockState.getHandle(); ++ definedstructure_blockinfo = new DefinedStructure.BlockInfo(blockposition2, iblockdata, (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); ++ } ++ // CraftBukkit end + + if (worldaccess.setBlock(blockposition2, iblockdata, i)) { + j = Math.min(j, blockposition2.getX()); +@@ -272,7 +310,7 @@ + if (definedstructure_blockinfo.nbt != null) { + tileentity = worldaccess.getBlockEntity(blockposition2); + if (tileentity != null) { +- if (tileentity instanceof TileEntityLootable) { ++ if (wrappedAccess == worldaccess && tileentity instanceof TileEntityLootable) { // CraftBukkit - only process if don't have a transformer access (originalAccess == worldaccess) + definedstructure_blockinfo.nbt.putLong("LootTableSeed", randomsource.nextLong()); + } + +@@ -377,7 +415,7 @@ + } + + if (!definedstructureinfo.isIgnoreEntities()) { +- this.placeEntities(worldaccess, blockposition, definedstructureinfo.getMirror(), definedstructureinfo.getRotation(), definedstructureinfo.getRotationPivot(), structureboundingbox, definedstructureinfo.shouldFinalizeEntities()); ++ this.placeEntities(wrappedAccess, blockposition, definedstructureinfo.getMirror(), definedstructureinfo.getRotation(), definedstructureinfo.getRotationPivot(), structureboundingbox, definedstructureinfo.shouldFinalizeEntities()); // CraftBukkit + } + + return true; +@@ -472,11 +510,13 @@ } private static Optional createEntityIgnoreException(WorldAccess worldaccess, NBTTagCompound nbttagcompound) { @@ -52,7 +111,7 @@ } public BaseBlockPosition getSize(EnumBlockRotation enumblockrotation) { -@@ -690,6 +703,11 @@ +@@ -690,6 +730,11 @@ nbttagcompound.put("entities", nbttaglist3); nbttagcompound.put("size", this.newIntegerList(this.size.getX(), this.size.getY(), this.size.getZ())); @@ -64,7 +123,7 @@ return GameProfileSerializer.addCurrentDataVersion(nbttagcompound); } -@@ -729,6 +747,12 @@ +@@ -729,6 +774,12 @@ } } @@ -77,7 +136,7 @@ } private void loadPalette(HolderGetter holdergetter, NBTTagList nbttaglist, NBTTagList nbttaglist1) { -@@ -858,7 +882,7 @@ +@@ -858,7 +909,7 @@ public IBlockData stateFor(int i) { IBlockData iblockdata = (IBlockData) this.ids.byId(i); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CapturedBlockState.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CapturedBlockState.java index 0dc91709aa..8440e6f0b1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CapturedBlockState.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CapturedBlockState.java @@ -21,6 +21,12 @@ public final class CapturedBlockState extends CraftBlockState { this.treeBlock = treeBlock; } + protected CapturedBlockState(CapturedBlockState state) { + super(state); + + this.treeBlock = state.treeBlock; + } + @Override public boolean update(boolean force, boolean applyPhysics) { boolean result = super.update(force, applyPhysics); @@ -50,6 +56,11 @@ public final class CapturedBlockState extends CraftBlockState { return result; } + @Override + public CapturedBlockState copy() { + return new CapturedBlockState(this); + } + public static CapturedBlockState getBlockState(World world, BlockPosition pos, int flag) { return new CapturedBlockState(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), flag, false); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java index 3012757934..05961f0335 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java @@ -23,6 +23,10 @@ public class CraftBanner extends CraftBlockEntityState impleme super(world, tileEntity); } + protected CraftBanner(CraftBanner state) { + super(state); + } + @Override public void load(TileEntityBanner banner) { super.load(banner); @@ -100,4 +104,9 @@ public class CraftBanner extends CraftBlockEntityState impleme } banner.itemPatterns = newPatterns; } + + @Override + public CraftBanner copy() { + return new CraftBanner(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java index 16b18d8a5f..3a4c9844fa 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBarrel.java @@ -15,6 +15,10 @@ public class CraftBarrel extends CraftLootable implements Barr super(world, tileEntity); } + protected CraftBarrel(CraftBarrel state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -58,4 +62,9 @@ public class CraftBarrel extends CraftLootable implements Barr } getTileEntity().openersCounter.opened = false; } + + @Override + public CraftBarrel copy() { + return new CraftBarrel(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java index 71c1060f33..df2177a6f1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeacon.java @@ -20,6 +20,10 @@ public class CraftBeacon extends CraftBlockEntityState impleme super(world, tileEntity); } + protected CraftBeacon(CraftBeacon state) { + super(state); + } + @Override public Collection getEntitiesInRange() { ensureNoWorldGeneration(); @@ -92,4 +96,9 @@ public class CraftBeacon extends CraftBlockEntityState impleme public void setLock(String key) { this.getSnapshot().lockKey = (key == null) ? ChestLock.NO_LOCK : new ChestLock(key); } + + @Override + public CraftBeacon copy() { + return new CraftBeacon(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBed.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBed.java index 2fb4c1383a..5bb2c75999 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBed.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBed.java @@ -11,6 +11,10 @@ public class CraftBed extends CraftBlockEntityState implements Be super(world, tileEntity); } + protected CraftBed(CraftBed state) { + super(state); + } + @Override public DyeColor getColor() { switch (getType()) { @@ -55,4 +59,9 @@ public class CraftBed extends CraftBlockEntityState implements Be public void setColor(DyeColor color) { throw new UnsupportedOperationException("Must set block type to appropriate bed colour"); } + + @Override + public CraftBed copy() { + return new CraftBed(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java index cbfbb12490..01f637e291 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBeehive.java @@ -20,6 +20,10 @@ public class CraftBeehive extends CraftBlockEntityState imple super(world, tileEntity); } + protected CraftBeehive(CraftBeehive state) { + super(state); + } + @Override public Location getFlower() { BlockPosition flower = getSnapshot().savedFlowerPos; @@ -81,4 +85,9 @@ public class CraftBeehive extends CraftBlockEntityState imple getSnapshot().addOccupant(((CraftBee) entity).getHandle(), false); } + + @Override + public CraftBeehive copy() { + return new CraftBeehive(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBell.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBell.java index 75b4aff2b5..eb0b93128a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBell.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBell.java @@ -18,6 +18,10 @@ public class CraftBell extends CraftBlockEntityState implements super(world, tileEntity); } + protected CraftBell(CraftBell state) { + super(state); + } + @Override public boolean ring(Entity entity, BlockFace direction) { Preconditions.checkArgument(direction == null || direction.isCartesian(), "direction must be cartesian, given %s", direction); @@ -67,4 +71,9 @@ public class CraftBell extends CraftBlockEntityState implements public int getResonatingTicks() { return isResonating() ? getSnapshot().ticks : 0; } + + @Override + public CraftBell copy() { + return new CraftBell(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlastFurnace.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlastFurnace.java index a0778746e5..c27ff1de4b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlastFurnace.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlastFurnace.java @@ -9,4 +9,13 @@ public class CraftBlastFurnace extends CraftFurnace impl public CraftBlastFurnace(World world, TileEntityBlastFurnace tileEntity) { super(world, tileEntity); } + + protected CraftBlastFurnace(CraftBlastFurnace state) { + super(state); + } + + @Override + public CraftBlastFurnace copy() { + return new CraftBlastFurnace(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java index 9c767dc3fa..6ef8f5ab17 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -28,6 +28,13 @@ public class CraftBlockEntityState extends CraftBlockState this.load(snapshot); } + protected CraftBlockEntityState(CraftBlockEntityState state) { + super(state); + this.tileEntity = createSnapshot(state.snapshot); + this.snapshot = tileEntity; + load(snapshot); + } + public void refreshSnapshot() { this.load(tileEntity); } @@ -43,6 +50,12 @@ public class CraftBlockEntityState extends CraftBlockState return snapshot; } + // Loads the specified data into the snapshot TileEntity. + public void loadData(NBTTagCompound nbtTagCompound) { + snapshot.load(nbtTagCompound); + load(snapshot); + } + // copies the TileEntity-specific data, retains the position private void copyData(T from, T to) { NBTTagCompound nbtTagCompound = from.saveWithFullMetadata(); @@ -118,4 +131,9 @@ public class CraftBlockEntityState extends CraftBlockState T vanillaTileEntitiy = (T) TileEntity.loadStatic(CraftLocation.toBlockPosition(location), getHandle(), getSnapshotNBT()); return PacketPlayOutTileEntityData.create(vanillaTileEntitiy); } + + @Override + public CraftBlockEntityState copy() { + return new CraftBlockEntityState<>(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java index 19de83433a..c90878017a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -50,6 +50,15 @@ public class CraftBlockState implements BlockState { data = blockData; } + // Creates a unplaced copy (world == null copy) + protected CraftBlockState(CraftBlockState state) { + this.world = null; + this.position = state.getPosition().immutable(); + this.data = state.data; + this.flag = state.flag; + setWorldHandle(state.getWorldHandle()); + } + public void setWorldHandle(GeneratorAccess generatorAccess) { if (generatorAccess instanceof net.minecraft.world.level.World) { this.weakWorld = null; @@ -318,4 +327,9 @@ public class CraftBlockState implements BlockState { protected void requirePlaced() { Preconditions.checkState(isPlaced(), "The blockState must be placed to call this method"); } + + @Override + public CraftBlockState copy() { + return new CraftBlockState(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java index 248b11d712..d64cf9dec6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java @@ -12,6 +12,10 @@ public class CraftBrewingStand extends CraftContainer im super(world, tileEntity); } + protected CraftBrewingStand(CraftBrewingStand state) { + super(state); + } + @Override public BrewerInventory getSnapshotInventory() { return new CraftInventoryBrewer(this.getSnapshot()); @@ -45,4 +49,9 @@ public class CraftBrewingStand extends CraftContainer im public void setFuelLevel(int level) { this.getSnapshot().fuel = level; } + + @Override + public CraftBrewingStand copy() { + return new CraftBrewingStand(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java index a821828e94..631de25b58 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBrushableBlock.java @@ -16,6 +16,10 @@ public class CraftBrushableBlock extends CraftBlockEntityState imp super(world, tileEntity); } + protected CraftCampfire(CraftCampfire state) { + super(state); + } + @Override public int getSize() { return getSnapshot().getItems().size(); @@ -47,4 +51,9 @@ public class CraftCampfire extends CraftBlockEntityState imp public void setCookTimeTotal(int index, int cookTimeTotal) { getSnapshot().cookingTime[index] = cookTimeTotal; } + + @Override + public CraftCampfire copy() { + return new CraftCampfire(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java index dcb38cbbb9..0eb6e09af9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java @@ -19,6 +19,10 @@ public class CraftChest extends CraftLootable implements Chest super(world, tileEntity); } + protected CraftChest(CraftChest state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -77,4 +81,9 @@ public class CraftChest extends CraftLootable implements Chest } getTileEntity().openersCounter.opened = false; } + + @Override + public CraftChest copy() { + return new CraftChest(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChiseledBookshelf.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChiseledBookshelf.java index 3dac492040..28bfa62098 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChiseledBookshelf.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftChiseledBookshelf.java @@ -17,6 +17,10 @@ public class CraftChiseledBookshelf extends CraftBlockEntityState super(world, tileEntity); } + protected CraftCommandBlock(CraftCommandBlock state) { + super(state); + } + @Override public String getCommand() { return getSnapshot().getCommandBlock().getCommand(); @@ -30,4 +34,9 @@ public class CraftCommandBlock extends CraftBlockEntityState public void setName(String name) { getSnapshot().getCommandBlock().setName(CraftChatMessage.fromStringOrNull(name != null ? name : "@")); } + + @Override + public CraftCommandBlock copy() { + return new CraftCommandBlock(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftComparator.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftComparator.java index b6d9050055..75c7902411 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftComparator.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftComparator.java @@ -9,4 +9,13 @@ public class CraftComparator extends CraftBlockEntityState public CraftComparator(World world, TileEntityComparator tileEntity) { super(world, tileEntity); } + + protected CraftComparator(CraftComparator state) { + super(state); + } + + @Override + public CraftComparator copy() { + return new CraftComparator(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java index db5285a267..cb7fa975eb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftConduit.java @@ -9,4 +9,13 @@ public class CraftConduit extends CraftBlockEntityState imple public CraftConduit(World world, TileEntityConduit tileEntity) { super(world, tileEntity); } + + protected CraftConduit(CraftConduit state) { + super(state); + } + + @Override + public CraftConduit copy() { + return new CraftConduit(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java index 7e3ad44017..16e7b64f79 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftContainer.java @@ -12,6 +12,10 @@ public abstract class CraftContainer extends Craf super(world, tileEntity); } + protected CraftContainer(CraftContainer state) { + super(state); + } + @Override public boolean isLocked() { return !this.getSnapshot().lockKey.key.isEmpty(); @@ -46,4 +50,7 @@ public abstract class CraftContainer extends Craf container.setCustomName(null); } } + + @Override + public abstract CraftContainer copy(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java index c7382a9f7e..5f22f59d0a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java @@ -18,6 +18,10 @@ public class CraftCreatureSpawner extends CraftBlockEntityState getShards() { return getSnapshot().getDecorations().sorted().map(CraftMagicNumbers::getMaterial).collect(Collectors.toUnmodifiableList()); } + + @Override + public CraftDecoratedPot copy() { + return new CraftDecoratedPot(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java index 32ef3ef469..b1f09f78d9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java @@ -19,6 +19,10 @@ public class CraftDispenser extends CraftLootable implement super(world, tileEntity); } + protected CraftDispenser(CraftDispenser state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -58,4 +62,9 @@ public class CraftDispenser extends CraftLootable implement return false; } } + + @Override + public CraftDispenser copy() { + return new CraftDispenser(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDropper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDropper.java index 64edfd457e..c8a9dd8372 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDropper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftDropper.java @@ -17,6 +17,10 @@ public class CraftDropper extends CraftLootable implements Dr super(world, tileEntity); } + protected CraftDropper(CraftDropper state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -42,4 +46,9 @@ public class CraftDropper extends CraftLootable implements Dr drop.dispenseFrom(world.getHandle(), this.getHandle(), this.getPosition()); } } + + @Override + public CraftDropper copy() { + return new CraftDropper(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java index b63bc3c4f0..d8ab94b8ce 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnchantingTable.java @@ -11,6 +11,10 @@ public class CraftEnchantingTable extends CraftBlockEntityState super(world, tileEntity); } + protected CraftEndGateway(CraftEndGateway state) { + super(state); + } + @Override public Location getExitLocation() { BlockPosition pos = this.getSnapshot().exitPortal; @@ -59,4 +63,9 @@ public class CraftEndGateway extends CraftBlockEntityState endGateway.exitPortal = null; } } + + @Override + public CraftEndGateway copy() { + return new CraftEndGateway(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEndPortal.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEndPortal.java index ef5b80a8a1..29d8ef3b10 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEndPortal.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEndPortal.java @@ -8,4 +8,13 @@ public class CraftEndPortal extends CraftBlockEntityState public CraftEndPortal(World world, TileEntityEnderPortal tileEntity) { super(world, tileEntity); } + + protected CraftEndPortal(CraftEndPortal state) { + super(state); + } + + @Override + public CraftEndPortal copy() { + return new CraftEndPortal(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java index 9e65fc72ef..0c4fd5a0f0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java @@ -11,6 +11,10 @@ public class CraftEnderChest extends CraftBlockEntityState super(world, tileEntity); } + protected CraftEnderChest(CraftEnderChest state) { + super(state); + } + @Override public void open() { requirePlaced(); @@ -36,4 +40,9 @@ public class CraftEnderChest extends CraftBlockEntityState } getTileEntity().openersCounter.opened = false; } + + @Override + public CraftEnderChest copy() { + return new CraftEnderChest(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java index 2c251acf34..8e4db069b7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnace.java @@ -20,6 +20,10 @@ public abstract class CraftFurnace extends CraftCon super(world, tileEntity); } + protected CraftFurnace(CraftFurnace state) { + super(state); + } + @Override public FurnaceInventory getSnapshotInventory() { return new CraftInventoryFurnace(this.getSnapshot()); @@ -78,4 +82,7 @@ public abstract class CraftFurnace extends CraftCon return recipesUsed.build(); } + + @Override + public abstract CraftFurnace copy(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnaceFurnace.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnaceFurnace.java index 6a5183886a..60e36850db 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnaceFurnace.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftFurnaceFurnace.java @@ -8,4 +8,13 @@ public class CraftFurnaceFurnace extends CraftFurnace public CraftFurnaceFurnace(World world, TileEntityFurnaceFurnace tileEntity) { super(world, tileEntity); } + + protected CraftFurnaceFurnace(CraftFurnaceFurnace state) { + super(state); + } + + @Override + public CraftFurnaceFurnace copy() { + return new CraftFurnaceFurnace(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHangingSign.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHangingSign.java index afea053c27..19ae36483c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHangingSign.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHangingSign.java @@ -9,4 +9,13 @@ public class CraftHangingSign extends CraftSign implemen public CraftHangingSign(World world, HangingSignBlockEntity tileEntity) { super(world, tileEntity); } + + protected CraftHangingSign(CraftHangingSign state) { + super(state); + } + + @Override + public CraftHangingSign copy() { + return new CraftHangingSign(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java index f1ecdbf666..bb9f6005d2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java @@ -12,6 +12,10 @@ public class CraftHopper extends CraftLootable implements Hopp super(world, tileEntity); } + protected CraftHopper(CraftHopper state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -25,4 +29,9 @@ public class CraftHopper extends CraftLootable implements Hopp return new CraftInventory(this.getTileEntity()); } + + @Override + public CraftHopper copy() { + return new CraftHopper(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJigsaw.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJigsaw.java index dc0222aa8a..43549465e0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJigsaw.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJigsaw.java @@ -9,4 +9,13 @@ public class CraftJigsaw extends CraftBlockEntityState impleme public CraftJigsaw(World world, TileEntityJigsaw tileEntity) { super(world, tileEntity); } + + protected CraftJigsaw(CraftJigsaw state) { + super(state); + } + + @Override + public CraftJigsaw copy() { + return new CraftJigsaw(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJukebox.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJukebox.java index dfb2db3e2a..c2c5e4baef 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJukebox.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftJukebox.java @@ -20,6 +20,10 @@ public class CraftJukebox extends CraftBlockEntityState imple super(world, tileEntity); } + protected CraftJukebox(CraftJukebox state) { + super(state); + } + @Override public JukeboxInventory getSnapshotInventory() { return new CraftInventoryJukebox(this.getSnapshot()); @@ -147,4 +151,9 @@ public class CraftJukebox extends CraftBlockEntityState imple jukebox.popOutRecord(); return result; } + + @Override + public CraftJukebox copy() { + return new CraftJukebox(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLectern.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLectern.java index f6f18e324d..3e99941ab1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLectern.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLectern.java @@ -14,6 +14,10 @@ public class CraftLectern extends CraftBlockEntityState imple super(world, tileEntity); } + protected CraftLectern(CraftLectern state) { + super(state); + } + @Override public int getPage() { return getSnapshot().getPage(); @@ -48,4 +52,9 @@ public class CraftLectern extends CraftBlockEntityState imple return result; } + + @Override + public CraftLectern copy() { + return new CraftLectern(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java index 791894642e..2b96471da0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java @@ -15,6 +15,10 @@ public abstract class CraftLootable extends CraftC super(world, tileEntity); } + protected CraftLootable(CraftLootable state) { + super(state); + } + @Override public void applyTo(T lootable) { super.applyTo(lootable); @@ -53,4 +57,7 @@ public abstract class CraftLootable extends CraftC MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); getSnapshot().setLootTable(key, seed); } + + @Override + public abstract CraftLootable copy(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java index 6685068208..a94a647b56 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java @@ -8,4 +8,13 @@ public class CraftMovingPiston extends CraftBlockEntityState { public CraftMovingPiston(World world, TileEntityPiston tileEntity) { super(world, tileEntity); } + + protected CraftMovingPiston(CraftMovingPiston state) { + super(state); + } + + @Override + public CraftMovingPiston copy() { + return new CraftMovingPiston(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java index e81cd23e38..d0eb52ef01 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java @@ -13,6 +13,10 @@ public class CraftSculkCatalyst extends CraftBlockEntityState extends CraftBlo super(world, tileEntity); } + protected CraftSculkSensor(CraftSculkSensor state) { + super(state); + } + @Override public int getLastVibrationFrequency() { return getSnapshot().getLastVibrationFrequency(); @@ -21,4 +25,9 @@ public class CraftSculkSensor extends CraftBlo Preconditions.checkArgument(0 <= lastVibrationFrequency && lastVibrationFrequency <= 15, "Vibration frequency must be between 0-15"); getSnapshot().lastVibrationFrequency = lastVibrationFrequency; } + + @Override + public CraftSculkSensor copy() { + return new CraftSculkSensor<>(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkShrieker.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkShrieker.java index d9e43669ce..2bff19c73b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkShrieker.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSculkShrieker.java @@ -13,6 +13,10 @@ public class CraftSculkShrieker extends CraftBlockEntityState impleme super(world, tileEntity); } + protected CraftShulkerBox(CraftShulkerBox state) { + super(state); + } + @Override public Inventory getSnapshotInventory() { return new CraftInventory(this.getSnapshot()); @@ -60,4 +64,9 @@ public class CraftShulkerBox extends CraftLootable impleme } getTileEntity().opened = false; } + + @Override + public CraftShulkerBox copy() { + return new CraftShulkerBox(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java index 49404b1427..4f45365df8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java @@ -27,6 +27,12 @@ public class CraftSign extends CraftBlockEntityState state) { + super(state); + this.front = new CraftSignSide(this.getSnapshot().getFrontText()); + this.back = new CraftSignSide(this.getSnapshot().getBackText()); + } + @Override public String[] getLines() { return front.getLines(); @@ -105,6 +111,11 @@ public class CraftSign extends CraftBlockEntityState copy() { + return new CraftSign(this); + } + public static void openSign(Sign sign, Player player, Side side) { Preconditions.checkArgument(sign != null, "sign == null"); Preconditions.checkArgument(side != null, "side == null"); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java index 29a9cace15..2702d98077 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java @@ -31,6 +31,10 @@ public class CraftSkull extends CraftBlockEntityState implement super(world, tileEntity); } + protected CraftSkull(CraftSkull state) { + super(state); + } + @Override public void load(TileEntitySkull skull) { super.load(skull); @@ -199,4 +203,9 @@ public class CraftSkull extends CraftBlockEntityState implement skull.setOwner(profile); } } + + @Override + public CraftSkull copy() { + return new CraftSkull(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSmoker.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSmoker.java index 0cec0853ab..fbb431468e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSmoker.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSmoker.java @@ -9,4 +9,13 @@ public class CraftSmoker extends CraftFurnace implements Smoke public CraftSmoker(World world, TileEntitySmoker tileEntity) { super(world, tileEntity); } + + protected CraftSmoker(CraftSmoker state) { + super(state); + } + + @Override + public CraftSmoker copy() { + return new CraftSmoker(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftStructureBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftStructureBlock.java index cbca862ca2..9b39a73807 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftStructureBlock.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftStructureBlock.java @@ -23,6 +23,10 @@ public class CraftStructureBlock extends CraftBlockEntityState= min && num <= max; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSuspiciousSand.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSuspiciousSand.java index 46d9148810..bdf0f4074b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSuspiciousSand.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSuspiciousSand.java @@ -9,4 +9,13 @@ public class CraftSuspiciousSand extends CraftBrushableBlock implements Suspicio public CraftSuspiciousSand(World world, BrushableBlockEntity tileEntity) { super(world, tileEntity); } + + protected CraftSuspiciousSand(CraftSuspiciousSand state) { + super(state); + } + + @Override + public CraftSuspiciousSand copy() { + return new CraftSuspiciousSand(this); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftStructureTransformer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftStructureTransformer.java new file mode 100644 index 0000000000..fe100a8261 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftStructureTransformer.java @@ -0,0 +1,125 @@ +package org.bukkit.craftbukkit.util; + +import java.util.Objects; +import net.minecraft.core.BlockPosition; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ChunkCoordIntPair; +import net.minecraft.world.level.GeneratorAccessSeed; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.levelgen.structure.Structure; +import net.minecraft.world.level.levelgen.structure.StructureBoundingBox; +import org.bukkit.Bukkit; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.generator.CraftLimitedRegion; +import org.bukkit.craftbukkit.generator.structure.CraftStructure; +import org.bukkit.event.world.AsyncStructureGenerateEvent; +import org.bukkit.event.world.AsyncStructureGenerateEvent.Cause; +import org.bukkit.util.BlockTransformer; +import org.bukkit.util.BlockTransformer.TransformationState; +import org.bukkit.util.EntityTransformer; + +public class CraftStructureTransformer { + + private static class CraftTransformationState implements TransformationState { + + private final BlockState original; + private final BlockState world; + + private BlockState originalCopy; + private BlockState worldCopy; + + private CraftTransformationState(BlockState original, BlockState world) { + this.original = original; + this.world = world; + } + + @Override + public BlockState getOriginal() { + if (originalCopy != null) { + return originalCopy; + } + return originalCopy = original.copy(); + } + + @Override + public BlockState getWorld() { + if (worldCopy != null) { + return worldCopy; + } + return worldCopy = world.copy(); + } + + private void destroyCopies() { + originalCopy = null; + worldCopy = null; + } + + } + + private CraftLimitedRegion limitedRegion; + private BlockTransformer[] blockTransformers; + private EntityTransformer[] entityTransformers; + + public CraftStructureTransformer(Cause cause, GeneratorAccessSeed generatoraccessseed, StructureManager structuremanager, Structure structure, StructureBoundingBox structureboundingbox, ChunkCoordIntPair chunkcoordintpair) { + AsyncStructureGenerateEvent event = new AsyncStructureGenerateEvent(structuremanager.level.getMinecraftWorld().getWorld(), !Bukkit.isPrimaryThread(), cause, CraftStructure.minecraftToBukkit(structure, structuremanager.registryAccess()), new org.bukkit.util.BoundingBox(structureboundingbox.minX(), structureboundingbox.minY(), structureboundingbox.minZ(), structureboundingbox.maxX(), structureboundingbox.maxY(), structureboundingbox.maxZ()), chunkcoordintpair.x, chunkcoordintpair.z); + Bukkit.getPluginManager().callEvent(event); + this.blockTransformers = event.getBlockTransformers().values().toArray(BlockTransformer[]::new); + this.entityTransformers = event.getEntityTransformers().values().toArray(EntityTransformer[]::new); + this.limitedRegion = new CraftLimitedRegion(generatoraccessseed, chunkcoordintpair); + } + + public boolean transformEntity(Entity entity) { + EntityTransformer[] transformers = entityTransformers; + if (transformers == null || transformers.length == 0) { + return true; + } + CraftLimitedRegion region = limitedRegion; + if (region == null) { + return true; + } + entity.generation = true; + CraftEntity craftEntity = entity.getBukkitEntity(); + int x = entity.getBlockX(); + int y = entity.getBlockY(); + int z = entity.getBlockZ(); + boolean allowedToSpawn = true; + for (EntityTransformer transformer : transformers) { + allowedToSpawn = transformer.transform(region, x, y, z, craftEntity, allowedToSpawn); + } + return allowedToSpawn; + } + + public boolean canTransformBlocks() { + return blockTransformers != null && blockTransformers.length != 0 && limitedRegion != null; + } + + public CraftBlockState transformCraftState(CraftBlockState originalState) { + BlockTransformer[] transformers = blockTransformers; + if (transformers == null || transformers.length == 0) { + return originalState; + } + CraftLimitedRegion region = limitedRegion; + if (region == null) { + return originalState; + } + originalState.setWorldHandle(region.getHandle()); + BlockPosition position = originalState.getPosition(); + BlockState blockState = originalState.copy(); + CraftTransformationState transformationState = new CraftTransformationState(originalState, region.getBlockState(position.getX(), position.getY(), position.getZ())); + for (BlockTransformer transformer : transformers) { + blockState = Objects.requireNonNull(transformer.transform(region, position.getX(), position.getY(), position.getZ(), blockState, transformationState), "BlockState can't be null"); + transformationState.destroyCopies(); + } + return (CraftBlockState) blockState; + } + + public void discard() { + limitedRegion.saveEntities(); + limitedRegion.breakLink(); + this.limitedRegion = null; + this.blockTransformers = null; + this.entityTransformers = null; + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java new file mode 100644 index 0000000000..2ed0eb4380 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java @@ -0,0 +1,821 @@ +package org.bukkit.craftbukkit.util; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Stream; +import net.minecraft.core.BlockPosition; +import net.minecraft.core.EnumDirection; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.IRegistry; +import net.minecraft.core.IRegistryCustom; +import net.minecraft.core.particles.ParticleParam; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.WorldServer; +import net.minecraft.sounds.SoundCategory; +import net.minecraft.sounds.SoundEffect; +import net.minecraft.util.RandomSource; +import net.minecraft.world.DifficultyDamageScaler; +import net.minecraft.world.EnumDifficulty; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityLiving; +import net.minecraft.world.entity.ai.targeting.PathfinderTargetCondition; +import net.minecraft.world.entity.player.EntityHuman; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.level.ClipBlockStateContext; +import net.minecraft.world.level.ColorResolver; +import net.minecraft.world.level.EnumSkyBlock; +import net.minecraft.world.level.GeneratorAccessSeed; +import net.minecraft.world.level.IBlockAccess; +import net.minecraft.world.level.RayTrace; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.biome.BiomeManager; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.TileEntity; +import net.minecraft.world.level.block.entity.TileEntityTypes; +import net.minecraft.world.level.block.state.IBlockData; +import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.chunk.IChunkAccess; +import net.minecraft.world.level.chunk.IChunkProvider; +import net.minecraft.world.level.dimension.DimensionManager; +import net.minecraft.world.level.entity.EntityTypeTest; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.levelgen.HeightMap; +import net.minecraft.world.level.lighting.LevelLightEngine; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidType; +import net.minecraft.world.level.storage.WorldData; +import net.minecraft.world.phys.AxisAlignedBB; +import net.minecraft.world.phys.MovingObjectPositionBlock; +import net.minecraft.world.phys.Vec3D; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.VoxelShapeCollision; +import net.minecraft.world.ticks.LevelTickAccess; +import net.minecraft.world.ticks.NextTickListEntry; +import net.minecraft.world.ticks.TickListPriority; +import org.bukkit.event.entity.CreatureSpawnEvent; + +public abstract class DelegatedGeneratorAccess implements GeneratorAccessSeed { + + private GeneratorAccessSeed handle; + + public void setHandle(GeneratorAccessSeed worldAccess) { + this.handle = worldAccess; + } + + public GeneratorAccessSeed getHandle() { + return handle; + } + + @Override + public long getSeed() { + return handle.getSeed(); + } + + @Override + public void setCurrentlyGenerating(Supplier arg0) { + handle.setCurrentlyGenerating(arg0); + } + + @Override + public boolean ensureCanWrite(BlockPosition arg0) { + return handle.ensureCanWrite(arg0); + } + + @Override + public WorldServer getLevel() { + return handle.getLevel(); + } + + @Override + public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) { + handle.addFreshEntityWithPassengers(arg0, arg1); + } + + @Override + public void addFreshEntityWithPassengers(Entity arg0) { + handle.addFreshEntityWithPassengers(arg0); + } + + @Override + public WorldServer getMinecraftWorld() { + return handle.getMinecraftWorld(); + } + + @Override + public DifficultyDamageScaler getCurrentDifficultyAt(BlockPosition arg0) { + return handle.getCurrentDifficultyAt(arg0); + } + + @Override + public void neighborShapeChanged(EnumDirection arg0, IBlockData arg1, BlockPosition arg2, BlockPosition arg3, int arg4, int arg5) { + handle.neighborShapeChanged(arg0, arg1, arg2, arg3, arg4, arg5); + } + + @Override + public long dayTime() { + return handle.dayTime(); + } + + @Override + public WorldData getLevelData() { + return handle.getLevelData(); + } + + @Override + public boolean hasChunk(int arg0, int arg1) { + return handle.hasChunk(arg0, arg1); + } + + @Override + public IChunkProvider getChunkSource() { + return handle.getChunkSource(); + } + + @Override + public void scheduleTick(BlockPosition arg0, Block arg1, int arg2, TickListPriority arg3) { + handle.scheduleTick(arg0, arg1, arg2, arg3); + } + + @Override + public void scheduleTick(BlockPosition arg0, Block arg1, int arg2) { + handle.scheduleTick(arg0, arg1, arg2); + } + + @Override + public void scheduleTick(BlockPosition arg0, FluidType arg1, int arg2, TickListPriority arg3) { + handle.scheduleTick(arg0, arg1, arg2, arg3); + } + + @Override + public void scheduleTick(BlockPosition arg0, FluidType arg1, int arg2) { + handle.scheduleTick(arg0, arg1, arg2); + } + + @Override + public EnumDifficulty getDifficulty() { + return handle.getDifficulty(); + } + + @Override + public void blockUpdated(BlockPosition arg0, Block arg1) { + handle.blockUpdated(arg0, arg1); + } + + @Override + public MinecraftServer getServer() { + return handle.getServer(); + } + + @Override + public RandomSource getRandom() { + return handle.getRandom(); + } + + @Override + public LevelTickAccess getBlockTicks() { + return handle.getBlockTicks(); + } + + @Override + public long nextSubTickCount() { + return handle.nextSubTickCount(); + } + + @Override + public NextTickListEntry createTick(BlockPosition arg0, T arg1, int arg2) { + return handle.createTick(arg0, arg1, arg2); + } + + @Override + public NextTickListEntry createTick(BlockPosition arg0, T arg1, int arg2, TickListPriority arg3) { + return handle.createTick(arg0, arg1, arg2, arg3); + } + + @Override + public LevelTickAccess getFluidTicks() { + return handle.getFluidTicks(); + } + + @Override + public void playSound(EntityHuman arg0, BlockPosition arg1, SoundEffect arg2, SoundCategory arg3) { + handle.playSound(arg0, arg1, arg2, arg3); + } + + @Override + public void playSound(EntityHuman arg0, BlockPosition arg1, SoundEffect arg2, SoundCategory arg3, float arg4, float arg5) { + handle.playSound(arg0, arg1, arg2, arg3, arg4, arg5); + } + + @Override + public void levelEvent(int arg0, BlockPosition arg1, int arg2) { + handle.levelEvent(arg0, arg1, arg2); + } + + @Override + public void levelEvent(EntityHuman arg0, int arg1, BlockPosition arg2, int arg3) { + handle.levelEvent(arg0, arg1, arg2, arg3); + } + + @Override + public void addParticle(ParticleParam arg0, double arg1, double arg2, double arg3, double arg4, double arg5, double arg6) { + handle.addParticle(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + } + + @Override + public void gameEvent(GameEvent arg0, Vec3D arg1, GameEvent.a arg2) { + handle.gameEvent(arg0, arg1, arg2); + } + + @Override + public void gameEvent(GameEvent arg0, BlockPosition arg1, GameEvent.a arg2) { + handle.gameEvent(arg0, arg1, arg2); + } + + @Override + public void gameEvent(Entity arg0, GameEvent arg1, BlockPosition arg2) { + handle.gameEvent(arg0, arg1, arg2); + } + + @Override + public void gameEvent(Entity arg0, GameEvent arg1, Vec3D arg2) { + handle.gameEvent(arg0, arg1, arg2); + } + + @Override + public List getEntityCollisions(Entity arg0, AxisAlignedBB arg1) { + return handle.getEntityCollisions(arg0, arg1); + } + + @Override + public Optional getBlockEntity(BlockPosition arg0, TileEntityTypes arg1) { + return handle.getBlockEntity(arg0, arg1); + } + + @Override + public BlockPosition getHeightmapPos(HeightMap.Type arg0, BlockPosition arg1) { + return handle.getHeightmapPos(arg0, arg1); + } + + @Override + public boolean isUnobstructed(Entity arg0, VoxelShape arg1) { + return handle.isUnobstructed(arg0, arg1); + } + + @Override + public boolean hasNearbyAlivePlayer(double arg0, double arg1, double arg2, double arg3) { + return handle.hasNearbyAlivePlayer(arg0, arg1, arg2, arg3); + } + + @Override + public List players() { + return handle.players(); + } + + @Override + public List getEntities(Entity arg0, AxisAlignedBB arg1, Predicate arg2) { + return handle.getEntities(arg0, arg1, arg2); + } + + @Override + public List getEntities(EntityTypeTest arg0, AxisAlignedBB arg1, Predicate arg2) { + return handle.getEntities(arg0, arg1, arg2); + } + + @Override + public List getEntities(Entity arg0, AxisAlignedBB arg1) { + return handle.getEntities(arg0, arg1); + } + + @Override + public List getEntitiesOfClass(Class arg0, AxisAlignedBB arg1) { + return handle.getEntitiesOfClass(arg0, arg1); + } + + @Override + public List getEntitiesOfClass(Class arg0, AxisAlignedBB arg1, Predicate arg2) { + return handle.getEntitiesOfClass(arg0, arg1, arg2); + } + + @Override + public EntityHuman getNearestPlayer(PathfinderTargetCondition arg0, EntityLiving arg1, double arg2, double arg3, double arg4) { + return handle.getNearestPlayer(arg0, arg1, arg2, arg3, arg4); + } + + @Override + public EntityHuman getNearestPlayer(PathfinderTargetCondition arg0, double arg1, double arg2, double arg3) { + return handle.getNearestPlayer(arg0, arg1, arg2, arg3); + } + + @Override + public EntityHuman getNearestPlayer(Entity arg0, double arg1) { + return handle.getNearestPlayer(arg0, arg1); + } + + @Override + public EntityHuman getNearestPlayer(double arg0, double arg1, double arg2, double arg3, Predicate arg4) { + return handle.getNearestPlayer(arg0, arg1, arg2, arg3, arg4); + } + + @Override + public EntityHuman getNearestPlayer(double arg0, double arg1, double arg2, double arg3, boolean arg4) { + return handle.getNearestPlayer(arg0, arg1, arg2, arg3, arg4); + } + + @Override + public EntityHuman getNearestPlayer(PathfinderTargetCondition arg0, EntityLiving arg1) { + return handle.getNearestPlayer(arg0, arg1); + } + + @Override + public T getNearestEntity(Class arg0, PathfinderTargetCondition arg1, EntityLiving arg2, double arg3, double arg4, double arg5, AxisAlignedBB arg6) { + return handle.getNearestEntity(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + } + + @Override + public T getNearestEntity(List arg0, PathfinderTargetCondition arg1, EntityLiving arg2, double arg3, double arg4, double arg5) { + return handle.getNearestEntity(arg0, arg1, arg2, arg3, arg4, arg5); + } + + @Override + public EntityHuman getPlayerByUUID(UUID arg0) { + return handle.getPlayerByUUID(arg0); + } + + @Override + public List getNearbyPlayers(PathfinderTargetCondition arg0, EntityLiving arg1, AxisAlignedBB arg2) { + return handle.getNearbyPlayers(arg0, arg1, arg2); + } + + @Override + public List getNearbyEntities(Class arg0, PathfinderTargetCondition arg1, EntityLiving arg2, AxisAlignedBB arg3) { + return handle.getNearbyEntities(arg0, arg1, arg2, arg3); + } + + @Override + @Deprecated + public float getLightLevelDependentMagicValue(BlockPosition arg0) { + return handle.getLightLevelDependentMagicValue(arg0); + } + + @Override + public IBlockAccess getChunkForCollisions(int arg0, int arg1) { + return handle.getChunkForCollisions(arg0, arg1); + } + + @Override + public int getMaxLocalRawBrightness(BlockPosition arg0) { + return handle.getMaxLocalRawBrightness(arg0); + } + + @Override + public int getMaxLocalRawBrightness(BlockPosition arg0, int arg1) { + return handle.getMaxLocalRawBrightness(arg0, arg1); + } + + @Override + public boolean canSeeSkyFromBelowWater(BlockPosition arg0) { + return handle.canSeeSkyFromBelowWater(arg0); + } + + @Override + public float getPathfindingCostFromLightLevels(BlockPosition arg0) { + return handle.getPathfindingCostFromLightLevels(arg0); + } + + @Override + public Stream getBlockStatesIfLoaded(AxisAlignedBB arg0) { + return handle.getBlockStatesIfLoaded(arg0); + } + + @Override + public Holder getUncachedNoiseBiome(int arg0, int arg1, int arg2) { + return handle.getUncachedNoiseBiome(arg0, arg1, arg2); + } + + @Override + @Deprecated + public int getSeaLevel() { + return handle.getSeaLevel(); + } + + @Override + public boolean containsAnyLiquid(AxisAlignedBB arg0) { + return handle.containsAnyLiquid(arg0); + } + + @Override + public int getMinBuildHeight() { + return handle.getMinBuildHeight(); + } + + @Override + public boolean isWaterAt(BlockPosition arg0) { + return handle.isWaterAt(arg0); + } + + @Override + public boolean isEmptyBlock(BlockPosition arg0) { + return handle.isEmptyBlock(arg0); + } + + @Override + public boolean isClientSide() { + return handle.isClientSide(); + } + + @Override + public DimensionManager dimensionType() { + return handle.dimensionType(); + } + + @Override + public FeatureFlagSet enabledFeatures() { + return handle.enabledFeatures(); + } + + @Override + @Deprecated + public boolean hasChunkAt(int arg0, int arg1) { + return handle.hasChunkAt(arg0, arg1); + } + + @Override + @Deprecated + public boolean hasChunkAt(BlockPosition arg0) { + return handle.hasChunkAt(arg0); + } + + @Override + public HolderLookup holderLookup(ResourceKey> arg0) { + return handle.holderLookup(arg0); + } + + @Override + public IRegistryCustom registryAccess() { + return handle.registryAccess(); + } + + @Override + public Holder getNoiseBiome(int arg0, int arg1, int arg2) { + return handle.getNoiseBiome(arg0, arg1, arg2); + } + + @Override + public int getBlockTint(BlockPosition arg0, ColorResolver arg1) { + return handle.getBlockTint(arg0, arg1); + } + + @Override + @Deprecated + public boolean hasChunksAt(BlockPosition arg0, BlockPosition arg1) { + return handle.hasChunksAt(arg0, arg1); + } + + @Override + @Deprecated + public boolean hasChunksAt(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5) { + return handle.hasChunksAt(arg0, arg1, arg2, arg3, arg4, arg5); + } + + @Override + @Deprecated + public boolean hasChunksAt(int arg0, int arg1, int arg2, int arg3) { + return handle.hasChunksAt(arg0, arg1, arg2, arg3); + } + + @Override + public IChunkAccess getChunk(int arg0, int arg1, ChunkStatus arg2, boolean arg3) { + return handle.getChunk(arg0, arg1, arg2, arg3); + } + + @Override + public IChunkAccess getChunk(int arg0, int arg1, ChunkStatus arg2) { + return handle.getChunk(arg0, arg1, arg2); + } + + @Override + public IChunkAccess getChunk(BlockPosition arg0) { + return handle.getChunk(arg0); + } + + @Override + public IChunkAccess getChunk(int arg0, int arg1) { + return handle.getChunk(arg0, arg1); + } + + @Override + public int getHeight(HeightMap.Type arg0, int arg1, int arg2) { + return handle.getHeight(arg0, arg1, arg2); + } + + @Override + public int getHeight() { + return handle.getHeight(); + } + + @Override + public Holder getBiome(BlockPosition arg0) { + return handle.getBiome(arg0); + } + + @Override + public int getSkyDarken() { + return handle.getSkyDarken(); + } + + @Override + public BiomeManager getBiomeManager() { + return handle.getBiomeManager(); + } + + @Override + public boolean canSeeSky(BlockPosition arg0) { + return handle.canSeeSky(arg0); + } + + @Override + public int getRawBrightness(BlockPosition arg0, int arg1) { + return handle.getRawBrightness(arg0, arg1); + } + + @Override + public LevelLightEngine getLightEngine() { + return handle.getLightEngine(); + } + + @Override + public int getBrightness(EnumSkyBlock arg0, BlockPosition arg1) { + return handle.getBrightness(arg0, arg1); + } + + @Override + public float getShade(EnumDirection arg0, boolean arg1) { + return handle.getShade(arg0, arg1); + } + + @Override + public TileEntity getBlockEntity(BlockPosition arg0) { + return handle.getBlockEntity(arg0); + } + + @Override + public double getBlockFloorHeight(VoxelShape arg0, Supplier arg1) { + return handle.getBlockFloorHeight(arg0, arg1); + } + + @Override + public double getBlockFloorHeight(BlockPosition arg0) { + return handle.getBlockFloorHeight(arg0); + } + + @Override + public MovingObjectPositionBlock clipWithInteractionOverride(Vec3D arg0, Vec3D arg1, BlockPosition arg2, VoxelShape arg3, IBlockData arg4) { + return handle.clipWithInteractionOverride(arg0, arg1, arg2, arg3, arg4); + } + + @Override + public IBlockData getBlockState(BlockPosition arg0) { + return handle.getBlockState(arg0); + } + + @Override + public Fluid getFluidState(BlockPosition arg0) { + return handle.getFluidState(arg0); + } + + @Override + public int getLightEmission(BlockPosition arg0) { + return handle.getLightEmission(arg0); + } + + @Override + public MovingObjectPositionBlock clip(RayTrace arg0) { + return handle.clip(arg0); + } + + @Override + public MovingObjectPositionBlock clip(RayTrace arg0, BlockPosition arg1) { + return handle.clip(arg0, arg1); + } + + @Override + public int getMaxLightLevel() { + return handle.getMaxLightLevel(); + } + + @Override + public MovingObjectPositionBlock isBlockInLine(ClipBlockStateContext arg0) { + return handle.isBlockInLine(arg0); + } + + @Override + public Stream getBlockStates(AxisAlignedBB arg0) { + return handle.getBlockStates(arg0); + } + + @Override + public boolean isOutsideBuildHeight(int arg0) { + return handle.isOutsideBuildHeight(arg0); + } + + @Override + public boolean isOutsideBuildHeight(BlockPosition arg0) { + return handle.isOutsideBuildHeight(arg0); + } + + @Override + public int getSectionIndexFromSectionY(int arg0) { + return handle.getSectionIndexFromSectionY(arg0); + } + + @Override + public int getSectionYFromSectionIndex(int arg0) { + return handle.getSectionYFromSectionIndex(arg0); + } + + @Override + public int getMaxSection() { + return handle.getMaxSection(); + } + + @Override + public int getMinSection() { + return handle.getMinSection(); + } + + @Override + public int getSectionIndex(int arg0) { + return handle.getSectionIndex(arg0); + } + + @Override + public int getSectionsCount() { + return handle.getSectionsCount(); + } + + @Override + public int getMaxBuildHeight() { + return handle.getMaxBuildHeight(); + } + + @Override + public boolean isUnobstructed(IBlockData arg0, BlockPosition arg1, VoxelShapeCollision arg2) { + return handle.isUnobstructed(arg0, arg1, arg2); + } + + @Override + public boolean isUnobstructed(Entity arg0) { + return handle.isUnobstructed(arg0); + } + + @Override + public WorldBorder getWorldBorder() { + return handle.getWorldBorder(); + } + + @Override + public Optional findFreePosition(Entity arg0, VoxelShape arg1, Vec3D arg2, double arg3, double arg4, double arg5) { + return handle.findFreePosition(arg0, arg1, arg2, arg3, arg4, arg5); + } + + @Override + public Iterable getCollisions(Entity arg0, AxisAlignedBB arg1) { + return handle.getCollisions(arg0, arg1); + } + + @Override + public Iterable getBlockCollisions(Entity arg0, AxisAlignedBB arg1) { + return handle.getBlockCollisions(arg0, arg1); + } + + @Override + public boolean noCollision(AxisAlignedBB arg0) { + return handle.noCollision(arg0); + } + + @Override + public boolean noCollision(Entity arg0) { + return handle.noCollision(arg0); + } + + @Override + public boolean noCollision(Entity arg0, AxisAlignedBB arg1) { + return handle.noCollision(arg0, arg1); + } + + @Override + public boolean collidesWithSuffocatingBlock(Entity arg0, AxisAlignedBB arg1) { + return handle.collidesWithSuffocatingBlock(arg0, arg1); + } + + @Override + public Optional findSupportingBlock(Entity arg0, AxisAlignedBB arg1) { + return handle.findSupportingBlock(arg0, arg1); + } + + @Override + public int getBestNeighborSignal(BlockPosition arg0) { + return handle.getBestNeighborSignal(arg0); + } + + @Override + public int getControlInputSignal(BlockPosition arg0, EnumDirection arg1, boolean arg2) { + return handle.getControlInputSignal(arg0, arg1, arg2); + } + + @Override + public int getDirectSignal(BlockPosition arg0, EnumDirection arg1) { + return handle.getDirectSignal(arg0, arg1); + } + + @Override + public int getDirectSignalTo(BlockPosition arg0) { + return handle.getDirectSignalTo(arg0); + } + + @Override + public boolean hasNeighborSignal(BlockPosition arg0) { + return handle.hasNeighborSignal(arg0); + } + + @Override + public boolean hasSignal(BlockPosition arg0, EnumDirection arg1) { + return handle.hasSignal(arg0, arg1); + } + + @Override + public int getSignal(BlockPosition arg0, EnumDirection arg1) { + return handle.getSignal(arg0, arg1); + } + + @Override + public boolean isStateAtPosition(BlockPosition arg0, Predicate arg1) { + return handle.isStateAtPosition(arg0, arg1); + } + + @Override + public boolean isFluidAtPosition(BlockPosition arg0, Predicate arg1) { + return handle.isFluidAtPosition(arg0, arg1); + } + + @Override + public boolean addFreshEntity(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) { + return handle.addFreshEntity(arg0, arg1); + } + + @Override + public boolean addFreshEntity(Entity arg0) { + return handle.addFreshEntity(arg0); + } + + @Override + public boolean removeBlock(BlockPosition arg0, boolean arg1) { + return handle.removeBlock(arg0, arg1); + } + + @Override + public boolean destroyBlock(BlockPosition arg0, boolean arg1, Entity arg2, int arg3) { + return handle.destroyBlock(arg0, arg1, arg2, arg3); + } + + @Override + public boolean destroyBlock(BlockPosition arg0, boolean arg1, Entity arg2) { + return handle.destroyBlock(arg0, arg1, arg2); + } + + @Override + public boolean destroyBlock(BlockPosition arg0, boolean arg1) { + return handle.destroyBlock(arg0, arg1); + } + + @Override + public boolean setBlock(BlockPosition arg0, IBlockData arg1, int arg2) { + return handle.setBlock(arg0, arg1, arg2); + } + + @Override + public boolean setBlock(BlockPosition arg0, IBlockData arg1, int arg2, int arg3) { + return handle.setBlock(arg0, arg1, arg2, arg3); + } + + @Override + public float getTimeOfDay(float arg0) { + return handle.getTimeOfDay(arg0); + } + + @Override + public float getMoonBrightness() { + return handle.getMoonBrightness(); + } + + @Override + public int getMoonPhase() { + return handle.getMoonPhase(); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java new file mode 100644 index 0000000000..05d792ee69 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java @@ -0,0 +1,96 @@ +package org.bukkit.craftbukkit.util; + +import net.minecraft.core.BlockPosition; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.entity.TileEntity; +import net.minecraft.world.level.block.state.IBlockData; +import net.minecraft.world.level.levelgen.structure.StructurePiece; +import net.minecraft.world.level.material.Fluid; +import org.bukkit.craftbukkit.block.CraftBlockEntityState; +import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.block.CraftBlockStates; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; + +public class TransformerGeneratorAccess extends DelegatedGeneratorAccess { + + private CraftStructureTransformer structureTransformer; + + public void setStructureTransformer(CraftStructureTransformer structureTransformer) { + this.structureTransformer = structureTransformer; + } + + public CraftStructureTransformer getStructureTransformer() { + return structureTransformer; + } + + @Override + public boolean addFreshEntity(Entity arg0) { + if (structureTransformer != null && !structureTransformer.transformEntity(arg0)) { + return false; + } + return super.addFreshEntity(arg0); + } + + @Override + public boolean addFreshEntity(Entity arg0, SpawnReason arg1) { + if (structureTransformer != null && !structureTransformer.transformEntity(arg0)) { + return false; + } + return super.addFreshEntity(arg0, arg1); + } + + @Override + public void addFreshEntityWithPassengers(Entity arg0) { + if (structureTransformer != null && !structureTransformer.transformEntity(arg0)) { + return; + } + super.addFreshEntityWithPassengers(arg0); + } + + @Override + public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) { + if (structureTransformer != null && !structureTransformer.transformEntity(arg0)) { + return; + } + super.addFreshEntityWithPassengers(arg0, arg1); + } + + public boolean setCraftBlock(BlockPosition position, CraftBlockState craftBlockState, int i, int j) { + if (structureTransformer != null) { + craftBlockState = structureTransformer.transformCraftState(craftBlockState); + } + // This code is based on the method 'net.minecraft.world.level.levelgen.structure.StructurePiece#placeBlock' + // It ensures that any kind of block is updated correctly upon placing it + IBlockData iblockdata = craftBlockState.getHandle(); + boolean result = super.setBlock(position, iblockdata, i, j); + Fluid fluid = getFluidState(position); + if (!fluid.isEmpty()) { + scheduleTick(position, fluid.getType(), 0); + } + if (StructurePiece.SHAPE_CHECK_BLOCKS.contains(iblockdata.getBlock())) { + getChunk(position).markPosForPostprocessing(position); + } + TileEntity tileEntity = getBlockEntity(position); + if (tileEntity != null && craftBlockState instanceof CraftBlockEntityState craftEntityState) { + tileEntity.load(craftEntityState.getSnapshotNBT()); + } + return result; + } + + public boolean setCraftBlock(BlockPosition position, CraftBlockState craftBlockState, int i) { + return setCraftBlock(position, craftBlockState, i, 512); + } + + @Override + public boolean setBlock(BlockPosition position, IBlockData iblockdata, int i, int j) { + if (structureTransformer == null || !structureTransformer.canTransformBlocks()) { + return super.setBlock(position, iblockdata, i, j); + } + return setCraftBlock(position, (CraftBlockState) CraftBlockStates.getBlockState(position, iblockdata, null), i, j); + } + + @Override + public boolean setBlock(BlockPosition position, IBlockData iblockdata, int i) { + return setBlock(position, iblockdata, i, 512); + } +}