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

package com.hypixel.hytale.server.core.asset;

import com.hypixel.hytale.server.core.asset.type.tagpattern.config.NotPatternOp;
import com.hypixel.hytale.server.core.asset.type.tagpattern.config.OrPatternOp;
import com.hypixel.hytale.server.core.asset.type.tagpattern.config.AndPatternOp;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.asset.type.tagpattern.TagPatternPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.tagpattern.config.EqualsTagOp;
import com.hypixel.hytale.assetstore.JsonAsset;
import com.hypixel.hytale.server.core.asset.type.item.config.BuilderToolItemReferenceAsset;
import com.hypixel.hytale.server.core.asset.type.blocktype.BlockGroupPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.item.config.BlockGroup;
import com.hypixel.hytale.server.core.modules.projectile.config.ProjectileConfigPacketGenerator;
import com.hypixel.hytale.server.core.modules.projectile.config.ProjectileConfig;
import com.hypixel.hytale.server.core.modules.item.ItemQualityPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.responsecurve.config.ExponentialResponseCurve;
import com.hypixel.hytale.server.core.asset.type.equalizereffect.EqualizerEffectPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.reverbeffect.ReverbEffectPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.audiocategory.AudioCategoryPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.soundset.SoundSetPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.soundevent.SoundEventPacketGenerator;
import com.hypixel.hytale.server.core.modules.entity.repulsion.RepulsionConfig;
import com.hypixel.hytale.server.core.modules.entity.hitboxcollision.HitboxCollisionConfig;
import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import com.hypixel.hytale.server.core.asset.type.weather.WeatherPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.item.ResourceTypePacketGenerator;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.asset.type.gamemode.GameModeType;
import com.hypixel.hytale.server.core.asset.type.modelvfx.ModelVFXPacketGenerator;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
import com.hypixel.hytale.server.core.asset.type.entityeffect.EntityEffectPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.projectile.config.Projectile;
import com.hypixel.hytale.server.core.asset.type.trail.TrailPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.particle.ParticleSystemPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.particle.ParticleSpawnerPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.particle.config.ParticleSpawner;
import com.hypixel.hytale.server.core.asset.type.trail.config.Trail;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.modules.item.CraftingRecipePacketGenerator;
import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe;
import com.hypixel.hytale.server.core.asset.type.item.config.ResourceType;
import com.hypixel.hytale.server.core.modules.interaction.interaction.UnarmedInteractions;
import com.hypixel.hytale.server.core.modules.item.ItemPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.portalworld.PortalType;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemToolSpec;
import com.hypixel.hytale.server.core.modules.item.ItemReticleConfigPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.wordlist.WordList;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import com.hypixel.hytale.server.core.asset.type.item.FieldcraftCategoryPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.item.config.FieldcraftCategory;
import com.hypixel.hytale.server.core.asset.type.item.ItemCategoryPacketGenerator;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemCategory;
import com.hypixel.hytale.server.core.asset.type.fluidfx.FluidFXPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.environment.EnvironmentPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.itemanimation.ItemPlayerAnimationsPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.itemanimation.config.ItemPlayerAnimations;
import com.hypixel.hytale.server.core.asset.type.fluid.FluidTypePacketGenerator;
import com.hypixel.hytale.server.core.asset.type.buildertool.config.BlockTypeListAsset;
import com.hypixel.hytale.server.core.asset.type.buildertool.config.PrefabListAsset;
import com.hypixel.hytale.server.core.universe.world.connectedblocks.CustomConnectedBlockTemplateAsset;
import com.hypixel.hytale.server.core.asset.type.blocktype.BlockTypePacketGenerator;
import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockMigration;
import com.hypixel.hytale.server.core.asset.type.blockbreakingdecal.BlockBreakingDecalPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.blockbreakingdecal.config.BlockBreakingDecal;
import com.hypixel.hytale.server.core.asset.type.particle.config.ParticleSystem;
import com.hypixel.hytale.server.core.asset.type.blockparticle.BlockParticleSetPacketGenerator;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.server.core.asset.type.blockparticle.config.BlockParticleSet;
import com.hypixel.hytale.server.core.asset.type.itemsound.ItemSoundSetPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.blocksound.BlockSoundSetPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.asset.type.blockset.BlockSetPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxesPacketGenerator;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import java.util.Collections;
import com.hypixel.hytale.server.core.asset.packet.AssetPacketGenerator;
import com.hypixel.hytale.server.core.asset.type.ambiencefx.AmbienceFXPacketGenerator;
import java.util.function.Function;
import com.hypixel.hytale.assetstore.map.IndexedAssetMap;
import com.hypixel.hytale.server.core.asset.type.ambiencefx.config.AmbienceFX;
import com.hypixel.hytale.server.core.asset.type.blockhitbox.BlockBoundingBoxes;
import com.hypixel.hytale.server.core.asset.type.blockset.config.BlockSet;
import com.hypixel.hytale.server.core.asset.type.blocksound.config.BlockSoundSet;
import com.hypixel.hytale.server.core.asset.type.itemsound.config.ItemSoundSet;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.fluid.Fluid;
import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
import com.hypixel.hytale.server.core.asset.type.fluidfx.config.FluidFX;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemReticleConfig;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.protocol.ItemWithAllMetadata;
import com.hypixel.hytale.server.core.asset.type.entityeffect.config.EntityEffect;
import com.hypixel.hytale.server.core.asset.type.modelvfx.config.ModelVFX;
import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.asset.type.soundevent.config.SoundEvent;
import com.hypixel.hytale.server.core.asset.type.soundset.config.SoundSet;
import com.hypixel.hytale.server.core.asset.type.audiocategory.config.AudioCategory;
import com.hypixel.hytale.server.core.asset.type.reverbeffect.config.ReverbEffect;
import com.hypixel.hytale.server.core.asset.type.equalizereffect.config.EqualizerEffect;
import com.hypixel.hytale.server.core.asset.type.responsecurve.config.ResponseCurve;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemQuality;
import com.hypixel.hytale.server.core.modules.entity.damage.DamageCause;
import com.hypixel.hytale.server.core.asset.type.camera.CameraEffect;
import com.hypixel.hytale.server.core.asset.type.tagpattern.config.TagPattern;
import java.util.stream.Stream;
import com.hypixel.hytale.server.core.util.BsonUtil;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.codec.EmptyExtraInfo;
import java.nio.file.FileVisitOption;
import java.nio.file.attribute.FileAttribute;
import com.hypixel.hytale.server.core.ShutdownReason;
import com.hypixel.hytale.assetstore.codec.AssetCodec;
import com.hypixel.hytale.event.IEvent;
import org.bson.BsonString;
import com.hypixel.hytale.assetstore.codec.AssetCodecMapCodec;
import java.util.HashMap;
import com.hypixel.hytale.codec.schema.SchemaConvertable;
import org.bson.BsonInt32;
import org.bson.BsonValue;
import org.bson.BsonArray;
import java.util.Arrays;
import java.util.Comparator;
import com.hypixel.hytale.codec.schema.config.Schema;
import java.util.Map;
import org.bson.BsonDocument;
import com.hypixel.hytale.codec.schema.SchemaContext;
import com.hypixel.hytale.protocol.Packet;
import java.util.function.Consumer;
import java.util.Objects;
import com.hypixel.hytale.server.core.io.PacketHandler;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import com.hypixel.hytale.assetstore.AssetLoadResult;
import java.util.Iterator;
import java.util.Collection;
import joptsimple.OptionSpec;
import com.hypixel.hytale.server.core.Options;
import com.hypixel.hytale.common.util.FormatUtil;
import com.hypixel.hytale.assetstore.AssetMap;
import com.hypixel.hytale.assetstore.map.JsonAssetWithMap;
import java.util.List;
import com.hypixel.hytale.assetstore.iterator.CircularDependencyException;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.assetstore.iterator.AssetStoreIterator;
import java.util.logging.Level;
import com.hypixel.hytale.assetstore.AssetStore;
import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.assetstore.AssetPack;
import javax.annotation.Nullable;
import com.hypixel.hytale.sneakythrow.SneakyThrow;
import javax.annotation.Nonnull;
import com.hypixel.hytale.logger.HytaleLogger;

