WorldSpawnJobSystems class

Пакет: com.hypixel.hytale.server.spawning.world.system

Файл: com/hypixel/hytale/server/spawning/world/system/WorldSpawnJobSystems.java

Поля (75)

МодификаторыТипИмя
final HytaleLogger LOGGER
SUCCESS, FAILED, TRY_AGAIN, PERMANENT_FAILURE
break
break
break
private final ComponentType<ChunkStore, ChunkSpawnData> chunkSpawnDataComponentType
private final ComponentType<ChunkStore, ChunkSpawnedNPCData> chunkSpawnedNPCDataComponentType
private final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType
private final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType
private final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType
private final ResourceType<EntityStore, SpawnSuppressionController> spawnSuppressionControllerResourceType
Builder var1
SpawnWrapper var10
SpawnTestResult var10
Store var10
WorldChunk var10
RoleSpawnParameters var11
World var11
Pair var11
ChunkSpawnedNPCData var11
double[] var12
Ref var12
ChunkSpawnData var12
SuppressionSpanHelper var13
HytaleLogger.Api var13
int var13
Long2ObjectConcurrentHashMap var14
HytaleLogger.Api var14
double var14
IntSet var15
int var16
ChunkEnvironmentSpawnData var16
RandomChunkColumnIterator var17
Ref var17
WorldSpawnJobSystems.Result var18
SpawnSuppressionController var18
WorldSpawnJobSystems.Result var19
HytaleLogger.Api var25
HytaleLogger.Api var26
boolean var3
NPCPlugin var4
HytaleLogger.Api var4
WorldEnvironmentSpawnData var4
SpawnJobData var4
SpawningContext var5
WorldChunk var5
SpawnJobData var5
Vector3d var6
World var6
World var6
WorldChunk var6
int var7
SpawningContext var7
Rotation3f var7
Store var7
Store var7
World var7
ISpawnableWithModel var8
var8
int var8
int var8
WorldSpawnData var8
WorldSpawnData var8
Store var8
SpawningContext var9
int var9
NPCEntity var9
SpawnJobData var9
WorldSpawnData var9
private final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType
private final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType
private final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType
private final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType
private final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType
private final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType

Методы (36)

