// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.universe.world.connectedblocks.builtin;

import com.hypixel.hytale.protocol.ConnectedBlockRuleSetType;
import javax.annotation.Nullable;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import java.util.Map;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockFace;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockFaceSupport;
import com.hypixel.hytale.server.core.universe.world.connectedblocks.ConnectedBlocksUtil;
import java.util.Optional;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.server.core.util.FillerBlockUtil;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.universe.world.connectedblocks.ConnectedBlockRuleSet;

public class RoofConnectedBlockRuleSet extends ConnectedBlockRuleSet implements StairLikeConnectedBlockRuleSet
{
    public static final BuilderCodec<RoofConnectedBlockRuleSet> CODEC;
    private StairConnectedBlockRuleSet regular;
    private StairConnectedBlockRuleSet hollow;
    private ConnectedBlockOutput topper;
    private String materialName;
    private int width;
    
    public RoofConnectedBlockRuleSet() {
        this.width = 1;
    }
    
    private static StairConnectedBlockRuleSet.StairType getConnectedBlockStairType(final World world, final Vector3i coordinate, final StairLikeConnectedBlockRuleSet currentRuleSet, final int blockId, final int rotation, final int width) {
        final RotationTuple currentRotation = RotationTuple.get(rotation);
        Rotation currentYaw = currentRotation.yaw();
        final Rotation currentPitch = currentRotation.pitch();
        final boolean upsideDown = currentPitch != Rotation.None;
        if (upsideDown) {
            currentYaw = currentYaw.flip();
        }
        final Vector3i mutablePos = new Vector3i();
        StairConnectedBlockRuleSet.StairType resultingStair = StairConnectedBlockRuleSet.StairType.STRAIGHT;
        final StairConnectedBlockRuleSet.StairConnection frontConnection = StairConnectedBlockRuleSet.getInvertedCornerConnection(world, currentRuleSet, coordinate, mutablePos, currentYaw, upsideDown);
        if (frontConnection != null) {
            final boolean valid = isWidthFulfilled(world, coordinate, mutablePos, frontConnection, currentYaw, blockId, rotation, width);
            if (valid) {
                resultingStair = frontConnection.getStairType(true);
            }
        }
        final StairConnectedBlockRuleSet.StairConnection backConnection = StairConnectedBlockRuleSet.getCornerConnection(world, currentRuleSet, coordinate, mutablePos, rotation, currentYaw, upsideDown, width);
        if (backConnection != null) {
            final boolean valid2 = isWidthFulfilled(world, coordinate, mutablePos, backConnection, currentYaw, blockId, rotation, width);
            if (valid2) {
                resultingStair = backConnection.getStairType(false);
            }
        }
        if (resultingStair == StairConnectedBlockRuleSet.StairType.STRAIGHT) {
            final Vector3i aboveCoordinate = new Vector3i(coordinate).add(0, 1, 0);
            final StairConnectedBlockRuleSet.StairConnection resultingConnection = getValleyConnection(world, coordinate, aboveCoordinate, currentRuleSet, currentRotation, mutablePos, false, blockId, rotation, width);
            if (resultingConnection != null) {
                resultingStair = resultingConnection.getStairType(true);
            }
        }
        if (resultingStair == StairConnectedBlockRuleSet.StairType.STRAIGHT) {
            final Vector3i belowCoordinate = new Vector3i(coordinate).add(0, -1, 0);
            final StairConnectedBlockRuleSet.StairConnection resultingConnection = getValleyConnection(world, coordinate, belowCoordinate, currentRuleSet, currentRotation, mutablePos, true, blockId, rotation, width);
            if (resultingConnection != null) {
                resultingStair = resultingConnection.getStairType(false);
            }
        }
        if (upsideDown) {
            resultingStair = switch (resultingStair) {
                case CORNER_LEFT -> StairConnectedBlockRuleSet.StairType.CORNER_RIGHT;
                case CORNER_RIGHT -> StairConnectedBlockRuleSet.StairType.CORNER_LEFT;
                case INVERTED_CORNER_LEFT -> StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_RIGHT;
                case INVERTED_CORNER_RIGHT -> StairConnectedBlockRuleSet.StairType.INVERTED_CORNER_LEFT;
                default -> resultingStair;
            };
        }
        return resultingStair;
    }
    
