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

import net.minecraft.world.level.block.state.AbstractStateHolder;
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.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.nbt.Tag;
import java.util.Iterator;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.LevelAccessor;
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 fp, final int integer7, final MineshaftFeature.Type b) {
        final int integer8 = random.nextInt(100);
        if (integer8 >= 80) {
            final BoundingBox clb10 = MineShaftCrossing.findCrossing(list, random, integer3, integer4, integer5, fp);
            if (clb10 != null) {
                return new MineShaftCrossing(integer7, clb10, fp, b);
            }
        }
        else if (integer8 >= 70) {
            final BoundingBox clb10 = MineShaftStairs.findStairs(list, random, integer3, integer4, integer5, fp);
            if (clb10 != null) {
                return new MineShaftStairs(integer7, clb10, fp, b);
            }
        }
        else {
            final BoundingBox clb10 = MineShaftCorridor.findCorridorSize(list, random, integer3, integer4, integer5, fp);
            if (clb10 != null) {
                return new MineShaftCorridor(integer7, random, clb10, fp, b);
            }
        }
        return null;
    }
    
    private static MineShaftPiece generateAndAddPiece(final StructurePiece clu, final List<StructurePiece> list, final Random random, final int integer4, final int integer5, final int integer6, final Direction fp, final int integer8) {
        if (integer8 > 8) {
            return null;
        }
        if (Math.abs(integer4 - clu.getBoundingBox().x0) > 80 || Math.abs(integer6 - clu.getBoundingBox().z0) > 80) {
            return null;
        }
        final MineshaftFeature.Type b9 = ((MineShaftPiece)clu).type;
        final MineShaftPiece c10 = createRandomShaftPiece(list, random, integer4, integer5, integer6, fp, integer8 + 1, b9);
        if (c10 != null) {
            list.add(c10);
            c10.addChildren(clu, list, random);
        }
        return c10;
    }
    
    abstract static class MineShaftPiece extends StructurePiece {
        protected MineshaftFeature.Type type;
        
        public MineShaftPiece(final StructurePieceType cfm, final int integer, final MineshaftFeature.Type b) {
            super(cfm, integer);
            this.type = b;
        }
        
        public MineShaftPiece(final StructurePieceType cfm, final CompoundTag jt) {
            super(cfm, jt);
            this.type = MineshaftFeature.Type.byId(jt.getInt("MST"));
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag jt) {
            jt.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 bjg, final BoundingBox clb, final int integer3, final int integer4, final int integer5, final int integer6) {
            for (int integer7 = integer3; integer7 <= integer4; ++integer7) {
                if (this.getBlock(bjg, integer7, integer5 + 1, integer6, clb).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 cmo, final CompoundTag jt) {
            super(StructurePieceType.MINE_SHAFT_ROOM, jt);
            this.childEntranceBoxes = Lists.newLinkedList();
            final ListTag jz4 = jt.getList("Entrances", 11);
            for (int integer5 = 0; integer5 < jz4.size(); ++integer5) {
                this.childEntranceBoxes.add(new BoundingBox(jz4.getIntArray(integer5)));
            }
        }
        
        @Override
        public void addChildren(final StructurePiece clu, 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(clu, 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 clb9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(clb9.x0, clb9.y0, this.boundingBox.z0, clb9.x1, clb9.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(clu, 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 clb9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(clb9.x0, clb9.y0, this.boundingBox.z1 - 1, clb9.x1, clb9.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(clu, 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 clb9 = c8.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.x0, clb9.y0, clb9.z0, this.boundingBox.x0 + 1, clb9.y1, clb9.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 clu2 = generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 + random.nextInt(integer6) + 1, this.boundingBox.z0 + integer7, Direction.EAST, integer5);
                if (clu2 != null) {
                    final BoundingBox clb9 = clu2.getBoundingBox();
                    this.childEntranceBoxes.add(new BoundingBox(this.boundingBox.x1 - 1, clb9.y0, clb9.z0, this.boundingBox.x1, clb9.y1, clb9.z1));
                }
            }
        }
        
        @Override
        public boolean postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            if (this.edgesLiquid(bjx, clb)) {
                return false;
            }
            this.generateBox(bjx, clb, 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(bjx, clb, 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 clb2 : this.childEntranceBoxes) {
                this.generateBox(bjx, clb, clb2.x0, clb2.y1 - 2, clb2.z0, clb2.x1, clb2.y1, clb2.z1, MineShaftRoom.CAVE_AIR, MineShaftRoom.CAVE_AIR, false);
            }
            this.generateUpperHalfSphere(bjx, clb, 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 clb6 : this.childEntranceBoxes) {
                clb6.move(integer1, integer2, integer3);
            }
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag jt) {
            super.addAdditionalSaveData(jt);
            final ListTag jz3 = new ListTag();
            for (final BoundingBox clb5 : this.childEntranceBoxes) {
                ((AbstractList<IntArrayTag>)jz3).add(clb5.createTag());
            }
            jt.put("Entrances", jz3);
        }
    }
    
    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 cmo, final CompoundTag jt) {
            super(StructurePieceType.MINE_SHAFT_CORRIDOR, jt);
            this.hasRails = jt.getBoolean("hr");
            this.spiderCorridor = jt.getBoolean("sc");
            this.hasPlacedSpider = jt.getBoolean("hps");
            this.numSections = jt.getInt("Num");
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag jt) {
            super.addAdditionalSaveData(jt);
            jt.putBoolean("hr", this.hasRails);
            jt.putBoolean("sc", this.spiderCorridor);
            jt.putBoolean("hps", this.hasPlacedSpider);
            jt.putInt("Num", this.numSections);
        }
        
        public MineShaftCorridor(final int integer, final Random random, final BoundingBox clb, final Direction fp, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_CORRIDOR, integer, b);
            this.setOrientation(fp);
            this.boundingBox = clb;
            this.hasRails = (random.nextInt(3) == 0);
            this.spiderCorridor = (!this.hasRails && random.nextInt(23) == 0);
            if (this.getOrientation().getAxis() == Direction.Axis.Z) {
                this.numSections = clb.getZSpan() / 5;
            }
            else {
                this.numSections = clb.getXSpan() / 5;
            }
        }
        
        public static BoundingBox findCorridorSize(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fp) {
            final BoundingBox clb7 = 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 (fp) {
                    default: {
                        clb7.x1 = integer3 + 3 - 1;
                        clb7.z0 = integer5 - (integer7 - 1);
                        break;
                    }
                    case SOUTH: {
                        clb7.x1 = integer3 + 3 - 1;
                        clb7.z1 = integer5 + integer7 - 1;
                        break;
                    }
                    case WEST: {
                        clb7.x0 = integer3 - (integer7 - 1);
                        clb7.z1 = integer5 + 3 - 1;
                        break;
                    }
                    case EAST: {
                        clb7.x1 = integer3 + integer7 - 1;
                        clb7.z1 = integer5 + 3 - 1;
                        break;
                    }
                }
                if (StructurePiece.findCollisionPiece(list, clb7) == null) {
                    break;
                }
            }
            if (integer6 > 0) {
                return clb7;
            }
            return null;
        }
        
        @Override
        public void addChildren(final StructurePiece clu, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            final int integer6 = random.nextInt(4);
            final Direction fp7 = this.getOrientation();
            if (fp7 != null) {
                switch (fp7) {
                    default: {
                        if (integer6 <= 1) {
                            generateAndAddPiece(clu, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, fp7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, Direction.WEST, integer5);
                            break;
                        }
                        generateAndAddPiece(clu, 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(clu, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 + 1, fp7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z1 - 3, Direction.WEST, integer5);
                            break;
                        }
                        generateAndAddPiece(clu, 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(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, fp7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(clu, list, random, this.boundingBox.x0, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                            break;
                        }
                        generateAndAddPiece(clu, 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(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0, fp7, integer5);
                            break;
                        }
                        if (integer6 == 2) {
                            generateAndAddPiece(clu, list, random, this.boundingBox.x1 - 3, this.boundingBox.y0 - 1 + random.nextInt(3), this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                            break;
                        }
                        generateAndAddPiece(clu, 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 (fp7 == Direction.NORTH || fp7 == 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(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, integer7, Direction.WEST, integer5 + 1);
                        }
                        else if (integer8 == 1) {
                            generateAndAddPiece(clu, 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(clu, list, random, integer7, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5 + 1);
                        }
                        else if (integer8 == 1) {
                            generateAndAddPiece(clu, list, random, integer7, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5 + 1);
                        }
                    }
                }
            }
        }
        
        @Override
        protected boolean createChest(final LevelAccessor bjx, final BoundingBox clb, final Random random, final int integer4, final int integer5, final int integer6, final ResourceLocation sm) {
            final BlockPos fk9 = new BlockPos(this.getWorldX(integer4, integer6), this.getWorldY(integer5), this.getWorldZ(integer4, integer6));
            if (clb.isInside(fk9) && bjx.getBlockState(fk9).isAir() && !bjx.getBlockState(fk9.below()).isAir()) {
                final BlockState byj10 = ((AbstractStateHolder<O, BlockState>)Blocks.RAIL.defaultBlockState()).<RailShape, RailShape>setValue(RailBlock.SHAPE, random.nextBoolean() ? RailShape.NORTH_SOUTH : RailShape.EAST_WEST);
                this.placeBlock(bjx, byj10, integer4, integer5, integer6, clb);
                final MinecartChest bab11 = new MinecartChest(bjx.getLevel(), fk9.getX() + 0.5f, fk9.getY() + 0.5f, fk9.getZ() + 0.5f);
                bab11.setLootTable(sm, random.nextLong());
                bjx.addFreshEntity(bab11);
                return true;
            }
            return false;
        }
        
        @Override
        public boolean postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            if (this.edgesLiquid(bjx, clb)) {
                return false;
            }
            final int integer7 = 0;
            final int integer8 = 2;
            final int integer9 = 0;
            final int integer10 = 2;
            final int integer11 = this.numSections * 5 - 1;
            final BlockState byj12 = this.getPlanksBlock();
            this.generateBox(bjx, clb, 0, 0, 0, 2, 1, integer11, MineShaftCorridor.CAVE_AIR, MineShaftCorridor.CAVE_AIR, false);
            this.generateMaybeBox(bjx, clb, random, 0.8f, 0, 2, 0, 2, 2, integer11, MineShaftCorridor.CAVE_AIR, MineShaftCorridor.CAVE_AIR, false, false);
            if (this.spiderCorridor) {
                this.generateMaybeBox(bjx, clb, random, 0.6f, 0, 0, 0, 2, 1, integer11, Blocks.COBWEB.defaultBlockState(), MineShaftCorridor.CAVE_AIR, false, true);
            }
            for (int integer12 = 0; integer12 < this.numSections; ++integer12) {
                final int integer13 = 2 + integer12 * 5;
                this.placeSupport(bjx, clb, 0, 0, integer13, 2, 2, random);
                this.placeCobWeb(bjx, clb, random, 0.1f, 0, 2, integer13 - 1);
                this.placeCobWeb(bjx, clb, random, 0.1f, 2, 2, integer13 - 1);
                this.placeCobWeb(bjx, clb, random, 0.1f, 0, 2, integer13 + 1);
                this.placeCobWeb(bjx, clb, random, 0.1f, 2, 2, integer13 + 1);
                this.placeCobWeb(bjx, clb, random, 0.05f, 0, 2, integer13 - 2);
                this.placeCobWeb(bjx, clb, random, 0.05f, 2, 2, integer13 - 2);
                this.placeCobWeb(bjx, clb, random, 0.05f, 0, 2, integer13 + 2);
                this.placeCobWeb(bjx, clb, random, 0.05f, 2, 2, integer13 + 2);
                if (random.nextInt(100) == 0) {
                    this.createChest(bjx, clb, random, 2, 0, integer13 - 1, BuiltInLootTables.ABANDONED_MINESHAFT);
                }
                if (random.nextInt(100) == 0) {
                    this.createChest(bjx, clb, random, 0, 0, integer13 + 1, BuiltInLootTables.ABANDONED_MINESHAFT);
                }
                if (this.spiderCorridor && !this.hasPlacedSpider) {
                    final int integer14 = this.getWorldY(0);
                    final int integer15 = integer13 - 1 + random.nextInt(3);
                    final int integer16 = this.getWorldX(1, integer15);
                    final int integer17 = this.getWorldZ(1, integer15);
                    final BlockPos fk19 = new BlockPos(integer16, integer14, integer17);
                    if (clb.isInside(fk19) && this.isInterior(bjx, 1, 0, integer15, clb)) {
                        this.hasPlacedSpider = true;
                        bjx.setBlock(fk19, Blocks.SPAWNER.defaultBlockState(), 2);
                        final BlockEntity bwl20 = bjx.getBlockEntity(fk19);
                        if (bwl20 instanceof SpawnerBlockEntity) {
                            ((SpawnerBlockEntity)bwl20).getSpawner().setEntityId(EntityType.CAVE_SPIDER);
                        }
                    }
                }
            }
            for (int integer12 = 0; integer12 <= 2; ++integer12) {
                for (int integer13 = 0; integer13 <= integer11; ++integer13) {
                    final int integer14 = -1;
                    final BlockState byj13 = this.getBlock(bjx, integer12, -1, integer13, clb);
                    if (byj13.isAir() && this.isInterior(bjx, integer12, -1, integer13, clb)) {
                        final int integer16 = -1;
                        this.placeBlock(bjx, byj12, integer12, -1, integer13, clb);
                    }
                }
            }
            if (this.hasRails) {
                final BlockState byj14 = ((AbstractStateHolder<O, BlockState>)Blocks.RAIL.defaultBlockState()).<RailShape, RailShape>setValue(RailBlock.SHAPE, RailShape.NORTH_SOUTH);
                for (int integer13 = 0; integer13 <= integer11; ++integer13) {
                    final BlockState byj15 = this.getBlock(bjx, 1, -1, integer13, clb);
                    if (!byj15.isAir() && byj15.isSolidRender(bjx, new BlockPos(this.getWorldX(1, integer13), this.getWorldY(-1), this.getWorldZ(1, integer13)))) {
                        final float float16 = this.isInterior(bjx, 1, 0, integer13, clb) ? 0.7f : 0.9f;
                        this.maybeGenerateBlock(bjx, clb, random, float16, 1, 0, integer13, byj14);
                    }
                }
            }
            return true;
        }
        
        private void placeSupport(final LevelAccessor bjx, final BoundingBox clb, final int integer3, final int integer4, final int integer5, final int integer6, final int integer7, final Random random) {
            if (!this.isSupportingBox(bjx, clb, integer3, integer7, integer6, integer5)) {
                return;
            }
            final BlockState byj10 = this.getPlanksBlock();
            final BlockState byj11 = this.getFenceBlock();
            this.generateBox(bjx, clb, integer3, integer4, integer5, integer3, integer6 - 1, integer5, ((AbstractStateHolder<O, BlockState>)byj11).<Comparable, Boolean>setValue((Property<Comparable>)FenceBlock.WEST, true), MineShaftCorridor.CAVE_AIR, false);
            this.generateBox(bjx, clb, integer7, integer4, integer5, integer7, integer6 - 1, integer5, ((AbstractStateHolder<O, BlockState>)byj11).<Comparable, Boolean>setValue((Property<Comparable>)FenceBlock.EAST, true), MineShaftCorridor.CAVE_AIR, false);
            if (random.nextInt(4) == 0) {
                this.generateBox(bjx, clb, integer3, integer6, integer5, integer3, integer6, integer5, byj10, MineShaftCorridor.CAVE_AIR, false);
                this.generateBox(bjx, clb, integer7, integer6, integer5, integer7, integer6, integer5, byj10, MineShaftCorridor.CAVE_AIR, false);
            }
            else {
                this.generateBox(bjx, clb, integer3, integer6, integer5, integer7, integer6, integer5, byj10, MineShaftCorridor.CAVE_AIR, false);
                this.maybeGenerateBlock(bjx, clb, random, 0.05f, integer3 + 1, integer6, integer5 - 1, ((AbstractStateHolder<O, BlockState>)Blocks.WALL_TORCH.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)WallTorchBlock.FACING, Direction.NORTH));
                this.maybeGenerateBlock(bjx, clb, random, 0.05f, integer3 + 1, integer6, integer5 + 1, ((AbstractStateHolder<O, BlockState>)Blocks.WALL_TORCH.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)WallTorchBlock.FACING, Direction.SOUTH));
            }
        }
        
        private void placeCobWeb(final LevelAccessor bjx, final BoundingBox clb, final Random random, final float float4, final int integer5, final int integer6, final int integer7) {
            if (this.isInterior(bjx, integer5, integer6, integer7, clb)) {
                this.maybeGenerateBlock(bjx, clb, 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 cmo, final CompoundTag jt) {
            super(StructurePieceType.MINE_SHAFT_CROSSING, jt);
            this.isTwoFloored = jt.getBoolean("tf");
            this.direction = Direction.from2DDataValue(jt.getInt("D"));
        }
        
        @Override
        protected void addAdditionalSaveData(final CompoundTag jt) {
            super.addAdditionalSaveData(jt);
            jt.putBoolean("tf", this.isTwoFloored);
            jt.putInt("D", this.direction.get2DDataValue());
        }
        
        public MineShaftCrossing(final int integer, final BoundingBox clb, @Nullable final Direction fp, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_CROSSING, integer, b);
            this.direction = fp;
            this.boundingBox = clb;
            this.isTwoFloored = (clb.getYSpan() > 3);
        }
        
        public static BoundingBox findCrossing(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fp) {
            final BoundingBox clb7 = new BoundingBox(integer3, integer4, integer5, integer3, integer4 + 3 - 1, integer5);
            if (random.nextInt(4) == 0) {
                final BoundingBox boundingBox = clb7;
                boundingBox.y1 += 4;
            }
            switch (fp) {
                default: {
                    clb7.x0 = integer3 - 1;
                    clb7.x1 = integer3 + 3;
                    clb7.z0 = integer5 - 4;
                    break;
                }
                case SOUTH: {
                    clb7.x0 = integer3 - 1;
                    clb7.x1 = integer3 + 3;
                    clb7.z1 = integer5 + 3 + 1;
                    break;
                }
                case WEST: {
                    clb7.x0 = integer3 - 4;
                    clb7.z0 = integer5 - 1;
                    clb7.z1 = integer5 + 3;
                    break;
                }
                case EAST: {
                    clb7.x1 = integer3 + 3 + 1;
                    clb7.z0 = integer5 - 1;
                    clb7.z1 = integer5 + 3;
                    break;
                }
            }
            if (StructurePiece.findCollisionPiece(list, clb7) != null) {
                return null;
            }
            return clb7;
        }
        
        @Override
        public void addChildren(final StructurePiece clu, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            switch (this.direction) {
                default: {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
                case SOUTH: {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
                case WEST: {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                    break;
                }
                case EAST: {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                    generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                    break;
                }
            }
            if (this.isTwoFloored) {
                if (random.nextBoolean()) {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 + 1, Direction.WEST, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z0 + 1, Direction.EAST, integer5);
                }
                if (random.nextBoolean()) {
                    generateAndAddPiece(clu, list, random, this.boundingBox.x0 + 1, this.boundingBox.y0 + 3 + 1, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                }
            }
        }
        
        @Override
        public boolean postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            if (this.edgesLiquid(bjx, clb)) {
                return false;
            }
            final BlockState byj7 = this.getPlanksBlock();
            if (this.isTwoFloored) {
                this.generateBox(bjx, clb, 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(bjx, clb, 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(bjx, clb, 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(bjx, clb, 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(bjx, clb, 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(bjx, clb, 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(bjx, clb, 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(bjx, clb, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.y1);
            this.placeSupportPillar(bjx, clb, this.boundingBox.x0 + 1, this.boundingBox.y0, this.boundingBox.z1 - 1, this.boundingBox.y1);
            this.placeSupportPillar(bjx, clb, this.boundingBox.x1 - 1, this.boundingBox.y0, this.boundingBox.z0 + 1, this.boundingBox.y1);
            this.placeSupportPillar(bjx, clb, this.boundingBox.x1 - 1, this.boundingBox.y0, this.boundingBox.z1 - 1, this.boundingBox.y1);
            for (int integer8 = this.boundingBox.x0; integer8 <= this.boundingBox.x1; ++integer8) {
                for (int integer9 = this.boundingBox.z0; integer9 <= this.boundingBox.z1; ++integer9) {
                    if (this.getBlock(bjx, integer8, this.boundingBox.y0 - 1, integer9, clb).isAir() && this.isInterior(bjx, integer8, this.boundingBox.y0 - 1, integer9, clb)) {
                        this.placeBlock(bjx, byj7, integer8, this.boundingBox.y0 - 1, integer9, clb);
                    }
                }
            }
            return true;
        }
        
        private void placeSupportPillar(final LevelAccessor bjx, final BoundingBox clb, final int integer3, final int integer4, final int integer5, final int integer6) {
            if (!this.getBlock(bjx, integer3, integer6 + 1, integer5, clb).isAir()) {
                this.generateBox(bjx, clb, 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 clb, final Direction fp, final MineshaftFeature.Type b) {
            super(StructurePieceType.MINE_SHAFT_STAIRS, integer, b);
            this.setOrientation(fp);
            this.boundingBox = clb;
        }
        
        public MineShaftStairs(final StructureManager cmo, final CompoundTag jt) {
            super(StructurePieceType.MINE_SHAFT_STAIRS, jt);
        }
        
        public static BoundingBox findStairs(final List<StructurePiece> list, final Random random, final int integer3, final int integer4, final int integer5, final Direction fp) {
            final BoundingBox clb7 = new BoundingBox(integer3, integer4 - 5, integer5, integer3, integer4 + 3 - 1, integer5);
            switch (fp) {
                default: {
                    clb7.x1 = integer3 + 3 - 1;
                    clb7.z0 = integer5 - 8;
                    break;
                }
                case SOUTH: {
                    clb7.x1 = integer3 + 3 - 1;
                    clb7.z1 = integer5 + 8;
                    break;
                }
                case WEST: {
                    clb7.x0 = integer3 - 8;
                    clb7.z1 = integer5 + 3 - 1;
                    break;
                }
                case EAST: {
                    clb7.x1 = integer3 + 8;
                    clb7.z1 = integer5 + 3 - 1;
                    break;
                }
            }
            if (StructurePiece.findCollisionPiece(list, clb7) != null) {
                return null;
            }
            return clb7;
        }
        
        @Override
        public void addChildren(final StructurePiece clu, final List<StructurePiece> list, final Random random) {
            final int integer5 = this.getGenDepth();
            final Direction fp6 = this.getOrientation();
            if (fp6 != null) {
                switch (fp6) {
                    default: {
                        generateAndAddPiece(clu, list, random, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z0 - 1, Direction.NORTH, integer5);
                        break;
                    }
                    case SOUTH: {
                        generateAndAddPiece(clu, list, random, this.boundingBox.x0, this.boundingBox.y0, this.boundingBox.z1 + 1, Direction.SOUTH, integer5);
                        break;
                    }
                    case WEST: {
                        generateAndAddPiece(clu, list, random, this.boundingBox.x0 - 1, this.boundingBox.y0, this.boundingBox.z0, Direction.WEST, integer5);
                        break;
                    }
                    case EAST: {
                        generateAndAddPiece(clu, list, random, this.boundingBox.x1 + 1, this.boundingBox.y0, this.boundingBox.z0, Direction.EAST, integer5);
                        break;
                    }
                }
            }
        }
        
        @Override
        public boolean postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            if (this.edgesLiquid(bjx, clb)) {
                return false;
            }
            this.generateBox(bjx, clb, 0, 5, 0, 2, 7, 1, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            this.generateBox(bjx, clb, 0, 0, 7, 2, 2, 8, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            for (int integer7 = 0; integer7 < 5; ++integer7) {
                this.generateBox(bjx, clb, 0, 5 - integer7 - ((integer7 < 4) ? 1 : 0), 2 + integer7, 2, 7 - integer7, 2 + integer7, MineShaftStairs.CAVE_AIR, MineShaftStairs.CAVE_AIR, false);
            }
            return true;
        }
    }
}
