package net.minecraft.world.level.levelgen.structure;

import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.nbt.IntArrayTag;
import java.util.AbstractList;
import net.minecraft.world.level.block.WallTorchBlock;
import net.minecraft.world.level.block.FenceBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.block.entity.SpawnerBlockEntity;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.vehicle.MinecartChest;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.level.block.RailBlock;
import net.minecraft.core.Vec3i;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.nbt.Tag;
import java.util.Iterator;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.nbt.ListTag;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import com.google.common.collect.Lists;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.levelgen.feature.StructurePieceType;
import net.minecraft.world.level.levelgen.feature.MineshaftFeature;
import javax.annotation.Nullable;
import net.minecraft.core.Direction;
import java.util.Random;
import java.util.List;

public class MineShaftPieces {
    private static MineShaftPiece createRandomShaftPiece(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, @Nullable final Direction fz, final int integer7, final MineshaftFeature.Type b) {
        final int integer8 = random.nextInt(100);
        if (integer8 >= 80) {
            final BoundingBox ctd10 = MineShaftCrossing.findCrossing(list, random, integer3, integer4, integer5, fz);
            if (ctd10 != null) {
                return new MineShaftCrossing(integer7, ctd10, fz, b);
            }
        }
        else if (integer8 >= 70) {
            final BoundingBox ctd10 = MineShaftStairs.findStairs(list, random, integer3, integer4, integer5, fz);
            if (ctd10 != null) {
                return new MineShaftStairs(integer7, ctd10, fz, b);
            }
        }
        else {
            final BoundingBox ctd10 = MineShaftCorridor.findCorridorSize(list, random, integer3, integer4, integer5, fz);
            if (ctd10 != null) {
                return new MineShaftCorridor(integer7, random, ctd10, fz, b);
            }
        }
        return null;
    }
    
    private static MineShaftPiece generateAndAddPiece(final StructurePiece cty, final List<StructurePiece> list, final Random random, final int integer4, final int integer5, final int integer6, final Direction fz, final int integer8) {
        if (integer8 > 8) {
            return null;
        }
        if (Math.abs(integer4 - cty.getBoundingBox().x0) > 80 || Math.abs(integer6 - cty.getBoundingBox().z0) > 80) {
            return null;
        }
        final MineshaftFeature.Type b9 = ((MineShaftPiece)cty).type;
        final MineShaftPiece c10 = createRandomShaftPiece(list, random, integer4, integer5, integer6, fz, integer8 + 1, b9);
        if (c10 != null) {
            list.add(c10);
            c10.addChildren(cty, list, random);
        }
        return c10;
    }
    
    abstract static class MineShaftPiece extends StructurePiece {
        protected MineshaftFeature.Type type;
        
        public MineShaftPiece(final StructurePieceType cmm, final int integer, final MineshaftFeature.Type b) {
            super(cmm, integer);
            this.type = b;
        }
        
        public MineShaftPiece(final StructurePieceType cmm, final CompoundTag le) {
            super(cmm, le);
            this.type = MineshaftFeature.Type.byId(le.getInt("MST"));
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag le) {
            le.putInt("MST", this.type.ordinal());
        }
        
        protected BlockState getPlanksBlock() {
            switch (this.type) {
                default: {
                    return Blocks.OAK_PLANKS.defaultBlockState();
                }
                case MESA: {
                    return Blocks.DARK_OAK_PLANKS.defaultBlockState();
                }
            }
        }
        
        protected BlockState getFenceBlock() {
            switch (this.type) {
                default: {
                    return Blocks.OAK_FENCE.defaultBlockState();
                }
                case MESA: {
                    return Blocks.DARK_OAK_FENCE.defaultBlockState();
                }
            }
        }
        
        protected boolean isSupportingBox(final BlockGetter bpg, final BoundingBox ctd, final int integer3, final int integer4, final int integer5, final int integer6) {
            for (int integer7 = integer3; integer7 <= integer4; ++integer7) {
                if (this.getBlock(bpg, integer7, integer5 + 1, integer6, ctd).isAir()) {
                    return false;
                }
            }
            return true;
        }
    }
    