public class AssetRegistryLoader
{
    public static final HytaleLogger LOGGER;
    
    public static void init() {
    }
    
    public static void preLoadAssets(@Nonnull final LoadAssetEvent event) {
        try {
            preLoadAssets0(event);
        }
        catch (final Throwable t) {
            event.failed(true, "failed to validate assets");
            throw SneakyThrow.sneakyThrow(t);
        }
    }
    
    public static void loadAssets(@Nullable final LoadAssetEvent event, @Nonnull final AssetPack assetPack) {
        AssetRegistry.ASSET_LOCK.writeLock().lock();
        try {
            loadAssets0(event, assetPack);
            AssetRegistry.HAS_INIT = true;
        }
        catch (final Throwable t) {
            if (event != null) {
                event.failed(true, "failed to validate assets");
            }
            throw SneakyThrow.sneakyThrow(t);
        }
        finally {
            AssetRegistry.ASSET_LOCK.writeLock().unlock();
        }
    }
    
    private static void preLoadAssets0(@Nonnull final LoadAssetEvent event) {
        AssetStore.DISABLE_DYNAMIC_DEPENDENCIES = true;
        final Collection<AssetStore<?, ?, ?>> values = AssetRegistry.getStoreMap().values();
        AssetRegistryLoader.LOGGER.at(Level.INFO).log("Loading %s asset stores...", values.size());
        for (final AssetStore<?, ?, ?> assetStore : values) {
            assetStore.simplifyLoadBeforeDependencies();
        }
        boolean failedToLoadAsset = false;
        AssetRegistryLoader.LOGGER.at(Level.INFO).log("Pre-adding assets...");
        try (final AssetStoreIterator iterator = new AssetStoreIterator(values)) {
            while (iterator.hasNext()) {
                if (HytaleServer.get().isShuttingDown()) {
                    AssetRegistryLoader.LOGGER.at(Level.INFO).log("Aborted asset loading due to server shutdown!");
                    iterator.close();
                    return;
                }
                final AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>> assetStore2 = (AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>>)iterator.next();
                if (assetStore2 == null) {
                    throw new CircularDependencyException(values, iterator);
                }
                final long start = System.nanoTime();
                final Class<? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>> assetClass = assetStore2.getAssetClass();
                try {
                    final List<?> preAddedAssets = assetStore2.getPreAddedAssets();
                    if (preAddedAssets == null || preAddedAssets.isEmpty()) {
                        continue;
                    }
                    final AssetLoadResult loadResult = assetStore2.loadAssets("Hytale:Hytale", (List<? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>>)preAddedAssets);
                    failedToLoadAsset |= loadResult.hasFailed();
                }
                catch (final Exception e) {
                    failedToLoadAsset = true;
                    final long end = System.nanoTime();
                    final long diff = end - start;
                    if (iterator.isBeingWaitedFor(assetStore2)) {
                        throw new RuntimeException(String.format("Failed to pre-add %s took %s", assetClass.getSimpleName(), FormatUtil.nanosToString(diff)), e);
                    }
                    AssetRegistryLoader.LOGGER.at(Level.SEVERE).withCause(e).log("Failed to pre-add %s took %s", assetClass.getSimpleName(), FormatUtil.nanosToString(diff));
                }
            }
        }
        if (failedToLoadAsset) {
            event.failed(Options.getOptionSet().has(Options.VALIDATE_ASSETS), "failed to validate internal assets");
        }
    }
    