МодификаторыВозвратСигнатура
public EntityRemovedpublic EntityRemoved(ResourceType<EntityStore, WorldSpawnData> var1, ComponentType<ChunkStore, SpawnJobData> var2)
Result Result()
public Tickingpublic Ticking(ResourceType<EntityStore, WorldSpawnData> var1, ResourceType<EntityStore, SpawnSuppressionController> var2, ComponentType<ChunkStore, SpawnJobData> var3, ComponentType<ChunkStore, ChunkSpawnData> var4, ComponentType<ChunkStore, ChunkSpawnedNPCData> var5)
public TickingStatepublic TickingState(ResourceType<EntityStore, WorldSpawnData> var1, ComponentType<ChunkStore, SpawnJobData> var2)
public ComponentType<ChunkStore, NonTicking<ChunkStore>> componentTypepublic ComponentType<ChunkStore, NonTicking<ChunkStore>> componentType()
abstract endProbing endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var2, var3, var5)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.FAILED, var2, var3, var5)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var2, var3, var5)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var3, var4, var6)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.FAILED, var3, var4, var6)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.FAILED, var0, var2, var3)
abstract return endProbingreturn endProbing(WorldSpawnJobSystems.Result.SUCCESS, var0, var2, var3)
public Query<ChunkStore> getQuerypublic Query<ChunkStore> getQuery()
public Query<ChunkStore> getQuerypublic Query<ChunkStore> getQuery()
public Query<ChunkStore> getQuerypublic Query<ChunkStore> getQuery()
if if(var8 == null)
if if(var12 == null)
if if(var18 != WorldSpawnJobSystems.Result.TRY_AGAIN)
if if(var1 == null)
if if(var8 > 0 && var9 == var8)
if if(var11 == null)
if if(var19 == WorldSpawnJobSystems.Result.SUCCESS)
if if(var19 != WorldSpawnJobSystems.Result.TRY_AGAIN)
public boolean isParallelpublic boolean isParallel(int var1, int var2)
public void onComponentAddedpublic void onComponentAdded(@Nonnull Ref<ChunkStore> var1, @Nonnull NonTicking<ChunkStore> var2, @Nonnull Store<ChunkStore> var3, @Nonnull CommandBuffer<ChunkStore> var4)
public void onComponentRemovedpublic void onComponentRemoved(@Nonnull Ref<ChunkStore> var1, @Nonnull NonTicking<ChunkStore> var2, @Nonnull Store<ChunkStore> var3, @Nonnull CommandBuffer<ChunkStore> var4)
public void onComponentSetpublic void onComponentSet(@Nonnull Ref<ChunkStore> var1, NonTicking<ChunkStore> var2, @Nonnull NonTicking<ChunkStore> var3, @Nonnull Store<ChunkStore> var4, @Nonnull CommandBuffer<ChunkStore> var5)
public void onEntityAddpublic void onEntityAdd(@Nonnull Holder<ChunkStore> var1, @Nonnull AddReason var2, @Nonnull Store<ChunkStore> var3)
public void onEntityRemovedpublic void onEntityRemoved(@Nonnull Holder<ChunkStore> var1, @Nonnull RemoveReason var2, @Nonnull Store<ChunkStore> var3)
static void preAddToWorldvoid preAddToWorld(@Nonnull NPCEntity var0, @Nonnull Holder<EntityStore> var1, int var2, @Nonnull SpawnJobData var3)
static void rejectSpawnvoid rejectSpawn(@Nonnull Object2IntMap<SpawnRejection> var0, @Nonnull SpawnRejection var1)
abstract return spawnreturn spawn(var3, var11, var4, var6)
switch switch(var10)
public void tickpublic void tick(float var1, int var2, @Nonnull ArchetypeChunk<ChunkStore> var3, @Nonnull Store<ChunkStore> var4, @Nonnull CommandBuffer<ChunkStore> var5)
static void updateSpawnStatsvoid updateSpawnStats(@Nonnull WorldSpawnData var0, @Nonnull SpawnJobData var1, WorldSpawnJobSystems.Result var2)
abstract updateSpawnStats updateSpawnStats(var3, var1, var0)

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.spawning.world.system;

class="kw">import com.hypixel.fastutil.longs.Long2ObjectConcurrentHashMap;
class="kw">import com.hypixel.hytale.component.AddReason;
class="kw">import com.hypixel.hytale.component.Archetype;
class="kw">import com.hypixel.hytale.component.ArchetypeChunk;
class="kw">import com.hypixel.hytale.component.CommandBuffer;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.Holder;
class="kw">import com.hypixel.hytale.component.NonTicking;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.RemoveReason;
class="kw">import com.hypixel.hytale.component.ResourceType;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.component.query.Query;
class="kw">import com.hypixel.hytale.component.system.HolderSystem;
class="kw">import com.hypixel.hytale.component.system.RefChangeSystem;
class="kw">import com.hypixel.hytale.component.system.tick.EntityTickingSystem;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.math.random.RandomExtra;
class="kw">import com.hypixel.hytale.math.vector.Rotation3f;
class="kw">import com.hypixel.hytale.server.core.entity.Frozen;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
class="kw">import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
class="kw">import com.hypixel.hytale.server.flock.FlockPlugin;
class="kw">import com.hypixel.hytale.server.npc.NPCPlugin;
class="kw">import com.hypixel.hytale.server.npc.asset.builder.Builder;
class="kw">import com.hypixel.hytale.server.npc.entities.NPCEntity;
class="kw">import com.hypixel.hytale.server.npc.movement.MovementMode;
class="kw">import com.hypixel.hytale.server.npc.role.Role;
class="kw">import com.hypixel.hytale.server.spawning.ISpawnableWithModel;
class="kw">import com.hypixel.hytale.server.spawning.SpawnRejection;
class="kw">import com.hypixel.hytale.server.spawning.SpawnTestResult;
class="kw">import com.hypixel.hytale.server.spawning.SpawningContext;
class="kw">import com.hypixel.hytale.server.spawning.assets.spawns.config.RoleSpawnParameters;
class="kw">import com.hypixel.hytale.server.spawning.suppression.SuppressionSpanHelper;
class="kw">import com.hypixel.hytale.server.spawning.suppression.component.ChunkSuppressionEntry;
class="kw">import com.hypixel.hytale.server.spawning.suppression.component.SpawnSuppressionController;
class="kw">import com.hypixel.hytale.server.spawning.util.RandomChunkColumnIterator;
class="kw">import com.hypixel.hytale.server.spawning.world.ChunkEnvironmentSpawnData;
class="kw">import com.hypixel.hytale.server.spawning.world.WorldEnvironmentSpawnData;
class="kw">import com.hypixel.hytale.server.spawning.world.component.ChunkSpawnData;
class="kw">import com.hypixel.hytale.server.spawning.world.component.ChunkSpawnedNPCData;
class="kw">import com.hypixel.hytale.server.spawning.world.component.SpawnJobData;
class="kw">import com.hypixel.hytale.server.spawning.world.component.WorldSpawnData;
class="kw">import com.hypixel.hytale.server.spawning.wrappers.SpawnWrapper;
class="kw">import it.unimi.dsi.fastutil.Pair;
class="kw">import it.unimi.dsi.fastutil.ints.IntSet;
class="kw">import it.unimi.dsi.fastutil.objects.Object2IntMap;
class="kw">import java.util.logging.Level;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector3d;