    public static class MineShaftRoom extends MineShaftPiece {
        private final List<BoundingBox> childEntranceBoxes;
        
        public MineShaftRoom(final int integer1, final Random random, final int integer3, final int integer4, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_ROOM, integer1, b);
            this.childEntranceBoxes = Lists.newLinkedList();
            this.type = b;
            this.boundingBox = new BoundingBox(integer3, 50, integer4, integer3 + 7 + random.nextInt(6), 54 + random.nextInt(6), integer4 + 7 + random.nextInt(6));
        }
        
        public MineShaftRoom(final StructureManager cva, final CompoundTag le) {
            super(StructurePieceType.MINE_SHAFT_ROOM, le);
            this.childEntranceBoxes = Lists.newLinkedList();
            final ListTag lk4 = le.getList("Entrances", 11);
            for (int integer5 = 0; integer5 < lk4.size(); ++integer5) {
                this.childEntranceBoxes.add(new BoundingBox(lk4.getIntArray(integer5)));
            }
        }
        
        @Override
        public void addChildren(final StructurePiece cty, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            int integer6 = this.boundingBox.getYSpan() - 3 - 1;
            if (integer6 <= 0) {
                integer6 = 1;
            }
            for (int integer7 = 0; integer7 < this.boundingBox.getXSpan(); integer7 += 4) {
                integer7 += random.nextInt(this.boundingBox.getXSpan());
                if (integer7 + 3 > this.boundingBox.getXSpan()) {
                    break;
                }
                final MineShaftPiece c8 = generateAndAddPiece(cty, list, random, this.boundingBox.x0 + integer7, this.boundingBox.y0 + random.nextInt(integer6) + 1, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                if (c8 != null) {
                    final BoundingBox ctd9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(ctd9.x0, ctd9.y0, this.boundingBox.z0, ctd9.x1, ctd9.y1, this.boundingBox.z0 + 1));
                }
            }
            for (int integer7 = 0; integer7 < this.boundingBox.getXSpan(); integer7 += 4) {
                integer7 += random.nextInt(this.boundingBox.getXSpan());
                if (integer7 + 3 > this.boundingBox.getXSpan()) {
                    break;
                }
                final MineShaftPiece c8 = generateAndAddPiece(cty, list, random, this.boundingBox.x0 + integer7, this.boundingBox.y0 + random.nextInt(integer6) + 1, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                if (c8 != null) {
                    final BoundingBox ctd9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(ctd9.x0, ctd9.y0, this.boundingBox.z1 - 1, ctd9.x1, ctd9.y1, this.boundingBox.z1));
                }
            }
            for (int integer7 = 0; integer7 < this.boundingBox.getZSpan(); integer7 += 4) {
                integer7 += random.nextInt(this.boundingBox.getZSpan());
                if (integer7 + 3 > this.boundingBox.getZSpan()) {
                    break;
                }
                final MineShaftPiece c8 = generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 + random.nextInt(integer6) + 1, this.boundingBox.z0 + integer7, Direction.WEST, integer5);
                if (c8 != null) {
                    final BoundingBox ctd9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.x0, ctd9.y0, ctd9.z0, this.boundingBox.x0 + 1, ctd9.y1, ctd9.z1));
                }
            }
            for (int integer7 = 0; integer7 < this.boundingBox.getZSpan(); integer7 += 4) {
                integer7 += random.nextInt(this.boundingBox.getZSpan());
                if (integer7 + 3 > this.boundingBox.getZSpan()) {
                    break;
                }
                final StructurePiece cty2 = generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 + random.nextInt(integer6) + 1, this.boundingBox.z0 + integer7, Direction.EAST, integer5);
                if (cty2 != null) {
                    final BoundingBox ctd9 = cty2.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.x1 - 1, ctd9.y0, ctd9.z0, this.boundingBox.x1, ctd9.y1, ctd9.z1));
                }
            }
        }
        
        @Override
        public boolean postProcess(final WorldGenLevel bqu, final StructureFeatureManager bqq, final ChunkGenerator cha, final Random random, final BoundingBox ctd, final ChunkPos bph, final BlockPos fu) {
            if (this.edgesLiquid(bqu, ctd)) {
                return false;
            }
            this.generateBox(bqu, ctd, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z0, this.boundingBox.x1, this.boundingBox.y0, this.boundingBox.z1, Blocks.DIRT.defaultBlockState(), MineShaftRoom.CAVE_AIR, true);
            this.generateBox(bqu, ctd, this.boundingBox.x0, this.boundingBox.y0 + 1, this.boundingBox.z0, this.boundingBox.x1, Math.min(this.boundingBox.y0 + 3, this.boundingBox.y1), this.boundingBox.z1, MineShaftRoom.CAVE_AIR, MineShaftRoom.CAVE_AIR, false);
            for (final BoundingBox ctd2 : this.childEntranceBoxes) {
                this.generateBox(bqu, ctd, ctd2.x0, ctd2.y1 - 2, ctd2.z0, ctd2.x1, ctd2.y1, ctd2.z1, MineShaftRoom.CAVE_AIR, MineShaftRoom.CAVE_AIR, false);
            }
            this.generateUpperHalfSphere(bqu, ctd, this.boundingBox.x0, this.boundingBox.y0 + 4, this.boundingBox.z0, this.boundingBox.x1, this.boundingBox.y1, this.boundingBox.z1, MineShaftRoom.CAVE_AIR, false);
            return true;
        }
        
        @Override
        public void move(final int integer1, final int integer2, final int integer3) {
            super.move(integer1, integer2, integer3);
            for (final BoundingBox ctd6 : this.childEntranceBoxes) {
                ctd6.move(integer1, integer2, integer3);
            }
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag le) {
            super.addAdditionalSaveData(le);
            final ListTag lk3 = new ListTag();
            for (final BoundingBox ctd5 : this.childEntranceBoxes) {
                ((AbstractList<IntArrayTag>)lk3).add(ctd5.createTag());
            }
            le.put("Entrances", lk3);
        }
    }
    
    public static class MineShaftCorridor extends MineShaftPiece {
        private final boolean hasRails;
        private final boolean spiderCorridor;
        private boolean hasPlacedSpider;
        private final int numSections;
        
        public MineShaftCorridor(final StructureManager cva, final CompoundTag le) {
            super(StructurePieceType.MINE_SHAFT_CORRIDOR, le);
            this.hasRails = le.getBoolean("hr");
            this.spiderCorridor = le.getBoolean("sc");
            this.hasPlacedSpider = le.getBoolean("hps");
            this.numSections = le.getInt("Num");
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag le) {
            super.addAdditionalSaveData(le);
            le.putBoolean("hr", this.hasRails);
            le.putBoolean("sc", this.spiderCorridor);
            le.putBoolean("hps", this.hasPlacedSpider);
            le.putInt("Num", this.numSections);
        }
        
        public MineShaftCorridor(final int integer, final Random random, final BoundingBox ctd, final Direction fz, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_CORRIDOR, integer, b);
            this.setOrientation(fz);
            this.boundingBox = ctd;
            this.hasRails = (random.nextInt(3) == 0);
            this.spiderCorridor = (!this.hasRails && random.nextInt(23) == 0);
            if (this.getOrientation().getAxis() == Direction.Axis.Z) {
                this.numSections = ctd.getZSpan() / 5;
            }
            else {
                this.numSections = ctd.getXSpan() / 5;
            }
        }
        
        public static BoundingBox findCorridorSize(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fz) {
            final BoundingBox ctd7 = new BoundingBox(integer3, integer4, integer5, integer3, integer4 + 3 - 1, integer5);
            int integer6;
            for (integer6 = random.nextInt(3) + 2; integer6 > 0; --integer6) {
                final int integer7 = integer6 * 5;
                switch (fz) {
                    default: {
                        ctd7.x1 = integer3 + 3 - 1;
                        ctd7.z0 = integer5 - (integer7 - 1);
                        break;
                    }
                    case SOUTH: {
                        ctd7.x1 = integer3 + 3 - 1;
                        ctd7.z1 = integer5 + integer7 - 1;
                        break;
                    }
                    case WEST: {
                        ctd7.x0 = integer3 - (integer7 - 1);
                        ctd7.z1 = integer5 + 3 - 1;
                        break;
                    }
                    case EAST: {
                        ctd7.x1 = integer3 + integer7 - 1;
                        ctd7.z1 = integer5 + 3 - 1;
                        break;
                    }
                }
                if (StructurePiece.findCollisionPiece(list, ctd7) == null) {
                    break;
                }
            }
            if (integer6 > 0) {
                return ctd7;
            }
            return null;
        }
        
        @Override
        public void addChildren(final StructurePiece cty, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            final int integer6 = random.nextInt(4);
            final Direction fz7 = this.getOrientation();
            if (fz7 != null) {
                switch (fz7) {
                    default: {
                        if (integer6 <= 1) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, fz7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, Direction.WEST, integer5);
                            break;
                        }
                        generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, Direction.EAST, integer5);
                        break;
                    }
                    case SOUTH: {
                        if (integer6 <= 1) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 + 1, fz7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 - 3, Direction.WEST, integer5);
                            break;
                        }
                        generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 - 3, Direction.EAST, integer5);
                        break;
                    }
                    case WEST: {
                        if (integer6 <= 1) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, fz7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                            break;
                        }
                        generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                        break;
                    }
                    case EAST: {
                        if (integer6 <= 1) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, fz7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x1 - 3, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                            break;
                        }
                        generateAndAddPiece(cty, list, random, this.boundingBox.x1 - 3, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                        break;
                    }
                }
            }
            if (integer5 < 8) {
                if (fz7 == Direction.NORTH || fz7 == Direction.SOUTH) {
                    for (int integer7 = this.boundingBox.z0 + 3; integer7 + 3 <= this.boundingBox.z1; integer7 += 5) {
                        final int integer8 = random.nextInt(5);
                        if (integer8 == 0) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, integer7, Direction.WEST, integer5 + 1);
                        }
                        else if (integer8 == 1) {
                            generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, integer7, Direction.EAST, integer5 + 1);
                        }
                    }
                }
                else {
                    for (int integer7 = this.boundingBox.x0 + 3; integer7 + 3 <= this.boundingBox.x1; integer7 += 5) {
                        final int integer8 = random.nextInt(5);
                        if (integer8 == 0) {
                            generateAndAddPiece(cty, list, random, integer7, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5 + 1);
                        }
                        else if (integer8 == 1) {
                            generateAndAddPiece(cty, list, random, integer7, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5 + 1);
                        }
                    }
                }
            }
        }
        
        @Override
        protected boolean createChest(final LevelAccessor bqc, final BoundingBox ctd, final Random random, final int integer4, final int integer5, final int integer6, final ResourceLocation uh) {
            final BlockPos fu9 = new BlockPos(this.getWorldX(integer4, integer6), this.getWorldY(integer5), this.getWorldZ(integer4, integer6));
            if (ctd.isInside(fu9) && bqc.getBlockState(fu9).isAir() && !bqc.getBlockState(fu9.below()).isAir()) {
                final BlockState cfj10 = ((StateHolder<O, BlockState>)Blocks.RAIL.defaultBlockState()).<RailShape, RailShape>setValue(RailBlock.SHAPE, random.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST);
                this.placeBlock(bqc, cfj10, integer4, integer5, integer6, ctd);
                final MinecartChest bfw11 = new MinecartChest(bqc.getLevel(), fu9.getX() + 0.5, fu9.getY() + 0.5, fu9.getZ() + 0.5);
                bfw11.setLootTable(uh, random.nextLong());
                bqc.addFreshEntity(bfw11);
                return true;
            }
            return false;
        }
        
        @Override
        public boolean postProcess(final WorldGenLevel bqu, final StructureFeatureManager bqq, final ChunkGenerator cha, final Random random, final BoundingBox ctd, final ChunkPos bph, final BlockPos fu) {
            if (this.edgesLiquid(bqu, ctd)) {
                return false;
            }
            final int integer9 = 0;
            final int integer10 = 2;
            final int integer11 = 0;
            final int integer12 = 2;
            final int integer13 = this.numSections * 5 - 1;
            final BlockState cfj14 = this.getPlanksBlock();
            this.generateBox(bqu, ctd, 0, 0, 0, 2, 1, integer13, MineShaftCorridor.CAVE_AIR, MineShaftCorridor.CAVE_AIR, false);
            this.generateMaybeBox(bqu, ctd, random, 0.8f, 0, 2, 0, 2, 2, integer13, MineShaftCorridor.CAVE_AIR, MineShaftCorridor.CAVE_AIR, false, false);
            if (this.spiderCorridor) {
                this.generateMaybeBox(bqu, ctd, random, 0.6f, 0, 0, 0, 2, 1, integer13, Blocks.COBWEB.defaultBlockState(), MineShaftCorridor.CAVE_AIR, false, true);
            }
            for (int integer14 = 0; integer14 < this.numSections; ++integer14) {
                final int integer15 = 2 + integer14 * 5;
                this.placeSupport(bqu, ctd, 0, 0, integer15, 2, 2, random);
                this.placeCobWeb(bqu, ctd, random, 0.1f, 0, 2, integer15 - 1);
                this.placeCobWeb(bqu, ctd, random, 0.1f, 2, 2, integer15 - 1);
                this.placeCobWeb(bqu, ctd, random, 0.1f, 0, 2, integer15 + 1);
                this.placeCobWeb(bqu, ctd, random, 0.1f, 2, 2, integer15 + 1);
                this.placeCobWeb(bqu, ctd, random, 0.05f, 0, 2, integer15 - 2);
                this.placeCobWeb(bqu, ctd, random, 0.05f, 2, 2, integer15 - 2);
                this.placeCobWeb(bqu, ctd, random, 0.05f, 0, 2, integer15 + 2);
                this.placeCobWeb(bqu, ctd, random, 0.05f, 2, 2, integer15 + 2);
                if (random.nextInt(100) == 0) {
                    this.createChest(bqu, ctd, random, 2, 0, integer15 - 1, BuiltInLootTables.ABANDONED_MINESHAFT);
                }
                if (random.nextInt(100) == 0) {
                    this.createChest(bqu, ctd, random, 0, 0, integer15 + 1, BuiltInLootTables.ABANDONED_MINESHAFT);
                }
                if (this.spiderCorridor && !this.hasPlacedSpider) {
                    final int integer16 = this.getWorldY(0);
                    final int integer17 = integer15 - 1 + random.nextInt(3);
                    final int integer18 = this.getWorldX(1, integer17);
                    final int integer19 = this.getWorldZ(1, integer17);
                    final BlockPos fu2 = new BlockPos(integer18, integer16, integer19);
                    if (ctd.isInside(fu2) && this.isInterior(bqu, 1, 0, integer17, ctd)) {
                        this.hasPlacedSpider = true;
                        bqu.setBlock(fu2, Blocks.SPAWNER.defaultBlockState(), 2);
                        final BlockEntity cdl22 = bqu.getBlockEntity(fu2);
                        if (cdl22 instanceof SpawnerBlockEntity) {
                            ((SpawnerBlockEntity)cdl22).getSpawner().setEntityId(EntityType.CAVE_SPIDER);
                        }
                    }
                }
            }
            for (int integer14 = 0; integer14 <= 2; ++integer14) {
                for (int integer15 = 0; integer15 <= integer13; ++integer15) {
                    final int integer16 = -1;
                    final BlockState cfj15 = this.getBlock(bqu, integer14, -1, integer15, ctd);
                    if (cfj15.isAir() && this.isInterior(bqu, integer14, -1, integer15, ctd)) {
                        final int integer18 = -1;
                        this.placeBlock(bqu, cfj14, integer14, -1, integer15, ctd);
                    }
                }
            }
            if (this.hasRails) {
                final BlockState cfj16 = ((StateHolder<O, BlockState>)Blocks.RAIL.defaultBlockState()).<RailShape, RailShape>setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH);
                for (int integer15 = 0; integer15 <= integer13; ++integer15) {
                    final BlockState cfj17 = this.getBlock(bqu, 1, -1, integer15, ctd);
                    if (!cfj17.isAir() && cfj17.isSolidRender(bqu, new BlockPos(this.getWorldX(1, integer15), this.getWorldY(-1), this.getWorldZ(1, integer15)))) {
                        final float float18 = this.isInterior(bqu, 1, 0, integer15, ctd) ? 0.7f : 0.9f;
                        this.maybeGenerateBlock(bqu, ctd, random, float18, 1, 0, integer15, cfj16);
                    }
                }
            }
            return true;
        }
        
        private void placeSupport(final LevelAccessor bqc, final BoundingBox ctd, final int integer3, final int integer4, final int integer5, final int integer6, final int integer7, final Random random) {
            if (!this.isSupportingBox(bqc, ctd, integer3, integer7, integer6, integer5)) {
                return;
            }
            final BlockState cfj10 = this.getPlanksBlock();
            final BlockState cfj11 = this.getFenceBlock();
            this.generateBox(bqc, ctd, integer3, integer4, integer5, integer3, integer6 - 1, integer5, ((StateHolder<O, BlockState>)cfj11).<Comparable, Boolean>setValue((Property<Comparable>)FenceBlock.WEST, true), MineShaftCorridor.CAVE_AIR, false);
            this.generateBox(bqc, ctd, integer7, integer4, integer5, integer7, integer6 - 1, integer5, ((StateHolder<O, BlockState>)cfj11).<Comparable, Boolean>setValue((Property<Comparable>)FenceBlock.EAST, true), MineShaftCorridor.CAVE_AIR, false);
            if (random.nextInt(4) == 0) {
                this.generateBox(bqc, ctd, integer3, integer6, integer5, integer3, integer6, integer5, cfj10, MineShaftCorridor.CAVE_AIR, false);
                this.generateBox(bqc, ctd, integer7, integer6, integer5, integer7, integer6, integer5, cfj10, MineShaftCorridor.CAVE_AIR, false);
            }
            else {
                this.generateBox(bqc, ctd, integer3, integer6, integer5, integer7, integer6, integer5, cfj10, MineShaftCorridor.CAVE_AIR, false);
                this.maybeGenerateBlock(bqc, ctd, random, 0.05f, integer3 + 1, integer6, integer5 - 1, ((StateHolder<O, BlockState>)Blocks.WALL_TORCH.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)WallTorchBlock.FACING, Direction.NORTH));
                this.maybeGenerateBlock(bqc, ctd, random, 0.05f, integer3 + 1, integer6, integer5 + 1, ((StateHolder<O, BlockState>)Blocks.WALL_TORCH.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)WallTorchBlock.FACING, Direction.SOUTH));
            }
        }
        
        private void placeCobWeb(final LevelAccessor bqc, final BoundingBox ctd, final Random random, final float float4, final int integer5, final int integer6, final int integer7) {
            if (this.isInterior(bqc, integer5, integer6, integer7, ctd)) {
                this.maybeGenerateBlock(bqc, ctd, random, float4, integer5, integer6, integer7, Blocks.COBWEB.defaultBlockState());
            }
        }
    }
    
    public static class MineShaftCrossing extends MineShaftPiece {
        private final Direction direction;
        private final boolean isTwoFloored;
        
        public MineShaftCrossing(final StructureManager cva, final CompoundTag le) {
            super(StructurePieceType.MINE_SHAFT_CROSSING, le);
            this.isTwoFloored = le.getBoolean("tf");
            this.direction = Direction.from2DDataValue(le.getInt("D"));
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag le) {
            super.addAdditionalSaveData(le);
            le.putBoolean("tf", this.isTwoFloored);
            le.putInt("D", this.direction.get2DDataValue());
        }
        
        public MineShaftCrossing(final int integer, final BoundingBox ctd, @Nullable final Direction fz, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_CROSSING, integer, b);
            this.direction = fz;
            this.boundingBox = ctd;
            this.isTwoFloored = (ctd.getYSpan() > 3);
        }
        
        public static BoundingBox findCrossing(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fz) {
            final BoundingBox ctd7 = new BoundingBox(integer3, integer4, integer5, integer3, integer4 + 3 - 1, integer5);
            if (random.nextInt(4) == 0) {
                final BoundingBox boundingBox = ctd7;
                boundingBox.y1 += 4;
            }
            switch (fz) {
                default: {
                    ctd7.x0 = integer3 - 1;
                    ctd7.x1 = integer3 + 3;
                    ctd7.z0 = integer5 - 4;
                    break;
                }
                case SOUTH: {
                    ctd7.x0 = integer3 - 1;
                    ctd7.x1 = integer3 + 3;
                    ctd7.z1 = integer5 + 3 + 1;
                    break;
                }
                case WEST: {
                    ctd7.x0 = integer3 - 4;
                    ctd7.z0 = integer5 - 1;
                    ctd7.z1 = integer5 + 3;
                    break;
                }
                case EAST: {
                    ctd7.x1 = integer3 + 3 + 1;
                    ctd7.z0 = integer5 - 1;
                    ctd7.z1 = integer5 + 3;
                    break;
                }
            }
            if (StructurePiece.findCollisionPiece(list, ctd7) != null) {
                return null;
            }
            return ctd7;
        }
        
        @Override
        public void addChildren(final StructurePiece cty, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            switch (this.direction) {
                default: {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
                case SOUTH: {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
                case WEST: {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    break;
                }
                case EAST: {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
            }
            if (this.isTwoFloored) {
                if (random.nextBoolean()) {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(cty, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                }
            }
        }
        
        @Override
        public boolean postProcess(final WorldGenLevel bqu, final StructureFeatureManager bqq, final ChunkGenerator cha, final Random random, final BoundingBox ctd, final ChunkPos bph, final BlockPos fu) {
            if (this.edgesLiquid(bqu, ctd)) {
                return false;
            }
            final BlockState cfj9 = this.getPlanksBlock();
            if (this.isTwoFloored) {
                this.generateBox(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0, this.boundingBox.x1 - 1, this.boundingBox.y0 + 3 - 1, this.boundingBox.z1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
                this.generateBox(bqu, ctd, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.x1, this.boundingBox.y0 + 3 - 1, this.boundingBox.z1 - 1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
                this.generateBox(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y1 - 2, this.boundingBox.z0, this.boundingBox.x1 - 1, this.boundingBox.y1, this.boundingBox.z1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
                this.generateBox(bqu, ctd, this.boundingBox.x0, this.boundingBox.y1 - 2, this.boundingBox.z0 + 1, this.boundingBox.x1, this.boundingBox.y1, this.boundingBox.z1 - 1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
                this.generateBox(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y0 + 3, this.boundingBox.z0 + 1, this.boundingBox.x1 - 1, this.boundingBox.y0 + 3, this.boundingBox.z1 - 1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
            }
            else {
                this.generateBox(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0, this.boundingBox.x1 - 1, this.boundingBox.y1, this.boundingBox.z1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
                this.generateBox(bqu, ctd, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.x1, this.boundingBox.y1, this.boundingBox.z1 - 1, MineShaftCrossing.CAVE_AIR, MineShaftCrossing.CAVE_AIR, false);
            }
            this.placeSupportPillar(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.y1);
            this.placeSupportPillar(bqu, ctd, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 - 1, this.boundingBox.y1);
            this.placeSupportPillar(bqu, ctd, this.boundingBox.x1 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.y1);
            this.placeSupportPillar(bqu, ctd, this.boundingBox.x1 - 1, this.boundingBox.y0, this.boundingBox.z1 - 1, this.boundingBox.y1);
            for (int integer10 = this.boundingBox.x0; integer10 <= this.boundingBox.x1; ++integer10) {
                for (int integer11 = this.boundingBox.z0; integer11 <= this.boundingBox.z1; ++integer11) {
                    if (this.getBlock(bqu, integer10, this.boundingBox.y0 - 1, integer11, ctd).isAir() && this.isInterior(bqu, integer10, this.boundingBox.y0 - 1, integer11, ctd)) {
                        this.placeBlock(bqu, cfj9, integer10, this.boundingBox.y0 - 1, integer11, ctd);
                    }
                }
            }
            return true;
        }
        
        private void placeSupportPillar(final LevelAccessor bqc, final BoundingBox ctd, final int integer3, final int integer4, final int integer5, final int integer6) {
            if (!this.getBlock(bqc, integer3, integer6 + 1, integer5, ctd).isAir()) {
                this.generateBox(bqc, ctd, integer3, integer4, integer5, integer3, integer6, integer5, this.getPlanksBlock(), MineShaftCrossing.CAVE_AIR, false);
            }
        }
    }
    
    public static class MineShaftStairs extends MineShaftPiece {
        public MineShaftStairs(final int integer, final BoundingBox ctd, final Direction fz, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_STAIRS, integer, b);
            this.setOrientation(fz);
            this.boundingBox = ctd;
        }
        
        public MineShaftStairs(final StructureManager cva, final CompoundTag le) {
            super(StructurePieceType.MINE_SHAFT_STAIRS, le);
        }
        
        public static BoundingBox findStairs(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fz) {
            final BoundingBox ctd7 = new BoundingBox(integer3, integer4 - 5, integer5, integer3, integer4 + 3 - 1, integer5);
            switch (fz) {
                default: {
                    ctd7.x1 = integer3 + 3 - 1;
                    ctd7.z0 = integer5 - 8;
                    break;
                }
                case SOUTH: {
                    ctd7.x1 = integer3 + 3 - 1;
                    ctd7.z1 = integer5 + 8;
                    break;
                }
                case WEST: {
                    ctd7.x0 = integer3 - 8;
                    ctd7.z1 = integer5 + 3 - 1;
                    break;
                }
                case EAST: {
                    ctd7.x1 = integer3 + 8;
                    ctd7.z1 = integer5 + 3 - 1;
                    break;
                }
            }
            if (StructurePiece.findCollisionPiece(list, ctd7) != null) {
                return null;
            }
            return ctd7;
        }
        
        @Override
        public void addChildren(final StructurePiece cty, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            final Direction fz6 = this.getOrientation();
            if (fz6 != null) {
                switch (fz6) {
                    default: {
                        generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                        break;
                    }
                    case SOUTH: {
                        generateAndAddPiece(cty, list, random, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                        break;
                    }
                    case WEST: {
                        generateAndAddPiece(cty, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0, Direction.WEST, integer5);
                        break;
                    }
                    case EAST: {
                        generateAndAddPiece(cty, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0, Direction.EAST, integer5);
                        break;
                    }
                }
            }
        }
        
        @Override
        public boolean postProcess(final WorldGenLevel bqu, final StructureFeatureManager bqq, final ChunkGenerator cha, final Random random, final BoundingBox ctd, final ChunkPos bph, final BlockPos fu) {
            if (this.edgesLiquid(bqu, ctd)) {
                return false;
            }
            this.generateBox(bqu, ctd, 0, 5, 0, 2, 7, 1, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            this.generateBox(bqu, ctd, 0, 0, 7, 2, 2, 8, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            for (int integer9 = 0; integer9 < 5; ++integer9) {
                this.generateBox(bqu, ctd, 0, 5 - integer9 - ((integer9 < 4) ? 1 : 0), 2 + integer9, 2, 7 - integer9, 2 + integer9, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            }
            return true;
        }
    }
}