    private static boolean isWidthFulfilled(final World world, final Vector3i coordinate, final Vector3i mutablePos, final StairConnectedBlockRuleSet.StairConnection backConnection, final Rotation currentYaw, final int blockId, final int rotation, final int width) {
        boolean valid = true;
        for (int i = 0; i < width - 1; ++i) {
            mutablePos.assign((backConnection == StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT) ? Vector3i.WEST : Vector3i.EAST).scale(i + 1);
            currentYaw.rotateY(mutablePos, mutablePos);
            final int requiredFiller = FillerBlockUtil.pack(mutablePos.x, mutablePos.y, mutablePos.z);
            mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
            final WorldChunk chunk = world.getChunkIfLoaded(ChunkUtil.indexChunkFromBlock(mutablePos.x, mutablePos.z));
            if (chunk != null) {
                final int otherRotation = chunk.getRotationIndex(mutablePos.x, mutablePos.y, mutablePos.z);
                final int otherFiller = chunk.getFiller(mutablePos.x, mutablePos.y, mutablePos.z);
                final int otherBlockId = chunk.getBlock(mutablePos);
                if ((otherFiller != 0 || otherBlockId != blockId || otherRotation != rotation) && (otherFiller != requiredFiller || otherBlockId != blockId || otherRotation != rotation)) {
                    valid = false;
                    break;
                }
            }
        }
        return valid;
    }
    
    private static StairConnectedBlockRuleSet.StairConnection getValleyConnection(final World world, final Vector3i placementCoordinate, final Vector3i checkCoordinate, final StairLikeConnectedBlockRuleSet currentRuleSet, final RotationTuple rotation, final Vector3i mutablePos, final boolean reverse, final int blockId, final int blockRotation, final int width) {
        final Rotation yaw = rotation.yaw();
        mutablePos.assign(reverse ? Vector3i.SOUTH : Vector3i.NORTH).scale(width);
        yaw.rotateY(mutablePos, mutablePos);
        mutablePos.add(checkCoordinate.x, checkCoordinate.y, checkCoordinate.z);
        final ObjectIntPair<StairConnectedBlockRuleSet.StairType> backStair = StairConnectedBlockRuleSet.getStairData(world, mutablePos, currentRuleSet.getMaterialName());
        if (backStair == null) {
            return null;
        }
        final boolean backConnection = reverse ? isTopperConnectionCompatible(rotation, backStair, Rotation.None) : isValleyConnectionCompatible(rotation, backStair, Rotation.None, false);
        if (!backConnection) {
            return null;
        }
        mutablePos.assign(reverse ? Vector3i.EAST : Vector3i.WEST).scale(width);
        yaw.rotateY(mutablePos, mutablePos);
        mutablePos.add(checkCoordinate.x, checkCoordinate.y, checkCoordinate.z);
        final ObjectIntPair<StairConnectedBlockRuleSet.StairType> leftStair = StairConnectedBlockRuleSet.getStairData(world, mutablePos, currentRuleSet.getMaterialName());
        mutablePos.assign(reverse ? Vector3i.WEST : Vector3i.EAST).scale(width);
        yaw.rotateY(mutablePos, mutablePos);
        mutablePos.add(checkCoordinate.x, checkCoordinate.y, checkCoordinate.z);
        final ObjectIntPair<StairConnectedBlockRuleSet.StairType> rightStair = StairConnectedBlockRuleSet.getStairData(world, mutablePos, currentRuleSet.getMaterialName());
        final boolean leftConnection = reverse ? isTopperConnectionCompatible(rotation, leftStair, Rotation.Ninety) : isValleyConnectionCompatible(rotation, leftStair, Rotation.Ninety, false);
        final boolean rightConnection = reverse ? isTopperConnectionCompatible(rotation, rightStair, Rotation.TwoSeventy) : isValleyConnectionCompatible(rotation, rightStair, Rotation.TwoSeventy, false);
        if (leftConnection == rightConnection) {
            return null;
        }
        final StairConnectedBlockRuleSet.StairConnection connection = leftConnection ? StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT : StairConnectedBlockRuleSet.StairConnection.CORNER_RIGHT;
        if (!isWidthFulfilled(world, placementCoordinate, mutablePos, connection, yaw, blockId, blockRotation, width)) {
            return null;
        }
        return connection;
    }
    