class="kw">public class WorldSpawnJobSystems {
   class="kw">private class="kw">static class="kw">final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
   class="kw">private class="kw">static class="kw">final Query<ChunkStore> QUERY = Archetype.of(SpawnJobData.getComponentType(), WorldChunk.getComponentType());
   class="kw">private class="kw">static class="kw">final Query<ChunkStore> TICKING_QUERY = Query.and(Query.not(ChunkStore.REGISTRY.getNonTickingComponentType()), QUERY);
   class="kw">private class="kw">static class="kw">final int JOB_BUDGET = 64;

   class="kw">public WorldSpawnJobSystems() {
   }

   @Nonnull
   class="kw">private class="kw">static WorldSpawnJobSystems.Result run(
      @Nonnull World var0,
      @Nonnull Ref<ChunkStore> var1,
      @Nonnull SpawnJobData var2,
      @Nonnull WorldChunk var3,
      @Nonnull ChunkEnvironmentSpawnData var4,
      @Nonnull WorldSpawnData var5,
      @Nonnull SpawnSuppressionController var6
   ) {
      int var7 = var2.getRoleIndex();

      ISpawnableWithModel var8;
      try {
         var8 = getSpawnable(var7);
      } catch (IllegalArgumentException var23) {
         endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var2, var3, var5);
         throw var23;
      }

