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

package com.hypixel.hytale.builtin.adventure.objectives;

import com.hypixel.hytale.server.core.event.events.entity.EntityEvent;
import com.hypixel.hytale.server.core.universe.datastore.DiskDataStoreProvider;
import com.hypixel.hytale.server.core.universe.datastore.DataStoreProvider;
import com.hypixel.hytale.component.CommandBuffer;
import com.hypixel.hytale.component.ArchetypeChunk;
import java.util.Arrays;
import com.hypixel.hytale.server.core.universe.world.worldmap.WorldMapManager;
import com.hypixel.hytale.builtin.adventure.objectives.markers.ObjectiveMarkerProvider;
import com.hypixel.hytale.server.core.inventory.container.CombinedItemContainer;
import com.hypixel.hytale.server.core.inventory.ItemStack;
import com.hypixel.hytale.server.core.entity.LivingEntity;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.component.query.AndQuery;
import com.hypixel.hytale.server.core.modules.entity.component.PersistentModel;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
import com.hypixel.hytale.common.util.ArrayUtil;
import com.hypixel.hytale.protocol.packets.assets.UntrackObjective;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.Universe;
import java.util.Iterator;
import com.hypixel.hytale.server.core.entity.entities.player.data.PlayerConfigData;
import com.hypixel.hytale.protocol.Packet;
import java.util.Collection;
import java.util.HashSet;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.protocol.packets.assets.TrackOrUpdateObjective;
import com.hypixel.hytale.server.core.Message;
import java.util.logging.Level;
import com.hypixel.hytale.component.Store;
import javax.annotation.Nullable;
import java.util.UUID;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.query.Query;
import com.hypixel.hytale.builtin.adventure.objectives.config.gameplayconfig.ObjectiveGameplayConfig;
import com.hypixel.hytale.builtin.adventure.objectives.blockstates.TreasureChestState;
import com.hypixel.hytale.server.core.universe.world.meta.BlockStateModule;
import com.hypixel.hytale.builtin.adventure.objectives.interactions.CanBreakRespawnPointInteraction;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.builtin.adventure.objectives.interactions.StartObjectiveInteraction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.builtin.adventure.objectives.systems.ObjectiveItemEntityRemovalSystem;
import com.hypixel.hytale.builtin.adventure.objectives.systems.ObjectivePlayerSetupSystem;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.builtin.adventure.objectives.historydata.ItemObjectiveRewardHistoryData;
import com.hypixel.hytale.builtin.adventure.objectives.historydata.ObjectiveRewardHistoryData;
import com.hypixel.hytale.builtin.adventure.objectives.historydata.ObjectiveLineHistoryData;
import com.hypixel.hytale.builtin.adventure.objectives.historydata.ObjectiveHistoryData;
import com.hypixel.hytale.builtin.adventure.objectives.historydata.CommonObjectiveHistoryData;
import com.hypixel.hytale.builtin.adventure.objectives.markers.objectivelocation.ObjectiveLocationMarkerSystems;
import com.hypixel.hytale.component.system.ISystem;
import com.hypixel.hytale.builtin.adventure.objectives.markers.reachlocation.ReachLocationMarkerSystems;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.builtin.adventure.objectives.commands.ObjectiveCommand;
import com.hypixel.hytale.server.core.universe.world.events.AddWorldEvent;
import com.hypixel.hytale.server.core.event.events.entity.LivingEntityInventoryChangeEvent;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.event.events.player.PlayerDisconnectEvent;
import com.hypixel.hytale.assetstore.event.LoadedAssetsEvent;
import com.hypixel.hytale.builtin.adventure.objectives.completion.ClearObjectiveItemsCompletion;
import com.hypixel.hytale.builtin.adventure.objectives.config.completion.ClearObjectiveItemsCompletionAsset;
import com.hypixel.hytale.builtin.adventure.objectives.completion.GiveItemsCompletion;
import com.hypixel.hytale.builtin.adventure.objectives.config.completion.GiveItemsCompletionAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.ReachLocationTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.ReachLocationTaskAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.TreasureMapObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.TreasureMapObjectiveTaskAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseEntityObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.UseEntityObjectiveTaskAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.UseBlockObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.UseBlockObjectiveTaskAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.GatherObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.GatherObjectiveTaskAsset;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.builtin.adventure.objectives.task.CraftObjectiveTask;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.CraftObjectiveTaskAsset;
import com.hypixel.hytale.server.core.asset.type.weather.config.Weather;
import com.hypixel.hytale.server.core.asset.type.environment.config.Environment;
import com.hypixel.hytale.builtin.adventure.objectives.config.ObjectiveLocationMarkerAsset;
import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import com.hypixel.hytale.builtin.adventure.objectives.config.ObjectiveLineAsset;
import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.builtin.adventure.objectives.markers.reachlocation.ReachLocationMarkerAsset;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.asset.type.item.config.ItemDropList;
import com.hypixel.hytale.assetstore.codec.AssetCodec;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.builtin.adventure.objectives.config.ObjectiveAsset;
import com.hypixel.hytale.assetstore.AssetStore;
import com.hypixel.hytale.server.core.asset.HytaleAssetStore;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.builtin.adventure.objectives.markers.objectivelocation.ObjectiveLocationMarker;
import com.hypixel.hytale.builtin.adventure.objectives.markers.reachlocation.ReachLocationMarker;
import com.hypixel.hytale.builtin.adventure.objectives.components.ObjectiveHistoryComponent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.util.Config;
import com.hypixel.hytale.builtin.adventure.objectives.completion.ObjectiveCompletion;
import java.util.function.Function;
import com.hypixel.hytale.builtin.adventure.objectives.config.completion.ObjectiveCompletionAsset;
import com.hypixel.hytale.builtin.adventure.objectives.task.ObjectiveTask;
import com.hypixel.hytale.function.function.TriFunction;
import com.hypixel.hytale.builtin.adventure.objectives.config.task.ObjectiveTaskAsset;
import java.util.Map;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;