    private static boolean isTopperConnectionCompatible(final RotationTuple rotation, final ObjectIntPair<StairConnectedBlockRuleSet.StairType> otherStair, final Rotation yawOffset) {
        return isValleyConnectionCompatible(rotation, otherStair, yawOffset, true);
    }
    
    private static boolean canBeTopper(final World world, final Vector3i coordinate, final StairLikeConnectedBlockRuleSet currentRuleSet, final RotationTuple rotation, final Vector3i mutablePos) {
        final Rotation yaw = rotation.yaw();
        final Vector3i[] directions = { Vector3i.NORTH, Vector3i.SOUTH, Vector3i.EAST, Vector3i.WEST };
        final Rotation[] yawOffsets = { Rotation.OneEighty, Rotation.None, Rotation.Ninety, Rotation.TwoSeventy };
        for (int i = 0; i < directions.length; ++i) {
            mutablePos.assign(directions[i]);
            yaw.rotateY(mutablePos, mutablePos);
            mutablePos.add(coordinate.x, coordinate.y, coordinate.z);
            final ObjectIntPair<StairConnectedBlockRuleSet.StairType> stair = StairConnectedBlockRuleSet.getStairData(world, mutablePos, currentRuleSet.getMaterialName());
            if (stair == null || !isTopperConnectionCompatible(rotation, stair, yawOffsets[i])) {
                return false;
            }
        }
        return true;
    }
    
    private static boolean isValleyConnectionCompatible(final RotationTuple rotation, final ObjectIntPair<StairConnectedBlockRuleSet.StairType> otherStair, final Rotation yawOffset, final boolean inverted) {
        final Rotation targetYaw = rotation.yaw().add(yawOffset);
        if (otherStair == null) {
            return false;
        }
        final RotationTuple stairRotation = RotationTuple.get(otherStair.rightInt());
        final StairConnectedBlockRuleSet.StairType otherStairType = otherStair.first();
        return stairRotation.pitch() == rotation.pitch() && (!inverted || !otherStairType.isCorner()) && (inverted || !otherStairType.isInvertedCorner()) && (stairRotation.yaw() == targetYaw || (otherStairType == StairConnectedBlockRuleSet.StairConnection.CORNER_RIGHT.getStairType(inverted) && stairRotation.yaw() == targetYaw.add(Rotation.Ninety)) || (otherStairType == StairConnectedBlockRuleSet.StairConnection.CORNER_LEFT.getStairType(inverted) && stairRotation.yaw() == targetYaw.add(Rotation.TwoSeventy)));
    }
    
    @Override
    public boolean onlyUpdateOnPlacement() {
        return false;
    }
    