      if (var8 == null) {
         HytaleLogger.Api var25 = LOGGER.at(Level.FINEST);
         if (var25.isEnabled()) {
            var25.log("Spawn job %s: Terminated, spawnable %s gone", var2.getJobId(), getSpawnableName(var7));
         }

         class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var2, var3, var5);
      } else {
         SpawningContext var9 = var2.getSpawningContext();
         if (!var9.setSpawnable(var8)) {
            HytaleLogger.Api var26 = LOGGER.at(Level.FINEST);
            if (var26.isEnabled()) {
               var26.log("Spawn job %s: Terminated, Unable to set spawnable %s", var2.getJobId(), getSpawnableName(var7));
            }

            class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var2, var3, var5);
         } else {
            SpawnWrapper var10 = var2.getSpawnConfig();
            RoleSpawnParameters var11 = (RoleSpawnParameters)var10.getRoles().get(var7);
            double[] var12 = var11.getOrComputeMovementModeWeights(var8, var9);
            if (var12 == null) {
               class="kw">return endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var2, var3, var5);
            }

            if (!var9.setMovementMode(MovementMode.values()[RandomExtra.pickWeightedIndex(var12)], var11.getEnableSafeSpawning())) {
               class="kw">return endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var2, var3, var5);
            }

            var9.setChunk(var0, var1, var2.getEnvironmentIndex());
            SuppressionSpanHelper var13 = var2.getSuppressionSpanHelper();
            Long2ObjectConcurrentHashMap var14 = var6.getChunkSuppressionMap();
            var13.optimiseSuppressedSpans(var7, var14.get(var3.getIndex()));

            try {
               IntSet var15 = var10.getSpawnBlockSet(var7);
               int var16 = var10.getSpawnFluidTag(var7);
               RandomChunkColumnIterator var17 = var4.getRandomChunkColumnIterator();
               var2.setBudgetUsed(0);

               while (var2.getBudgetUsed() < 64) {
                  var17.nextPositionAvoidBorders();
                  var2.adjustBudgetUsed(3);
                  var9.setColumn(var17.getCurrentX(), var17.getCurrentZ(), var13);
                  WorldSpawnJobSystems.Result var18 = trySpawn(var8, var15, var16, var2, var3, var4, var5);
                  if (var18 != WorldSpawnJobSystems.Result.TRY_AGAIN) {
                     class="kw">return var18;
                  }
               }
            } class="kw">finally {
               var9.release();
            }

            class="kw">return WorldSpawnJobSystems.Result.TRY_AGAIN;
         }
      }
   }

   @Nullable
   class="kw">private class="kw">static ISpawnableWithModel getSpawnable(int var0) {
      Builder var1 = NPCPlugin.get().tryGetCachedValidRole(var0);
      if (var1 == null) {
         class="kw">return null;
      } else if (!var1.isSpawnable()) {
         throw new IllegalArgumentException("Spawn job: Role must be a spawnable (non-class="kw">abstract) type for spawning: " + NPCPlugin.get().getName(var0));
      } else if (!(var1 class="kw">instanceof ISpawnableWithModel)) {
         throw new IllegalArgumentException("Spawn job: Need ISpawnableWithModel class="kw">interface for spawning: " + NPCPlugin.get().getName(var0));
      } else {
         class="kw">return (ISpawnableWithModel)var1;
      }
   }

   @Nonnull
   class="kw">private class="kw">static WorldSpawnJobSystems.Result trySpawn(
      @Nonnull ISpawnableWithModel var0,
      @Nullable IntSet var1,
      int var2,
      @Nonnull SpawnJobData var3,
      @Nonnull WorldChunk var4,
      @Nonnull ChunkEnvironmentSpawnData var5,
      @Nonnull WorldSpawnData var6
   ) {
      var3.incrementTotalColumnsTested();
      SpawningContext var7 = var3.getSpawningContext();

      try {
         int var8 = 0;
         int var9 = 0;

         while (var7.selectRandomSpawnSpan()) {
            var3.adjustBudgetUsed(1);
            var3.incrementSpansTried();
            var9++;
            if (!var3.getSpawnConfig().withinLightRange(var7)) {
               rejectSpawn(var3.getRejectionMap(), SpawnRejection.OUTSIDE_LIGHT_RANGE);
            } else if (!var7.canSpawnOnBlock(var1, var2)) {
               var8++;
               rejectSpawn(var3.getRejectionMap(), SpawnRejection.INVALID_SPAWN_BLOCK);
            } else {
               SpawnTestResult var10 = var7.canSpawn();
               class="kw">switch (var10) {
                  case TEST_OK:
                     World var11 = var7.getWorld();
                     assert var11 != null : "Context lost its bound world between setChunk and trySpawn";
                     class="kw">return spawn(var3, var11, var4, var6);
                  case FAIL_INVALID_POSITION:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.INVALID_POSITION);
                     var8++;
                     break;
                  case FAIL_NO_POSITION:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.NO_POSITION);
                     var8++;
                     break;
                  case FAIL_NOT_BREATHABLE:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.NOT_BREATHABLE);
                     var8++;
                     break;
                  case FAIL_NO_MOTION_CONTROLLERS:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.NO_MOTION_CONTROLLERS);
                     class="kw">return endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var3, var4, var6);
                  case FAIL_NO_MOTION_CONTROLLER_MATCH:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.NO_MOTION_CONTROLLER_MATCH);
                     class="kw">return endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var3, var4, var6);
                  case FAIL_BREATHING_INCOMPATIBLE:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.BREATHING_INCOMPATIBLE);
                     class="kw">return endProbing(WorldSpawnJobSystems.Result.PERMANENT_FAILURE, var3, var4, var6);
                  class="kw">default:
                     rejectSpawn(var3.getRejectionMap(), SpawnRejection.OTHER);
               }
            }

            var7.deleteCurrentSpawnSpan();
         }

         if (var8 > 0 && var9 == var8) {
            var3.incrementTotalColumnsBlocked();
         }
      } catch (IllegalStateException var12) {
         LOGGER.at(Level.WARNING)
            .log(
               "%s with spawnable=%s spwnCfg=%s X/Y/Z=%s/%s/%s",
               var12.getMessage(),
               getSpawnableName(var3.getRoleIndex()),
               var3.getSpawnConfig().getSpawn().getId(),
               var7.xSpawn,
               var7.ySpawn,
               var7.zSpawn
            );
         var0.markNeedsReload();
         class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var3, var4, var6);
      }

      if (var5.getRandomChunkColumnIterator().isAtSavedIteratorPosition()) {
         if (var3.getTotalColumnsBlocked() == var3.getTotalColumnsTested()) {
            var5.markRoleAsUnspawnable(var3.getRoleIndex());
            HytaleLogger.Api var13 = LOGGER.at(Level.FINEST);
            if (var13.isEnabled()) {
               var13.log(
                  "Spawn job %s: No column to create %s (env %s) at chunk %s/%s, columns probed %s",
                  var3.getJobId(),
                  getSpawnableName(var3.getRoleIndex()),
                  var3.getEnvironment().getId(),
                  var4.getX(),
                  var4.getZ(),
                  var3.getTotalColumnsTested()
               );
            }

            if (var5.allRolesUnspawnable()) {
               var6.queueUnspawnableChunk(var3.getEnvironmentIndex(), var4.getIndex());
               if (var13.isEnabled()) {
                  var13.log("Spawn job %s: All roles unspawnable. Queued for processing.", var3.getJobId());
               }
            }
         }

         class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var3, var4, var6);
      } else {
         class="kw">return WorldSpawnJobSystems.Result.TRY_AGAIN;
      }
   }

   @Nonnull
   class="kw">private class="kw">static WorldSpawnJobSystems.Result spawn(@Nonnull SpawnJobData var0, @Nonnull World var1, @Nonnull WorldChunk var2, @Nonnull WorldSpawnData var3) {
      NPCPlugin var4 = NPCPlugin.get();
      SpawningContext var5 = var0.getSpawningContext();
      Vector3d var6 = var5.newPosition();
      Rotation3f var7 = var5.newRotation();
      int var8 = var0.getRoleIndex();

      try {
         Store var10 = var1.getEntityStore().getStore();
         Pair var11 = var4.spawnEntity(var10, var8, var6, var7, var5.getModel(), (var2x, var3x, var4x) -> preAddToWorld(var2x, var3x, var8, var0), null);
         if (var11 == null) {
            LOGGER.at(Level.SEVERE).log("Spawn job %s: Failed to create %s: The spawned entity returned null", var0.getJobId(), var4.getName(var8));
            rejectSpawn(var0.getRejectionMap(), SpawnRejection.OTHER);
            class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var0, var2, var3);
         }

         NPCEntity var9 = (NPCEntity)var11.right();
         Ref var12 = (Ref<EntityStore>)var11.left();
         FlockPlugin.trySpawnFlock(
            var12,
            var9,
            var8,
            var6,
            var7,
            var0.getFlockSize(),
            var0.getFlockAsset(),
            (var2x, var3x, var4x) -> preAddToWorld(var2x, var3x, var8, var0),
            null,
            var10
         );
      } catch (RuntimeException var13) {
         ((HytaleLogger.Api)LOGGER.at(Level.SEVERE).withCause(var13))
            .log("Spawn job %s: Failed to create %s: %s", var0.getJobId(), var4.getName(var8), var13.getMessage());
         rejectSpawn(var0.getRejectionMap(), SpawnRejection.OTHER);
         class="kw">return endProbing(WorldSpawnJobSystems.Result.FAILED, var0, var2, var3);
      }

      HytaleLogger.Api var14 = LOGGER.at(Level.FINEST);
      if (var14.isEnabled()) {
         var14.log(
            "Spawn job %s: Created %s with flock size %s (env %s) at chunk %s/%s, columns probed %s",
            var0.getJobId(),
            NPCPlugin.get().getName(var8),
            var0.getFlockSize(),
            var0.getEnvironment().getId(),
            var2.getX(),
            var2.getZ(),
            var0.getTotalColumnsTested()
         );
      }

      var0.incrementSpansSuccess();
      class="kw">return endProbing(WorldSpawnJobSystems.Result.SUCCESS, var0, var2, var3);
   }

   class="kw">private class="kw">static void preAddToWorld(@Nonnull NPCEntity var0, @Nonnull Holder<EntityStore> var1, int var2, @Nonnull SpawnJobData var3) {
      var0.setSpawnRoleIndex(var2);
      if (var3.isSpawnFrozen()) {
         var1.ensureComponent(Frozen.getComponentType());
      }

      var0.setEnvironment(var3.getEnvironmentIndex());
      var0.setSpawnConfiguration(var3.getSpawnConfigIndex());
      var0.setActiveMotionControllerName(var3.getSpawningContext().activeMotionControllerType);
   }

   class="kw">private class="kw">static void rejectSpawn(@Nonnull Object2IntMap<SpawnRejection> var0, @Nonnull SpawnRejection var1) {
      var0.mergeInt(var1, 1, Integer::sum);
   }

   @Nonnull
   class="kw">protected class="kw">static WorldSpawnJobSystems.Result endProbing(
      @Nonnull WorldSpawnJobSystems.Result var0, @Nonnull SpawnJobData var1, @Nonnull WorldChunk var2, @Nonnull WorldSpawnData var3
   ) {
      HytaleLogger.Api var4 = LOGGER.at(Level.FINEST);
      if (var4.isEnabled()) {
         var4.log(
            "Term Spawnjob id=%s env=%s role=%s chunk=[%s/%s] tested=%s result=%s budgetUsed=%s",
            var1.getJobId(),
            var1.getEnvironment().getId(),
            getSpawnableName(var1.getRoleIndex()),
            var2.getX(),
            var2.getZ(),
            var1.getTotalColumnsTested(),
            var0,
            var1.getTotalBudgetUsed()
         );
      }

      var3.untrackNPC(var1.getEnvironmentIndex(), var1.getRoleIndex(), var1.getFlockSize());
      updateSpawnStats(var3, var1, var0);
      var3.adjustActiveSpawnJobs(-1, -var1.getFlockSize());
      class="kw">return var0;
   }

   class="kw">private class="kw">static void updateSpawnStats(@Nonnull WorldSpawnData var0, @Nonnull SpawnJobData var1, WorldSpawnJobSystems.Result var2) {
      boolean var3 = var2 == WorldSpawnJobSystems.Result.SUCCESS;
      WorldEnvironmentSpawnData var4 = var0.getWorldEnvironmentSpawnData(var1.getEnvironmentIndex());
      var4.updateSpawnStats(var1.getRoleIndex(), var1.getSpansTried(), var1.getSpansSuccess(), var1.getTotalBudgetUsed(), var1.getRejectionMap(), var3);
      var0.addCompletedSpawnJob(var1.getTotalBudgetUsed());
   }

   @Nullable
   class="kw">private class="kw">static String getSpawnableName(int var0) {
      class="kw">return NPCPlugin.get().getName(var0);
   }

   class="kw">public class="kw">static class EntityRemoved class="kw">extends HolderSystem<ChunkStore> {
      class="kw">private class="kw">final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType;
      class="kw">private class="kw">final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType;
      class="kw">private class="kw">final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType;

      class="kw">public EntityRemoved(ResourceType<EntityStore, WorldSpawnData> var1, ComponentType<ChunkStore, SpawnJobData> var2) {
         this.worldSpawnDataResourceType = var1;
         this.spawnJobDataComponentType = var2;
         this.worldChunkComponentType = WorldChunk.getComponentType();
      }

      @Nonnull
      @Override
      class="kw">public Query<ChunkStore> getQuery() {
         class="kw">return WorldSpawnJobSystems.TICKING_QUERY;
      }

      @Override
      class="kw">public void onEntityAdd(@Nonnull Holder<ChunkStore> var1, @Nonnull AddReason var2, @Nonnull Store<ChunkStore> var3) {
      }

      @Override
      class="kw">public void onEntityRemoved(@Nonnull Holder<ChunkStore> var1, @Nonnull RemoveReason var2, @Nonnull Store<ChunkStore> var3) {
         SpawnJobData var4 = var1.getComponent(this.spawnJobDataComponentType);
         assert var4 != null;
         WorldChunk var5 = var1.getComponent(this.worldChunkComponentType);
         assert var5 != null;
         World var6 = var3.getExternalData().getWorld();
         Store var7 = var6.getEntityStore().getStore();
         WorldSpawnData var8 = var7.getResource(this.worldSpawnDataResourceType);
         WorldSpawnJobSystems.endProbing(WorldSpawnJobSystems.Result.FAILED, var4, var5, var8);
         var1.removeComponent(this.spawnJobDataComponentType);
      }
   }

   class="kw">protected enum Result {
      SUCCESS,
      FAILED,
      TRY_AGAIN,
      PERMANENT_FAILURE;

      Result() {
      }
   }

   class="kw">public class="kw">static class Ticking class="kw">extends EntityTickingSystem<ChunkStore> {
      class="kw">private class="kw">final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType;
      class="kw">private class="kw">final ResourceType<EntityStore, SpawnSuppressionController> spawnSuppressionControllerResourceType;
      class="kw">private class="kw">final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType;
      class="kw">private class="kw">final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType;
      class="kw">private class="kw">final ComponentType<ChunkStore, ChunkSpawnData> chunkSpawnDataComponentType;
      class="kw">private class="kw">final ComponentType<ChunkStore, ChunkSpawnedNPCData> chunkSpawnedNPCDataComponentType;

      class="kw">public Ticking(
         ResourceType<EntityStore, WorldSpawnData> var1,
         ResourceType<EntityStore, SpawnSuppressionController> var2,
         ComponentType<ChunkStore, SpawnJobData> var3,
         ComponentType<ChunkStore, ChunkSpawnData> var4,
         ComponentType<ChunkStore, ChunkSpawnedNPCData> var5
      ) {
         this.worldSpawnDataResourceType = var1;
         this.spawnSuppressionControllerResourceType = var2;
         this.spawnJobDataComponentType = var3;
         this.worldChunkComponentType = WorldChunk.getComponentType();
         this.chunkSpawnDataComponentType = var4;
         this.chunkSpawnedNPCDataComponentType = var5;
      }

      @Override
      class="kw">public Query<ChunkStore> getQuery() {
         class="kw">return WorldSpawnJobSystems.QUERY;
      }

      @Override
      class="kw">public boolean isParallel(int var1, int var2) {
         class="kw">return false;
      }

      @Override
      class="kw">public void tick(float var1, int var2, @Nonnull ArchetypeChunk<ChunkStore> var3, @Nonnull Store<ChunkStore> var4, @Nonnull CommandBuffer<ChunkStore> var5) {
         World var6 = var4.getExternalData().getWorld();
         Store var7 = var6.getEntityStore().getStore();
         WorldSpawnData var8 = var7.getResource(this.worldSpawnDataResourceType);
         SpawnJobData var9 = var3.getComponent(var2, this.spawnJobDataComponentType);
         assert var9 != null;
         WorldChunk var10 = var3.getComponent(var2, this.worldChunkComponentType);
         assert var10 != null;
         if (!var9.isTerminated() && !(var8.getActualNPCs() > var8.getExpectedNPCs())) {
            ChunkSpawnedNPCData var11 = var3.getComponent(var2, this.chunkSpawnedNPCDataComponentType);
            assert var11 != null;
            ChunkSpawnData var12 = var3.getComponent(var2, this.chunkSpawnDataComponentType);
            assert var12 != null;
            int var13 = var9.getEnvironmentIndex();
            double var14 = var11.getEnvironmentSpawnCount(var13);
            ChunkEnvironmentSpawnData var16 = var12.getEnvironmentSpawnData(var13);
            if (!var16.allRolesUnspawnable() && (var9.isIgnoreFullyPopulated() || !var16.isFullyPopulated(var14))) {
               Ref var17 = var3.getReferenceTo(var2);
               SpawnSuppressionController var18 = var7.getResource(this.spawnSuppressionControllerResourceType);
               WorldSpawnJobSystems.Result var19 = WorldSpawnJobSystems.run(var6, var17, var9, var10, var16, var8, var18);
               if (var19 == WorldSpawnJobSystems.Result.SUCCESS) {
                  var12.setLastSpawn(System.nanoTime());
               }

               if (var19 != WorldSpawnJobSystems.Result.TRY_AGAIN) {
                  var5.removeComponent(var3.getReferenceTo(var2), this.spawnJobDataComponentType);
               }
            } else {
               WorldSpawnJobSystems.endProbing(WorldSpawnJobSystems.Result.FAILED, var9, var10, var8);
               var5.removeComponent(var3.getReferenceTo(var2), this.spawnJobDataComponentType);
            }
         } else {
            WorldSpawnJobSystems.endProbing(WorldSpawnJobSystems.Result.FAILED, var9, var10, var8);
            var5.removeComponent(var3.getReferenceTo(var2), this.spawnJobDataComponentType);
         }
      }
   }

   class="kw">public class="kw">static class TickingState class="kw">extends RefChangeSystem<ChunkStore, NonTicking<ChunkStore>> {
      class="kw">private class="kw">final ResourceType<EntityStore, WorldSpawnData> worldSpawnDataResourceType;
      class="kw">private class="kw">final ComponentType<ChunkStore, SpawnJobData> spawnJobDataComponentType;
      class="kw">private class="kw">final ComponentType<ChunkStore, WorldChunk> worldChunkComponentType;

      class="kw">public TickingState(ResourceType<EntityStore, WorldSpawnData> var1, ComponentType<ChunkStore, SpawnJobData> var2) {
         this.worldSpawnDataResourceType = var1;
         this.spawnJobDataComponentType = var2;
         this.worldChunkComponentType = WorldChunk.getComponentType();
      }

      @Override
      class="kw">public Query<ChunkStore> getQuery() {
         class="kw">return WorldSpawnJobSystems.QUERY;
      }

      @Nonnull
      @Override
      class="kw">public ComponentType<ChunkStore, NonTicking<ChunkStore>> componentType() {
         class="kw">return ChunkStore.REGISTRY.getNonTickingComponentType();
      }

      class="kw">public void onComponentAdded(
         @Nonnull Ref<ChunkStore> var1, @Nonnull NonTicking<ChunkStore> var2, @Nonnull Store<ChunkStore> var3, @Nonnull CommandBuffer<ChunkStore> var4
      ) {
         SpawnJobData var5 = var3.getComponent(var1, this.spawnJobDataComponentType);
         assert var5 != null;
         WorldChunk var6 = var3.getComponent(var1, this.worldChunkComponentType);
         assert var6 != null;
         World var7 = var3.getExternalData().getWorld();
         Store var8 = var7.getEntityStore().getStore();
         WorldSpawnData var9 = var8.getResource(this.worldSpawnDataResourceType);
         WorldSpawnJobSystems.endProbing(WorldSpawnJobSystems.Result.FAILED, var5, var6, var9);
         var4.removeComponent(var1, this.spawnJobDataComponentType);
      }

      class="kw">public void onComponentSet(
         @Nonnull Ref<ChunkStore> var1,
         NonTicking<ChunkStore> var2,
         @Nonnull NonTicking<ChunkStore> var3,
         @Nonnull Store<ChunkStore> var4,
         @Nonnull CommandBuffer<ChunkStore> var5
      ) {
      }

      class="kw">public void onComponentRemoved(
         @Nonnull Ref<ChunkStore> var1, @Nonnull NonTicking<ChunkStore> var2, @Nonnull Store<ChunkStore> var3, @Nonnull CommandBuffer<ChunkStore> var4
      ) {
      }
   }
}