package com.hypixel.hytale.server.npc;
import com.hypixel.hytale.assetstore.AssetMap;
import com.hypixel.hytale.assetstore.AssetPack;
import com.hypixel.hytale.assetstore.AssetRegistry;
import com.hypixel.hytale.assetstore.event.LoadedAssetsEvent;
import com.hypixel.hytale.assetstore.event.RemovedAssetsEvent;
import com.hypixel.hytale.assetstore.map.DefaultAssetMap;
import com.hypixel.hytale.assetstore.map.IndexedLookupTableAssetMap;
import com.hypixel.hytale.builtin.path.path.TransientPathDefinition;
import com.hypixel.hytale.builtin.path.waypoint.RelativeWaypointDefinition;
import com.hypixel.hytale.builtin.tagset.TagSetPlugin;
import com.hypixel.hytale.builtin.tagset.config.NPCGroup;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.common.benchmark.TimeDistributionRecorder;
import com.hypixel.hytale.common.util.FormatUtil;
import com.hypixel.hytale.component.AddReason;
import com.hypixel.hytale.component.ComponentRegistryProxy;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.component.Holder;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.RemoveReason;
import com.hypixel.hytale.component.ResourceType;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.component.dependency.Dependency;
import com.hypixel.hytale.component.dependency.Order;
import com.hypixel.hytale.component.dependency.SystemDependency;
import com.hypixel.hytale.component.spatial.KDTree;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.event.EventRegistry;
import com.hypixel.hytale.function.consumer.TriConsumer;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.logger.sentry.SkipSentryException;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.Options;
import com.hypixel.hytale.server.core.asset.AssetModule;
import com.hypixel.hytale.server.core.asset.AssetPackRegisterEvent;
import com.hypixel.hytale.server.core.asset.AssetPackUnregisterEvent;
import com.hypixel.hytale.server.core.asset.GenerateSchemaEvent;
import com.hypixel.hytale.server.core.asset.HytaleAssetStore;
import com.hypixel.hytale.server.core.asset.LoadAssetEvent;
import com.hypixel.hytale.server.core.asset.type.item.config.Item;
import com.hypixel.hytale.server.core.asset.type.model.config.Model;
import com.hypixel.hytale.server.core.asset.type.model.config.ModelAsset;
import com.hypixel.hytale.server.core.asset.type.responsecurve.config.ResponseCurve;
import com.hypixel.hytale.server.core.entity.UUIDComponent;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.server.core.modules.entity.component.DisplayNameComponent;
import com.hypixel.hytale.server.core.modules.entity.component.HeadRotation;
import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
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.entitystats.EntityStatMap;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatsSystems;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.Interaction;
import com.hypixel.hytale.server.core.modules.interaction.interaction.config.RootInteraction;
import com.hypixel.hytale.server.core.modules.migrations.MigrationModule;
import com.hypixel.hytale.server.core.modules.time.WorldTimeResource;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter;
import com.hypixel.hytale.server.core.universe.world.path.WorldPathChangedEvent;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.server.core.util.Config;
import com.hypixel.hytale.server.flock.FlockPlugin;
import com.hypixel.hytale.server.flock.config.FlockAsset;
import com.hypixel.hytale.server.migrations.RenameSpawnMarkerMigration;
import com.hypixel.hytale.server.npc.asset.builder.Builder;
import com.hypixel.hytale.server.npc.asset.builder.BuilderDescriptor;
import com.hypixel.hytale.server.npc.asset.builder.BuilderFactory;
import com.hypixel.hytale.server.npc.asset.builder.BuilderInfo;
import com.hypixel.hytale.server.npc.asset.builder.BuilderManager;
import com.hypixel.hytale.server.npc.asset.builder.BuilderSupport;
import com.hypixel.hytale.server.npc.blackboard.Blackboard;
import com.hypixel.hytale.server.npc.blackboard.view.attitude.AttitudeMap;
import com.hypixel.hytale.server.npc.blackboard.view.attitude.ItemAttitudeMap;
import com.hypixel.hytale.server.npc.blackboard.view.combat.CombatViewSystems;
import com.hypixel.hytale.server.npc.commands.NPCCommand;
import com.hypixel.hytale.server.npc.commands.NPCRunTestsCommand;
import com.hypixel.hytale.server.npc.components.FailedSpawnComponent;
import com.hypixel.hytale.server.npc.components.SortBufferProviderResource;
import com.hypixel.hytale.server.npc.components.StepComponent;
import com.hypixel.hytale.server.npc.components.Timers;
import com.hypixel.hytale.server.npc.components.messaging.BeaconSupport;
import com.hypixel.hytale.server.npc.components.messaging.NPCBlockEventSupport;
import com.hypixel.hytale.server.npc.components.messaging.NPCEntityEventSupport;
import com.hypixel.hytale.server.npc.components.messaging.PlayerBlockEventSupport;
import com.hypixel.hytale.server.npc.components.messaging.PlayerEntityEventSupport;
import com.hypixel.hytale.server.npc.config.AttitudeGroup;
import com.hypixel.hytale.server.npc.config.ItemAttitudeGroup;
import com.hypixel.hytale.server.npc.config.balancing.BalanceAsset;
import com.hypixel.hytale.server.npc.corecomponents.IEntityFilter;
import com.hypixel.hytale.server.npc.corecomponents.ISensorEntityCollector;
import com.hypixel.hytale.server.npc.corecomponents.ISensorEntityPrioritiser;
import com.hypixel.hytale.server.npc.corecomponents.WeightedAction;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionAppearance;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionDisplayName;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionModelAttachment;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionPlayAnimation;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionPlaySound;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderActionSpawnParticles;
import com.hypixel.hytale.server.npc.corecomponents.audiovisual.builders.BuilderSensorAnimation;
import com.hypixel.hytale.server.npc.corecomponents.builders.BuilderWeightedAction;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderActionApplyEntityEffect;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderActionAttack;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderBodyMotionAimCharge;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderHeadMotionAim;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderSensorDamage;
import com.hypixel.hytale.server.npc.corecomponents.combat.builders.BuilderSensorIsBackingAway;
import com.hypixel.hytale.server.npc.corecomponents.debug.builders.BuilderActionLog;
import com.hypixel.hytale.server.npc.corecomponents.debug.builders.BuilderActionTest;
import com.hypixel.hytale.server.npc.corecomponents.debug.builders.BuilderBodyMotionTestProbe;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionBeacon;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionIgnoreForAvoidance;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionNotify;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionOverrideAttitude;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionReleaseTarget;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionSetMarkedTarget;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderActionSetStat;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderHeadMotionWatch;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorBeacon;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorCount;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorEntity;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorKill;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorPlayer;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorSelf;
import com.hypixel.hytale.server.npc.corecomponents.entity.builders.BuilderSensorTarget;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterAltitude;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterAnd;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterAttitude;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterCombat;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterHeightDifference;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterInsideBlock;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterInventory;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterItemInHand;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterLineOfSight;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterMovementState;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterNPCGroup;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterNot;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterOr;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterSpotsMe;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterStandingOnBlock;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterStat;
import com.hypixel.hytale.server.npc.corecomponents.entity.filters.builders.BuilderEntityFilterViewSector;
import com.hypixel.hytale.server.npc.corecomponents.entity.prioritisers.builders.BuilderSensorEntityPrioritiserAttitude;
import com.hypixel.hytale.server.npc.corecomponents.interaction.builders.BuilderActionLockOnInteractionTarget;
import com.hypixel.hytale.server.npc.corecomponents.interaction.builders.BuilderActionSetInteractable;
import com.hypixel.hytale.server.npc.corecomponents.interaction.builders.BuilderSensorCanInteract;
import com.hypixel.hytale.server.npc.corecomponents.interaction.builders.BuilderSensorHasInteracted;
import com.hypixel.hytale.server.npc.corecomponents.interaction.builders.BuilderSensorInteractionContext;
import com.hypixel.hytale.server.npc.corecomponents.items.builders.BuilderActionDropItem;
import com.hypixel.hytale.server.npc.corecomponents.items.builders.BuilderActionInventory;
import com.hypixel.hytale.server.npc.corecomponents.items.builders.BuilderActionPickUpItem;
import com.hypixel.hytale.server.npc.corecomponents.items.builders.BuilderSensorDroppedItem;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionDelayDespawn;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionDespawn;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionDie;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionRemove;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionRole;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderActionSpawn;
import com.hypixel.hytale.server.npc.corecomponents.lifecycle.builders.BuilderSensorAge;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderActionCrouch;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderActionOverrideAltitude;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderActionRecomputePath;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionFind;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionLand;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionLeave;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionMaintainDistance;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionMatchLook;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionMoveAway;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionTakeOff;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionTeleport;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionWander;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionWanderInCircle;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderBodyMotionWanderInRect;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderSensorInAir;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderSensorMotionController;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderSensorNav;
import com.hypixel.hytale.server.npc.corecomponents.movement.builders.BuilderSensorOnGround;
import com.hypixel.hytale.server.npc.corecomponents.statemachine.builders.BuilderActionParentState;
import com.hypixel.hytale.server.npc.corecomponents.statemachine.builders.BuilderActionState;
import com.hypixel.hytale.server.npc.corecomponents.statemachine.builders.BuilderActionToggleStateEvaluator;
import com.hypixel.hytale.server.npc.corecomponents.statemachine.builders.BuilderSensorIsBusy;
import com.hypixel.hytale.server.npc.corecomponents.statemachine.builders.BuilderSensorState;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionSetAlarm;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerContinue;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerModify;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerPause;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerRestart;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerStart;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderActionTimerStop;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderBodyMotionTimer;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderHeadMotionTimer;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderSensorAlarm;
import com.hypixel.hytale.server.npc.corecomponents.timer.builders.BuilderSensorTimer;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionNothing;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionRandom;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionResetInstructions;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionSequence;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionSetFlag;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderActionTimeout;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderBodyMotionNothing;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderBodyMotionSequence;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderHeadMotionNothing;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderHeadMotionSequence;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorAdjustPosition;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorAnd;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorAny;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorEval;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorFlag;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorNot;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorOr;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorRandom;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorSwitch;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderSensorValueProviderWrapper;
import com.hypixel.hytale.server.npc.corecomponents.utility.builders.BuilderValueToParameterMapping;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionMakePath;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionPlaceBlock;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionResetBlockSensors;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionResetPath;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionResetSearchRays;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionSetBlockToPlace;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionSetLeashPosition;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionStorePosition;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderActionTriggerSpawners;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderBodyMotionPath;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderHeadMotionObserve;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorBlock;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorBlockChange;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorBlockType;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorCanPlace;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorEntityEvent;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorInWater;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorLeash;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorLight;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorPath;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorReadPosition;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorSearchRay;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorTime;
import com.hypixel.hytale.server.npc.corecomponents.world.builders.BuilderSensorWeather;
import com.hypixel.hytale.server.npc.decisionmaker.core.conditions.base.Condition;
import com.hypixel.hytale.server.npc.decisionmaker.stateevaluator.StateEvaluator;
import com.hypixel.hytale.server.npc.entities.NPCEntity;
import com.hypixel.hytale.server.npc.instructions.Action;
import com.hypixel.hytale.server.npc.instructions.ActionList;
import com.hypixel.hytale.server.npc.instructions.BodyMotion;
import com.hypixel.hytale.server.npc.instructions.HeadMotion;
import com.hypixel.hytale.server.npc.instructions.Instruction;
import com.hypixel.hytale.server.npc.instructions.Sensor;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderActionList;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderInstruction;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderInstructionRandomized;
import com.hypixel.hytale.server.npc.instructions.builders.BuilderInstructionReference;
import com.hypixel.hytale.server.npc.interactions.ContextualUseNPCInteraction;
import com.hypixel.hytale.server.npc.interactions.SpawnNPCInteraction;
import com.hypixel.hytale.server.npc.interactions.UseNPCInteraction;
import com.hypixel.hytale.server.npc.movement.controllers.BuilderMotionControllerMapUtil;
import com.hypixel.hytale.server.npc.movement.controllers.MotionController;
import com.hypixel.hytale.server.npc.movement.controllers.builders.BuilderMotionControllerDive;
import com.hypixel.hytale.server.npc.movement.controllers.builders.BuilderMotionControllerFly;
import com.hypixel.hytale.server.npc.movement.controllers.builders.BuilderMotionControllerMap;
import com.hypixel.hytale.server.npc.movement.controllers.builders.BuilderMotionControllerWalk;
import com.hypixel.hytale.server.npc.navigation.AStarNodePoolProviderSimple;
import com.hypixel.hytale.server.npc.path.builders.BuilderRelativeWaypointDefinition;
import com.hypixel.hytale.server.npc.path.builders.BuilderTransientPathDefinition;
import com.hypixel.hytale.server.npc.role.Role;
import com.hypixel.hytale.server.npc.role.builders.BuilderRole;
import com.hypixel.hytale.server.npc.role.builders.BuilderRoleAbstract;
import com.hypixel.hytale.server.npc.role.builders.BuilderRoleVariant;
import com.hypixel.hytale.server.npc.statetransition.StateTransitionController;
import com.hypixel.hytale.server.npc.systems.AvoidanceSystem;
import com.hypixel.hytale.server.npc.systems.BalancingInitialisationSystem;
import com.hypixel.hytale.server.npc.systems.BlackboardSystems;
import com.hypixel.hytale.server.npc.systems.ComputeVelocitySystem;
import com.hypixel.hytale.server.npc.systems.FailedSpawnSystem;
import com.hypixel.hytale.server.npc.systems.MessageSupportSystem;
import com.hypixel.hytale.server.npc.systems.MovementStatesSystem;
import com.hypixel.hytale.server.npc.systems.NPCDamageSystems;
import com.hypixel.hytale.server.npc.systems.NPCDeathSystems;
import com.hypixel.hytale.server.npc.systems.NPCInteractionSystems;
import com.hypixel.hytale.server.npc.systems.NPCPreTickSystem;
import com.hypixel.hytale.server.npc.systems.NPCSpatialSystem;
import com.hypixel.hytale.server.npc.systems.NPCSystems;
import com.hypixel.hytale.server.npc.systems.NPCVelocityInstructionSystem;
import com.hypixel.hytale.server.npc.systems.NewSpawnStartTickingSystem;
import com.hypixel.hytale.server.npc.systems.PositionCacheSystems;
import com.hypixel.hytale.server.npc.systems.RoleBuilderSystem;
import com.hypixel.hytale.server.npc.systems.RoleChangeSystem;
import com.hypixel.hytale.server.npc.systems.RoleSystems;
import com.hypixel.hytale.server.npc.systems.StateEvaluatorSystem;
import com.hypixel.hytale.server.npc.systems.SteeringSystem;
import com.hypixel.hytale.server.npc.systems.StepCleanupSystem;
import com.hypixel.hytale.server.npc.systems.TimerSystem;
import com.hypixel.hytale.server.npc.util.SensorSupportBenchmark;
import com.hypixel.hytale.server.npc.util.expression.StdScope;
import com.hypixel.hytale.server.npc.valuestore.ValueStore;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class NPCPlugin extends JavaPlugin {
@Nonnull
public static String FACTORY_CLASS_ROLE = "Role";
@Nonnull
public static String FACTORY_CLASS_BODY_MOTION = "BodyMotion";
@Nonnull
public static String FACTORY_CLASS_HEAD_MOTION = "HeadMotion";
@Nonnull
public static String FACTORY_CLASS_ACTION = "Action";
@Nonnull
public static String FACTORY_CLASS_SENSOR = "Sensor";
@Nonnull
public static String FACTORY_CLASS_INSTRUCTION = "Instruction";
@Nonnull
public static String FACTORY_CLASS_TRANSIENT_PATH = "Path";
@Nonnull
public static String FACTORY_CLASS_ACTION_LIST = "ActionList";
@Nonnull
public static String ROLE_ASSETS_PATH = "Server/NPC/Roles";
private static NPCPlugin instance;
protected List<BuilderDescriptor> builderDescriptors;
protected final BuilderManager builderManager = new BuilderManager();
protected boolean validateBuilder;
protected int maxBlackboardBlockCountPerType = 20;
protected boolean logFailingTestErrors;
protected String[] presetCoverageTestNPCs;
@Nonnull
protected AtomicInteger pathChangeRevision = new AtomicInteger(0);
@Nonnull
protected Lock benchmarkLock = new ReentrantLock();
@Nullable
protected Int2ObjectMap<TimeDistributionRecorder> roleTickDistribution;
@Nullable
protected Int2ObjectMap<SensorSupportBenchmark> roleSensorSupportDistribution;
@Nullable
protected TimeDistributionRecorder roleTickDistributionAll;
@Nullable
protected SensorSupportBenchmark roleSensorSupportDistributionAll;
protected boolean autoReload;
private AttitudeMap attitudeMap;
private ItemAttitudeMap itemAttitudeMap;
private static final Vector3f NULL_ROTATION = new Vector3f(0.0F, 0.0F, 0.0F);
public static final short PRIORITY_LOAD_NPC = -8;
public static final short PRIORITY_SPAWN_VALIDATION = -7;
private final Config<NPCConfig> config;
private ResourceType<EntityStore, Blackboard> blackboardResourceType;
private ResourceType<EntityStore, CombatViewSystems.CombatDataPool> combatDataPoolResourceType;
private ResourceType<EntityStore, RoleChangeSystem.RoleChangeQueue> roleChangeQueueResourceType;
private ResourceType<EntityStore, NewSpawnStartTickingSystem.QueueResource> newSpawnStartTickingQueueResourceType;
private ResourceType<EntityStore, SortBufferProviderResource> sortBufferProviderResourceResourceType;
private ResourceType<EntityStore, AStarNodePoolProviderSimple> aStarNodePoolProviderSimpleResourceType;
private ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> npcSpatialResource;
private ComponentType<EntityStore, CombatViewSystems.CombatData> combatDataComponentType;
private ComponentType<EntityStore, NPCRunTestsCommand.NPCTestData> npcTestDataComponentType;
private ComponentType<EntityStore, BeaconSupport> beaconSupportComponentType;
private ComponentType<EntityStore, NPCBlockEventSupport> npcBlockEventSupportComponentType;
private ComponentType<EntityStore, PlayerBlockEventSupport> playerBlockEventSupportComponentType;
private ComponentType<EntityStore, NPCEntityEventSupport> npcEntityEventSupportComponentType;
private ComponentType<EntityStore, PlayerEntityEventSupport> playerEntityEventSupportComponentType;
private ComponentType<EntityStore, StepComponent> stepComponentType;
private ComponentType<EntityStore, FailedSpawnComponent> failedSpawnComponentType;
private ComponentType<EntityStore, Timers> timersComponentType;
private ComponentType<EntityStore, StateEvaluator> stateEvaluatorComponentType;
private ComponentType<EntityStore, ValueStore> valueStoreComponentType;
public static NPCPlugin get() {
return instance;
}
public NPCPlugin(@Nonnull JavaPluginInit init) {
super(init);
this.config = this.withConfig("NPCModule", NPCPlugin.NPCConfig.CODEC);
}
protected void setup() {
instance = this;
ComponentRegistryProxy<EntityStore> entityStoreRegistry = this.getEntityStoreRegistry();
EventRegistry eventRegistry = this.getEventRegistry();
this.getCommandRegistry().registerCommand(new NPCCommand());
eventRegistry.register((Class)LoadedAssetsEvent.class, ModelAsset.class, this::onModelsChanged);
eventRegistry.register((Class)LoadedAssetsEvent.class, NPCGroup.class, this::onNPCGroupsLoaded);
eventRegistry.register((Class)RemovedAssetsEvent.class, NPCGroup.class, this::onNPCGroupsRemoved);
eventRegistry.register((Class)LoadedAssetsEvent.class, AttitudeGroup.class, this::onAttitudeGroupsLoaded);
eventRegistry.register((Class)RemovedAssetsEvent.class, AttitudeGroup.class, this::onAttitudeGroupsRemoved);
eventRegistry.register((Class)LoadedAssetsEvent.class, ItemAttitudeGroup.class, this::onItemAttitudeGroupsLoaded);
eventRegistry.register((Class)RemovedAssetsEvent.class, ItemAttitudeGroup.class, this::onItemAttitudeGroupsRemoved);
eventRegistry.register((Class)LoadedAssetsEvent.class, BalanceAsset.class, NPCPlugin::onBalanceAssetsChanged);
eventRegistry.register((Class)RemovedAssetsEvent.class, BalanceAsset.class, NPCPlugin::onBalanceAssetsRemoved);
eventRegistry.register(WorldPathChangedEvent.class, this::onPathChange);
eventRegistry.register(AllNPCsLoadedEvent.class, this::onNPCsLoaded);
eventRegistry.register((short)-8, LoadAssetEvent.class, (event) -> {
HytaleLogger.getLogger().at(Level.INFO).log("Loading NPC assets phase...");
long start = System.nanoTime();
this.builderManager.setAutoReload(this.autoReload);
boolean validateAssets = Options.getOptionSet().has(Options.VALIDATE_ASSETS);
List<AssetPack> assetPacks = AssetModule.get().getAssetPacks();
for(int i = 0; i < assetPacks.size(); ++i) {
boolean includeTests = i == 0;
boolean loadSucceeded = this.builderManager.loadBuilders((AssetPack)assetPacks.get(i), includeTests);
if (!loadSucceeded) {
event.failed(validateAssets, "failed to validate npc's");
}
}
HytaleLogger.getLogger().at(Level.INFO).log("Loading NPC assets phase completed! Boot time %s, Took %s", FormatUtil.nanosToString(System.nanoTime() - event.getBootStart()), FormatUtil.nanosToString(System.nanoTime() - start));
});
eventRegistry.register(AssetPackRegisterEvent.class, (event) -> this.builderManager.loadBuilders(event.getAssetPack(), false));
eventRegistry.register(AssetPackUnregisterEvent.class, (event) -> this.builderManager.unloadBuilders(event.getAssetPack()));
eventRegistry.register(GenerateSchemaEvent.class, this::onSchemaGenerate);
AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(AttitudeGroup.class, new IndexedLookupTableAssetMap((x$0) -> new AttitudeGroup[x$0])).setPath("NPC/Attitude/Roles")).setCodec(AttitudeGroup.CODEC)).setKeyFunction(AttitudeGroup::getId)).setReplaceOnRemove(AttitudeGroup::new)).loadsAfter(new Class[]{NPCGroup.class})).build());
AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(ItemAttitudeGroup.class, new IndexedLookupTableAssetMap((x$0) -> new ItemAttitudeGroup[x$0])).setPath("NPC/Attitude/Items")).setCodec(ItemAttitudeGroup.CODEC)).setKeyFunction(ItemAttitudeGroup::getId)).setReplaceOnRemove(ItemAttitudeGroup::new)).loadsAfter(new Class[]{Item.class})).build());
AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(BalanceAsset.class, new DefaultAssetMap()).setPath("NPC/Balancing")).setCodec(BalanceAsset.CODEC)).setKeyFunction(BalanceAsset::getId)).loadsAfter(new Class[]{Condition.class})).build());
AssetRegistry.register(((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)((HytaleAssetStore.Builder)HytaleAssetStore.builder(Condition.class, new IndexedLookupTableAssetMap((x$0) -> new Condition[x$0])).setPath("NPC/DecisionMaking/Conditions")).setCodec(Condition.CODEC)).setKeyFunction(Condition::getId)).setReplaceOnRemove(Condition::getAlwaysTrueFor)).loadsAfter(new Class[]{ResponseCurve.class, NPCGroup.class, EntityStatType.class})).build());
this.getEntityRegistry().registerEntity("NPC", NPCEntity.class, NPCEntity::new, NPCEntity.CODEC);
Interaction.CODEC.register("ContextualUseNPC", ContextualUseNPCInteraction.class, ContextualUseNPCInteraction.CODEC);
Interaction.CODEC.register("UseNPC", UseNPCInteraction.class, UseNPCInteraction.CODEC);
Interaction.CODEC.register("SpawnNPC", SpawnNPCInteraction.class, SpawnNPCInteraction.CODEC);
Interaction.getAssetStore().loadAssets("Hytale:Hytale", List.of(new UseNPCInteraction("*UseNPC")));
RootInteraction.getAssetStore().loadAssets("Hytale:Hytale", List.of(UseNPCInteraction.DEFAULT_ROOT));
MigrationModule.get().register("spawnMarkers", RenameSpawnMarkerMigration::new);
this.setupNPCLoading();
this.blackboardResourceType = entityStoreRegistry.registerResource(Blackboard.class, Blackboard::new);
this.combatDataPoolResourceType = entityStoreRegistry.registerResource(CombatViewSystems.CombatDataPool.class, CombatViewSystems.CombatDataPool::new);
this.roleChangeQueueResourceType = entityStoreRegistry.registerResource(RoleChangeSystem.RoleChangeQueue.class, RoleChangeSystem.RoleChangeQueue::new);
this.newSpawnStartTickingQueueResourceType = entityStoreRegistry.registerResource(NewSpawnStartTickingSystem.QueueResource.class, NewSpawnStartTickingSystem.QueueResource::new);
this.sortBufferProviderResourceResourceType = entityStoreRegistry.registerResource(SortBufferProviderResource.class, SortBufferProviderResource::new);
this.aStarNodePoolProviderSimpleResourceType = entityStoreRegistry.registerResource(AStarNodePoolProviderSimple.class, AStarNodePoolProviderSimple::new);
this.npcSpatialResource = entityStoreRegistry.registerSpatialResource(() -> new KDTree(Ref::isValid));
this.combatDataComponentType = entityStoreRegistry.registerComponent(CombatViewSystems.CombatData.class, CombatViewSystems.CombatData::new);
this.npcTestDataComponentType = entityStoreRegistry.registerComponent(NPCRunTestsCommand.NPCTestData.class, NPCRunTestsCommand.NPCTestData::new);
this.beaconSupportComponentType = entityStoreRegistry.registerComponent(BeaconSupport.class, BeaconSupport::new);
this.npcBlockEventSupportComponentType = entityStoreRegistry.registerComponent(NPCBlockEventSupport.class, NPCBlockEventSupport::new);
this.playerBlockEventSupportComponentType = entityStoreRegistry.registerComponent(PlayerBlockEventSupport.class, PlayerBlockEventSupport::new);
this.npcEntityEventSupportComponentType = entityStoreRegistry.registerComponent(NPCEntityEventSupport.class, NPCEntityEventSupport::new);
this.playerEntityEventSupportComponentType = entityStoreRegistry.registerComponent(PlayerEntityEventSupport.class, PlayerEntityEventSupport::new);
this.stepComponentType = entityStoreRegistry.registerComponent(StepComponent.class, () -> {
throw new UnsupportedOperationException("Not implemented");
});
this.failedSpawnComponentType = entityStoreRegistry.registerComponent(FailedSpawnComponent.class, FailedSpawnComponent::new);
this.timersComponentType = entityStoreRegistry.registerComponent(Timers.class, () -> {
throw new UnsupportedOperationException("Not implemented");
});
this.stateEvaluatorComponentType = entityStoreRegistry.registerComponent(StateEvaluator.class, () -> {
throw new UnsupportedOperationException("Not implemented");
});
this.valueStoreComponentType = entityStoreRegistry.registerComponent(ValueStore.class, () -> {
throw new UnsupportedOperationException("Not implemented");
});
ComponentType<EntityStore, NPCEntity> npcComponentType = NPCEntity.getComponentType();
entityStoreRegistry.registerSystem(new BlackboardSystems.InitSystem(this.blackboardResourceType));
entityStoreRegistry.registerSystem(new BlackboardSystems.TickingSystem(this.blackboardResourceType));
entityStoreRegistry.registerSystem(new BlackboardSystems.DamageBlockEventSystem());
entityStoreRegistry.registerSystem(new BlackboardSystems.BreakBlockEventSystem());
entityStoreRegistry.registerSystem(new CombatViewSystems.Ensure(this.combatDataComponentType));
entityStoreRegistry.registerSystem(new CombatViewSystems.EntityRemoved(this.combatDataComponentType, this.combatDataPoolResourceType));
entityStoreRegistry.registerSystem(new CombatViewSystems.Ticking(this.combatDataComponentType, this.combatDataPoolResourceType));
entityStoreRegistry.registerSystem(new NPCSystems.ModelChangeSystem());
entityStoreRegistry.registerSystem(new RoleBuilderSystem());
entityStoreRegistry.registerSystem(new BalancingInitialisationSystem());
entityStoreRegistry.registerSystem(new RoleSystems.RoleActivateSystem(npcComponentType));
entityStoreRegistry.registerSystem(new PositionCacheSystems.RoleActivateSystem(npcComponentType, this.stateEvaluatorComponentType));
entityStoreRegistry.registerSystem(new NPCInteractionSystems.AddSimulationManagerSystem(npcComponentType));
entityStoreRegistry.registerSystem(new NPCInteractionSystems.TickHeldInteractionsSystem(npcComponentType));
entityStoreRegistry.registerSystem(new FailedSpawnSystem());
entityStoreRegistry.registerSystem(new NPCSystems.AddedSystem(npcComponentType));
entityStoreRegistry.registerSystem(new NPCSystems.AddedFromExternalSystem(npcComponentType));
entityStoreRegistry.registerSystem(new NPCSystems.AddedFromWorldGenSystem());
entityStoreRegistry.registerSystem(new NPCSystems.AddSpawnEntityEffectSystem(npcComponentType));
entityStoreRegistry.registerSystem(new RoleSystems.BehaviourTickSystem(npcComponentType, this.stepComponentType));
entityStoreRegistry.registerSystem(new RoleSystems.PreBehaviourSupportTickSystem(npcComponentType));
entityStoreRegistry.registerSystem(new StateEvaluatorSystem(this.stateEvaluatorComponentType, npcComponentType));
entityStoreRegistry.registerSystem(new PositionCacheSystems.UpdateSystem(npcComponentType, this.npcSpatialResource));
entityStoreRegistry.registerSystem(new NPCPreTickSystem(npcComponentType));
Set<Dependency<EntityStore>> postBehaviourDependency = Set.of(new SystemDependency(Order.AFTER, RoleSystems.PostBehaviourSupportTickSystem.class));
entityStoreRegistry.registerSystem(new AvoidanceSystem(npcComponentType));
entityStoreRegistry.registerSystem(new SteeringSystem(npcComponentType));
entityStoreRegistry.registerSystem(new RoleSystems.PostBehaviourSupportTickSystem(npcComponentType));
entityStoreRegistry.registerSystem(new RoleSystems.RoleDebugSystem(npcComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new TimerSystem(this.timersComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new ComputeVelocitySystem(npcComponentType, EntityModule.get().getVelocityComponentType(), postBehaviourDependency));
entityStoreRegistry.registerSystem(new MovementStatesSystem(npcComponentType, EntityModule.get().getVelocityComponentType(), EntityModule.get().getMovementStatesComponentType()));
entityStoreRegistry.registerSystem(new MessageSupportSystem.BeaconSystem(this.beaconSupportComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new MessageSupportSystem.NPCBlockEventSystem(this.npcBlockEventSupportComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new MessageSupportSystem.PlayerBlockEventSystem(this.playerBlockEventSupportComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new MessageSupportSystem.NPCEntityEventSystem(this.npcEntityEventSupportComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new MessageSupportSystem.PlayerEntityEventSystem(this.playerEntityEventSupportComponentType, postBehaviourDependency));
entityStoreRegistry.registerSystem(new StepCleanupSystem(this.stepComponentType));
entityStoreRegistry.registerSystem(new NewSpawnStartTickingSystem(this.newSpawnStartTickingQueueResourceType));
entityStoreRegistry.registerSystem(new RoleChangeSystem(this.roleChangeQueueResourceType, this.beaconSupportComponentType, this.playerBlockEventSupportComponentType, this.npcBlockEventSupportComponentType, this.playerEntityEventSupportComponentType, this.npcEntityEventSupportComponentType, this.timersComponentType, this.stateEvaluatorComponentType, this.valueStoreComponentType));
entityStoreRegistry.registerSystem(new NPCSpatialSystem(this.npcSpatialResource));
entityStoreRegistry.registerSystem(new NPCDeathSystems.NPCKillsEntitySystem());
entityStoreRegistry.registerSystem(new NPCDeathSystems.EntityViewSystem());
entityStoreRegistry.registerSystem(new NPCDamageSystems.FilterDamageSystem());
entityStoreRegistry.registerSystem(new NPCDamageSystems.DamageReceivedSystem());
entityStoreRegistry.registerSystem(new NPCDamageSystems.DamageDealtSystem());
entityStoreRegistry.registerSystem(new NPCDamageSystems.DamageReceivedEventViewSystem());
entityStoreRegistry.registerSystem(new NPCDamageSystems.DropDeathItems());
entityStoreRegistry.registerSystem(new NPCSystems.OnTeleportSystem());
entityStoreRegistry.registerSystem(new NPCSystems.OnDeathSystem());
entityStoreRegistry.registerSystem(new NPCSystems.LegacyWorldGenId());
entityStoreRegistry.registerSystem(new NPCSystems.KillFeedKillerEventSystem());
entityStoreRegistry.registerSystem(new NPCSystems.KillFeedDecedentEventSystem());
entityStoreRegistry.registerSystem(new NPCSystems.PrefabPlaceEntityEventSystem());
entityStoreRegistry.registerSystem(new NPCVelocityInstructionSystem());
this.getEntityStoreRegistry().registerSystem(new NPCEntityRegenerateStatsSystem());
}
public void onSchemaGenerate(@Nonnull GenerateSchemaEvent event) {
Schema schema = this.builderManager.generateSchema(event.getContext());
event.addSchema("NPCRole.json", schema);
event.addSchemaLink("NPCRole", List.of("NPC/Roles/*.json", "NPC/Roles/**/*.json"), (String)null);
Schema.HytaleMetadata hytale = schema.getHytale();
hytale.setPath("NPC/Roles");
hytale.setExtension(".json");
schema.setId("NPCRole.json");
schema.setTitle("NPCRole");
}
protected void start() {
NPCConfig config = this.config.get();
if (config.isGenerateDescriptors()) {
this.generateDescriptors();
if (config.isGenerateDescriptorsFile()) {
this.saveDescriptors();
}
}
}
public ResourceType<EntityStore, Blackboard> getBlackboardResourceType() {
return this.blackboardResourceType;
}
public ResourceType<EntityStore, CombatViewSystems.CombatDataPool> getCombatDataPoolResourceType() {
return this.combatDataPoolResourceType;
}
public ResourceType<EntityStore, RoleChangeSystem.RoleChangeQueue> getRoleChangeQueueResourceType() {
return this.roleChangeQueueResourceType;
}
public ResourceType<EntityStore, NewSpawnStartTickingSystem.QueueResource> getNewSpawnStartTickingQueueResourceType() {
return this.newSpawnStartTickingQueueResourceType;
}
public ResourceType<EntityStore, SortBufferProviderResource> getSortBufferProviderResourceResourceType() {
return this.sortBufferProviderResourceResourceType;
}
public ResourceType<EntityStore, AStarNodePoolProviderSimple> getAStarNodePoolProviderSimpleResourceType() {
return this.aStarNodePoolProviderSimpleResourceType;
}
public ResourceType<EntityStore, SpatialResource<Ref<EntityStore>, EntityStore>> getNpcSpatialResource() {
return this.npcSpatialResource;
}
public ComponentType<EntityStore, CombatViewSystems.CombatData> getCombatDataComponentType() {
return this.combatDataComponentType;
}
public ComponentType<EntityStore, NPCRunTestsCommand.NPCTestData> getNpcTestDataComponentType() {
return this.npcTestDataComponentType;
}
public ComponentType<EntityStore, BeaconSupport> getBeaconSupportComponentType() {
return this.beaconSupportComponentType;
}
public ComponentType<EntityStore, NPCBlockEventSupport> getNpcBlockEventSupportComponentType() {
return this.npcBlockEventSupportComponentType;
}
public ComponentType<EntityStore, PlayerBlockEventSupport> getPlayerBlockEventSupportComponentType() {
return this.playerBlockEventSupportComponentType;
}
public ComponentType<EntityStore, NPCEntityEventSupport> getNpcEntityEventSupportComponentType() {
return this.npcEntityEventSupportComponentType;
}
public ComponentType<EntityStore, PlayerEntityEventSupport> getPlayerEntityEventSupportComponentType() {
return this.playerEntityEventSupportComponentType;
}
public ComponentType<EntityStore, StepComponent> getStepComponentType() {
return this.stepComponentType;
}
public ComponentType<EntityStore, FailedSpawnComponent> getFailedSpawnComponentType() {
return this.failedSpawnComponentType;
}
public ComponentType<EntityStore, Timers> getTimersComponentType() {
return this.timersComponentType;
}
public ComponentType<EntityStore, StateEvaluator> getStateEvaluatorComponentType() {
return this.stateEvaluatorComponentType;
}
public ComponentType<EntityStore, ValueStore> getValueStoreComponentType() {
return this.valueStoreComponentType;
}
public void setupNPCLoading() {
this.builderManager.addCategory(FACTORY_CLASS_ROLE, Role.class);
this.builderManager.addCategory(FACTORY_CLASS_BODY_MOTION, BodyMotion.class);
this.builderManager.addCategory(FACTORY_CLASS_HEAD_MOTION, HeadMotion.class);
this.builderManager.addCategory(FACTORY_CLASS_ACTION, Action.class);
this.builderManager.addCategory(FACTORY_CLASS_SENSOR, Sensor.class);
this.builderManager.addCategory(FACTORY_CLASS_INSTRUCTION, Instruction.class);
this.builderManager.addCategory(FACTORY_CLASS_TRANSIENT_PATH, TransientPathDefinition.class);
this.builderManager.addCategory(FACTORY_CLASS_ACTION_LIST, ActionList.class);
this.registerCoreFactories();
this.registerCoreComponentType("Nothing", BuilderBodyMotionNothing::new).registerCoreComponentType("Wander", BuilderBodyMotionWander::new).registerCoreComponentType("WanderInCircle", BuilderBodyMotionWanderInCircle::new).registerCoreComponentType("WanderInRect", BuilderBodyMotionWanderInRect::new).registerCoreComponentType("Timer", BuilderBodyMotionTimer::new).registerCoreComponentType("Sequence", BuilderBodyMotionSequence::new).registerCoreComponentType("Flee", BuilderBodyMotionMoveAway::new).registerCoreComponentType("Seek", BuilderBodyMotionFind::new).registerCoreComponentType("Leave", BuilderBodyMotionLeave::new).registerCoreComponentType("Path", BuilderBodyMotionPath::new).registerCoreComponentType("TakeOff", BuilderBodyMotionTakeOff::new).registerCoreComponentType("TestProbe", BuilderBodyMotionTestProbe::new).registerCoreComponentType("Teleport", BuilderBodyMotionTeleport::new).registerCoreComponentType("Land", BuilderBodyMotionLand::new).registerCoreComponentType("MatchLook", BuilderBodyMotionMatchLook::new).registerCoreComponentType("MaintainDistance", BuilderBodyMotionMaintainDistance::new).registerCoreComponentType("AimCharge", BuilderBodyMotionAimCharge::new);
this.registerCoreComponentType("Aim", BuilderHeadMotionAim::new).registerCoreComponentType("Watch", BuilderHeadMotionWatch::new).registerCoreComponentType("Observe", BuilderHeadMotionObserve::new).registerCoreComponentType("Sequence", BuilderHeadMotionSequence::new).registerCoreComponentType("Timer", BuilderHeadMotionTimer::new).registerCoreComponentType("Nothing", BuilderHeadMotionNothing::new);
this.registerCoreComponentType("Appearance", BuilderActionAppearance::new).registerCoreComponentType("Timeout", BuilderActionTimeout::new).registerCoreComponentType("Spawn", BuilderActionSpawn::new).registerCoreComponentType("Nothing", BuilderActionNothing::new).registerCoreComponentType("Attack", BuilderActionAttack::new).registerCoreComponentType("State", BuilderActionState::new).registerCoreComponentType("ReleaseTarget", BuilderActionReleaseTarget::new).registerCoreComponentType("SetMarkedTarget", BuilderActionSetMarkedTarget::new).registerCoreComponentType("Inventory", BuilderActionInventory::new).registerCoreComponentType("DisplayName", BuilderActionDisplayName::new).registerCoreComponentType("Sequence", BuilderActionSequence::new).registerCoreComponentType("Random", BuilderActionRandom::new).registerCoreComponentType("Beacon", BuilderActionBeacon::new).registerCoreComponentType("SetLeashPosition", BuilderActionSetLeashPosition::new).registerCoreComponentType("PlaySound", BuilderActionPlaySound::new).registerCoreComponentType("Despawn", BuilderActionDespawn::new).registerCoreComponentType("PlayAnimation", BuilderActionPlayAnimation::new).registerCoreComponentType("DelayDespawn", BuilderActionDelayDespawn::new).registerCoreComponentType("SpawnParticles", BuilderActionSpawnParticles::new).registerCoreComponentType("Crouch", BuilderActionCrouch::new).registerCoreComponentType("TimerStart", BuilderActionTimerStart::new).registerCoreComponentType("TimerContinue", BuilderActionTimerContinue::new).registerCoreComponentType("TimerPause", BuilderActionTimerPause::new).registerCoreComponentType("TimerModify", BuilderActionTimerModify::new).registerCoreComponentType("TimerStop", BuilderActionTimerStop::new).registerCoreComponentType("TimerRestart", BuilderActionTimerRestart::new).registerCoreComponentType("Test", BuilderActionTest::new).registerCoreComponentType("Log", BuilderActionLog::new).registerCoreComponentType("Role", BuilderActionRole::new).registerCoreComponentType("SetFlag", BuilderActionSetFlag::new).registerCoreComponentType("DropItem", BuilderActionDropItem::new).registerCoreComponentType("PickUpItem", BuilderActionPickUpItem::new).registerCoreComponentType("ResetInstructions", BuilderActionResetInstructions::new).registerCoreComponentType("ParentState", BuilderActionParentState::new).registerCoreComponentType("Notify", BuilderActionNotify::new).registerCoreComponentType("TriggerSpawners", BuilderActionTriggerSpawners::new).registerCoreComponentType("ResetBlockSensors", BuilderActionResetBlockSensors::new).registerCoreComponentType("MakePath", BuilderActionMakePath::new).registerCoreComponentType("OverrideAttitude", BuilderActionOverrideAttitude::new).registerCoreComponentType("SetInteractable", BuilderActionSetInteractable::new).registerCoreComponentType("LockOnInteractionTarget", BuilderActionLockOnInteractionTarget::new).registerCoreComponentType("StorePosition", BuilderActionStorePosition::new).registerCoreComponentType("SetBlockToPlace", BuilderActionSetBlockToPlace::new).registerCoreComponentType("PlaceBlock", BuilderActionPlaceBlock::new).registerCoreComponentType("RecomputePath", BuilderActionRecomputePath::new).registerCoreComponentType("IgnoreForAvoidance", BuilderActionIgnoreForAvoidance::new).registerCoreComponentType("ModelAttachment", BuilderActionModelAttachment::new).registerCoreComponentType("SetAlarm", BuilderActionSetAlarm::new).registerCoreComponentType("ToggleStateEvaluator", BuilderActionToggleStateEvaluator::new).registerCoreComponentType("OverrideAltitude", BuilderActionOverrideAltitude::new).registerCoreComponentType("ResetSearchRays", BuilderActionResetSearchRays::new).registerCoreComponentType("Die", BuilderActionDie::new).registerCoreComponentType("Remove", BuilderActionRemove::new).registerCoreComponentType("ApplyEntityEffect", BuilderActionApplyEntityEffect::new).registerCoreComponentType("ResetPath", BuilderActionResetPath::new).registerCoreComponentType("SetStat", BuilderActionSetStat::new);
this.registerCoreComponentType("Any", BuilderSensorAny::new).registerCoreComponentType("And", BuilderSensorAnd::new).registerCoreComponentType("Or", BuilderSensorOr::new).registerCoreComponentType("Not", BuilderSensorNot::new).registerCoreComponentType("Player", BuilderSensorPlayer::new).registerCoreComponentType("Mob", BuilderSensorEntity::new).registerCoreComponentType("State", BuilderSensorState::new).registerCoreComponentType("InAir", BuilderSensorInAir::new).registerCoreComponentType("OnGround", BuilderSensorOnGround::new).registerCoreComponentType("Eval", BuilderSensorEval::new).registerCoreComponentType("Damage", BuilderSensorDamage::new).registerCoreComponentType("IsBackingAway", BuilderSensorIsBackingAway::new).registerCoreComponentType("Kill", BuilderSensorKill::new).registerCoreComponentType("Beacon", BuilderSensorBeacon::new).registerCoreComponentType("MotionController", BuilderSensorMotionController::new).registerCoreComponentType("Leash", BuilderSensorLeash::new).registerCoreComponentType("Time", BuilderSensorTime::new).registerCoreComponentType("Count", BuilderSensorCount::new).registerCoreComponentType("Target", BuilderSensorTarget::new).registerCoreComponentType("Timer", BuilderSensorTimer::new).registerCoreComponentType("Switch", BuilderSensorSwitch::new).registerCoreComponentType("Light", BuilderSensorLight::new).registerCoreComponentType("Age", BuilderSensorAge::new).registerCoreComponentType("Flag", BuilderSensorFlag::new).registerCoreComponentType("DroppedItem", BuilderSensorDroppedItem::new).registerCoreComponentType("Path", BuilderSensorPath::new).registerCoreComponentType("Weather", BuilderSensorWeather::new).registerCoreComponentType("Block", BuilderSensorBlock::new).registerCoreComponentType("BlockChange", BuilderSensorBlockChange::new).registerCoreComponentType("EntityEvent", BuilderSensorEntityEvent::new).registerCoreComponentType("Random", BuilderSensorRandom::new).registerCoreComponentType("CanInteract", BuilderSensorCanInteract::new).registerCoreComponentType("HasInteracted", BuilderSensorHasInteracted::new).registerCoreComponentType("ReadPosition", BuilderSensorReadPosition::new).registerCoreComponentType("Animation", BuilderSensorAnimation::new).registerCoreComponentType("CanPlaceBlock", BuilderSensorCanPlace::new).registerCoreComponentType("Nav", BuilderSensorNav::new).registerCoreComponentType("InWater", BuilderSensorInWater::new).registerCoreComponentType("IsBusy", BuilderSensorIsBusy::new).registerCoreComponentType("InteractionContext", BuilderSensorInteractionContext::new).registerCoreComponentType("Alarm", BuilderSensorAlarm::new).registerCoreComponentType("AdjustPosition", BuilderSensorAdjustPosition::new).registerCoreComponentType("SearchRay", BuilderSensorSearchRay::new).registerCoreComponentType("BlockType", BuilderSensorBlockType::new).registerCoreComponentType("Self", BuilderSensorSelf::new).registerCoreComponentType("ValueProviderWrapper", BuilderSensorValueProviderWrapper::new);
this.registerCoreComponentType("Attitude", BuilderEntityFilterAttitude::new).registerCoreComponentType("LineOfSight", BuilderEntityFilterLineOfSight::new).registerCoreComponentType("HeightDifference", BuilderEntityFilterHeightDifference::new).registerCoreComponentType("ViewSector", BuilderEntityFilterViewSector::new).registerCoreComponentType("Combat", BuilderEntityFilterCombat::new).registerCoreComponentType("ItemInHand", BuilderEntityFilterItemInHand::new).registerCoreComponentType("NPCGroup", BuilderEntityFilterNPCGroup::new).registerCoreComponentType("MovementState", BuilderEntityFilterMovementState::new).registerCoreComponentType("SpotsMe", BuilderEntityFilterSpotsMe::new).registerCoreComponentType("StandingOnBlock", BuilderEntityFilterStandingOnBlock::new).registerCoreComponentType("Stat", BuilderEntityFilterStat::new).registerCoreComponentType("Inventory", BuilderEntityFilterInventory::new).registerCoreComponentType("Not", BuilderEntityFilterNot::new).registerCoreComponentType("And", BuilderEntityFilterAnd::new).registerCoreComponentType("Or", BuilderEntityFilterOr::new).registerCoreComponentType("Altitude", BuilderEntityFilterAltitude::new).registerCoreComponentType("InsideBlock", BuilderEntityFilterInsideBlock::new);
this.registerCoreComponentType("Attitude", BuilderSensorEntityPrioritiserAttitude::new);
NPCConfig config = this.config.get();
this.autoReload = config.isAutoReload();
this.validateBuilder = config.isValidateBuilder();
this.maxBlackboardBlockCountPerType = config.getMaxBlackboardBlockType();
this.logFailingTestErrors = config.isLogFailingTestErrors();
this.presetCoverageTestNPCs = config.getPresetCoverageTestNPCs();
}
public String[] getPresetCoverageTestNPCs() {
return this.presetCoverageTestNPCs;
}
@Nullable
public Pair<Ref<EntityStore>, INonPlayerCharacter> spawnNPC(@Nonnull Store<EntityStore> store, @Nonnull String npcType, @Nullable String groupType, @Nonnull Vector3d position, @Nonnull Vector3f rotation) {
int roleIndex = this.getIndex(npcType);
if (roleIndex < 0) {
return null;
} else {
Pair<Ref<EntityStore>, NPCEntity> npcPair = this.spawnEntity(store, roleIndex, position, rotation, (Model)null, (TriConsumer)null);
FlockAsset flockDefinition = groupType != null ? (FlockAsset)FlockAsset.getAssetMap().getAsset(groupType) : null;
if (npcPair != null) {
Ref<EntityStore> npcRef = npcPair.first();
NPCEntity npcComponent = npcPair.second();
FlockPlugin.trySpawnFlock(npcRef, npcComponent, store, roleIndex, position, rotation, flockDefinition, (TriConsumer)null);
return Pair.<Ref<EntityStore>, INonPlayerCharacter>of(npcPair.first(), npcPair.second());
} else {
return null;
}
}
}
public static void reloadNPCsWithRole(int roleIndex) {
Universe.get().getWorlds().forEach((s, world) -> world.execute(() -> world.getEntityStore().getStore().forEachChunk(NPCEntity.getComponentType(), (BiConsumer)((archetypeChunk, commandBuffer) -> {
for(int index = 0; index < archetypeChunk.size(); ++index) {
NPCEntity npc = (NPCEntity)archetypeChunk.getComponent(index, NPCEntity.getComponentType());
if (npc.getRoleIndex() == roleIndex && !npc.getRole().isRoleChangeRequested()) {
RoleChangeSystem.requestRoleChange(archetypeChunk.getReferenceTo(index), npc.getRole(), roleIndex, true, world.getEntityStore().getStore());
}
}
}))));
}
protected void onNPCGroupsLoaded(LoadedAssetsEvent<String, NPCGroup, AssetMap<String, NPCGroup>> event) {
this.putNPCGroups();
}
protected void onNPCGroupsRemoved(RemovedAssetsEvent<String, NPCGroup, AssetMap<String, NPCGroup>> event) {
this.putNPCGroups();
}
protected void onAttitudeGroupsLoaded(@Nonnull LoadedAssetsEvent<String, AttitudeGroup, AssetMap<String, AttitudeGroup>> event) {
if (this.attitudeMap == null) {
this.putAttitudeGroups();
} else {
Map<String, AttitudeGroup> loadedAssets = event.getLoadedAssets();
IndexedLookupTableAssetMap<String, AttitudeGroup> assets = AttitudeGroup.getAssetMap();
int attitudeGroupCount = this.attitudeMap.getAttitudeGroupCount();
for(String id : loadedAssets.keySet()) {
int index = assets.getIndex(id);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + id);
}
if (index >= attitudeGroupCount) {
this.putAttitudeGroups();
return;
}
}
loadedAssets.forEach((idx, group) -> {
int index = assets.getIndex(idx);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + idx);
} else {
this.attitudeMap.updateAttitudeGroup(index, group);
}
});
}
}
protected void onAttitudeGroupsRemoved(RemovedAssetsEvent<String, AttitudeGroup, AssetMap<String, AttitudeGroup>> event) {
this.putAttitudeGroups();
}
protected void onItemAttitudeGroupsLoaded(@Nonnull LoadedAssetsEvent<String, ItemAttitudeGroup, AssetMap<String, ItemAttitudeGroup>> event) {
if (this.itemAttitudeMap == null) {
this.putItemAttitudeGroups();
} else {
Map<String, ItemAttitudeGroup> loadedAssets = event.getLoadedAssets();
IndexedLookupTableAssetMap<String, ItemAttitudeGroup> assets = ItemAttitudeGroup.getAssetMap();
int attitudeGroupCount = this.itemAttitudeMap.getAttitudeGroupCount();
for(String id : loadedAssets.keySet()) {
int index = assets.getIndex(id);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + id);
}
if (index >= attitudeGroupCount) {
this.putItemAttitudeGroups();
return;
}
}
loadedAssets.forEach((idx, group) -> {
int index = assets.getIndex(idx);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + idx);
} else {
this.itemAttitudeMap.updateAttitudeGroup(index, group);
}
});
}
}
protected void onItemAttitudeGroupsRemoved(RemovedAssetsEvent<String, ItemAttitudeGroup, AssetMap<String, ItemAttitudeGroup>> event) {
this.putItemAttitudeGroups();
}
private void putItemAttitudeGroups() {
ItemAttitudeMap.Builder builder = new ItemAttitudeMap.Builder();
builder.addAttitudeGroups(ItemAttitudeGroup.getAssetMap().getAssetMap());
this.itemAttitudeMap = builder.build();
}
protected void onPathChange(WorldPathChangedEvent event) {
this.pathChangeRevision.getAndIncrement();
}
public int getPathChangeRevision() {
return this.pathChangeRevision.get();
}
protected void onNPCsLoaded(AllNPCsLoadedEvent event) {
this.putNPCGroups();
}
private void putNPCGroups() {
IndexedLookupTableAssetMap<String, NPCGroup> indexedAssetMap = NPCGroup.getAssetMap();
Object2IntOpenHashMap<String> tagSetIndexMap = new Object2IntOpenHashMap<String>();
indexedAssetMap.getAssetMap().forEach((name, group) -> {
int index = indexedAssetMap.getIndex(name);
if (index == -2147483648) {
throw new IllegalArgumentException("Unknown key! " + name);
} else {
tagSetIndexMap.put(name, index);
}
});
TagSetPlugin.get(NPCGroup.class).putAssetSets(indexedAssetMap.getAssetMap(), tagSetIndexMap, this.builderManager.getNameToIndexMap());
this.putAttitudeGroups();
}
private void putAttitudeGroups() {
AttitudeMap.Builder builder = new AttitudeMap.Builder();
builder.addAttitudeGroups(AttitudeGroup.getAssetMap().getAssetMap());
this.attitudeMap = builder.build();
}
@Nullable
public String getName(int builderIndex) {
return this.builderManager.lookupName(builderIndex);
}
public int getIndex(String builderName) {
return this.builderManager.getIndex(builderName);
}
@Nullable
public Builder<Role> tryGetCachedValidRole(int roleIndex) {
return this.builderManager.tryGetCachedValidRole(roleIndex);
}
@Nullable
public BuilderInfo getBuilderInfo(Builder<?> builder) {
return this.builderManager.getBuilderInfo(builder);
}
public List<String> getRoleTemplateNames(boolean spawnableOnly) {
return (List)this.builderManager.collectMatchingBuilders(new ObjectArrayList(), (entry) -> entry.getBuilder().category() == Role.class && (!spawnableOnly || entry.getBuilder().isSpawnable()), (builderInfo, objects) -> objects.add(builderInfo.getKeyName()));
}
public boolean hasRoleName(String roleName) {
return this.getRoleBuilderInfo(this.getIndex(roleName)) != null;
}
public void validateSpawnableRole(String roleName) {
BuilderInfo builder = this.getRoleBuilderInfo(this.getIndex(roleName));
if (builder == null) {
throw new SkipSentryException(new IllegalArgumentException(roleName + " does not exist as a role!"));
} else if (!builder.getBuilder().isSpawnable()) {
throw new SkipSentryException(new IllegalArgumentException(roleName + " is an abstract role type and cannot be spawned directly!"));
}
}
@Nullable
public BuilderInfo getRoleBuilderInfo(int roleIndex) {
BuilderInfo builderInfo = this.builderManager.tryGetBuilderInfo(roleIndex);
return builderInfo != null && builderInfo.getBuilder().category() == Role.class ? builderInfo : null;
}
public void setBuilderInvalid(int builderIndex) {
BuilderInfo builderInfo = this.builderManager.tryGetBuilderInfo(builderIndex);
if (builderInfo != null) {
builderInfo.setNeedsReload();
}
}
public AttitudeMap getAttitudeMap() {
return this.attitudeMap;
}
public ItemAttitudeMap getItemAttitudeMap() {
return this.itemAttitudeMap;
}
public boolean testAndValidateRole(@Nullable BuilderInfo builderInfo) {
return builderInfo != null && builderInfo.getBuilder() != null && builderInfo.getBuilder().category() == Role.class && this.builderManager.validateBuilder(builderInfo);
}
public void forceValidation(int builderIndex) {
this.builderManager.forceValidation(builderIndex);
}
@Nullable
public Pair<Ref<EntityStore>, NPCEntity> spawnEntity(@Nonnull Store<EntityStore> store, int roleIndex, @Nonnull Vector3d position, Vector3f rotation, Model spawnModel, TriConsumer<NPCEntity, Ref<EntityStore>, Store<EntityStore>> postSpawn) {
return this.spawnEntity(store, roleIndex, position, rotation, spawnModel, (TriConsumer)null, postSpawn);
}
@Nullable
public Pair<Ref<EntityStore>, NPCEntity> spawnEntity(@Nonnull Store<EntityStore> store, int roleIndex, @Nonnull Vector3d position, @Nullable Vector3f rotation, @Nullable Model spawnModel, @Nullable TriConsumer<NPCEntity, Holder<EntityStore>, Store<EntityStore>> preAddToWorld, @Nullable TriConsumer<NPCEntity, Ref<EntityStore>, Store<EntityStore>> postSpawn) {
WorldTimeResource worldTimeResource = (WorldTimeResource)store.getResource(WorldTimeResource.getResourceType());
NPCEntity npcComponent = new NPCEntity();
npcComponent.setSpawnInstant(worldTimeResource.getGameTime());
if (rotation == null) {
rotation = NULL_ROTATION;
}
npcComponent.saveLeashInformation(position, rotation);
String roleName = this.getName(roleIndex);
if (roleName == null) {
get().getLogger().at(Level.WARNING).log("Unable to spawn entity with invalid role index: %s!", roleIndex);
return null;
} else {
npcComponent.setRoleName(roleName);
npcComponent.setRoleIndex(roleIndex);
Holder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
holder.addComponent(NPCEntity.getComponentType(), npcComponent);
holder.addComponent(TransformComponent.getComponentType(), new TransformComponent(position, rotation));
holder.addComponent(HeadRotation.getComponentType(), new HeadRotation(rotation));
DisplayNameComponent displayNameComponent = new DisplayNameComponent(Message.raw(roleName));
holder.addComponent(DisplayNameComponent.getComponentType(), displayNameComponent);
holder.ensureComponent(UUIDComponent.getComponentType());
if (spawnModel != null) {
npcComponent.setInitialModelScale(spawnModel.getScale());
holder.addComponent(ModelComponent.getComponentType(), new ModelComponent(spawnModel));
holder.addComponent(PersistentModel.getComponentType(), new PersistentModel(spawnModel.toReference()));
}
if (preAddToWorld != null) {
preAddToWorld.accept(npcComponent, holder, store);
}
Ref<EntityStore> ref = store.addEntity(holder, AddReason.SPAWN);
if (ref == null) {
get().getLogger().at(Level.WARNING).log("Unable to handle non-spawned entity: %s!", this.getName(roleIndex));
return null;
} else {
if (postSpawn != null) {
postSpawn.accept(npcComponent, ref, store);
}
return Pair.<Ref<EntityStore>, NPCEntity>of(ref, npcComponent);
}
}
}
@Nonnull
public BuilderInfo prepareRoleBuilderInfo(int roleIndex) {
try {
BuilderInfo builderInfo = this.builderManager.getCachedBuilderInfo(roleIndex, Role.class);
if (this.validateBuilder) {
if (!builderInfo.isValidated()) {
this.builderManager.validateBuilder(builderInfo);
}
if (!builderInfo.isValid()) {
throw new SkipSentryException(new IllegalStateException("Builder " + builderInfo.getKeyName() + " failed validation!"));
}
}
return builderInfo;
} catch (RuntimeException e) {
throw new SkipSentryException(new RuntimeException(String.format("Cannot use role template '%s' (%s): %s", this.getName(roleIndex), roleIndex, e.getMessage()), e));
}
}
@Nonnull
public static Role buildRole(@Nonnull Builder<Role> roleBuilder, @Nonnull BuilderInfo builderInfo, @Nonnull BuilderSupport builderSupport, int roleIndex) {
Role role;
try {
StdScope scope = roleBuilder.getBuilderParameters().createScope();
builderSupport.setScope(scope);
builderSupport.setGlobalScope(scope);
role = roleBuilder.build(builderSupport);
role.postRoleBuilt(builderSupport);
} catch (Throwable e) {
builderInfo.setNeedsReload();
throw new SkipSentryException(e);
}
role.setRoleIndex(roleIndex, builderInfo.getKeyName());
return role;
}
protected void onModelsChanged(@Nonnull LoadedAssetsEvent<String, ModelAsset, DefaultAssetMap<String, ModelAsset>> event) {
Map<String, ModelAsset> loadedModelAssets = event.getLoadedAssets();
Universe.get().getWorlds().values().forEach((world) -> world.execute(() -> {
Store<EntityStore> store = world.getEntityStore().getStore();
store.forEachEntityParallel(NPCEntity.getComponentType(), (index, archetypeChunk, commandBuffer) -> {
ModelComponent entityModelComponent = (ModelComponent)archetypeChunk.getComponent(index, ModelComponent.getComponentType());
if (entityModelComponent != null) {
Model oldModel = entityModelComponent.getModel();
ModelAsset newModelAsset = (ModelAsset)loadedModelAssets.get(oldModel.getModelAssetId());
if (newModelAsset != null) {
Ref<EntityStore> entityReference = archetypeChunk.getReferenceTo(index);
commandBuffer.putComponent(entityReference, ModelComponent.getComponentType(), new ModelComponent(Model.createScaledModel(newModelAsset, oldModel.getScale(), oldModel.getRandomAttachmentIds())));
}
}
});
}));
}
protected void generateDescriptors() {
this.getLogger().at(Level.INFO).log("===== Generating descriptors for NPC!");
this.builderDescriptors = this.builderManager.generateDescriptors();
}
protected void saveDescriptors() {
this.getLogger().at(Level.INFO).log("===== Saving descriptors for NPC!");
Path path = Path.of("npc_descriptors.json");
BuilderManager.saveDescriptors(this.builderDescriptors, path);
this.getLogger().at(Level.INFO).log("Saved NPC descriptors to: %s", path);
}
public BuilderManager getBuilderManager() {
return this.builderManager;
}
public int getMaxBlackboardBlockCountPerType() {
return this.maxBlackboardBlockCountPerType;
}
public boolean isLogFailingTestErrors() {
return this.logFailingTestErrors;
}
public boolean startRoleBenchmark(double seconds, @Nonnull Consumer<Int2ObjectMap<TimeDistributionRecorder>> onFinished) {
this.benchmarkLock.lock();
label44: {
boolean var4;
try {
if (!this.isBenchmarking()) {
this.roleTickDistribution = new Int2ObjectOpenHashMap<TimeDistributionRecorder>();
this.roleTickDistributionAll = new TimeDistributionRecorder(0.01, 1.0E-5);
this.roleTickDistribution.put(-1, this.roleTickDistributionAll);
break label44;
}
var4 = false;
} finally {
this.benchmarkLock.unlock();
}
return var4;
}
(new CompletableFuture()).completeOnTimeout((Object)null, Math.round(seconds * 1000.0), TimeUnit.MILLISECONDS).thenRunAsync(() -> {
Int2ObjectMap<TimeDistributionRecorder> distribution = this.roleTickDistribution;
this.benchmarkLock.lock();
try {
this.roleTickDistribution = null;
this.roleTickDistributionAll = null;
} finally {
this.benchmarkLock.unlock();
}
onFinished.accept(distribution);
});
return true;
}
public void collectRoleTick(int roleIndex, long nanos) {
if (this.benchmarkLock.tryLock()) {
try {
if (this.roleTickDistribution != null) {
((TimeDistributionRecorder)this.roleTickDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new TimeDistributionRecorder(0.01, 1.0E-5)))).recordNanos(nanos);
this.roleTickDistributionAll.recordNanos(nanos);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public boolean isBenchmarkingRole() {
return this.roleTickDistribution != null;
}
public boolean startSensorSupportBenchmark(double seconds, @Nonnull Consumer<Int2ObjectMap<SensorSupportBenchmark>> onFinished) {
this.benchmarkLock.lock();
label44: {
boolean var4;
try {
if (!this.isBenchmarking()) {
this.roleSensorSupportDistribution = new Int2ObjectOpenHashMap<SensorSupportBenchmark>();
this.roleSensorSupportDistributionAll = new SensorSupportBenchmark();
this.roleSensorSupportDistribution.put(-1, this.roleSensorSupportDistributionAll);
break label44;
}
var4 = false;
} finally {
this.benchmarkLock.unlock();
}
return var4;
}
(new CompletableFuture()).completeOnTimeout((Object)null, Math.round(seconds * 1000.0), TimeUnit.MILLISECONDS).thenRunAsync(() -> {
Int2ObjectMap<SensorSupportBenchmark> distribution = this.roleSensorSupportDistribution;
this.benchmarkLock.lock();
try {
this.roleSensorSupportDistribution = null;
this.roleSensorSupportDistributionAll = null;
} finally {
this.benchmarkLock.unlock();
}
onFinished.accept(distribution);
});
return true;
}
public boolean isBenchmarkingSensorSupport() {
return this.roleSensorSupportDistributionAll != null;
}
protected boolean isBenchmarking() {
return this.isBenchmarkingRole() || this.isBenchmarkingSensorSupport();
}
public void collectSensorSupportPlayerList(int roleIndex, long getNanos, double maxPlayerDistanceSorted, double maxPlayerDistance, double maxPlayerDistanceAvoidance, int numPlayers) {
if (this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).collectPlayerList(getNanos, maxPlayerDistanceSorted, maxPlayerDistance, maxPlayerDistanceAvoidance, numPlayers);
this.roleSensorSupportDistributionAll.collectPlayerList(getNanos, maxPlayerDistanceSorted, maxPlayerDistance, maxPlayerDistanceAvoidance, numPlayers);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public void collectSensorSupportEntityList(int roleIndex, long getNanos, double maxEntityDistanceSorted, double maxEntityDistance, double maxEntityDistanceAvoidance, int numEntities) {
if (this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).collectEntityList(getNanos, maxEntityDistanceSorted, maxEntityDistance, maxEntityDistanceAvoidance, numEntities);
this.roleSensorSupportDistributionAll.collectEntityList(getNanos, maxEntityDistanceSorted, maxEntityDistance, maxEntityDistanceAvoidance, numEntities);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public void collectSensorSupportLosTest(int roleIndex, boolean cacheHit, long time) {
if (this.isBenchmarkingSensorSupport() && this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).collectLosTest(cacheHit, time);
this.roleSensorSupportDistributionAll.collectLosTest(cacheHit, time);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public void collectSensorSupportInverseLosTest(int roleIndex, boolean cacheHit) {
if (this.isBenchmarkingSensorSupport() && this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).collectInverseLosTest(cacheHit);
this.roleSensorSupportDistributionAll.collectInverseLosTest(cacheHit);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public void collectSensorSupportFriendlyBlockingTest(int roleIndex, boolean cacheHit) {
if (this.isBenchmarkingSensorSupport() && this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).collectFriendlyBlockingTest(cacheHit);
this.roleSensorSupportDistributionAll.collectFriendlyBlockingTest(cacheHit);
}
} finally {
this.benchmarkLock.unlock();
}
}
}
public void collectSensorSupportTickDone(int roleIndex) {
if (this.isBenchmarkingSensorSupport() && this.benchmarkLock.tryLock()) {
try {
if (this.roleSensorSupportDistribution != null) {
((SensorSupportBenchmark)this.roleSensorSupportDistribution.computeIfAbsent(roleIndex, (Int2ObjectFunction)((i) -> new SensorSupportBenchmark()))).tickDone();
this.roleSensorSupportDistributionAll.tickDone();
}
} finally {
this.benchmarkLock.unlock();
}
}
}
@Nonnull
public <T> NPCPlugin registerCoreComponentType(String name, @Nonnull Supplier<Builder<T>> builder) {
BuilderFactory<T> factory = this.builderManager.<T>getFactory(((Builder)builder.get()).category());
factory.add(name, builder);
return this;
}
public void setRoleBuilderNeedsReload(Builder<?> builder) {
BuilderInfo builderInfo = this.getBuilderInfo(builder);
Objects.requireNonNull(builderInfo, "Have builder but can't get builderInfo for it");
builderInfo.setNeedsReload();
}
protected void registerCoreFactories() {
BuilderFactory<Role> roleFactory = new BuilderFactory<Role>(Role.class, "Type");
roleFactory.add("Generic", BuilderRole::new);
roleFactory.add("Abstract", BuilderRoleAbstract::new);
roleFactory.add("Variant", BuilderRoleVariant::new);
this.builderManager.registerFactory(roleFactory);
BuilderFactory<MotionController> motionControllerFactory = new BuilderFactory<MotionController>(MotionController.class, "Type");
motionControllerFactory.add("Walk", BuilderMotionControllerWalk::new);
motionControllerFactory.add("Fly", BuilderMotionControllerFly::new);
motionControllerFactory.add("Dive", BuilderMotionControllerDive::new);
this.builderManager.registerFactory(motionControllerFactory);
BuilderFactory<Map<String, MotionController>> motionControllerMapFactory = new BuilderFactory<Map<String, MotionController>>(BuilderMotionControllerMapUtil.CLASS_REFERENCE, "Type", BuilderMotionControllerMap::new);
this.builderManager.registerFactory(motionControllerMapFactory);
BuilderFactory<ActionList> actionListFactory = new BuilderFactory<ActionList>(ActionList.class, "Type", BuilderActionList::new);
this.builderManager.registerFactory(actionListFactory);
BuilderFactory<Instruction> instructionFactory = new BuilderFactory<Instruction>(Instruction.class, "Type", BuilderInstruction::new);
instructionFactory.add("Random", BuilderInstructionRandomized::new);
instructionFactory.add("Reference", BuilderInstructionReference::new);
this.builderManager.registerFactory(instructionFactory);
BuilderFactory<TransientPathDefinition> transientPathFactory = new BuilderFactory<TransientPathDefinition>(TransientPathDefinition.class, "Type", BuilderTransientPathDefinition::new);
this.builderManager.registerFactory(transientPathFactory);
BuilderFactory<RelativeWaypointDefinition> relativeWaypointFactory = new BuilderFactory<RelativeWaypointDefinition>(RelativeWaypointDefinition.class, "Type", BuilderRelativeWaypointDefinition::new);
this.builderManager.registerFactory(relativeWaypointFactory);
BuilderFactory<WeightedAction> weightedActionFactory = new BuilderFactory<WeightedAction>(WeightedAction.class, "Type", BuilderWeightedAction::new);
this.builderManager.registerFactory(weightedActionFactory);
BuilderFactory<BuilderValueToParameterMapping.ValueToParameterMapping> valueToParameterMappingFactory = new BuilderFactory<BuilderValueToParameterMapping.ValueToParameterMapping>(BuilderValueToParameterMapping.ValueToParameterMapping.class, "Type", BuilderValueToParameterMapping::new);
this.builderManager.registerFactory(valueToParameterMappingFactory);
StateTransitionController.registerFactories(this.builderManager);
this.builderManager.registerFactory(new BuilderFactory(BodyMotion.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(HeadMotion.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(Action.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(Sensor.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(IEntityFilter.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(ISensorEntityPrioritiser.class, "Type"));
this.builderManager.registerFactory(new BuilderFactory(ISensorEntityCollector.class, "Type"));
}
protected static void onBalanceAssetsChanged(@Nonnull LoadedAssetsEvent<String, BalanceAsset, DefaultAssetMap<String, BalanceAsset>> event) {
Map<String, BalanceAsset> loadedAssets = event.getLoadedAssets();
Universe.get().getWorlds().forEach((name, world) -> world.execute(() -> world.getEntityStore().getStore().forEachChunk(NPCEntity.getComponentType(), (BiConsumer)((archetypeChunk, commandBuffer) -> {
for(int index = 0; index < archetypeChunk.size(); ++index) {
NPCEntity npcComponent = (NPCEntity)archetypeChunk.getComponent(index, NPCEntity.getComponentType());
assert npcComponent != null;
if (loadedAssets.containsKey(npcComponent.getRole().getBalanceAsset())) {
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
RoleChangeSystem.requestRoleChange(ref, npcComponent.getRole(), npcComponent.getRoleIndex(), false, world.getEntityStore().getStore());
}
}
}))));
}
protected static void onBalanceAssetsRemoved(@Nonnull RemovedAssetsEvent<String, BalanceAsset, DefaultAssetMap<String, BalanceAsset>> event) {
Set<String> removedAssets = event.getRemovedAssets();
Universe.get().getWorlds().forEach((name, world) -> world.execute(() -> world.getEntityStore().getStore().forEachChunk(NPCEntity.getComponentType(), (BiConsumer)((archetypeChunk, commandBuffer) -> {
for(int index = 0; index < archetypeChunk.size(); ++index) {
NPCEntity npcComponent = (NPCEntity)archetypeChunk.getComponent(index, NPCEntity.getComponentType());
assert npcComponent != null;
if (removedAssets.contains(npcComponent.getRole().getBalanceAsset())) {
Ref<EntityStore> ref = archetypeChunk.getReferenceTo(index);
commandBuffer.removeEntity(ref, RemoveReason.REMOVE);
}
}
}))));
}
public static class NPCConfig {
public static final BuilderCodec<NPCConfig> CODEC;
private boolean generateDescriptors;
private boolean generateDescriptorsFile;
private boolean autoReload = true;
private boolean validateBuilder = true;
private int maxBlackboardBlockType = 20;
private boolean logFailingTestErrors;
private String[] presetCoverageTestNPCs = new String[]{"Test_Bird", "Test_Block_Sensor", "Test_Attack_Bow", "Test_Combat_Sensor_Sheep", "Test_Bow_Charge", "Test_OffHand_Swap", "Test_Patrol_Path", "Test_Flock_Mixed#4", "Test_Group_Sheep", "Test_Attack_Flying_Ranged", "Test_Interaction_Complete_Task", "Test_Hotbar_Weapon_Swap", "Test_Inventory_Contents", "Test_Dive_Flee", "Test_Jumping", "Test_Walk_Leave", "Test_Walk_Seek", "Test_Watch", "Test_Chained_Path", "Test_Spawn_Action", "Test_State_Evaluator_Toggle", "Test_State_Evaluator_Sleep", "Test_Alarm", "Test_Timer_Repeating", "Test_Action_Model_Attachment", "Test_Animation_State_Change", "Test_Block_Change", "Test_Crouch", "Test_Drop_Item", "Test_Entity_Damage_Event", "Test_Hover_Parrot", "Test_In_Water", "Test_Light_Sensor", "Test_Model_Change", "Test_Particle_Emotions", "Test_Place_Blocks", "Test_Position_Adjustment_Wrapper", "Test_Probe", "Test_Sensor_Age", "Test_Sensor_DroppedItem", "Test_Shoot_At_Block", "Test_Species_Attitude", "Test_Standing_On_Block_Sensor", "Test_Teleport", "Test_Throw_NPC", "Test_Trigger_Spawners", "Test_Weather_Sensor", "Test_Bird_Land"};
public NPCConfig() {
}
public boolean isGenerateDescriptors() {
return this.generateDescriptors;
}
public boolean isGenerateDescriptorsFile() {
return this.generateDescriptorsFile;
}
public boolean isAutoReload() {
return this.autoReload;
}
public boolean isValidateBuilder() {
return this.validateBuilder;
}
public int getMaxBlackboardBlockType() {
return this.maxBlackboardBlockType;
}
public boolean isLogFailingTestErrors() {
return this.logFailingTestErrors;
}
public String[] getPresetCoverageTestNPCs() {
return this.presetCoverageTestNPCs;
}
static {
CODEC = ((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)((BuilderCodec.Builder)BuilderCodec.builder(NPCConfig.class, NPCConfig::new).append(new KeyedCodec("Descriptors", Codec.BOOLEAN), (o, i) -> o.generateDescriptors = i, (o) -> o.generateDescriptors).add()).append(new KeyedCodec("DescriptorsFile", Codec.BOOLEAN), (o, i) -> o.generateDescriptorsFile = i, (o) -> o.generateDescriptorsFile).add()).append(new KeyedCodec("AutoReload", Codec.BOOLEAN), (o, i) -> o.autoReload = i, (o) -> o.autoReload).add()).append(new KeyedCodec("ValidateBuilders", Codec.BOOLEAN), (o, i) -> o.validateBuilder = i, (o) -> o.validateBuilder).add()).append(new KeyedCodec("MaxBlackboardBlockType", Codec.INTEGER), (o, i) -> o.maxBlackboardBlockType = i, (o) -> o.maxBlackboardBlockType).add()).append(new KeyedCodec("LogFailingTestErrors", Codec.BOOLEAN), (o, i) -> o.logFailingTestErrors = i, (o) -> o.logFailingTestErrors).add()).append(new KeyedCodec("PresetCoverageTestNPCs", Codec.STRING_ARRAY), (o, i) -> o.presetCoverageTestNPCs = i, (o) -> o.presetCoverageTestNPCs).add()).build();
}
}
public static class NPCEntityRegenerateStatsSystem extends EntityStatsSystems.Regenerate<NPCEntity> {
public NPCEntityRegenerateStatsSystem() {
super(EntityStatMap.getComponentType(), NPCEntity.getComponentType());
}
}
}