    @Override
    public Optional<ConnectedBlocksUtil.ConnectedBlockResult> getConnectedBlockType(final World world, final Vector3i coordinate, final BlockType blockType, final int rotation, final Vector3i placementNormal, final boolean isPlacement) {
        final WorldChunk chunk = world.getChunkIfLoaded(ChunkUtil.indexChunkFromBlock(coordinate.x, coordinate.z));
        if (chunk == null) {
            return Optional.empty();
        }
        final int belowBlockId = chunk.getBlock(coordinate.x, coordinate.y - 1, coordinate.z);
        final BlockType belowBlockType = BlockType.getAssetMap().getAsset(belowBlockId);
        final int belowBlockRotation = chunk.getRotationIndex(coordinate.x, coordinate.y - 1, coordinate.z);
        boolean hollow = true;
        if (belowBlockType != null) {
            final Map<BlockFace, BlockFaceSupport[]> supporting = belowBlockType.getSupporting(belowBlockRotation);
            if (supporting != null) {
                final BlockFaceSupport[] support = supporting.get(BlockFace.UP);
                hollow = (support == null);
            }
        }
        final int blockId = BlockType.getAssetMap().getIndex(blockType.getId());
        final StairConnectedBlockRuleSet.StairType stairType = getConnectedBlockStairType(world, coordinate, this, blockId, rotation, this.width);
        if (this.topper != null && stairType == StairConnectedBlockRuleSet.StairType.STRAIGHT) {
            final Vector3i belowCoordinate = new Vector3i(coordinate).add(0, -1, 0);
            RotationTuple currentRotation = RotationTuple.get(rotation);
            currentRotation = RotationTuple.of(Rotation.None, currentRotation.pitch(), currentRotation.roll());
            final Vector3i mutablePos = new Vector3i();
            final boolean topper = canBeTopper(world, belowCoordinate, this, currentRotation, mutablePos);
            if (topper) {
                final BlockType topperBlockType = BlockType.getAssetMap().getAsset(this.topper.blockTypeKey);
                if (topperBlockType != null) {
                    return Optional.of(new ConnectedBlocksUtil.ConnectedBlockResult(topperBlockType.getId(), rotation));
                }
            }
        }
        if (this.hollow != null && hollow) {
            final BlockType hollowBlockType = this.hollow.getStairBlockType(stairType);
            if (hollowBlockType != null) {
                return Optional.of(new ConnectedBlocksUtil.ConnectedBlockResult(hollowBlockType.getId(), rotation));
            }
        }
        final BlockType regularBlockType = this.regular.getStairBlockType(stairType);
        if (regularBlockType != null) {
            final ConnectedBlocksUtil.ConnectedBlockResult result = new ConnectedBlocksUtil.ConnectedBlockResult(regularBlockType.getId(), rotation);
            if (this.regular != null && this.width > 0) {
                final StairConnectedBlockRuleSet.StairType existingStairType = this.regular.getStairType(BlockType.getAssetMap().getIndex(blockType.getId()));
                if (existingStairType != null && existingStairType != StairConnectedBlockRuleSet.StairType.STRAIGHT) {
                    final int previousWidth = existingStairType.isLeft() ? (-(this.width - 1)) : (existingStairType.isRight() ? (this.width - 1) : 0);
                    final int newWidth = stairType.isLeft() ? (-(this.width - 1)) : (stairType.isRight() ? (this.width - 1) : 0);
                    if (newWidth != previousWidth) {
                        final Vector3i mutablePos2 = new Vector3i();
                        final Rotation currentYaw = RotationTuple.get(rotation).yaw();
                        mutablePos2.assign(Vector3i.EAST).scale(previousWidth);
                        currentYaw.rotateY(mutablePos2, mutablePos2);
                        result.addAdditionalBlock(mutablePos2, regularBlockType.getId(), rotation);
                    }
                }
            }
            return Optional.of(result);
        }
        return Optional.empty();
    }
    
    @Override
    public void updateCachedBlockTypes(final BlockType baseBlockType, final BlockTypeAssetMap<String, BlockType> assetMap) {
        if (this.regular != null) {
            this.regular.updateCachedBlockTypes(baseBlockType, assetMap);
        }
        if (this.hollow != null) {
            this.hollow.updateCachedBlockTypes(baseBlockType, assetMap);
        }
        if (this.topper != null) {
            this.topper.resolve(baseBlockType, assetMap);
        }
    }
    
    @Override
    public StairConnectedBlockRuleSet.StairType getStairType(final int blockId) {
        final StairConnectedBlockRuleSet.StairType regularStairType = this.regular.getStairType(blockId);
        if (regularStairType != null) {
            return regularStairType;
        }
        if (this.hollow != null) {
            return this.hollow.getStairType(blockId);
        }
        return null;
    }
    
    @Nullable
    @Override
    public String getMaterialName() {
        return this.materialName;
    }
    