    private static void loadAssets0(@Nullable final LoadAssetEvent event, @Nonnull final AssetPack assetPack) {
        AssetStore.DISABLE_DYNAMIC_DEPENDENCIES = true;
        final Path serverAssetDirectory = assetPack.getRoot().resolve("Server");
        HytaleLogger.getLogger().at(Level.INFO).log("Loading assets from: %s", serverAssetDirectory);
        final long startAll = System.nanoTime();
        boolean failedToLoadAsset = false;
        AssetRegistryLoader.LOGGER.at(Level.INFO).log("Loading assets from %s", serverAssetDirectory);
        final Collection<AssetStore<?, ?, ?>> values = AssetRegistry.getStoreMap().values();
        try (final AssetStoreIterator iterator = new AssetStoreIterator(values)) {
            while (iterator.hasNext()) {
                if (HytaleServer.get().isShuttingDown()) {
                    AssetRegistryLoader.LOGGER.at(Level.INFO).log("Aborted asset loading due to server shutdown!");
                    iterator.close();
                    return;
                }
                final AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>> assetStore = (AssetStore<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>, ? extends AssetMap<?, ? extends JsonAssetWithMap<?, ?>>>)iterator.next();
                if (assetStore == null) {
                    throw new CircularDependencyException(values, iterator);
                }
                final long start = System.nanoTime();
                final Class<? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>> assetClass = assetStore.getAssetClass();
                try {
                    final String path = assetStore.getPath();
                    if (path == null) {
                        continue;
                    }
                    final Path assetsPath = serverAssetDirectory.resolve(path);
                    if (!Files.isDirectory(assetsPath, new LinkOption[0])) {
                        continue;
                    }
                    final AssetLoadResult<?, ? extends JsonAssetWithMap<?, ? extends AssetMap<?, ?>>> loadResult = assetStore.loadAssetsFromDirectory(assetPack.getName(), assetsPath);
                    failedToLoadAsset |= loadResult.hasFailed();
                }
                catch (final Exception e) {
                    failedToLoadAsset = true;
                    final long end = System.nanoTime();
                    final long diff = end - start;
                    if (iterator.isBeingWaitedFor(assetStore)) {
                        throw new RuntimeException(String.format("Failed to load %s from path '%s' took %s", assetClass.getSimpleName(), assetStore.getPath(), FormatUtil.nanosToString(diff)), e);
                    }
                    AssetRegistryLoader.LOGGER.at(Level.SEVERE).withCause(e).log("Failed to load %s from path '%s' took %s", assetClass.getSimpleName(), assetStore.getPath(), FormatUtil.nanosToString(diff));
                }
            }
        }
        for (final AssetStore<?, ?, ?> assetStore2 : values) {
            if (assetPack.getName().equals("Hytale:Hytale")) {
                assetStore2.validateCodecDefaults();
            }
            final String path2 = assetStore2.getPath();
            if (path2 != null) {
                final Path assetsPath2 = serverAssetDirectory.resolve(path2);
                if (!Files.isDirectory(assetsPath2, new LinkOption[0]) || assetPack.isImmutable()) {
                    continue;
                }
                assetStore2.addFileMonitor(assetPack.getName(), assetsPath2);
            }
        }
        final long endAll = System.nanoTime();
        final long diffAll = endAll - startAll;
        AssetRegistryLoader.LOGGER.at(Level.INFO).log("Took %s to load all assets", FormatUtil.nanosToString(diffAll));
        if (failedToLoadAsset && event != null) {
            event.failed(Options.getOptionSet().has(Options.VALIDATE_ASSETS), "failed to validate assets");
        }
    }
    
