--- a/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java
+++ b/net/minecraft/world/level/levelgen/structure/structures/OceanRuinPieces.java
@@ -1,6 +1,7 @@
 package net.minecraft.world.level.levelgen.structure.structures;
 
 import com.google.common.collect.Lists;
+import java.util.Iterator;
 import java.util.List;
 import net.minecraft.Util;
 import net.minecraft.core.BlockPos;
@@ -25,8 +26,6 @@
 import net.minecraft.world.level.block.ChestBlock;
 import net.minecraft.world.level.block.Mirror;
 import net.minecraft.world.level.block.Rotation;
-import net.minecraft.world.level.block.entity.BlockEntity;
-import net.minecraft.world.level.block.entity.ChestBlockEntity;
 import net.minecraft.world.level.block.state.BlockState;
 import net.minecraft.world.level.chunk.ChunkGenerator;
 import net.minecraft.world.level.levelgen.Heightmap;
@@ -52,8 +51,9 @@
 import net.minecraft.world.level.storage.loot.BuiltInLootTables;
 
 public class OceanRuinPieces {
-    static final StructureProcessor WARM_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor(Blocks.SAND, Blocks.SUSPICIOUS_SAND, BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY);
-    static final StructureProcessor COLD_SUSPICIOUS_BLOCK_PROCESSOR = archyRuleProcessor(Blocks.GRAVEL, Blocks.SUSPICIOUS_GRAVEL, BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY);
+
+    static final StructureProcessor WARM_SUSPICIOUS_BLOCK_PROCESSOR = OceanRuinPieces.archyRuleProcessor(Blocks.SAND, Blocks.SUSPICIOUS_SAND, BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY);
+    static final StructureProcessor COLD_SUSPICIOUS_BLOCK_PROCESSOR = OceanRuinPieces.archyRuleProcessor(Blocks.GRAVEL, Blocks.SUSPICIOUS_GRAVEL, BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY);
     private static final ResourceLocation[] WARM_RUINS = new ResourceLocation[]{new ResourceLocation("underwater_ruin/warm_1"), new ResourceLocation("underwater_ruin/warm_2"), new ResourceLocation("underwater_ruin/warm_3"), new ResourceLocation("underwater_ruin/warm_4"), new ResourceLocation("underwater_ruin/warm_5"), new ResourceLocation("underwater_ruin/warm_6"), new ResourceLocation("underwater_ruin/warm_7"), new ResourceLocation("underwater_ruin/warm_8")};
     private static final ResourceLocation[] RUINS_BRICK = new ResourceLocation[]{new ResourceLocation("underwater_ruin/brick_1"), new ResourceLocation("underwater_ruin/brick_2"), new ResourceLocation("underwater_ruin/brick_3"), new ResourceLocation("underwater_ruin/brick_4"), new ResourceLocation("underwater_ruin/brick_5"), new ResourceLocation("underwater_ruin/brick_6"), new ResourceLocation("underwater_ruin/brick_7"), new ResourceLocation("underwater_ruin/brick_8")};
     private static final ResourceLocation[] RUINS_CRACKED = new ResourceLocation[]{new ResourceLocation("underwater_ruin/cracked_1"), new ResourceLocation("underwater_ruin/cracked_2"), new ResourceLocation("underwater_ruin/cracked_3"), new ResourceLocation("underwater_ruin/cracked_4"), new ResourceLocation("underwater_ruin/cracked_5"), new ResourceLocation("underwater_ruin/cracked_6"), new ResourceLocation("underwater_ruin/cracked_7"), new ResourceLocation("underwater_ruin/cracked_8")};
@@ -63,45 +63,49 @@
     private static final ResourceLocation[] BIG_RUINS_CRACKED = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_cracked_1"), new ResourceLocation("underwater_ruin/big_cracked_2"), new ResourceLocation("underwater_ruin/big_cracked_3"), new ResourceLocation("underwater_ruin/big_cracked_8")};
     private static final ResourceLocation[] BIG_WARM_RUINS = new ResourceLocation[]{new ResourceLocation("underwater_ruin/big_warm_4"), new ResourceLocation("underwater_ruin/big_warm_5"), new ResourceLocation("underwater_ruin/big_warm_6"), new ResourceLocation("underwater_ruin/big_warm_7")};
 
+    public OceanRuinPieces() {}
+
     private static StructureProcessor archyRuleProcessor(Block baseBlock, Block suspiciousBlock, ResourceLocation lootTableId) {
         return new CappedProcessor(new RuleProcessor(List.of(new ProcessorRule(new BlockMatchTest(baseBlock), AlwaysTrueTest.INSTANCE, PosAlwaysTrueTest.INSTANCE, suspiciousBlock.defaultBlockState(), new AppendLoot(lootTableId)))), ConstantInt.of(5));
     }
 
     private static ResourceLocation getSmallWarmRuin(RandomSource random) {
-        return Util.getRandom(WARM_RUINS, random);
+        return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.WARM_RUINS, random);
     }
 
     private static ResourceLocation getBigWarmRuin(RandomSource random) {
-        return Util.getRandom(BIG_WARM_RUINS, random);
+        return (ResourceLocation) Util.getRandom((Object[]) OceanRuinPieces.BIG_WARM_RUINS, random);
     }
 
     public static void addPieces(StructureTemplateManager manager, BlockPos pos, Rotation rotation, StructurePieceAccessor holder, RandomSource random, OceanRuinStructure structure) {
-        boolean bl = random.nextFloat() <= structure.largeProbability;
-        float f = bl ? 0.9F : 0.8F;
-        addPiece(manager, pos, rotation, holder, random, structure, bl, f);
-        if (bl && random.nextFloat() <= structure.clusterProbability) {
-            addClusterRuins(manager, random, rotation, pos, structure, holder);
+        boolean flag = random.nextFloat() <= structure.largeProbability;
+        float f = flag ? 0.9F : 0.8F;
+
+        OceanRuinPieces.addPiece(manager, pos, rotation, holder, random, structure, flag, f);
+        if (flag && random.nextFloat() <= structure.clusterProbability) {
+            OceanRuinPieces.addClusterRuins(manager, random, rotation, pos, structure, holder);
         }
 
     }
 
     private static void addClusterRuins(StructureTemplateManager manager, RandomSource random, Rotation rotation, BlockPos pos, OceanRuinStructure structure, StructurePieceAccessor pieces) {
-        BlockPos blockPos = new BlockPos(pos.getX(), 90, pos.getZ());
-        BlockPos blockPos2 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockPos);
-        BoundingBox boundingBox = BoundingBox.fromCorners(blockPos, blockPos2);
-        BlockPos blockPos3 = new BlockPos(Math.min(blockPos.getX(), blockPos2.getX()), blockPos.getY(), Math.min(blockPos.getZ(), blockPos2.getZ()));
-        List<BlockPos> list = allPositions(random, blockPos3);
+        BlockPos blockposition1 = new BlockPos(pos.getX(), 90, pos.getZ());
+        BlockPos blockposition2 = StructureTemplate.transform(new BlockPos(15, 0, 15), Mirror.NONE, rotation, BlockPos.ZERO).offset(blockposition1);
+        BoundingBox structureboundingbox = BoundingBox.fromCorners(blockposition1, blockposition2);
+        BlockPos blockposition3 = new BlockPos(Math.min(blockposition1.getX(), blockposition2.getX()), blockposition1.getY(), Math.min(blockposition1.getZ(), blockposition2.getZ()));
+        List<BlockPos> list = OceanRuinPieces.allPositions(random, blockposition3);
         int i = Mth.nextInt(random, 4, 8);
 
-        for(int j = 0; j < i; ++j) {
+        for (int j = 0; j < i; ++j) {
             if (!list.isEmpty()) {
                 int k = random.nextInt(list.size());
-                BlockPos blockPos4 = list.remove(k);
-                Rotation rotation2 = Rotation.getRandom(random);
-                BlockPos blockPos5 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, rotation2, BlockPos.ZERO).offset(blockPos4);
-                BoundingBox boundingBox2 = BoundingBox.fromCorners(blockPos4, blockPos5);
-                if (!boundingBox2.intersects(boundingBox)) {
-                    addPiece(manager, blockPos4, rotation2, pieces, random, structure, false, 0.8F);
+                BlockPos blockposition4 = (BlockPos) list.remove(k);
+                Rotation enumblockrotation1 = Rotation.getRandom(random);
+                BlockPos blockposition5 = StructureTemplate.transform(new BlockPos(5, 0, 6), Mirror.NONE, enumblockrotation1, BlockPos.ZERO).offset(blockposition4);
+                BoundingBox structureboundingbox1 = BoundingBox.fromCorners(blockposition4, blockposition5);
+
+                if (!structureboundingbox1.intersects(structureboundingbox)) {
+                    OceanRuinPieces.addPiece(manager, blockposition4, enumblockrotation1, pieces, random, structure, false, 0.8F);
                 }
             }
         }
@@ -110,6 +114,7 @@
 
     private static List<BlockPos> allPositions(RandomSource random, BlockPos pos) {
         List<BlockPos> list = Lists.newArrayList();
+
         list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, 16 + Mth.nextInt(random, 1, 7)));
         list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, Mth.nextInt(random, 1, 7)));
         list.add(pos.offset(-16 + Mth.nextInt(random, 1, 8), 0, -16 + Mth.nextInt(random, 4, 8)));