public class ObjectivePlugin extends JavaPlugin
{
    protected static ObjectivePlugin instance;
    public static final String OBJECTIVE_LOCATION_MARKER_MODEL_ID = "Objective_Location_Marker";
    public static final long SAVE_INTERVAL_MINUTES = 5L;
    private final Map<Class<? extends ObjectiveTaskAsset>, TriFunction<ObjectiveTaskAsset, Integer, Integer, ? extends ObjectiveTask>> taskGenerators;
    private final Map<Class<? extends ObjectiveCompletionAsset>, Function<ObjectiveCompletionAsset, ? extends ObjectiveCompletion>> completionGenerators;
    private final Config<ObjectivePluginConfig> config;
    private Model objectiveLocationMarkerModel;
    private ComponentType<EntityStore, ObjectiveHistoryComponent> objectiveHistoryComponentType;
    private ComponentType<EntityStore, ReachLocationMarker> reachLocationMarkerComponentType;
    private ComponentType<EntityStore, ObjectiveLocationMarker> objectiveLocationMarkerComponentType;
    private ObjectiveDataStore objectiveDataStore;
    static final /* synthetic */ boolean $assertionsDisabled;
    
    public static ObjectivePlugin get() {
        return ObjectivePlugin.instance;
    }
    
    public ObjectivePlugin(@Nonnull final JavaPluginInit init) {
        super(init);
        this.taskGenerators = new ConcurrentHashMap<Class<? extends ObjectiveTaskAsset>, TriFunction<ObjectiveTaskAsset, Integer, Integer, ? extends ObjectiveTask>>();
        this.completionGenerators = new ConcurrentHashMap<Class<? extends ObjectiveCompletionAsset>, Function<ObjectiveCompletionAsset, ? extends ObjectiveCompletion>>();
        this.config = this.withConfig(ObjectivePluginConfig.CODEC);
    }
    
    public ComponentType<EntityStore, ObjectiveHistoryComponent> getObjectiveHistoryComponentType() {
        return this.objectiveHistoryComponentType;
    }
    
    public Model getObjectiveLocationMarkerModel() {
        return this.objectiveLocationMarkerModel;
    }
    
    public ObjectiveDataStore getObjectiveDataStore() {
        return this.objectiveDataStore;
    }
    
