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

package com.hypixel.hytale.server.npc.pages;

import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.npc.asset.builder.Builder;
import com.hypixel.hytale.server.npc.asset.builder.BuilderInfo;
import com.hypixel.hytale.server.spawning.SpawningContext;
import com.hypixel.hytale.server.spawning.ISpawnableWithModel;
import com.hypixel.hytale.server.core.command.system.exceptions.GeneralCommandException;
import com.hypixel.hytale.component.NonSerialized;
import com.hypixel.hytale.math.vector.Vector3i;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.util.TargetUtil;
import com.hypixel.hytale.math.vector.Transform;
import com.hypixel.hytale.server.core.modules.entity.component.EntityScaleComponent;
import com.hypixel.hytale.server.core.entity.entities.BlockEntity;
import com.hypixel.hytale.server.core.modules.entity.item.PreventItemMerging;
import com.hypixel.hytale.server.core.modules.entity.item.PreventPickup;
import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import java.util.Set;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import java.util.HashSet;
import java.util.stream.Stream;
import java.util.Iterator;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.ToIntFunction;
import java.util.Comparator;
import java.util.Objects;
import com.hypixel.hytale.common.util.StringCompareUtil;
import java.util.Locale;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.modules.entity.component.PropComponent;
import java.util.Map;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.server.core.modules.entity.tracker.NetworkId;
import com.hypixel.hytale.protocol.packets.interface_.Page;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.npc.NPCPlugin;
import com.hypixel.hytale.server.core.ui.ItemGridSlot;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.ui.builder.EventData;
import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import javax.annotation.Nullable;
import java.util.List;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.ui.Value;
import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage;

public class EntitySpawnPage extends InteractiveCustomUIPage<EntitySpawnPageEventData>
{
    private static final String COMMON_TEXT_BUTTON_DOCUMENT = "Common/TextButton.ui";
    private static final String COMMON_UI_DOCUMENT = "Common.ui";
    private static final Value<String> BUTTON_LABEL_STYLE;
    private static final Value<String> BUTTON_LABEL_STYLE_SELECTED;
    private static final Value<String> TAB_STYLE_ACTIVE;
    private static final Value<String> TAB_STYLE_INACTIVE;
    private static final String TAB_NPC = "NPC";
    private static final String TAB_ITEMS = "Items";
    private static final String TAB_MODEL = "Model";
    private static final String KEY_SELECT_AN_ITEM = "server.customUI.entitySpawnPage.selectAnItem";
    private static final String KEY_SELECT_AN_NPC = "server.customUI.entitySpawnPage.selectAnNpc";
    private static final String KEY_SELECT_A_MODEL = "server.customUI.entitySpawnPage.selectAModel";
    private static final int MAX_SPAWN_COUNT = 100;
    private static final float BLOCK_ENTITY_BASE_SCALE = 2.0f;
    private static final int LOOK_RAYCAST_DISTANCE = 4;
    private static final int FALLBACK_RAYCAST_DOWN_DISTANCE = 3;
    private static final double FALLBACK_RAYCAST_Y_OFFSET = 0.5;
    @Nonnull
    private String activeTab;
    @Nonnull
    private String searchQuery;
    private List<String> npcRoles;
    @Nullable
    private String selectedNpcRole;
    private List<String> modelIds;
    @Nullable
    private String selectedModelId;
    @Nullable
    private String selectedItemId;
    @Nullable
    private Ref<EntityStore> modelPreview;
    private Vector3d position;
    private Vector3f rotation;
    private float currentRotationOffset;
    private float currentScale;
    private float lastPreviewScale;
    private long lastScaleUpdateTime;
    
    public EntitySpawnPage(@Nonnull final PlayerRef playerRef) {
        super(playerRef, CustomPageLifetime.CanDismiss, EntitySpawnPageEventData.CODEC);
        this.activeTab = "NPC";
        this.searchQuery = "";
        this.currentRotationOffset = 0.0f;
        this.currentScale = 1.0f;
        this.lastPreviewScale = 1.0f;
        this.lastScaleUpdateTime = 0L;
    }
    
    @Override
    public void build(@Nonnull final Ref<EntityStore> ref, @Nonnull final UICommandBuilder commandBuilder, @Nonnull final UIEventBuilder eventBuilder, @Nonnull final Store<EntityStore> store) {
        commandBuilder.append("Pages/EntitySpawnPage.ui");
        eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#SearchInput", EventData.of("@SearchQuery", "#SearchInput.Value"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#RotationOffset", new EventData().append("Type", "UpdateRotationOffset").append("@RotationOffset", "#RotationOffset.Value"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.ValueChanged, "#ScaleSlider", new EventData().append("Type", "UpdateScale").append("@Scale", "#ScaleSlider.Value"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.MouseButtonReleased, "#ScaleSlider", new EventData().append("Type", "ScaleReleased").append("@Scale", "#ScaleSlider.Value"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#Spawn", new EventData().append("Type", "Spawn").append("@Count", "#Count.Value").append("@Scale", "#ScaleSlider.Value"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#TabNPC", new EventData().append("Type", "TabSwitch").append("Tab", "NPC"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#TabItems", new EventData().append("Type", "TabSwitch").append("Tab", "Items"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#TabModel", new EventData().append("Type", "TabSwitch").append("Tab", "Model"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Dropped, "#ItemMaterialSlot", new EventData().append("Type", "SetItemMaterial"), false);
        eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#ClearMaterial", new EventData().append("Type", "ClearMaterial"), false);
        this.buildList(ref, store, commandBuilder, eventBuilder);
    }
    