    public static void sendAssets(@Nonnull final PacketHandler packetHandler) {
        Objects.requireNonNull(packetHandler);
        final Consumer<Packet[]> packetConsumer = packetHandler::write;
        Objects.requireNonNull(packetHandler);
        final Consumer<Packet> singlePacketConsumer = packetHandler::write;
        AssetRegistry.ASSET_LOCK.writeLock().lock();
        try {
            HytaleAssetStore.SETUP_PACKET_CONSUMERS.add(singlePacketConsumer);
        }
        finally {
            AssetRegistry.ASSET_LOCK.writeLock().unlock();
        }
        try {
            for (final AssetStore<?, ?, ?> assetStore : AssetRegistry.getStoreMap().values()) {
                ((HytaleAssetStore)assetStore).sendAssets(packetConsumer);
            }
        }
        finally {
            AssetRegistry.ASSET_LOCK.writeLock().lock();
            try {
                HytaleAssetStore.SETUP_PACKET_CONSUMERS.remove(singlePacketConsumer);
            }
            finally {
                AssetRegistry.ASSET_LOCK.writeLock().unlock();
            }
        }
    }
    
    @Nonnull
    public static Map<String, Schema> generateSchemas(@Nonnull final SchemaContext context, @Nonnull final BsonDocument vsCodeConfig) {
        final AssetStore[] values = AssetRegistry.getStoreMap().values().toArray(AssetStore[]::new);
        AssetStore store = null;
        Arrays.sort(values, Comparator.comparing(store -> store.getAssetClass().getSimpleName()));
        final BsonArray vsCodeSchemas = new BsonArray();
        final BsonDocument vsCodeFiles = new BsonDocument();
        vsCodeConfig.put("json.schemas", vsCodeSchemas);
        vsCodeConfig.put("files.associations", vsCodeFiles);
        vsCodeConfig.put("editor.tabSize", new BsonInt32(2));
        final AssetStore[] array = values;
        for (int length = array.length, j = 0; j < length; ++j) {
            store = array[j];
            final Class assetClass = store.getAssetClass();
            final String name = assetClass.getSimpleName();
            final AssetCodec codec = store.getCodec();
            context.addFileReference(name + ".json", (SchemaConvertable<?>)codec);
        }
        final HashMap<String, Schema> schemas = new HashMap<String, Schema>();
        final AssetStore[] array2 = values;
        for (int length2 = array2.length, l = 0; l < length2; ++l) {
            final AssetStore store2 = array2[l];
            final Class assetClass2 = store2.getAssetClass();
            final String path = store2.getPath();
            final String name2 = assetClass2.getSimpleName();
            final AssetCodec codec2 = store2.getCodec();
            final Schema schema = codec2.toSchema(context);
            if (codec2 instanceof AssetCodecMapCodec) {
                schema.setTitle(name2);
            }
            schema.setId(name2 + ".json");
            final Schema.HytaleMetadata hytale = schema.getHytale();
            hytale.setPath(path);
            hytale.setExtension(store2.getExtension());
            final Class idProvider = store2.getIdProvider();
            if (idProvider != null) {
                hytale.setIdProvider(idProvider.getSimpleName());
            }
            final List preload = store2.getPreAddedAssets();
            if (preload != null && !preload.isEmpty()) {
                final String[] internal = new String[preload.size()];
                for (int i = 0; i < preload.size(); ++i) {
                    final Object p = preload.get(i);
                    final Object k = store2.getKeyFunction().apply(p);
                    internal[i] = k.toString();
                }
                hytale.setInternalKeys(internal);
            }
            final BsonDocument config = new BsonDocument();
            config.put("fileMatch", new BsonArray(List.of(new BsonString("/Server/" + path + "/*" + store2.getExtension()), new BsonString("/Server/" + path + "/**/*" + store2.getExtension()))));
            config.put("url", new BsonString("./Schema/" + name2 + ".json"));
            vsCodeSchemas.add(config);
            if (!store2.getExtension().equals(".json")) {
                vsCodeFiles.put("*" + store2.getExtension(), (BsonValue)new BsonString("json"));
            }
            schemas.put(name2 + ".json", schema);
        }
        HytaleServer.get().getEventBus().dispatchFor((Class<? super IEvent<Void>>)GenerateSchemaEvent.class).dispatch(new GenerateSchemaEvent(schemas, context, vsCodeConfig));
        final Schema definitions = new Schema();
        definitions.setDefinitions(context.getDefinitions());
        definitions.setId("common.json");
        schemas.put("common.json", definitions);
        final Schema otherDefinitions = new Schema();
        otherDefinitions.setDefinitions(context.getOtherDefinitions());
        otherDefinitions.setId("other.json");
        schemas.put("other.json", otherDefinitions);
        return schemas;
    }
    
