--- a/net/minecraft/world/level/levelgen/structure/StructurePiece.java
+++ b/net/minecraft/world/level/levelgen/structure/StructurePiece.java
@@ -47,7 +_,7 @@
     private Rotation rotation;
     protected int genDepth;
     private final StructurePieceType type;
-    private static final Set<Block> SHAPE_CHECK_BLOCKS = ImmutableSet.<Block>builder()
+    public static final Set<Block> SHAPE_CHECK_BLOCKS = ImmutableSet.<Block>builder() // PAIL private -> public
         .add(Blocks.NETHER_BRICK_FENCE)
         .add(Blocks.TORCH)
         .add(Blocks.WALL_TORCH)
@@ -189,6 +_,11 @@
                 }
 
                 level.setBlock(worldPos, blockstate, 2);
+                // CraftBukkit start - fluid handling is already done if we have a transformer generator access
+                if (level instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess) {
+                    return;
+                }
+                // CraftBukkit end
                 FluidState fluidState = level.getFluidState(worldPos);
                 if (!fluidState.isEmpty()) {
                     level.scheduleTick(worldPos, fluidState.getType(), 0);
@@ -201,6 +_,38 @@
         }
     }
 
+    // CraftBukkit start
+    protected boolean placeCraftBlockEntity(ServerLevelAccessor levelAccessor, BlockPos pos, org.bukkit.craftbukkit.block.CraftBlockEntityState<?> craftBlockEntityState, int flags) {
+        if (levelAccessor instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+            return transformerAccess.setCraftBlock(pos, craftBlockEntityState, flags);
+        }
+        boolean result = levelAccessor.setBlock(pos, craftBlockEntityState.getHandle(), flags);
+        BlockEntity blockEntity = levelAccessor.getBlockEntity(pos);
+        if (blockEntity != null) {
+            blockEntity.loadWithComponents(craftBlockEntityState.getSnapshotNBT(), levelAccessor.registryAccess());
+        }
+        return result;
+    }
+
+    protected void placeCraftSpawner(ServerLevelAccessor levelAccessor, BlockPos pos, org.bukkit.entity.EntityType entityType, int flags) {
+        // 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(levelAccessor, pos, Blocks.SPAWNER.defaultBlockState(), null);
+        spawner.setSpawnedType(entityType);
+        this.placeCraftBlockEntity(levelAccessor, pos, spawner, flags);
+    }
+
+    protected void setCraftLootTable(ServerLevelAccessor levelAccessor, BlockPos pos, RandomSource randomSource, ResourceKey<LootTable> lootTable) {
+        // 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.BlockEntity blockEntity = levelAccessor.getBlockEntity(pos);
+        if (blockEntity instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity lootContainerBlockEntity) {
+            lootContainerBlockEntity.setLootTable(lootTable, randomSource.nextLong());
+            if (levelAccessor instanceof org.bukkit.craftbukkit.util.TransformerGeneratorAccess transformerAccess) {
+                transformerAccess.setCraftBlock(pos, (org.bukkit.craftbukkit.block.CraftBlockState) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(levelAccessor, pos, blockEntity.getBlockState(), lootContainerBlockEntity.saveWithFullMetadata(levelAccessor.registryAccess())), 3);
+            }
+        }
+    }
+    // CraftBukkit end
+
     protected boolean canBeReplaced(LevelReader level, int x, int y, int z, BoundingBox box) {
         return true;
     }
@@ -429,11 +_,17 @@
                 state = reorient(level, pos, Blocks.CHEST.defaultBlockState());
             }
 
-            level.setBlock(pos, state, 2);
-            BlockEntity blockEntity = level.getBlockEntity(pos);
-            if (blockEntity instanceof ChestBlockEntity) {
-                ((ChestBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong());
-            }
+            // CraftBukkit start
+            // level.setBlock(pos, state, 2);
+            // BlockEntity blockEntity = level.getBlockEntity(pos);
+            // if (blockEntity instanceof ChestBlockEntity) {
+            //     ((ChestBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong());
+            // }
+            org.bukkit.craftbukkit.block.CraftChest chestState = (org.bukkit.craftbukkit.block.CraftChest) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(level, pos, state, null);
+            chestState.setLootTable(org.bukkit.craftbukkit.CraftLootTable.minecraftToBukkit(lootTable));
+            chestState.setSeed(random.nextLong());
+            this.placeCraftBlockEntity(level, pos, chestState, 2);
+            // CraftBukkit end
 
             return true;
         } else {
@@ -446,11 +_,28 @@
     ) {
         BlockPos worldPos = this.getWorldPos(x, y, z);
         if (box.isInside(worldPos) && !level.getBlockState(worldPos).is(Blocks.DISPENSER)) {
-            this.placeBlock(level, Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing), x, y, z, box);
-            BlockEntity blockEntity = level.getBlockEntity(worldPos);
-            if (blockEntity instanceof DispenserBlockEntity) {
-                ((DispenserBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong());
-            }
+            // CraftBukkit start
+            // this.placeBlock(level, Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing), x, y, z, box);
+            // BlockEntity blockEntity = level.getBlockEntity(worldPos);
+            // if (blockEntity instanceof DispenserBlockEntity) {
+            //     ((DispenserBlockEntity)blockEntity).setLootTable(lootTable, random.nextLong());
+            // }
+            if (!this.canBeReplaced(level, x, y, z, this.boundingBox)) {
+                return true;
+            }
+            BlockState dispenserBlockState = Blocks.DISPENSER.defaultBlockState().setValue(DispenserBlock.FACING, facing);
+            if (this.mirror != Mirror.NONE) {
+                dispenserBlockState = dispenserBlockState.mirror(this.mirror);
+            }
+            if (this.rotation != Rotation.NONE) {
+                dispenserBlockState = dispenserBlockState.rotate(this.rotation);
+            }
+
+            org.bukkit.craftbukkit.block.CraftDispenser dispenserState = (org.bukkit.craftbukkit.block.CraftDispenser) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(level, worldPos, dispenserBlockState, null);
+            dispenserState.setLootTable(org.bukkit.craftbukkit.CraftLootTable.minecraftToBukkit(lootTable));
+            dispenserState.setSeed(random.nextLong());
+            this.placeCraftBlockEntity(level, worldPos, dispenserState, 2);
+            // CraftBukkit end
 
             return true;
         } else {