    @Override
    public void handleDataEvent(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final EntitySpawnPageEventData data) {
        if (data.searchQuery != null) {
            this.searchQuery = data.searchQuery.trim().toLowerCase();
            final UICommandBuilder commandBuilder = new UICommandBuilder();
            final UIEventBuilder eventBuilder = new UIEventBuilder();
            this.buildList(ref, store, commandBuilder, eventBuilder);
            this.sendUpdate(commandBuilder, eventBuilder, false);
        }
        else {
            final String type = data.type;
            switch (type) {
                case "TabSwitch": {
                    if (data.tab != null && !data.tab.equals(this.activeTab)) {
                        this.activeTab = data.tab;
                        this.searchQuery = "";
                        this.clearPreview(store);
                        final UICommandBuilder commandBuilder2 = new UICommandBuilder();
                        final UIEventBuilder eventBuilder2 = new UIEventBuilder();
                        this.updateTabVisibility(commandBuilder2);
                        commandBuilder2.set("#SearchInput.Value", "");
                        this.buildList(ref, store, commandBuilder2, eventBuilder2);
                        this.sendUpdate(commandBuilder2, eventBuilder2, false);
                        break;
                    }
                    break;
                }
                case "Select": {
                    this.handleSelect(ref, store, data);
                    break;
                }
                case "SetItemMaterial": {
                    this.handleSetItemMaterial(ref, store, data);
                    break;
                }
                case "ClearMaterial": {
                    this.clearSelectedItem(ref, store);
                    break;
                }
                case "UpdateRotationOffset": {
                    this.currentRotationOffset = (float)Math.toRadians(data.rotationOffset);
                    if (this.modelPreview != null && this.modelPreview.isValid()) {
                        final TransformComponent transform = store.getComponent(this.modelPreview, TransformComponent.getComponentType());
                        transform.getRotation().setYaw(this.rotation.getYaw() + this.currentRotationOffset);
                        final HeadRotation headRotation = store.getComponent(this.modelPreview, HeadRotation.getComponentType());
                        if (headRotation != null) {
                            headRotation.getRotation().setYaw(this.rotation.getYaw() + this.currentRotationOffset);
                        }
                        break;
                    }
                    break;
                }
                case "UpdateScale": {
                    if (data.scale != null && data.scale >= 0.1f) {
                        this.currentScale = data.scale;
                        final UICommandBuilder commandBuilder2 = new UICommandBuilder();
                        commandBuilder2.set("#ScaleValue.Text", String.format("%.1f", this.currentScale));
                        this.sendUpdate(commandBuilder2, null, false);
                        final long now = System.currentTimeMillis();
                        if (this.modelPreview != null && this.modelPreview.isValid() && this.currentScale != this.lastPreviewScale && now - this.lastScaleUpdateTime >= 200L) {
                            this.lastScaleUpdateTime = now;
                            this.lastPreviewScale = this.currentScale;
                            this.updatePreviewScale(ref, store);
                        }
                        break;
                    }
                    break;
                }
                case "ScaleReleased": {
                    if (data.scale == null || data.scale < 0.1f) {
                        break;
                    }
                    this.currentScale = data.scale;
                    if ("Model".equals(this.activeTab) && this.selectedModelId != null) {
                        final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(this.selectedModelId);
                        if (modelAsset != null) {
                            final UICommandBuilder commandBuilder3 = new UICommandBuilder();
                            this.createOrUpdatePreview(ref, store, commandBuilder3, Model.createStaticScaledModel(modelAsset, this.currentScale));
                        }
                        break;
                    }
                    if ("Items".equals(this.activeTab) && this.selectedItemId != null) {
                        final Item item = Item.getAssetMap().getAsset(this.selectedItemId);
                        if (item != null) {
                            final Model model = this.getItemModel(item);
                            if (model != null) {
                                final UICommandBuilder commandBuilder4 = new UICommandBuilder();
                                this.createOrUpdatePreview(ref, store, commandBuilder4, model);
                            }
                            else if (item.hasBlockType()) {
                                this.createOrUpdateBlockPreview(ref, store, this.selectedItemId);
                            }
                            else {
                                this.createOrUpdateItemPreview(ref, store, this.selectedItemId);
                            }
                        }
                        break;
                    }
                    break;
                }
                case "Spawn": {
                    this.handleSpawn(ref, store, data);
                    break;
                }
            }
        }
    }
    
    private void handleSelect(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final EntitySpawnPageEventData data) {
        final UICommandBuilder commandBuilder = new UICommandBuilder();
        final String activeTab = this.activeTab;
        switch (activeTab) {
            case "NPC": {
                if (data.npcRole != null) {
                    this.selectNPCRole(ref, store, data.npcRole, commandBuilder);
                    break;
                }
                break;
            }
            case "Items": {
                if (data.itemId != null) {
                    this.selectItem(ref, store, data.itemId, commandBuilder);
                    break;
                }
                break;
            }
            case "Model": {
                if (data.modelId != null) {
                    this.selectModel(ref, store, data.modelId, commandBuilder);
                    break;
                }
                break;
            }
        }
        this.sendUpdate(commandBuilder, null, false);
    }
    