    @Nullable
    @Override
    public com.hypixel.hytale.protocol.ConnectedBlockRuleSet toPacket(final BlockTypeAssetMap<String, BlockType> assetMap) {
        final com.hypixel.hytale.protocol.ConnectedBlockRuleSet packet = new com.hypixel.hytale.protocol.ConnectedBlockRuleSet();
        packet.type = ConnectedBlockRuleSetType.Roof;
        final com.hypixel.hytale.protocol.RoofConnectedBlockRuleSet roofPacket = new com.hypixel.hytale.protocol.RoofConnectedBlockRuleSet();
        if (this.regular != null) {
            roofPacket.regular = this.regular.toProtocol(assetMap);
        }
        if (this.hollow != null) {
            roofPacket.hollow = this.hollow.toProtocol(assetMap);
        }
        if (this.topper != null) {
            roofPacket.topperBlockId = assetMap.getIndex(this.topper.blockTypeKey);
        }
        else {
            roofPacket.topperBlockId = -1;
        }
        roofPacket.width = this.width;
        roofPacket.materialName = this.materialName;
        packet.roof = roofPacket;
        return packet;
    }
    
    static {
        // 
        // This method could not be decompiled.
        // 
        // Original Bytecode:
        // 
        //     2: invokedynamic   BootstrapMethod #0, get:()Ljava/util/function/Supplier;
        //     7: invokestatic    com/hypixel/hytale/codec/builder/BuilderCodec.builder:(Ljava/lang/Class;Ljava/util/function/Supplier;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    10: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    13: dup            
        //    14: ldc_w           "Regular"
        //    17: getstatic       com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //    20: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    23: invokedynamic   BootstrapMethod #1, accept:()Ljava/util/function/BiConsumer;
        //    28: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/Function;
        //    33: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    36: invokestatic    com/hypixel/hytale/codec/validation/Validators.nonNull:()Lcom/hypixel/hytale/codec/validation/Validator;
        //    39: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.addValidator:(Lcom/hypixel/hytale/codec/validation/Validator;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    42: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //    45: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    48: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    51: dup            
        //    52: ldc_w           "Hollow"
        //    55: getstatic       com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/StairConnectedBlockRuleSet.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //    58: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    61: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
        //    66: invokedynamic   BootstrapMethod #4, apply:()Ljava/util/function/Function;
        //    71: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //    74: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //    77: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //    80: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //    83: dup            
        //    84: ldc_w           "Topper"
        //    87: getstatic       com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/ConnectedBlockOutput.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //    90: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //    93: invokedynamic   BootstrapMethod #5, accept:()Ljava/util/function/BiConsumer;
        //    98: invokedynamic   BootstrapMethod #6, apply:()Ljava/util/function/Function;
        //   103: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   106: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   109: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   112: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //   115: dup            
        //   116: ldc_w           "Width"
        //   119: new             Lcom/hypixel/hytale/codec/codecs/simple/IntegerCodec;
        //   122: dup            
        //   123: invokespecial   com/hypixel/hytale/codec/codecs/simple/IntegerCodec.<init>:()V
        //   126: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //   129: invokedynamic   BootstrapMethod #7, accept:()Ljava/util/function/BiConsumer;
        //   134: invokedynamic   BootstrapMethod #8, apply:()Ljava/util/function/Function;
        //   139: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   142: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   145: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   148: new             Lcom/hypixel/hytale/codec/KeyedCodec;
        //   151: dup            
        //   152: ldc_w           "MaterialName"
        //   155: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
        //   158: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
        //   161: invokedynamic   BootstrapMethod #9, accept:()Ljava/util/function/BiConsumer;
        //   166: invokedynamic   BootstrapMethod #10, apply:()Ljava/util/function/Function;
        //   171: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
        //   174: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
        //   177: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
        //   180: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   183: putstatic       com/hypixel/hytale/server/core/universe/world/connectedblocks/builtin/RoofConnectedBlockRuleSet.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
        //   186: return         
        // 
        // The error that occurred was:
        // 
        // java.lang.UnsupportedOperationException: The requested operation is not supported.
        //     at com.strobel.util.ContractUtils.unsupported(ContractUtils.java:27)
        //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:284)
        //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:279)
        //     at com.strobel.assembler.metadata.TypeReference.makeGenericType(TypeReference.java:154)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:225)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
        //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:211)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
        //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
        //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:314)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2611)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
        //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1083)
        //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:684)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:667)
        //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:373)
        //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:344)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:42)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:206)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
        //     at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
        //     at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
        //     at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:129)
        // 
        throw new IllegalStateException("An error occurred while decompiling this method.");
    }
}