@@ -125,36 +130,39 @@
         switch (structure.biomeTemp) {
             case WARM:
             default:
-                ResourceLocation resourceLocation = large ? getBigWarmRuin(random) : getSmallWarmRuin(random);
-                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, resourceLocation, pos, rotation, integrity, structure.biomeTemp, large));
+                ResourceLocation minecraftkey = large ? OceanRuinPieces.getBigWarmRuin(random) : OceanRuinPieces.getSmallWarmRuin(random);
+
+                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, minecraftkey, pos, rotation, integrity, structure.biomeTemp, large));
                 break;
             case COLD:
-                ResourceLocation[] resourceLocations = large ? BIG_RUINS_BRICK : RUINS_BRICK;
-                ResourceLocation[] resourceLocations2 = large ? BIG_RUINS_CRACKED : RUINS_CRACKED;
-                ResourceLocation[] resourceLocations3 = large ? BIG_RUINS_MOSSY : RUINS_MOSSY;
-                int i = random.nextInt(resourceLocations.length);
-                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, resourceLocations[i], pos, rotation, integrity, structure.biomeTemp, large));
-                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, resourceLocations2[i], pos, rotation, 0.7F, structure.biomeTemp, large));
-                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, resourceLocations3[i], pos, rotation, 0.5F, structure.biomeTemp, large));
+                ResourceLocation[] aminecraftkey = large ? OceanRuinPieces.BIG_RUINS_BRICK : OceanRuinPieces.RUINS_BRICK;
+                ResourceLocation[] aminecraftkey1 = large ? OceanRuinPieces.BIG_RUINS_CRACKED : OceanRuinPieces.RUINS_CRACKED;
+                ResourceLocation[] aminecraftkey2 = large ? OceanRuinPieces.BIG_RUINS_MOSSY : OceanRuinPieces.RUINS_MOSSY;
+                int i = random.nextInt(aminecraftkey.length);
+
+                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, aminecraftkey[i], pos, rotation, integrity, structure.biomeTemp, large));
+                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, aminecraftkey1[i], pos, rotation, 0.7F, structure.biomeTemp, large));
+                holder.addPiece(new OceanRuinPieces.OceanRuinPiece(manager, aminecraftkey2[i], pos, rotation, 0.5F, structure.biomeTemp, large));
         }
 
     }
 
     public static class OceanRuinPiece extends TemplateStructurePiece {
+
         private final OceanRuinStructure.Type biomeType;
         private final float integrity;
         private final boolean isLarge;
 
         public OceanRuinPiece(StructureTemplateManager structureTemplateManager, ResourceLocation template, BlockPos pos, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean large) {
-            super(StructurePieceType.OCEAN_RUIN, 0, structureTemplateManager, template, template.toString(), makeSettings(rotation, integrity, biomeType), pos);
+            super(StructurePieceType.OCEAN_RUIN, 0, structureTemplateManager, template, template.toString(), OceanRuinPiece.makeSettings(rotation, integrity, biomeType), pos);
             this.integrity = integrity;
             this.biomeType = biomeType;
             this.isLarge = large;
         }
 
         private OceanRuinPiece(StructureTemplateManager holder, CompoundTag nbt, Rotation rotation, float integrity, OceanRuinStructure.Type biomeType, boolean large) {
-            super(StructurePieceType.OCEAN_RUIN, nbt, holder, (resourceLocation) -> {
-                return makeSettings(rotation, integrity, biomeType);
+            super(StructurePieceType.OCEAN_RUIN, nbt, holder, (minecraftkey) -> {
+                return OceanRuinPiece.makeSettings(rotation, integrity, biomeType);
             });
             this.integrity = integrity;
             this.biomeType = biomeType;
@@ -162,16 +170,18 @@
         }
 
         private static StructurePlaceSettings makeSettings(Rotation rotation, float integrity, OceanRuinStructure.Type temperature) {
-            StructureProcessor structureProcessor = temperature == OceanRuinStructure.Type.COLD ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR;
-            return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).addProcessor(new BlockRotProcessor(integrity)).addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(structureProcessor);
+            StructureProcessor definedstructureprocessor = temperature == OceanRuinStructure.Type.COLD ? OceanRuinPieces.COLD_SUSPICIOUS_BLOCK_PROCESSOR : OceanRuinPieces.WARM_SUSPICIOUS_BLOCK_PROCESSOR;
+
+            return (new StructurePlaceSettings()).setRotation(rotation).setMirror(Mirror.NONE).addProcessor(new BlockRotProcessor(integrity)).addProcessor(BlockIgnoreProcessor.STRUCTURE_AND_AIR).addProcessor(definedstructureprocessor);
         }
 
         public static OceanRuinPieces.OceanRuinPiece create(StructureTemplateManager structureTemplateManager, CompoundTag nbt) {
-            Rotation rotation = Rotation.valueOf(nbt.getString("Rot"));
+            Rotation enumblockrotation = Rotation.valueOf(nbt.getString("Rot"));
             float f = nbt.getFloat("Integrity");
-            OceanRuinStructure.Type type = OceanRuinStructure.Type.valueOf(nbt.getString("BiomeType"));
-            boolean bl = nbt.getBoolean("IsLarge");
-            return new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, nbt, rotation, f, type, bl);
+            OceanRuinStructure.Type oceanruinstructure_a = OceanRuinStructure.Type.valueOf(nbt.getString("BiomeType"));
+            boolean flag = nbt.getBoolean("IsLarge");
+
+            return new OceanRuinPieces.OceanRuinPiece(structureTemplateManager, nbt, enumblockrotation, f, oceanruinstructure_a, flag);
         }
 
         @Override
@@ -186,18 +196,28 @@
         @Override
         protected void handleDataMarker(String metadata, BlockPos pos, ServerLevelAccessor world, RandomSource random, BoundingBox boundingBox) {
             if ("chest".equals(metadata)) {
-                world.setBlock(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, Boolean.valueOf(world.getFluidState(pos).is(FluidTags.WATER))), 2);
-                BlockEntity blockEntity = world.getBlockEntity(pos);
-                if (blockEntity instanceof ChestBlockEntity) {
-                    ((ChestBlockEntity)blockEntity).setLootTable(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL, random.nextLong());
+                // 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.v1_20_R2.block.CraftChest craftChest = (org.bukkit.craftbukkit.v1_20_R2.block.CraftChest) org.bukkit.craftbukkit.v1_20_R2.block.CraftBlockStates.getBlockState(pos, Blocks.CHEST.defaultBlockState().setValue(ChestBlock.WATERLOGGED, world.getFluidState(pos).is(FluidTags.WATER)), null);
+                craftChest.setSeed(random.nextLong());
+                craftChest.setLootTable(org.bukkit.Bukkit.getLootTable(org.bukkit.craftbukkit.v1_20_R2.util.CraftNamespacedKey.fromMinecraft(this.isLarge ? BuiltInLootTables.UNDERWATER_RUIN_BIG : BuiltInLootTables.UNDERWATER_RUIN_SMALL)));
+                this.placeCraftBlockEntity(world, pos, craftChest, 2);
+                // CraftBukkit end
             } else if ("drowned".equals(metadata)) {
-                Drowned drowned = EntityType.DROWNED.create(world.getLevel());
-                if (drowned != null) {
-                    drowned.setPersistenceRequired();
-                    drowned.moveTo(pos, 0.0F, 0.0F);
-                    drowned.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.STRUCTURE, (SpawnGroupData)null, (CompoundTag)null);
-                    world.addFreshEntityWithPassengers(drowned);
+                Drowned entitydrowned = (Drowned) EntityType.DROWNED.create(world.getLevel());
+
+                if (entitydrowned != null) {
+                    entitydrowned.setPersistenceRequired();
+                    entitydrowned.moveTo(pos, 0.0F, 0.0F);
+                    entitydrowned.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.STRUCTURE, (SpawnGroupData) null, (CompoundTag) null);
+                    world.addFreshEntityWithPassengers(entitydrowned);
                     if (pos.getY() > world.getSeaLevel()) {
                         world.setBlock(pos, Blocks.AIR.defaultBlockState(), 2);
                     } else {
@@ -211,9 +231,11 @@
         @Override
         public void postProcess(WorldGenLevel world, StructureManager structureAccessor, ChunkGenerator chunkGenerator, RandomSource random, BoundingBox chunkBox, ChunkPos chunkPos, BlockPos pivot) {
             int i = world.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, this.templatePosition.getX(), this.templatePosition.getZ());
+
             this.templatePosition = new BlockPos(this.templatePosition.getX(), i, this.templatePosition.getZ());
-            BlockPos blockPos = StructureTemplate.transform(new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), Mirror.NONE, this.placeSettings.getRotation(), BlockPos.ZERO).offset(this.templatePosition);
-            this.templatePosition = new BlockPos(this.templatePosition.getX(), this.getHeight(this.templatePosition, world, blockPos), this.templatePosition.getZ());
+            BlockPos blockposition1 = StructureTemplate.transform(new BlockPos(this.template.getSize().getX() - 1, 0, this.template.getSize().getZ() - 1), Mirror.NONE, this.placeSettings.getRotation(), BlockPos.ZERO).offset(this.templatePosition);
+
+            this.templatePosition = new BlockPos(this.templatePosition.getX(), this.getHeight(this.templatePosition, world, blockposition1), this.templatePosition.getZ());
             super.postProcess(world, structureAccessor, chunkGenerator, random, chunkBox, chunkPos, pivot);
         }
 
@@ -222,28 +244,31 @@
             int j = 512;
             int k = i - 1;
             int l = 0;
+            Iterator iterator = BlockPos.betweenClosed(start, end).iterator();
 
-            for(BlockPos blockPos : BlockPos.betweenClosed(start, end)) {
-                int m = blockPos.getX();
-                int n = blockPos.getZ();
-                int o = start.getY() - 1;
-                BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(m, o, n);
-                BlockState blockState = world.getBlockState(mutableBlockPos);
+            while (iterator.hasNext()) {
+                BlockPos blockposition2 = (BlockPos) iterator.next();
+                int i1 = blockposition2.getX();
+                int j1 = blockposition2.getZ();
+                int k1 = start.getY() - 1;
+                BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(i1, k1, j1);
+                BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition);
 
-                for(FluidState fluidState = world.getFluidState(mutableBlockPos); (blockState.isAir() || fluidState.is(FluidTags.WATER) || blockState.is(BlockTags.ICE)) && o > world.getMinBuildHeight() + 1; fluidState = world.getFluidState(mutableBlockPos)) {
-                    --o;
-                    mutableBlockPos.set(m, o, n);
-                    blockState = world.getBlockState(mutableBlockPos);
+                for (FluidState fluid = world.getFluidState(blockposition_mutableblockposition); (iblockdata.isAir() || fluid.is(FluidTags.WATER) || iblockdata.is(BlockTags.ICE)) && k1 > world.getMinBuildHeight() + 1; fluid = world.getFluidState(blockposition_mutableblockposition)) {
+                    --k1;
+                    blockposition_mutableblockposition.set(i1, k1, j1);
+                    iblockdata = world.getBlockState(blockposition_mutableblockposition);
                 }
 
-                j = Math.min(j, o);
-                if (o < k - 2) {
+                j = Math.min(j, k1);
+                if (k1 < k - 2) {
                     ++l;
                 }
             }
 
-            int p = Math.abs(start.getX() - end.getX());
-            if (k - j > 2 && l > p - 2) {
+            int l1 = Math.abs(start.getX() - end.getX());
+
+            if (k - j > 2 && l > l1 - 2) {
                 i = j + 1;
             }
 