    public static void writeSchemas(final LoadAssetEvent event) {
        if (!Options.getOptionSet().has(Options.GENERATE_SCHEMA)) {
            return;
        }
        try {
            final AssetPack pack = AssetModule.get().getBaseAssetPack();
            if (pack.isImmutable()) {
                AssetRegistryLoader.LOGGER.at(Level.SEVERE).log("Not generating schema due launcher assets");
                HytaleServer.get().shutdownServer(ShutdownReason.VALIDATE_ERROR.withMessage("Not generating scheme due launcher assets"));
                return;
            }
            final BsonDocument vsCodeConfig = new BsonDocument();
            final Path assetDirectory = pack.getRoot();
            final Path schemaDir = assetDirectory.resolve("Schema");
            Files.createDirectories(schemaDir, (FileAttribute<?>[])new FileAttribute[0]);
            try (final Stream<Path> stream = Files.walk(schemaDir, 1, new FileVisitOption[0])) {
                stream.filter(v -> v.toString().endsWith(".json")).forEach(SneakyThrow.sneakyConsumer(Files::delete));
            }
            final SchemaContext context = new SchemaContext();
            final Map<String, Schema> schemas = generateSchemas(context, vsCodeConfig);
            for (final Map.Entry<String, Schema> schema : schemas.entrySet()) {
                BsonUtil.writeDocument(schemaDir.resolve(schema.getKey()), Schema.CODEC.encode((Schema)schema.getValue(), (ExtraInfo)EmptyExtraInfo.EMPTY).asDocument(), false).join();
            }
            Files.createDirectories(assetDirectory.resolve(".vscode"), (FileAttribute<?>[])new FileAttribute[0]);
            BsonUtil.writeDocument(assetDirectory.resolve(".vscode/settings.json"), vsCodeConfig, false).join();
        }
        catch (final Throwable t) {
            AssetRegistryLoader.LOGGER.at(Level.SEVERE).withCause(t).log("Schema generation failed");
            HytaleServer.get().shutdownServer(ShutdownReason.CRASH.withMessage("Schema generation failed"));
            return;
        }
        HytaleServer.get().shutdownServer(ShutdownReason.SHUTDOWN.withMessage("Schema generated"));
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(AmbienceFX.class, new IndexedAssetMap()).setPath()).setCodec(AmbienceFX.CODEC)).setKeyFunction(AmbienceFX::getId)).setReplaceOnRemove(AmbienceFX::new)).setPacketGenerator(new AmbienceFXPacketGenerator()).loadsAfter(Weather.class, Environment.class, FluidFX.class, SoundEvent.class, BlockSoundSet.class, TagPattern.class, AudioCategory.class, ReverbEffect.class, EqualizerEffect.class)).preLoadAssets(Collections.singletonList(AmbienceFX.EMPTY))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockBoundingBoxes.class, new IndexedLookupTableAssetMap(BlockBoundingBoxes[]::new)).setPath()).setCodec(BlockBoundingBoxes.CODEC)).setKeyFunction(BlockBoundingBoxes::getId)).setReplaceOnRemove(BlockBoundingBoxes::getUnitBoxFor)).setPacketGenerator(new BlockBoundingBoxesPacketGenerator()).preLoadAssets(Collections.singletonList(BlockBoundingBoxes.UNIT_BOX))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockSet.class, new IndexedLookupTableAssetMap(BlockSet[]::new)).setPath()).setCodec(BlockSet.CODEC)).setKeyFunction(BlockSet::getId)).setReplaceOnRemove(BlockSet::new)).setPacketGenerator(new BlockSetPacketGenerator()).loadsBefore(Item.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockSoundSet.class, new IndexedLookupTableAssetMap(BlockSoundSet[]::new)).setPath()).setCodec(BlockSoundSet.CODEC)).setKeyFunction(BlockSoundSet::getId)).setReplaceOnRemove(BlockSoundSet::new)).setPacketGenerator(new BlockSoundSetPacketGenerator()).loadsAfter(SoundEvent.class)).preLoadAssets(Collections.singletonList(BlockSoundSet.EMPTY_BLOCK_SOUND_SET))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemSoundSet.class, new IndexedLookupTableAssetMap(ItemSoundSet[]::new)).setPath()).setCodec(ItemSoundSet.CODEC)).setKeyFunction(ItemSoundSet::getId)).setReplaceOnRemove(ItemSoundSet::new)).setPacketGenerator(new ItemSoundSetPacketGenerator()).loadsAfter(SoundEvent.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockParticleSet.class, new DefaultAssetMap()).setPath()).setCodec(BlockParticleSet.CODEC)).setKeyFunction(BlockParticleSet::getId)).setPacketGenerator(new BlockParticleSetPacketGenerator()).loadsAfter(ParticleSystem.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockBreakingDecal.class, new DefaultAssetMap()).setPath()).setCodec(BlockBreakingDecal.CODEC)).setKeyFunction(BlockBreakingDecal::getId)).setPacketGenerator(new BlockBreakingDecalPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Integer.class, BlockMigration.class, new DefaultAssetMap()).setPath()).setCodec(BlockMigration.CODEC)).setKeyFunction(BlockMigration::getId)).build());
        final BlockTypeAssetMap<String, BlockType> blockTypeAssetMap = new BlockTypeAssetMap<String, BlockType>(BlockType[]::new, BlockType::getGroup);
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockType.class, blockTypeAssetMap).setPath()).setCodec(BlockType.CODEC)).setKeyFunction(BlockType::getId)).setPacketGenerator(new BlockTypePacketGenerator()).loadsAfter(BlockBoundingBoxes.class, BlockSoundSet.class, SoundEvent.class, BlockParticleSet.class, BlockBreakingDecal.class, CustomConnectedBlockTemplateAsset.class, PrefabListAsset.class, BlockTypeListAsset.class)).setNotificationItemFunction(item -> new ItemStack(item, 1).toPacket()).setReplaceOnRemove()).preLoadAssets(Arrays.asList(BlockType.EMPTY, BlockType.UNKNOWN, BlockType.DEBUG_CUBE, BlockType.DEBUG_MODEL))).setIdProvider(Item.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Fluid.class, new IndexedLookupTableAssetMap(Fluid[]::new)).setPath()).setCodec(Fluid.CODEC)).setKeyFunction(Fluid::getId)).setReplaceOnRemove(Fluid::getUnknownFor)).setPacketGenerator(new FluidTypePacketGenerator()).loadsAfter(FluidFX.class, BlockSoundSet.class, BlockParticleSet.class, SoundEvent.class)).preLoadAssets(List.of(Fluid.EMPTY, Fluid.UNKNOWN))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemPlayerAnimations.class, new DefaultAssetMap()).setPath()).setCodec(ItemPlayerAnimations.CODEC)).setKeyFunction(ItemPlayerAnimations::getId)).setPacketGenerator(new ItemPlayerAnimationsPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Environment.class, new IndexedLookupTableAssetMap(Environment[]::new)).setPath()).setCodec(Environment.CODEC)).setKeyFunction(Environment::getId)).setReplaceOnRemove(Environment::getUnknownFor)).setPacketGenerator(new EnvironmentPacketGenerator()).loadsAfter(Weather.class, FluidFX.class, ParticleSystem.class)).preLoadAssets(Collections.singletonList(Environment.UNKNOWN))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(FluidFX.class, new IndexedLookupTableAssetMap(FluidFX[]::new)).setPath()).setCodec(FluidFX.CODEC)).setKeyFunction(FluidFX::getId)).setReplaceOnRemove(FluidFX::getUnknownFor)).setPacketGenerator(new FluidFXPacketGenerator()).loadsAfter(ParticleSystem.class)).preLoadAssets(Collections.singletonList(FluidFX.EMPTY_FLUID_FX))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemCategory.class, new DefaultAssetMap(Collections.synchronizedMap((Map<String, T>)new Object2ObjectLinkedOpenHashMap<String, Object>()))).setPath()).setCodec(ItemCategory.CODEC)).setKeyFunction(ItemCategory::getId)).setPacketGenerator(new ItemCategoryPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(FieldcraftCategory.class, new DefaultAssetMap(Collections.synchronizedMap((Map<String, T>)new Object2ObjectLinkedOpenHashMap<String, Object>()))).setPath()).setCodec(FieldcraftCategory.CODEC)).setKeyFunction(FieldcraftCategory::getId)).setPacketGenerator(new FieldcraftCategoryPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemDropList.class, new DefaultAssetMap()).setPath()).setCodec(ItemDropList.CODEC)).setKeyFunction(ItemDropList::getId)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(WordList.class, new DefaultAssetMap()).setPath()).setCodec(WordList.CODEC)).setKeyFunction(WordList::getId)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemReticleConfig.class, new IndexedLookupTableAssetMap(ItemReticleConfig[]::new)).setPath()).setCodec(ItemReticleConfig.CODEC)).setKeyFunction(ItemReticleConfig::getId)).setReplaceOnRemove(ItemReticleConfig::new)).setPacketGenerator(new ItemReticleConfigPacketGenerator()).preLoadAssets(Collections.singletonList(ItemReticleConfig.DEFAULT))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemToolSpec.class, new DefaultAssetMap()).setPath()).setCodec(ItemToolSpec.CODEC)).setKeyFunction(ItemToolSpec::getGatherType).loadsAfter(SoundEvent.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(PortalType.class, new DefaultAssetMap()).setPath()).setCodec(PortalType.CODEC)).setKeyFunction(PortalType::getId)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Item.class, new DefaultAssetMap()).setPath()).setCodec(Item.CODEC)).setKeyFunction(Item::getId)).setPacketGenerator(new ItemPacketGenerator()).loadsAfter(ItemCategory.class, ItemPlayerAnimations.class, UnarmedInteractions.class, ResourceType.class, BlockType.class, EntityEffect.class, ItemQuality.class, ItemReticleConfig.class, SoundEvent.class, PortalType.class, ItemSoundSet.class)).setNotificationItemFunction(item -> new ItemStack(item, 1).toPacket()).preLoadAssets()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(CraftingRecipe.class, new DefaultAssetMap()).setPath()).setCodec(CraftingRecipe.CODEC)).setKeyFunction(CraftingRecipe::getId)).setPacketGenerator(new CraftingRecipePacketGenerator()).loadsAfter(Item.class, BlockType.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ModelAsset.class, new DefaultAssetMap()).setPath()).setCodec(ModelAsset.CODEC)).setKeyFunction(ModelAsset::getId).loadsAfter(ParticleSystem.class, SoundEvent.class, Trail.class)).preLoadAssets(List.of(ModelAsset.DEBUG))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ParticleSpawner.class, new DefaultAssetMap()).setPath()).setExtension(".particlespawner")).setCodec(ParticleSpawner.CODEC)).setKeyFunction(ParticleSpawner::getId)).setPacketGenerator(new ParticleSpawnerPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ParticleSystem.class, new DefaultAssetMap()).setPath()).setExtension(".particlesystem")).setCodec(ParticleSystem.CODEC)).setKeyFunction(ParticleSystem::getId)).setPacketGenerator(new ParticleSystemPacketGenerator()).loadsAfter(ParticleSpawner.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Trail.class, new DefaultAssetMap()).setPath()).setCodec(Trail.CODEC)).setKeyFunction(Trail::getId)).setPacketGenerator(new TrailPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Projectile.class, new DefaultAssetMap()).setPath()).setCodec(Projectile.CODEC)).setKeyFunction(Projectile::getId).loadsAfter(SoundEvent.class, ModelAsset.class, ParticleSystem.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(EntityEffect.class, new IndexedLookupTableAssetMap(EntityEffect[]::new)).setPath()).setCodec(EntityEffect.CODEC)).setKeyFunction(EntityEffect::getId)).setReplaceOnRemove(EntityEffect::new)).setPacketGenerator(new EntityEffectPacketGenerator()).loadsAfter(ModelAsset.class, ParticleSystem.class, EntityStatType.class, ModelVFX.class, DamageCause.class, CameraEffect.class, SoundEvent.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ModelVFX.class, new IndexedLookupTableAssetMap(ModelVFX[]::new)).setPath()).setCodec(ModelVFX.CODEC)).setKeyFunction(ModelVFX::getId)).setReplaceOnRemove(ModelVFX::new)).setPacketGenerator(new ModelVFXPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(GameModeType.class, new DefaultAssetMap()).setPath()).setCodec(GameModeType.CODEC)).setKeyFunction(GameModeType::getId).loadsAfter(Interaction.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ResourceType.class, new DefaultAssetMap()).setPath()).setCodec(ResourceType.CODEC)).setKeyFunction(ResourceType::getId)).setPacketGenerator(new ResourceTypePacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Weather.class, new IndexedLookupTableAssetMap(Weather[]::new)).setPath()).setCodec(Weather.CODEC)).setKeyFunction(Weather::getId)).setReplaceOnRemove(Weather::new)).setPacketGenerator(new WeatherPacketGenerator()).loadsAfter(ParticleSystem.class)).preLoadAssets(Collections.singletonList(Weather.UNKNOWN))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(GameplayConfig.class, new DefaultAssetMap()).setPath()).setCodec(GameplayConfig.CODEC)).setKeyFunction(GameplayConfig::getId).loadsAfter(Item.class, SoundEvent.class, SoundSet.class, BlockType.class, EntityEffect.class, HitboxCollisionConfig.class, DamageCause.class, RepulsionConfig.class, ParticleSystem.class, AmbienceFX.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(SoundEvent.class, new IndexedLookupTableAssetMap(SoundEvent[]::new)).setPath()).setCodec(SoundEvent.CODEC)).setKeyFunction(SoundEvent::getId)).setReplaceOnRemove(SoundEvent::new)).setPacketGenerator(new SoundEventPacketGenerator()).preLoadAssets(Collections.singletonList(SoundEvent.EMPTY_SOUND_EVENT)).loadsAfter(AudioCategory.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(SoundSet.class, new IndexedLookupTableAssetMap(SoundSet[]::new)).setPath()).setCodec(SoundSet.CODEC)).setKeyFunction(SoundSet::getId)).setReplaceOnRemove(SoundSet::new)).setPacketGenerator(new SoundSetPacketGenerator()).loadsAfter(SoundEvent.class)).preLoadAssets(Collections.singletonList(SoundSet.EMPTY_SOUND_SET))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(AudioCategory.class, new IndexedLookupTableAssetMap(AudioCategory[]::new)).setPath()).setCodec(AudioCategory.CODEC)).setKeyFunction(AudioCategory::getId)).setReplaceOnRemove(AudioCategory::new)).setPacketGenerator(new AudioCategoryPacketGenerator()).preLoadAssets(Collections.singletonList(AudioCategory.EMPTY_AUDIO_CATEGORY))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ReverbEffect.class, new IndexedLookupTableAssetMap(ReverbEffect[]::new)).setPath()).setCodec(ReverbEffect.CODEC)).setKeyFunction(ReverbEffect::getId)).setReplaceOnRemove(ReverbEffect::new)).setPacketGenerator(new ReverbEffectPacketGenerator()).preLoadAssets(Collections.singletonList(ReverbEffect.EMPTY_REVERB_EFFECT))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(EqualizerEffect.class, new IndexedLookupTableAssetMap(EqualizerEffect[]::new)).setPath()).setCodec(EqualizerEffect.CODEC)).setKeyFunction(EqualizerEffect::getId)).setReplaceOnRemove(EqualizerEffect::new)).setPacketGenerator(new EqualizerEffectPacketGenerator()).preLoadAssets(Collections.singletonList(EqualizerEffect.EMPTY_EQUALIZER_EFFECT))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ResponseCurve.class, new IndexedLookupTableAssetMap(ResponseCurve[]::new)).setPath()).setCodec(ResponseCurve.CODEC)).setKeyFunction(ResponseCurve::getId)).setReplaceOnRemove(ExponentialResponseCurve::new)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemQuality.class, new IndexedLookupTableAssetMap(ItemQuality[]::new)).setPath()).setCodec(ItemQuality.CODEC)).setKeyFunction(ItemQuality::getId)).setPacketGenerator(new ItemQualityPacketGenerator()).setReplaceOnRemove(ItemQuality::new).loadsAfter(ParticleSystem.class)).preLoadAssets(Collections.singletonList(ItemQuality.DEFAULT_ITEM_QUALITY))).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(DamageCause.class, new IndexedLookupTableAssetMap(DamageCause[]::new)).setPath()).setCodec(DamageCause.CODEC)).setKeyFunction(DamageCause::getId)).setReplaceOnRemove(DamageCause::new).loadsBefore(Item.class, Interaction.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ProjectileConfig.class, new DefaultAssetMap()).setPath()).setCodec(ProjectileConfig.CODEC)).setKeyFunction(ProjectileConfig::getId).loadsAfter(Interaction.class, SoundEvent.class, ModelAsset.class, ParticleSystem.class)).setPacketGenerator(new ProjectileConfigPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockGroup.class, new DefaultAssetMap()).setPath()).setCodec(BlockGroup.CODEC)).setKeyFunction(BlockGroup::getId).loadsAfter(BlockType.class, Item.class)).setPacketGenerator(new BlockGroupPacketGenerator()).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BuilderToolItemReferenceAsset.class, new DefaultAssetMap()).setPath()).setCodec(BuilderToolItemReferenceAsset.CODEC)).setKeyFunction(BuilderToolItemReferenceAsset::getId).loadsAfter(BlockType.class, Item.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BlockTypeListAsset.class, new DefaultAssetMap()).setPath()).setKeyFunction(BlockTypeListAsset::getId)).setCodec(BlockTypeListAsset.CODEC)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(PrefabListAsset.class, new DefaultAssetMap()).setPath()).setKeyFunction(PrefabListAsset::getId)).setCodec(PrefabListAsset.CODEC)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(CameraEffect.class, new IndexedLookupTableAssetMap(CameraEffect[]::new)).loadsBefore(GameplayConfig.class, Interaction.class).setPath("Camera/CameraEffect")).setCodec(CameraEffect.CODEC)).setKeyFunction(CameraEffect::getId)).setReplaceOnRemove(CameraEffect.MissingCameraEffect::new)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(TagPattern.class, new IndexedLookupTableAssetMap(TagPattern[]::new)).setPath()).setCodec(TagPattern.CODEC)).setKeyFunction(TagPattern::getId)).setReplaceOnRemove(EqualsTagOp::new)).setPacketGenerator(new TagPatternPacketGenerator()).build());
        TagPattern.CODEC.register("Equals", EqualsTagOp.class, EqualsTagOp.CODEC);
        TagPattern.CODEC.register("And", AndPatternOp.class, AndPatternOp.CODEC);
        TagPattern.CODEC.register("Or", OrPatternOp.class, OrPatternOp.CODEC);
        TagPattern.CODEC.register("Not", NotPatternOp.class, NotPatternOp.CODEC);
    }
}