    @Override
    protected void setup() {
        ObjectivePlugin.instance = this;
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ObjectiveAsset.class, new DefaultAssetMap()).setPath()).setCodec(ObjectiveAsset.CODEC)).setKeyFunction(ObjectiveAsset::getId).loadsAfter(ItemDropList.class, Item.class, BlockType.class, ReachLocationMarkerAsset.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ObjectiveLineAsset.class, new DefaultAssetMap()).setPath()).setCodec(ObjectiveLineAsset.CODEC)).setKeyFunction(ObjectiveLineAsset::getId).loadsAfter(ObjectiveAsset.class).loadsBefore(GameplayConfig.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ObjectiveLocationMarkerAsset.class, new DefaultAssetMap()).setPath()).setCodec(ObjectiveLocationMarkerAsset.CODEC)).setKeyFunction(ObjectiveLocationMarkerAsset::getId).loadsAfter(ObjectiveAsset.class, Environment.class, Weather.class)).build());
        AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ReachLocationMarkerAsset.class, new DefaultAssetMap()).setPath()).setCodec(ReachLocationMarkerAsset.CODEC)).setKeyFunction(ReachLocationMarkerAsset::getId)).build());
        this.objectiveDataStore = new ObjectiveDataStore(this.config.get().getDataStoreProvider().create(Objective.CODEC));
        this.reachLocationMarkerComponentType = this.getEntityStoreRegistry().registerComponent(ReachLocationMarker.class, "ReachLocationMarker", ReachLocationMarker.CODEC);
        this.objectiveLocationMarkerComponentType = this.getEntityStoreRegistry().registerComponent(ObjectiveLocationMarker.class, "ObjectiveLocation", ObjectiveLocationMarker.CODEC);
        this.registerTask("Craft", CraftObjectiveTaskAsset.class, CraftObjectiveTaskAsset.CODEC, CraftObjectiveTask.class, CraftObjectiveTask.CODEC, CraftObjectiveTask::new);
        this.registerTask("Gather", GatherObjectiveTaskAsset.class, GatherObjectiveTaskAsset.CODEC, GatherObjectiveTask.class, GatherObjectiveTask.CODEC, GatherObjectiveTask::new);
        this.registerTask("UseBlock", UseBlockObjectiveTaskAsset.class, UseBlockObjectiveTaskAsset.CODEC, UseBlockObjectiveTask.class, UseBlockObjectiveTask.CODEC, UseBlockObjectiveTask::new);
        this.registerTask("UseEntity", UseEntityObjectiveTaskAsset.class, UseEntityObjectiveTaskAsset.CODEC, UseEntityObjectiveTask.class, UseEntityObjectiveTask.CODEC, UseEntityObjectiveTask::new);
        this.registerTask("TreasureMap", TreasureMapObjectiveTaskAsset.class, TreasureMapObjectiveTaskAsset.CODEC, TreasureMapObjectiveTask.class, TreasureMapObjectiveTask.CODEC, TreasureMapObjectiveTask::new);
        this.registerTask("ReachLocation", ReachLocationTaskAsset.class, ReachLocationTaskAsset.CODEC, ReachLocationTask.class, ReachLocationTask.CODEC, ReachLocationTask::new);
        this.registerCompletion("GiveItems", GiveItemsCompletionAsset.class, GiveItemsCompletionAsset.CODEC, GiveItemsCompletion::new);
        this.registerCompletion("ClearObjectiveItems", ClearObjectiveItemsCompletionAsset.class, ClearObjectiveItemsCompletionAsset.CODEC, ClearObjectiveItemsCompletion::new);
        this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLineAsset.class, this::onObjectiveLineAssetLoaded);
        this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveAsset.class, this::onObjectiveAssetLoaded);
        this.getEventRegistry().register(PlayerDisconnectEvent.class, this::onPlayerDisconnect);
        this.getEventRegistry().register(LoadedAssetsEvent.class, ObjectiveLocationMarkerAsset.class, ObjectivePlugin::onObjectiveLocationMarkerChange);
        this.getEventRegistry().register(LoadedAssetsEvent.class, ModelAsset.class, this::onModelAssetChange);
        this.getEventRegistry().registerGlobal(LivingEntityInventoryChangeEvent.class, this::onLivingEntityInventoryChange);
        this.getEventRegistry().registerGlobal(AddWorldEvent.class, this::onWorldAdded);
        this.getCommandRegistry().registerCommand(new ObjectiveCommand());
        final EntityModule entityModule = EntityModule.get();
        final ComponentType<EntityStore, PlayerRef> playerRefComponentType = PlayerRef.getComponentType();
        final ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> playerSpatialComponent = entityModule.getPlayerSpatialResourceType();
        this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EntityAdded(this.reachLocationMarkerComponentType));
        this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.EnsureNetworkSendable());
        this.getEntityStoreRegistry().registerSystem(new ReachLocationMarkerSystems.Ticking(this.reachLocationMarkerComponentType, playerSpatialComponent));
        this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.EnsureNetworkSendableSystem());
        this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.InitSystem(this.objectiveLocationMarkerComponentType));
        this.getEntityStoreRegistry().registerSystem(new ObjectiveLocationMarkerSystems.TickingSystem(this.objectiveLocationMarkerComponentType, playerRefComponentType, playerSpatialComponent));
        CommonObjectiveHistoryData.CODEC.register("Objective", ObjectiveHistoryData.class, ObjectiveHistoryData.CODEC);
        CommonObjectiveHistoryData.CODEC.register("ObjectiveLine", ObjectiveLineHistoryData.class, ObjectiveLineHistoryData.CODEC);
        ObjectiveRewardHistoryData.CODEC.register("Item", ItemObjectiveRewardHistoryData.class, ItemObjectiveRewardHistoryData.CODEC);
        this.objectiveHistoryComponentType = this.getEntityStoreRegistry().registerComponent(ObjectiveHistoryComponent.class, "ObjectiveHistory", ObjectiveHistoryComponent.CODEC);
        this.getEntityStoreRegistry().registerSystem(new ObjectivePlayerSetupSystem(this.objectiveHistoryComponentType, Player.getComponentType()));
        this.getEntityStoreRegistry().registerSystem(new ObjectiveItemEntityRemovalSystem());
        this.getCodecRegistry(Interaction.CODEC).register("StartObjective", StartObjectiveInteraction.class, StartObjectiveInteraction.CODEC);
        this.getCodecRegistry(Interaction.CODEC).register("CanBreakRespawnPoint", CanBreakRespawnPointInteraction.class, CanBreakRespawnPointInteraction.CODEC);
        BlockStateModule.get().registerBlockState(TreasureChestState.class, "TreasureChest", TreasureChestState.CODEC);
        this.getCodecRegistry(GameplayConfig.PLUGIN_CODEC).register(ObjectiveGameplayConfig.class, "Objective", ObjectiveGameplayConfig.CODEC);
        this.getEntityStoreRegistry().registerSystem(new EntityModule.TangibleMigrationSystem((Query<EntityStore>)Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true);
        this.getEntityStoreRegistry().registerSystem(new EntityModule.HiddenFromPlayerMigrationSystem((Query<EntityStore>)Query.or(ObjectiveLocationMarker.getComponentType(), ReachLocationMarker.getComponentType())), true);
    }
    
    @Override
    protected void start() {
        final ModelAsset modelAsset = ModelAsset.getAssetMap().getAsset("Objective_Location_Marker");
        if (modelAsset == null) {
            throw new IllegalStateException(String.format("Default objective location marker model '%s' not found", "Objective_Location_Marker"));
        }
        this.objectiveLocationMarkerModel = Model.createUnitScaleModel(modelAsset);
        HytaleServer.SCHEDULED_EXECUTOR.scheduleWithFixedDelay(() -> this.objectiveDataStore.saveToDiskAllObjectives(), 5L, 5L, TimeUnit.MINUTES);
    }
    
    @Override
    protected void shutdown() {
        this.objectiveDataStore.saveToDiskAllObjectives();
    }
    
    public ComponentType<EntityStore, ReachLocationMarker> getReachLocationMarkerComponentType() {
        return this.reachLocationMarkerComponentType;
    }
    
    public ComponentType<EntityStore, ObjectiveLocationMarker> getObjectiveLocationMarkerComponentType() {
        return this.objectiveLocationMarkerComponentType;
    }
    
    public <T extends ObjectiveTaskAsset, U extends ObjectiveTask> void registerTask(final String id, final Class<T> assetClass, final Codec<T> assetCodec, final Class<U> implementationClass, final Codec<U> implementationCodec, final TriFunction<T, Integer, Integer, U> generator) {
        ObjectiveTaskAsset.CODEC.register(id, assetClass, assetCodec);
        ObjectiveTask.CODEC.register(id, implementationClass, implementationCodec);
        this.taskGenerators.put(assetClass, (TriFunction<ObjectiveTaskAsset, Integer, Integer, ? extends ObjectiveTask>)generator);
        this.objectiveDataStore.registerTaskRef(implementationClass);
    }
    
    public <T extends ObjectiveCompletionAsset, U extends ObjectiveCompletion> void registerCompletion(final String id, final Class<T> assetClass, final Codec<T> codec, final Function<T, U> generator) {
        ObjectiveCompletionAsset.CODEC.register(id, assetClass, codec);
        this.completionGenerators.put(assetClass, (Function<ObjectiveCompletionAsset, ? extends ObjectiveCompletion>)generator);
    }
    
    public ObjectiveTask createTask(@Nonnull final ObjectiveTaskAsset task, final int taskSetIndex, final int taskIndex) {
        return this.taskGenerators.get(task.getClass()).apply(task, taskSetIndex, taskIndex);
    }
    
    public ObjectiveCompletion createCompletion(@Nonnull final ObjectiveCompletionAsset completionAsset) {
        return this.completionGenerators.get(completionAsset.getClass()).apply(completionAsset);
    }
    
    @Nullable
    public Objective startObjective(@Nonnull final String objectiveId, @Nonnull final Set<UUID> playerUUIDs, @Nonnull final UUID worldUUID, @Nullable final UUID markerUUID, @Nonnull final Store<EntityStore> store) {
        return this.startObjective(objectiveId, null, playerUUIDs, worldUUID, markerUUID, store);
    }
    
    @Nullable
    public Objective startObjective(@Nonnull final String objectiveId, @Nullable final UUID objectiveUUID, @Nonnull final Set<UUID> playerUUIDs, @Nonnull final UUID worldUUID, @Nullable final UUID markerUUID, @Nonnull final Store<EntityStore> store) {
        final ObjectiveAsset asset = ObjectiveAsset.getAssetMap().getAsset(objectiveId);
        if (asset == null) {
            this.getLogger().at(Level.WARNING).log("Failed to find objective asset '%s'", objectiveId);
            return null;
        }
        if (markerUUID == null && !asset.isValidForPlayer()) {
            this.getLogger().at(Level.WARNING).log("Objective %s can't be used for Player", asset.getId());
            return null;
        }
        final Objective objective = new Objective(asset, objectiveUUID, playerUUIDs, worldUUID, markerUUID);
        final boolean setupResult = objective.setup(store);
        final Message assetTitleMessage = Message.translation(asset.getTitleKey());
        if (!setupResult || !this.objectiveDataStore.addObjective(objective.getObjectiveUUID(), objective)) {
            this.getLogger().at(Level.WARNING).log("Failed to start objective %s", asset.getId());
            if (objective.getPlayerUUIDs() == null) {
                return null;
            }
            objective.forEachParticipant(participantReference -> {
                final PlayerRef playerRefComponent = store.getComponent(participantReference, PlayerRef.getComponentType());
                if (playerRefComponent != null) {
                    playerRefComponent.sendMessage(Message.translation("server.modules.objective.start.failed").param("title", assetTitleMessage));
                }
                return;
            });
            return null;
        }
        else {
            if (objective.getPlayerUUIDs() == null) {
                return objective;
            }
            final TrackOrUpdateObjective trackObjectivePacket = new TrackOrUpdateObjective(objective.toPacket());
            final String objectiveAssetId = asset.getId();
            objective.forEachParticipant(participantReference -> {
                final Player playerComponent = store.getComponent(participantReference, Player.getComponentType());
                if (playerComponent == null) {
                    return;
                }
                else if (!this.canPlayerDoObjective(playerComponent, objectiveAssetId)) {
                    playerComponent.sendMessage(Message.translation("server.modules.objective.playerAlreadyDoingObjective").param("title", assetTitleMessage));
                    return;
                }
                else {
                    final PlayerRef playerRefComponent2 = store.getComponent(participantReference, PlayerRef.getComponentType());
                    if (!ObjectivePlugin.$assertionsDisabled && playerRefComponent2 == null) {
                        throw new AssertionError();
                    }
                    else {
                        final UUIDComponent uuidComponent = store.getComponent(participantReference, UUIDComponent.getComponentType());
                        if (!ObjectivePlugin.$assertionsDisabled && uuidComponent == null) {
                            throw new AssertionError();
                        }
                        else {
                            objective.addActivePlayerUUID(uuidComponent.getUuid());
                            final PlayerConfigData playerConfigData = playerComponent.getPlayerConfigData();
                            final HashSet<UUID> activeObjectiveUUIDs = new HashSet<UUID>(playerConfigData.getActiveObjectiveUUIDs());
                            activeObjectiveUUIDs.add(objective.getObjectiveUUID());
                            playerConfigData.setActiveObjectiveUUIDs(activeObjectiveUUIDs);
                            playerRefComponent2.sendMessage(Message.translation("server.modules.objective.start.success").param("title", assetTitleMessage));
                            playerRefComponent2.sendMessage(objective.getTaskInfoMessage());
                            playerRefComponent2.getPacketHandler().writeNoCache(trackObjectivePacket);
                            return;
                        }
                    }
                }
            });
            objective.markDirty();
            return objective;
        }
    }
    
    public boolean canPlayerDoObjective(@Nonnull final Player player, @Nonnull final String objectiveAssetId) {
        final Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
        if (activeObjectiveUUIDs == null) {
            return true;
        }
        for (final UUID objectiveUUID : activeObjectiveUUIDs) {
            final Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
            if (objective == null) {
                continue;
            }
            if (objective.getObjectiveId().equals(objectiveAssetId)) {
                return false;
            }
        }
        return true;
    }
    
    @Nullable
    public Objective startObjectiveLine(@Nonnull final Store<EntityStore> store, @Nonnull final String objectiveLineId, @Nonnull final Set<UUID> playerUUIDs, @Nonnull final UUID worldUUID, @Nullable final UUID markerUUID) {
        final ObjectiveLineAsset objectiveLineAsset = ObjectiveLineAsset.getAssetMap().getAsset(objectiveLineId);
        if (objectiveLineAsset == null) {
            return null;
        }
        final String[] objectiveIds = objectiveLineAsset.getObjectiveIds();
        if (objectiveIds == null || objectiveIds.length == 0) {
            return null;
        }
        final Universe universe = Universe.get();
        final HashSet<UUID> playerList = new HashSet<UUID>();
        for (final UUID playerUUID : playerUUIDs) {
            final PlayerRef playerRef = universe.getPlayer(playerUUID);
            if (playerRef == null) {
                continue;
            }
            final Ref<EntityStore> playerReference = playerRef.getReference();
            if (playerReference == null) {
                continue;
            }
            if (!playerReference.isValid()) {
                continue;
            }
            final Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
            assert playerComponent != null;
            if (this.canPlayerDoObjectiveLine(playerComponent, objectiveLineId)) {
                playerList.add(playerUUID);
            }
            else {
                final Message objectiveLineIdMessage = Message.translation(objectiveLineId);
                playerRef.sendMessage(Message.translation("server.modules.objective.playerAlreadyDoingObjectiveLine").param("id", objectiveLineIdMessage));
            }
        }
        final Objective objective = this.startObjective(objectiveLineAsset.getObjectiveIds()[0], playerList, worldUUID, markerUUID, store);
        if (objective == null) {
            return null;
        }
        objective.setObjectiveLineHistoryData(new ObjectiveLineHistoryData(objectiveLineId, objectiveLineAsset.getCategory(), objectiveLineAsset.getNextObjectiveLineIds()));
        objective.checkTaskSetCompletion(store);
        return objective;
    }
    
    public boolean canPlayerDoObjectiveLine(@Nonnull final Player player, @Nonnull final String objectiveLineId) {
        final Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
        if (activeObjectiveUUIDs == null) {
            return true;
        }
        for (final UUID objectiveUUID : activeObjectiveUUIDs) {
            final Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
            if (objective == null) {
                continue;
            }
            final ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData();
            if (objectiveLineHistoryData != null && objectiveLineId.equals(objectiveLineHistoryData.getId())) {
                return false;
            }
        }
        return true;
    }
    
    public void objectiveCompleted(@Nonnull final Objective objective, @Nonnull final Store<EntityStore> store) {
        for (final UUID playerUUID : objective.getPlayerUUIDs()) {
            this.untrackObjectiveForPlayer(objective, playerUUID);
        }
        final UUID objectiveUUID = objective.getObjectiveUUID();
        this.objectiveDataStore.removeObjective(objectiveUUID);
        if (!this.objectiveDataStore.removeFromDisk(objectiveUUID.toString())) {
            return;
        }
        final ObjectiveLineAsset objectiveLineAsset = objective.getObjectiveLineAsset();
        if (objectiveLineAsset == null) {
            this.storeObjectiveHistoryData(objective);
            return;
        }
        final ObjectiveLineHistoryData objectiveLineHistoryData = objective.getObjectiveLineHistoryData();
        assert objectiveLineHistoryData != null;
        objectiveLineHistoryData.addObjectiveHistoryData(objective.getObjectiveHistoryData());
        final String nextObjectiveId = objectiveLineAsset.getNextObjectiveId(objective.getObjectiveId());
        if (nextObjectiveId == null) {
            this.storeObjectiveLineHistoryData(objectiveLineHistoryData, objective.getPlayerUUIDs());
            final String[] nextObjectiveLineIds = objectiveLineHistoryData.getNextObjectiveLineIds();
            if (nextObjectiveLineIds == null) {
                return;
            }
            for (final String nextObjectiveLineId : nextObjectiveLineIds) {
                this.startObjectiveLine(store, nextObjectiveLineId, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID());
            }
        }
        else {
            final Objective newObjective = this.startObjective(nextObjectiveId, objectiveUUID, objective.getPlayerUUIDs(), objective.getWorldUUID(), objective.getMarkerUUID(), store);
            if (newObjective == null) {
                return;
            }
            newObjective.setObjectiveLineHistoryData(objectiveLineHistoryData);
            newObjective.checkTaskSetCompletion(store);
        }
    }
    
    public void storeObjectiveHistoryData(@Nonnull final Objective objective) {
        final String objectiveId = objective.getObjectiveId();
        final Universe universe = Universe.get();
        for (final UUID playerUUID : objective.getPlayerUUIDs()) {
            final PlayerRef playerRef = universe.getPlayer(playerUUID);
            if (playerRef != null) {
                if (!playerRef.isValid()) {
                    continue;
                }
                final Ref<EntityStore> playerReference = playerRef.getReference();
                if (playerReference == null) {
                    continue;
                }
                if (!playerReference.isValid()) {
                    continue;
                }
                final Store<EntityStore> store = playerReference.getStore();
                final World world = store.getExternalData().getWorld();
                world.execute(() -> {
                    final ObjectiveHistoryComponent objectiveHistoryComponent = store.getComponent(playerReference, this.objectiveHistoryComponentType);
                    if (!ObjectivePlugin.$assertionsDisabled && objectiveHistoryComponent == null) {
                        throw new AssertionError();
                    }
                    else {
                        final Map<String, ObjectiveHistoryData> completedObjectiveDataMap = objectiveHistoryComponent.getObjectiveHistoryMap();
                        final ObjectiveHistoryData completedObjectiveData = completedObjectiveDataMap.get(objectiveId);
                        if (completedObjectiveData != null) {
                            completedObjectiveData.completed(playerUUID, objective.getObjectiveHistoryData());
                        }
                        else {
                            completedObjectiveDataMap.put(objectiveId, objective.getObjectiveHistoryData().cloneForPlayer(playerUUID));
                        }
                    }
                });
            }
        }
    }
    
    public void storeObjectiveLineHistoryData(@Nonnull final ObjectiveLineHistoryData objectiveLineHistoryData, @Nonnull final Set<UUID> playerUUIDs) {
        final Map<UUID, ObjectiveLineHistoryData> objectiveLineHistoryPerPlayerMap = objectiveLineHistoryData.cloneForPlayers(playerUUIDs);
        final String objectiveLineId = objectiveLineHistoryData.getId();
        final Universe universe = Universe.get();
        for (final Map.Entry<UUID, ObjectiveLineHistoryData> entry : objectiveLineHistoryPerPlayerMap.entrySet()) {
            final UUID playerUUID = entry.getKey();
            final PlayerRef playerRef = universe.getPlayer(playerUUID);
            if (playerRef != null) {
                if (!playerRef.isValid()) {
                    continue;
                }
                final Ref<EntityStore> playerReference = playerRef.getReference();
                if (playerReference == null) {
                    continue;
                }
                if (!playerReference.isValid()) {
                    continue;
                }
                final Store<EntityStore> store = playerReference.getStore();
                final World world = store.getExternalData().getWorld();
                world.execute(() -> {
                    final ObjectiveHistoryComponent objectiveHistoryComponent = store.getComponent(playerReference, this.objectiveHistoryComponentType);
                    if (!ObjectivePlugin.$assertionsDisabled && objectiveHistoryComponent == null) {
                        throw new AssertionError();
                    }
                    else {
                        final Map<String, ObjectiveLineHistoryData> completedObjectiveLineDataMap = objectiveHistoryComponent.getObjectiveLineHistoryMap();
                        final ObjectiveLineHistoryData completedObjectiveLineData = completedObjectiveLineDataMap.get(objectiveLineId);
                        if (completedObjectiveLineData != null) {
                            completedObjectiveLineData.completed(playerUUID, entry.getValue());
                        }
                        else {
                            completedObjectiveLineDataMap.put(objectiveLineId, entry.getValue());
                        }
                    }
                });
            }
        }
    }
    
    public void cancelObjective(@Nonnull final UUID objectiveUUID, @Nonnull final Store<EntityStore> store) {
        final Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
        if (objective == null) {
            return;
        }
        objective.cancel();
        for (final UUID playerUUID : objective.getPlayerUUIDs()) {
            this.untrackObjectiveForPlayer(objective, playerUUID);
        }
        this.objectiveDataStore.removeObjective(objectiveUUID);
        this.objectiveDataStore.removeFromDisk(objectiveUUID.toString());
    }
    
    public void untrackObjectiveForPlayer(@Nonnull final Objective objective, @Nonnull final UUID playerUUID) {
        final UUID objectiveUUID = objective.getObjectiveUUID();
        final ObjectiveTask[] currentTasks2;
        final ObjectiveTask[] currentTasks = currentTasks2 = objective.getCurrentTasks();
        for (final ObjectiveTask task : currentTasks2) {
            if (task instanceof final UseEntityObjectiveTask useEntityObjectiveTask) {
                this.objectiveDataStore.removeEntityTaskForPlayer(objectiveUUID, useEntityObjectiveTask.getAsset().getTaskId(), playerUUID);
            }
        }
        final PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
        if (playerRef == null) {
            return;
        }
        final Player player = playerRef.getComponent(Player.getComponentType());
        final HashSet<UUID> activeObjectiveUUIDs = new HashSet<UUID>(player.getPlayerConfigData().getActiveObjectiveUUIDs());
        activeObjectiveUUIDs.remove(objectiveUUID);
        player.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
        playerRef.getPacketHandler().writeNoCache(new UntrackObjective(objectiveUUID));
    }
    
    public void addPlayerToExistingObjective(@Nonnull final Store<EntityStore> store, @Nonnull final UUID playerUUID, @Nonnull final UUID objectiveUUID) {
        final Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
        if (objective == null) {
            return;
        }
        objective.addActivePlayerUUID(playerUUID);
        final ObjectiveDataStore objectiveDataStore = get().getObjectiveDataStore();
        final ObjectiveTask[] currentTasks2;
        final ObjectiveTask[] currentTasks = currentTasks2 = objective.getCurrentTasks();
        for (final ObjectiveTask task : currentTasks2) {
            if (task instanceof final UseEntityObjectiveTask useEntityObjectiveTask) {
                objectiveDataStore.addEntityTaskForPlayer(playerUUID, useEntityObjectiveTask.getAsset().getTaskId(), objectiveUUID);
            }
        }
        final PlayerRef playerRef = Universe.get().getPlayer(playerUUID);
        if (playerRef == null || !playerRef.isValid()) {
            return;
        }
        final Ref<EntityStore> playerReference = playerRef.getReference();
        if (playerReference == null || !playerReference.isValid()) {
            return;
        }
        final Player playerComponent = store.getComponent(playerReference, Player.getComponentType());
        assert playerComponent != null;
        final HashSet<UUID> activeObjectiveUUIDs = new HashSet<UUID>(playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs());
        activeObjectiveUUIDs.add(objectiveUUID);
        playerComponent.getPlayerConfigData().setActiveObjectiveUUIDs(activeObjectiveUUIDs);
        playerRef.getPacketHandler().writeNoCache(new TrackOrUpdateObjective(objective.toPacket()));
    }
    
    public void removePlayerFromExistingObjective(@Nonnull final Store<EntityStore> store, @Nonnull final UUID playerUUID, @Nonnull final UUID objectiveUUID) {
        final Objective objective = this.objectiveDataStore.loadObjective(objectiveUUID, store);
        if (objective == null) {
            return;
        }
        objective.removeActivePlayerUUID(playerUUID);
        if (objective.getActivePlayerUUIDs().isEmpty()) {
            this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective);
            this.objectiveDataStore.unloadObjective(objectiveUUID);
        }
        this.untrackObjectiveForPlayer(objective, playerUUID);
    }
    
    private void onPlayerDisconnect(@Nonnull final PlayerDisconnectEvent event) {
        final PlayerRef playerRef = event.getPlayerRef();
        final Ref<EntityStore> ref = playerRef.getReference();
        if (ref == null) {
            return;
        }
        final Store<EntityStore> store = ref.getStore();
        final World world = store.getExternalData().getWorld();
        world.execute(() -> {
            if (!(!ref.isValid())) {
                final UUID playerUUID = playerRef.getUuid();
                this.getLogger().at(Level.INFO).log("Checking objectives for disconnecting player '" + playerRef.getUsername() + "' (" + String.valueOf(playerUUID));
                final Player playerComponent = store.getComponent(ref, Player.getComponentType());
                if (playerComponent != null) {
                    final Set<UUID> activeObjectiveUUIDs = playerComponent.getPlayerConfigData().getActiveObjectiveUUIDs();
                    if (activeObjectiveUUIDs == null) {
                        this.getLogger().at(Level.INFO).log("No active objectives found for player '" + playerRef.getUsername() + "' (" + String.valueOf(playerUUID));
                    }
                    else {
                        this.getLogger().at(Level.INFO).log("Processing " + activeObjectiveUUIDs.size() + " active objectives for '" + playerRef.getUsername() + "' (" + String.valueOf(playerUUID));
                        for (final UUID objectiveUUID : activeObjectiveUUIDs) {
                            final Objective objective = this.objectiveDataStore.getObjective(objectiveUUID);
                            if (objective == null) {
                                continue;
                            }
                            else {
                                objective.removeActivePlayerUUID(playerUUID);
                                if (!objective.getActivePlayerUUIDs().isEmpty()) {
                                    continue;
                                }
                                else {
                                    this.objectiveDataStore.saveToDisk(objectiveUUID.toString(), objective);
                                    this.objectiveDataStore.unloadObjective(objectiveUUID);
                                }
                            }
                        }
                    }
                }
            }
        });
    }
    
    private void onObjectiveLineAssetLoaded(@Nonnull final LoadedAssetsEvent<String, ObjectiveLineAsset, DefaultAssetMap<String, ObjectiveLineAsset>> event) {
        if (this.objectiveDataStore == null) {
            return;
        }
        for (final Map.Entry<String, ObjectiveLineAsset> objectiveLineEntry : event.getLoadedAssets().entrySet()) {
            final String objectiveLineId = objectiveLineEntry.getKey();
            final String[] objectiveIds = objectiveLineEntry.getValue().getObjectiveIds();
            for (final Objective activeObjective : this.objectiveDataStore.getObjectiveCollection()) {
                final ObjectiveLineHistoryData objectiveLineHistoryData = activeObjective.getObjectiveLineHistoryData();
                if (objectiveLineHistoryData == null) {
                    continue;
                }
                if (!objectiveLineId.equals(objectiveLineHistoryData.getId())) {
                    continue;
                }
                if (ArrayUtil.contains(objectiveIds, activeObjective.getObjectiveId())) {
                    continue;
                }
                final World objectiveWorld = Universe.get().getWorld(activeObjective.worldUUID);
                if (objectiveWorld != null) {
                    objectiveWorld.execute(() -> {
                        final Store<EntityStore> store = objectiveWorld.getEntityStore().getStore();
                        this.cancelObjective(activeObjective.getObjectiveUUID(), store);
                        return;
                    });
                    break;
                }
                break;
            }
        }
    }
    
    private void onObjectiveAssetLoaded(@Nonnull final LoadedAssetsEvent<String, ObjectiveAsset, DefaultAssetMap<String, ObjectiveAsset>> event) {
        this.objectiveDataStore.getObjectiveCollection().forEach(objective -> objective.reloadObjectiveAsset(event.getLoadedAssets()));
    }
    
    private static void onObjectiveLocationMarkerChange(@Nonnull final LoadedAssetsEvent<String, ObjectiveLocationMarkerAsset, DefaultAssetMap<String, ObjectiveLocationMarkerAsset>> event) {
        final Map<String, ObjectiveLocationMarkerAsset> loadedAssets = event.getLoadedAssets();
        final AndQuery<EntityStore> query = Query.and(ObjectiveLocationMarker.getComponentType(), ModelComponent.getComponentType(), TransformComponent.getComponentType());
        Universe.get().getWorlds().forEach((s, world) -> world.execute(() -> {
            final Store<EntityStore> store = world.getEntityStore().getStore();
            store.forEachChunk(query, (archetypeChunk, commandBuffer) -> {
                int index = 0;
                while (index < archetypeChunk.size()) {
                    final ObjectiveLocationMarker objectiveLocationMarkerComponent = archetypeChunk.getComponent(index, ObjectiveLocationMarker.getComponentType());
                    if (!ObjectivePlugin.$assertionsDisabled && objectiveLocationMarkerComponent == null) {
                        throw new AssertionError();
                    }
                    else {
                        final ObjectiveLocationMarkerAsset objectiveLocationMarkerAsset = loadedAssets.get(objectiveLocationMarkerComponent.getObjectiveLocationMarkerId());
                        if (objectiveLocationMarkerAsset != null) {
                            final TransformComponent transformComponent = archetypeChunk.getComponent(index, TransformComponent.getComponentType());
                            if (!ObjectivePlugin.$assertionsDisabled && transformComponent == null) {
                                throw new AssertionError();
                            }
                            else {
                                final Vector3f rotation = transformComponent.getRotation();
                                objectiveLocationMarkerComponent.updateLocationMarkerValues(objectiveLocationMarkerAsset, rotation.getYaw(), store);
                                final ModelComponent modelComponent = archetypeChunk.getComponent(index, ModelComponent.getComponentType());
                                if (!ObjectivePlugin.$assertionsDisabled && modelComponent == null) {
                                    throw new AssertionError();
                                }
                                else {
                                    final Model oldModel = modelComponent.getModel();
                                    final PersistentModel persistentModelComponent = archetypeChunk.getComponent(index, PersistentModel.getComponentType());
                                    if (!ObjectivePlugin.$assertionsDisabled && persistentModelComponent == null) {
                                        throw new AssertionError();
                                    }
                                    else {
                                        final Model newModel = new Model(oldModel.getModelAssetId(), oldModel.getScale(), oldModel.getRandomAttachmentIds(), oldModel.getAttachments(), objectiveLocationMarkerComponent.getArea().getBoxForEntryArea(), oldModel.getModel(), oldModel.getTexture(), oldModel.getGradientSet(), oldModel.getGradientId(), oldModel.getEyeHeight(), oldModel.getCrouchOffset(), oldModel.getAnimationSetMap(), oldModel.getCamera(), oldModel.getLight(), oldModel.getParticles(), oldModel.getTrails(), oldModel.getPhysicsValues(), oldModel.getDetailBoxes(), oldModel.getPhobia(), oldModel.getPhobiaModelAssetId());
                                        persistentModelComponent.setModelReference(newModel.toReference());
                                        commandBuffer.putComponent(archetypeChunk.getReferenceTo(index), ModelComponent.getComponentType(), new ModelComponent(newModel));
                                    }
                                }
                            }
                        }
                        ++index;
                    }
                }
            });
        }));
    }
    
    private void onModelAssetChange(@Nonnull final LoadedAssetsEvent<String, ModelAsset, DefaultAssetMap<String, ModelAsset>> event) {
        final Map<String, ModelAsset> modelMap = event.getLoadedAssets();
        final ModelAsset modelAsset = modelMap.get("Objective_Location_Marker");
        if (modelAsset == null) {
            return;
        }
        this.objectiveLocationMarkerModel = Model.createUnitScaleModel(modelAsset);
    }
    
    private void onLivingEntityInventoryChange(@Nonnull final LivingEntityInventoryChangeEvent event) {
        final LivingEntity entity = ((EntityEvent<LivingEntity, KeyType>)event).getEntity();
        if (!(entity instanceof Player)) {
            return;
        }
        final Player player = (Player)entity;
        final Set<UUID> activeObjectiveUUIDs = player.getPlayerConfigData().getActiveObjectiveUUIDs();
        if (activeObjectiveUUIDs.isEmpty()) {
            return;
        }
        Set<UUID> inventoryItemObjectiveUUIDs = null;
        final CombinedItemContainer inventory = entity.getInventory().getCombinedHotbarFirst();
        for (short i = 0; i < inventory.getCapacity(); ++i) {
            final ItemStack itemStack = inventory.getItemStack(i);
            if (!ItemStack.isEmpty(itemStack)) {
                final UUID objectiveUUID = itemStack.getFromMetadataOrNull(StartObjectiveInteraction.OBJECTIVE_UUID);
                if (objectiveUUID != null) {
                    if (inventoryItemObjectiveUUIDs == null) {
                        inventoryItemObjectiveUUIDs = new HashSet<UUID>(activeObjectiveUUIDs);
                    }
                    inventoryItemObjectiveUUIDs.add(objectiveUUID);
                }
            }
        }
        for (final UUID activeObjectiveUUID : activeObjectiveUUIDs) {
            if (inventoryItemObjectiveUUIDs != null && inventoryItemObjectiveUUIDs.contains(activeObjectiveUUID)) {
                continue;
            }
            final Objective objective = this.objectiveDataStore.getObjective(activeObjectiveUUID);
            if (objective == null) {
                continue;
            }
            final ObjectiveAsset objectiveAsset = objective.getObjectiveAsset();
            if (objectiveAsset == null) {
                continue;
            }
            if (!objectiveAsset.isRemoveOnItemDrop()) {
                continue;
            }
            final Ref<EntityStore> reference = entity.getReference();
            final Store<EntityStore> store = reference.getStore();
            final World world = store.getExternalData().getWorld();
            world.execute(() -> {
                final UUIDComponent uuidComponent = store.getComponent(reference, UUIDComponent.getComponentType());
                if (!ObjectivePlugin.$assertionsDisabled && uuidComponent == null) {
                    throw new AssertionError();
                }
                else {
                    get().removePlayerFromExistingObjective(store, uuidComponent.getUuid(), activeObjectiveUUID);
                }
            });
        }
    }
    
    private void onWorldAdded(final AddWorldEvent event) {
        event.getWorld().getWorldMapManager().addMarkerProvider("objectives", ObjectiveMarkerProvider.INSTANCE);
    }
    
    @Nonnull
    public String getObjectiveDataDump() {
        final StringBuilder sb = new StringBuilder("Objective Data\n");
        for (final Objective objective : this.objectiveDataStore.getObjectiveCollection()) {
            sb.append("Objective ID: ").append(objective.getObjectiveId()).append("\n\t").append("UUID: ").append(objective.getObjectiveUUID()).append("\n\t").append("Players: ").append(Arrays.toString(objective.getPlayerUUIDs().toArray())).append("\n\t").append("Active players: ").append(Arrays.toString(objective.getActivePlayerUUIDs().toArray())).append("\n\n");
        }
        return sb.toString();
    }
    
    public static class ObjectivePluginConfig
    {
        public static final BuilderCodec<ObjectivePluginConfig> CODEC;
        private DataStoreProvider dataStoreProvider;
        
        public ObjectivePluginConfig() {
            this.dataStoreProvider = new DiskDataStoreProvider("objectives");
        }
        
        public DataStoreProvider getDataStoreProvider() {
            return this.dataStoreProvider;
        }
        
        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             "DataStore"
            //    16: getstatic       com/hypixel/hytale/server/core/universe/datastore/DataStoreProvider.CODEC:Lcom/hypixel/hytale/codec/lookup/BuilderCodecMapCodec;
            //    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: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //    44: putstatic       com/hypixel/hytale/builtin/adventure/objectives/ObjectivePlugin$ObjectivePluginConfig.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //    47: return         
            // 
            // The error that occurred was:
            // 
            // java.lang.UnsupportedOperationException: The requested operation is not supported.
            //     at com.strobel.util.ContractUtils.unsupported(ContractUtils.java:27)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:284)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:279)
            //     at com.strobel.assembler.metadata.TypeReference.makeGenericType(TypeReference.java:154)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:225)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:211)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:314)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2611)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java: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.runInference(TypeAnalysis.java:684)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypesForVariables(TypeAnalysis.java:593)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:405)
            //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
            //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:109)
            //     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.");
        }
    }
}