    private void handleSetItemMaterial(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final EntitySpawnPageEventData data) {
        if (data.itemStackId == null) {
            return;
        }
        final UICommandBuilder commandBuilder = new UICommandBuilder();
        this.selectItem(ref, store, data.itemStackId, commandBuilder);
        this.sendUpdate(commandBuilder, null, false);
    }
    
    private void clearSelectedItem(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        this.selectedItemId = null;
        this.clearPreview(store);
        final UICommandBuilder commandBuilder = new UICommandBuilder();
        commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAnItem"));
        commandBuilder.set("#ItemMaterialSlot.Slots", new ItemGridSlot[] { new ItemGridSlot() });
        commandBuilder.set("#ClearMaterial.Visible", false);
        commandBuilder.set("#DropIndicator.Visible", true);
        this.sendUpdate(commandBuilder, null, false);
    }
    
    private void handleSpawn(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final EntitySpawnPageEventData data) {
        final String activeTab = this.activeTab;
        switch (activeTab) {
            case "NPC": {
                this.spawnNPC(ref, store, data.count);
                break;
            }
            case "Items": {
                this.spawnItem(ref, store, data.count);
                break;
            }
            case "Model": {
                this.spawnModel(ref, store, data.count);
                break;
            }
        }
    }
    
    private void spawnNPC(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, final int count) {
        if (this.selectedNpcRole == null || this.position == null || this.rotation == null) {
            return;
        }
        if (count < 1 || count > 100) {
            return;
        }
        this.clearPreview(store);
        final Vector3f spawnRotation = this.rotation.clone();
        spawnRotation.setYaw(this.rotation.getYaw() + this.currentRotationOffset);
        for (int i = 0; i < count; ++i) {
            NPCPlugin.get().spawnNPC(store, this.selectedNpcRole, null, this.position, spawnRotation);
        }
        store.getComponent(ref, Player.getComponentType()).getPageManager().setPage(ref, store, Page.None);
        this.playerRef.sendMessage(Message.translation((count == 1) ? "server.npc.spawn.spawnedOne" : "server.npc.spawn.spawnedMany").param("quantity", count).param("type", this.selectedNpcRole));
    }
    
    private void spawnModel(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, final int count) {
        if (this.selectedModelId == null || this.position == null || this.rotation == null) {
            return;
        }
        if (count < 1 || count > 100) {
            return;
        }
        this.clearPreview(store);
        final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(this.selectedModelId);
        if (modelAsset == null) {
            return;
        }
        final Model model = Model.createStaticScaledModel(modelAsset, this.currentScale);
        final Vector3f spawnRotation = this.rotation.clone();
        spawnRotation.setYaw(this.rotation.getYaw() + this.currentRotationOffset);
        for (int i = 0; i < count; ++i) {
            final Holder<EntityStore> holder = store.getRegistry().newHolder();
            holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
            holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, spawnRotation));
            holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
            holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(new Model.ModelReference(this.selectedModelId, this.currentScale, null, true)));
            holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(spawnRotation));
            holder.addComponent(PropComponent.getComponentType(), PropComponent.get());
            holder.ensureComponent(UUIDComponent.getComponentType());
            store.addEntity(holder, AddReason.SPAWN);
        }
        store.getComponent(ref, Player.getComponentType()).getPageManager().setPage(ref, store, Page.None);
        this.playerRef.sendMessage(Message.translation("server.customUI.entitySpawnPage.spawnedModel").param("quantity", count).param("model", this.selectedModelId));
    }
    
    @Override
    public void onDismiss(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        this.clearPreview(store);
    }
    
    private void clearPreview(@Nonnull final Store<EntityStore> store) {
        if (this.modelPreview != null && this.modelPreview.isValid()) {
            store.removeEntity(this.modelPreview, RemoveReason.REMOVE);
        }
        this.modelPreview = null;
    }
    
    private void updateTabVisibility(@Nonnull final UICommandBuilder commandBuilder) {
        commandBuilder.set("#NPCContent.Visible", this.activeTab.equals("NPC"));
        commandBuilder.set("#ItemsContent.Visible", this.activeTab.equals("Items"));
        commandBuilder.set("#ModelContent.Visible", this.activeTab.equals("Model"));
        commandBuilder.set("#TabNPC.Style", this.activeTab.equals("NPC") ? EntitySpawnPage.TAB_STYLE_ACTIVE : EntitySpawnPage.TAB_STYLE_INACTIVE);
        commandBuilder.set("#TabItems.Style", this.activeTab.equals("Items") ? EntitySpawnPage.TAB_STYLE_ACTIVE : EntitySpawnPage.TAB_STYLE_INACTIVE);
        commandBuilder.set("#TabModel.Style", this.activeTab.equals("Model") ? EntitySpawnPage.TAB_STYLE_ACTIVE : EntitySpawnPage.TAB_STYLE_INACTIVE);
        commandBuilder.set("#RotationGroup.Visible", this.activeTab.equals("Model") || this.activeTab.equals("NPC") || this.activeTab.equals("Items"));
        commandBuilder.set("#ScaleGroup.Visible", this.activeTab.equals("Model") || this.activeTab.equals("Items"));
        if (this.activeTab.equals("Model") || this.activeTab.equals("Items")) {
            commandBuilder.set("#ScaleSlider.Value", this.currentScale);
            commandBuilder.set("#ScaleValue.Text", String.format("%.1f", this.currentScale));
        }
    }
    
    private void buildList(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final UICommandBuilder commandBuilder, @Nonnull final UIEventBuilder eventBuilder) {
        this.updateTabVisibility(commandBuilder);
        final String activeTab = this.activeTab;
        switch (activeTab) {
            case "NPC": {
                this.buildNPCList(ref, store, commandBuilder, eventBuilder);
                break;
            }
            case "Items": {
                this.buildItemsContent(ref, store, commandBuilder);
                break;
            }
            case "Model": {
                this.buildModelList(ref, store, commandBuilder, eventBuilder);
                break;
            }
        }
    }
    
    private void buildNPCList(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final UICommandBuilder commandBuilder, @Nonnull final UIEventBuilder eventBuilder) {
        commandBuilder.clear("#NPCList");
        final List<String> roleTemplateNames = NPCPlugin.get().getRoleTemplateNames(true);
        if (!this.searchQuery.isEmpty()) {
            final Object2IntMap<String> map = new Object2IntOpenHashMap<String>(roleTemplateNames.size());
            for (final String value : roleTemplateNames) {
                final int fuzzyDistance = StringCompareUtil.getFuzzyDistance(value, this.searchQuery, Locale.ENGLISH);
                if (fuzzyDistance > 0) {
                    map.put(value, fuzzyDistance);
                }
            }
            final Stream<Object> sorted = map.keySet().stream().sorted();
            final Object2IntMap<String> obj = map;
            Objects.requireNonNull((Object2IntOpenHashMap)obj);
            this.npcRoles = sorted.sorted(Comparator.comparingInt(obj::getInt).reversed()).limit(20L).collect((Collector<? super Object, ?, List<String>>)Collectors.toList());
        }
        else {
            roleTemplateNames.sort(String::compareTo);
            this.npcRoles = roleTemplateNames;
        }
        for (int i = 0, bound = this.npcRoles.size(); i < bound; ++i) {
            final String id = this.npcRoles.get(i);
            final String selector = "#NPCList[" + i;
            commandBuilder.append("#NPCList", "Common/TextButton.ui");
            commandBuilder.set(selector + " #Button.Text", id);
            eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, selector + " #Button", new EventData().append("Type", "Select").append("NPCRole", id), false);
        }
        if (!this.npcRoles.isEmpty() && this.selectedNpcRole != null) {
            if (this.npcRoles.contains(this.selectedNpcRole)) {
                this.selectNPCRole(ref, store, this.selectedNpcRole, commandBuilder);
            }
            else {
                this.selectedNpcRole = null;
                this.clearPreview(store);
                commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAnNpc"));
            }
        }
        else if (this.selectedNpcRole == null) {
            commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAnNpc"));
        }
    }
    
    private void buildModelList(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final UICommandBuilder commandBuilder, @Nonnull final UIEventBuilder eventBuilder) {
        commandBuilder.clear("#ModelList");
        final Set<String> itemAndBlockModelPaths = new HashSet<String>();
        for (final Item item : Item.getAssetMap().getAssetMap().values()) {
            if (item.getModel() != null) {
                itemAndBlockModelPaths.add(item.getModel());
            }
        }
        for (final BlockType blockType : BlockType.getAssetMap().getAssetMap().values()) {
            if (blockType.getCustomModel() != null) {
                itemAndBlockModelPaths.add(blockType.getCustomModel());
            }
        }
        final Set<String> allModels = new HashSet<String>();
        for (final Map.Entry<String, ModelAsset> entry : ModelAsset.getAssetMap().getAssetMap().entrySet()) {
            final String modelPath = entry.getValue().getModel();
            if (modelPath != null) {
                if (itemAndBlockModelPaths.contains(modelPath)) {
                    continue;
                }
                if (modelPath.startsWith("Items/Projectiles/")) {
                    continue;
                }
                allModels.add(entry.getKey());
            }
        }
        if (!this.searchQuery.isEmpty()) {
            final Object2IntMap<String> map = new Object2IntOpenHashMap<String>(allModels.size());
            for (final String value : allModels) {
                final int fuzzyDistance = StringCompareUtil.getFuzzyDistance(value, this.searchQuery, Locale.ENGLISH);
                if (fuzzyDistance > 0) {
                    map.put(value, fuzzyDistance);
                }
            }
            final Stream<Object> sorted = map.keySet().stream().sorted();
            final Object2IntMap<String> obj = map;
            Objects.requireNonNull(obj);
            this.modelIds = sorted.sorted(Comparator.comparingInt(obj::getInt).reversed()).limit(20L).collect((Collector<? super Object, ?, List<String>>)Collectors.toList());
        }
        else {
            this.modelIds = allModels.stream().sorted().collect((Collector<? super Object, ?, List<String>>)Collectors.toList());
        }
        for (int i = 0, bound = this.modelIds.size(); i < bound; ++i) {
            final String id = this.modelIds.get(i);
            final String selector = "#ModelList[" + i;
            commandBuilder.append("#ModelList", "Common/TextButton.ui");
            commandBuilder.set(selector + " #Button.Text", id);
            eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, selector + " #Button", new EventData().append("Type", "Select").append("ModelId", id), false);
        }
        if (!this.modelIds.isEmpty() && this.selectedModelId != null) {
            if (this.modelIds.contains(this.selectedModelId)) {
                this.selectModel(ref, store, this.selectedModelId, commandBuilder);
            }
            else {
                this.selectedModelId = null;
                this.clearPreview(store);
                commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAModel"));
            }
        }
        else if (this.selectedModelId == null) {
            commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAModel"));
        }
    }
    
    private void buildItemsContent(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final UICommandBuilder commandBuilder) {
        if (this.selectedItemId != null) {
            final Item item = Item.getAssetMap().getAsset(this.selectedItemId);
            if (item != null) {
                commandBuilder.set("#SelectedName.Text", this.selectedItemId);
                commandBuilder.set("#ItemMaterialSlot.Slots", new ItemGridSlot[] { new ItemGridSlot(new ItemStack(this.selectedItemId, 1)) });
                commandBuilder.set("#ClearMaterial.Visible", true);
                commandBuilder.set("#DropIndicator.Visible", false);
            }
        }
        else {
            commandBuilder.set("#SelectedName.Text", Message.translation("server.customUI.entitySpawnPage.selectAnItem"));
            commandBuilder.set("#ItemMaterialSlot.Slots", new ItemGridSlot[] { new ItemGridSlot() });
            commandBuilder.set("#ClearMaterial.Visible", false);
            commandBuilder.set("#DropIndicator.Visible", true);
        }
    }
    
    private void selectItem(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final String itemId, @Nonnull final UICommandBuilder commandBuilder) {
        final Item item = Item.getAssetMap().getAsset(itemId);
        if (item == null) {
            return;
        }
        commandBuilder.set("#SelectedName.Text", this.selectedItemId = itemId);
        commandBuilder.set("#ItemMaterialSlot.Slots", new ItemGridSlot[] { new ItemGridSlot(new ItemStack(itemId, 1)) });
        commandBuilder.set("#ClearMaterial.Visible", true);
        commandBuilder.set("#DropIndicator.Visible", false);
        final Model model = this.getItemModel(item);
        if (model != null) {
            this.createOrUpdatePreview(ref, store, commandBuilder, model);
        }
        else if (item.hasBlockType()) {
            this.createOrUpdateBlockPreview(ref, store, itemId);
        }
        else {
            this.createOrUpdateItemPreview(ref, store, itemId);
        }
    }
    
    private void spawnItem(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, final int count) {
        if (this.selectedItemId == null || this.position == null || this.rotation == null) {
            return;
        }
        if (count < 1 || count > 100) {
            return;
        }
        final Item item = Item.getAssetMap().getAsset(this.selectedItemId);
        if (item == null) {
            return;
        }
        this.clearPreview(store);
        final Vector3f spawnRotation = this.rotation.clone();
        spawnRotation.setYaw(this.rotation.getYaw() + this.currentRotationOffset);
        final Model model = this.getItemModel(item);
        if (model != null) {
            final String modelId = this.getItemModelId(item);
            for (int i = 0; i < count; ++i) {
                final Holder<EntityStore> holder = store.getRegistry().newHolder();
                holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
                holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, spawnRotation));
                holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
                holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(new Model.ModelReference(modelId, this.currentScale, null, true)));
                final ItemStack itemStack = new ItemStack(this.selectedItemId, 1);
                itemStack.setOverrideDroppedItemAnimation(true);
                holder.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack));
                holder.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE);
                holder.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE);
                holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(spawnRotation));
                holder.addComponent(PropComponent.getComponentType(), PropComponent.get());
                holder.ensureComponent(UUIDComponent.getComponentType());
                store.addEntity(holder, AddReason.SPAWN);
            }
        }
        else if (item.hasBlockType()) {
            for (int j = 0; j < count; ++j) {
                final Holder<EntityStore> holder2 = store.getRegistry().newHolder();
                holder2.addComponent(BlockEntity.getComponentType(), new BlockEntity(this.selectedItemId));
                holder2.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, spawnRotation));
                holder2.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(this.currentScale * 2.0f));
                final ItemStack itemStack2 = new ItemStack(this.selectedItemId, 1);
                itemStack2.setOverrideDroppedItemAnimation(true);
                holder2.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack2));
                holder2.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE);
                holder2.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE);
                holder2.addComponent(HeadRotation.getComponentType(), new HeadRotation(spawnRotation));
                holder2.addComponent(PropComponent.getComponentType(), PropComponent.get());
                holder2.ensureComponent(UUIDComponent.getComponentType());
                store.addEntity(holder2, AddReason.SPAWN);
            }
        }
        else {
            for (int j = 0; j < count; ++j) {
                final Holder<EntityStore> holder2 = store.getRegistry().newHolder();
                holder2.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
                holder2.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, spawnRotation));
                final ItemStack itemStack2 = new ItemStack(this.selectedItemId, 1);
                itemStack2.setOverrideDroppedItemAnimation(true);
                holder2.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack2));
                holder2.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(this.currentScale));
                holder2.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE);
                holder2.addComponent(PreventItemMerging.getComponentType(), PreventItemMerging.INSTANCE);
                holder2.addComponent(HeadRotation.getComponentType(), new HeadRotation(spawnRotation));
                holder2.addComponent(PropComponent.getComponentType(), PropComponent.get());
                store.addEntity(holder2, AddReason.SPAWN);
            }
        }
        store.getComponent(ref, Player.getComponentType()).getPageManager().setPage(ref, store, Page.None);
        this.playerRef.sendMessage(Message.translation("server.customUI.entitySpawnPage.spawnedItem").param("quantity", count).param("item", this.selectedItemId));
    }
    
    @Nullable
    private String getItemModelId(@Nonnull final Item item) {
        String modelId = item.getModel();
        if (modelId == null && item.hasBlockType()) {
            final BlockType blockType = BlockType.getAssetMap().getAsset(item.getId());
            if (blockType != null && blockType.getCustomModel() != null) {
                modelId = blockType.getCustomModel();
            }
        }
        return modelId;
    }
    
    @Nullable
    private Model getItemModel(@Nonnull final Item item) {
        final String modelId = this.getItemModelId(item);
        if (modelId == null) {
            return null;
        }
        final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(modelId);
        if (modelAsset != null) {
            return Model.createStaticScaledModel(modelAsset, this.currentScale);
        }
        return null;
    }
    
    private void selectNPCRole(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final String npcRole, @Nonnull final UICommandBuilder commandBuilder) {
        if (this.selectedNpcRole != null && this.npcRoles.contains(this.selectedNpcRole)) {
            commandBuilder.set("#NPCList[" + this.npcRoles.indexOf(this.selectedNpcRole) + "] #Button.Style", EntitySpawnPage.BUTTON_LABEL_STYLE);
        }
        commandBuilder.set("#NPCList[" + this.npcRoles.indexOf(npcRole) + "] #Button.Style", EntitySpawnPage.BUTTON_LABEL_STYLE_SELECTED);
        commandBuilder.set("#SelectedName.Text", npcRole);
        this.selectedNpcRole = npcRole;
        this.createOrUpdatePreview(ref, store, commandBuilder, this.getNPCModel());
    }
    
    private void selectModel(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final String modelId, @Nonnull final UICommandBuilder commandBuilder) {
        if (this.selectedModelId != null && this.modelIds.contains(this.selectedModelId)) {
            commandBuilder.set("#ModelList[" + this.modelIds.indexOf(this.selectedModelId) + "] #Button.Style", EntitySpawnPage.BUTTON_LABEL_STYLE);
        }
        commandBuilder.set("#ModelList[" + this.modelIds.indexOf(modelId) + "] #Button.Style", EntitySpawnPage.BUTTON_LABEL_STYLE_SELECTED);
        commandBuilder.set("#SelectedName.Text", modelId);
        this.selectedModelId = modelId;
        final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(modelId);
        if (modelAsset != null) {
            this.createOrUpdatePreview(ref, store, commandBuilder, Model.createStaticScaledModel(modelAsset, this.currentScale));
        }
    }
    
    private void initPosition(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
        assert transformComponent != null;
        final HeadRotation headRotationComponent = store.getComponent(ref, HeadRotation.getComponentType());
        assert headRotationComponent != null;
        final Vector3d playerPosition = transformComponent.getPosition();
        final Vector3f headRotation = headRotationComponent.getRotation();
        final Vector3d direction = Transform.getDirection(headRotation.getPitch(), headRotation.getYaw());
        final Vector3d lookTarget = TargetUtil.getTargetLocation(ref, 4.0, store);
        Vector3d previewPosition;
        if (lookTarget != null) {
            previewPosition = lookTarget;
        }
        else {
            final Vector3d aheadPosition = playerPosition.clone().add(direction.clone().scale(4.0));
            final World world = store.getExternalData().getWorld();
            final Vector3i groundTarget = TargetUtil.getTargetBlock(world, (blockId, fluidId) -> blockId != 0, aheadPosition.x, aheadPosition.y + 0.5, aheadPosition.z, 0.0, -1.0, 0.0, 3.0);
            if (groundTarget != null) {
                previewPosition = new Vector3d(groundTarget.x + 0.5, groundTarget.y + 1, groundTarget.z + 0.5);
            }
            else {
                previewPosition = aheadPosition;
            }
        }
        final Vector3d relativePos = playerPosition.clone().subtract(previewPosition);
        relativePos.setY(0.0);
        final Vector3f previewRotation = Vector3f.lookAt(relativePos);
        this.position = previewPosition;
        this.rotation = previewRotation;
        this.currentRotationOffset = 0.0f;
    }
    
    private void createOrUpdatePreview(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final UICommandBuilder commandBuilder, @Nullable final Model model) {
        if (model == null) {
            return;
        }
        if (this.modelPreview == null || !this.modelPreview.isValid()) {
            this.initPosition(ref, store);
            final Holder<EntityStore> holder = store.getRegistry().newHolder();
            holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
            holder.addComponent(EntityStore.REGISTRY.getNonSerializedComponentType(), NonSerialized.get());
            holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, this.rotation));
            holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(model));
            holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(this.rotation));
            this.modelPreview = store.addEntity(holder, AddReason.SPAWN);
            this.lastPreviewScale = this.currentScale;
        }
        else {
            store.putComponent(this.modelPreview, ModelComponent.getComponentType(), new ModelComponent(model));
        }
    }
    
    private void updatePreviewScale(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        if (this.modelPreview == null || !this.modelPreview.isValid()) {
            return;
        }
        final EntityScaleComponent existingScale = store.getComponent(this.modelPreview, EntityScaleComponent.getComponentType());
        if (existingScale != null) {
            final boolean hasBlock = store.getComponent(this.modelPreview, BlockEntity.getComponentType()) != null;
            existingScale.setScale(hasBlock ? (this.currentScale * 2.0f) : this.currentScale);
        }
        else if ("Model".equals(this.activeTab) && this.selectedModelId != null) {
            final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset(this.selectedModelId);
            if (modelAsset != null) {
                store.putComponent(this.modelPreview, ModelComponent.getComponentType(), new ModelComponent(Model.createStaticScaledModel(modelAsset, this.currentScale)));
            }
        }
    }
    
    private void createOrUpdateBlockPreview(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final String blockTypeKey) {
        this.clearPreview(store);
        this.initPosition(ref, store);
        final Holder<EntityStore> holder = store.getRegistry().newHolder();
        holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
        holder.addComponent(EntityStore.REGISTRY.getNonSerializedComponentType(), NonSerialized.get());
        holder.addComponent(BlockEntity.getComponentType(), new BlockEntity(blockTypeKey));
        holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, this.rotation));
        holder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(this.currentScale * 2.0f));
        holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(this.rotation));
        this.modelPreview = store.addEntity(holder, AddReason.SPAWN);
        this.lastPreviewScale = this.currentScale;
    }
    
    private void createOrUpdateItemPreview(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final String itemId) {
        this.clearPreview(store);
        this.initPosition(ref, store);
        final Holder<EntityStore> holder = store.getRegistry().newHolder();
        holder.addComponent(NetworkId.getComponentType(), new NetworkId(store.getExternalData().takeNextNetworkId()));
        holder.addComponent(EntityStore.REGISTRY.getNonSerializedComponentType(), NonSerialized.get());
        final ItemStack itemStack = new ItemStack(itemId, 1);
        itemStack.setOverrideDroppedItemAnimation(true);
        holder.addComponent(ItemComponent.getComponentType(), new ItemComponent(itemStack));
        holder.addComponent(EntityScaleComponent.getComponentType(), new EntityScaleComponent(this.currentScale));
        holder.addComponent(PreventPickup.getComponentType(), PreventPickup.INSTANCE);
        holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(this.position, this.rotation));
        holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(this.rotation));
        this.modelPreview = store.addEntity(holder, AddReason.SPAWN);
        this.lastPreviewScale = this.currentScale;
    }
    
    @Nullable
    private Model getNPCModel() {
        final NPCPlugin npcPlugin = NPCPlugin.get();
        final int roleIndex = npcPlugin.getIndex(this.selectedNpcRole);
        npcPlugin.forceValidation(roleIndex);
        final BuilderInfo roleBuilderInfo = npcPlugin.getRoleBuilderInfo(roleIndex);
        if (roleBuilderInfo == null) {
            throw new IllegalStateException("Can't find a matching role builder");
        }
        if (!npcPlugin.testAndValidateRole(roleBuilderInfo)) {
            throw new GeneralCommandException(Message.translation("server.commands.npc.spawn.validation_failed"));
        }
        final Builder<Role> roleBuilder = npcPlugin.tryGetCachedValidRole(roleIndex);
        if (roleBuilder == null) {
            throw new IllegalArgumentException("Can't find a matching role builder");
        }
        if (!(roleBuilder instanceof ISpawnableWithModel)) {
            throw new IllegalArgumentException("Role builder must support ISpawnableWithModel interface");
        }
        final ISpawnableWithModel spawnable = (ISpawnableWithModel)roleBuilder;
        if (!roleBuilder.isSpawnable()) {
            throw new IllegalArgumentException("Abstract role templates cannot be spawned directly - a variant needs to be created!");
        }
        final SpawningContext spawningContext = new SpawningContext();
        if (!spawningContext.setSpawnable(spawnable)) {
            throw new GeneralCommandException(Message.translation("server.commands.npc.spawn.cantSetRolebuilder"));
        }
        return spawningContext.getModel();
    }
    
    static {
        BUTTON_LABEL_STYLE = Value.ref("Common/TextButton.ui", "LabelStyle");
        BUTTON_LABEL_STYLE_SELECTED = Value.ref("Common/TextButton.ui", "SelectedLabelStyle");
        TAB_STYLE_ACTIVE = Value.ref("Common.ui", "DefaultTextButtonStyle");
        TAB_STYLE_INACTIVE = Value.ref("Common.ui", "SecondaryTextButtonStyle");
    }
    
    public static class EntitySpawnPageEventData
    {
        static final String KEY_NPC_ROLE = "NPCRole";
        static final String KEY_MODEL_ID = "ModelId";
        static final String KEY_ITEM_ID = "ItemId";
        static final String KEY_ITEM_STACK_ID = "ItemStackId";
        static final String KEY_TYPE = "Type";
        static final String KEY_TAB = "Tab";
        static final String KEY_SEARCH_QUERY = "@SearchQuery";
        static final String KEY_COUNT = "@Count";
        static final String KEY_ROTATION_OFFSET = "@RotationOffset";
        static final String KEY_SCALE = "@Scale";
        public static final BuilderCodec<EntitySpawnPageEventData> CODEC;
        private String npcRole;
        private String modelId;
        private String itemId;
        private String itemStackId;
        private String type;
        private String tab;
        private String searchQuery;
        private int count;
        private float rotationOffset;
        private Float scale;
        
        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             "NPCRole"
            //    16: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    19: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    22: invokedynamic   BootstrapMethod #1, accept:()Ljava/util/function/BiConsumer;
            //    27: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/Function;
            //    32: 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;
            //    35: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    38: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    41: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    44: dup            
            //    45: ldc             "ModelId"
            //    47: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    50: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    53: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
            //    58: invokedynamic   BootstrapMethod #4, apply:()Ljava/util/function/Function;
            //    63: 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;
            //    66: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    69: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    72: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    75: dup            
            //    76: ldc             "ItemId"
            //    78: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    81: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    84: invokedynamic   BootstrapMethod #5, accept:()Ljava/util/function/BiConsumer;
            //    89: invokedynamic   BootstrapMethod #6, apply:()Ljava/util/function/Function;
            //    94: 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;
            //    97: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   100: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   103: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   106: dup            
            //   107: ldc             "ItemStackId"
            //   109: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //   112: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   115: invokedynamic   BootstrapMethod #7, accept:()Ljava/util/function/BiConsumer;
            //   120: invokedynamic   BootstrapMethod #8, apply:()Ljava/util/function/Function;
            //   125: 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;
            //   128: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   131: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   134: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   137: dup            
            //   138: ldc             "Type"
            //   140: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //   143: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   146: invokedynamic   BootstrapMethod #9, accept:()Ljava/util/function/BiConsumer;
            //   151: invokedynamic   BootstrapMethod #10, apply:()Ljava/util/function/Function;
            //   156: 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;
            //   159: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   162: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   165: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   168: dup            
            //   169: ldc             "Tab"
            //   171: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //   174: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   177: invokedynamic   BootstrapMethod #11, accept:()Ljava/util/function/BiConsumer;
            //   182: invokedynamic   BootstrapMethod #12, apply:()Ljava/util/function/Function;
            //   187: 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;
            //   190: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   193: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   196: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   199: dup            
            //   200: ldc             "@SearchQuery"
            //   202: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //   205: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   208: invokedynamic   BootstrapMethod #13, accept:()Ljava/util/function/BiConsumer;
            //   213: invokedynamic   BootstrapMethod #14, apply:()Ljava/util/function/Function;
            //   218: 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;
            //   221: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   224: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   227: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   230: dup            
            //   231: ldc             "@Count"
            //   233: getstatic       com/hypixel/hytale/codec/Codec.INTEGER:Lcom/hypixel/hytale/codec/codecs/simple/IntegerCodec;
            //   236: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   239: invokedynamic   BootstrapMethod #15, accept:()Ljava/util/function/BiConsumer;
            //   244: invokedynamic   BootstrapMethod #16, apply:()Ljava/util/function/Function;
            //   249: 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;
            //   252: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   255: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   258: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   261: dup            
            //   262: ldc             "@RotationOffset"
            //   264: getstatic       com/hypixel/hytale/codec/Codec.FLOAT:Lcom/hypixel/hytale/codec/codecs/simple/FloatCodec;
            //   267: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   270: invokedynamic   BootstrapMethod #17, accept:()Ljava/util/function/BiConsumer;
            //   275: invokedynamic   BootstrapMethod #18, apply:()Ljava/util/function/Function;
            //   280: 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;
            //   283: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   286: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   289: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //   292: dup            
            //   293: ldc             "@Scale"
            //   295: getstatic       com/hypixel/hytale/codec/Codec.FLOAT:Lcom/hypixel/hytale/codec/codecs/simple/FloatCodec;
            //   298: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //   301: invokedynamic   BootstrapMethod #19, accept:()Ljava/util/function/BiConsumer;
            //   306: invokedynamic   BootstrapMethod #20, apply:()Ljava/util/function/Function;
            //   311: 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;
            //   314: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   317: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   320: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   323: putstatic       com/hypixel/hytale/server/npc/pages/EntitySpawnPage$EntitySpawnPageEventData.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   326: 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.visitClassType(TypeSubstitutionVisitor.java:267)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitClassType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.TypeDefinition.accept(TypeDefinition.java:189)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:324)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2586)
            //     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: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: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.inferCall(TypeAnalysis.java:2483)
            //     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:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2483)
            //     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.inferCall(TypeAnalysis.java:2483)
            //     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:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2483)
            //     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.inferCall(TypeAnalysis.java:2483)
            //     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:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2483)
            //     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.inferCall(TypeAnalysis.java:2483)
            //     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:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2483)
            //     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.addTypeMembers(AstBuilder.java:662)
            //     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.");
        }
    }
}
