ColumnState enum

Пакет: com.hypixel.hytale.server.core.modules.entity.player

Файл: com/hypixel/hytale/server/core/modules/entity/player/ChunkTracker.java

Поля (1)

МодификаторыТипИмя
NONE, LOADING, READY

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.core.modules.entity.player;

class="kw">import com.hypixel.hytale.codec.Codec;
class="kw">import com.hypixel.hytale.component.CommandBuffer;
class="kw">import com.hypixel.hytale.component.Component;
class="kw">import com.hypixel.hytale.component.ComponentAccessor;
class="kw">import com.hypixel.hytale.component.ComponentType;
class="kw">import com.hypixel.hytale.component.NonTicking;
class="kw">import com.hypixel.hytale.component.Ref;
class="kw">import com.hypixel.hytale.component.Store;
class="kw">import com.hypixel.hytale.function.consumer.TriIntConsumer;
class="kw">import com.hypixel.hytale.logger.HytaleLogger;
class="kw">import com.hypixel.hytale.math.data.Int3OpenHashSet;
class="kw">import com.hypixel.hytale.math.iterator.SphereOffsets;
class="kw">import com.hypixel.hytale.math.iterator.SpherePosition;
class="kw">import com.hypixel.hytale.math.iterator.SphereSpiralIterator;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.metrics.MetricsRegistry;
class="kw">import com.hypixel.hytale.protocol.NetworkChannel;
class="kw">import com.hypixel.hytale.protocol.ToClientPacket;
class="kw">import com.hypixel.hytale.protocol.packets.world.SetAbsentChunks;
class="kw">import com.hypixel.hytale.protocol.packets.world.UnloadChunks;
class="kw">import com.hypixel.hytale.server.core.HytaleServer;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.io.PacketHandler;
class="kw">import com.hypixel.hytale.server.core.modules.entity.EntityModule;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
class="kw">import com.hypixel.hytale.server.core.universe.PlayerRef;
class="kw">import com.hypixel.hytale.server.core.universe.world.World;
class="kw">import com.hypixel.hytale.server.core.universe.world.chunk.ChunkFlag;
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 it.unimi.dsi.fastutil.ints.IntArrayList;
class="kw">import it.unimi.dsi.fastutil.ints.IntIterator;
class="kw">import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
class="kw">import it.unimi.dsi.fastutil.ints.IntSet;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectIterator;
class="kw">import java.util.Arrays;
class="kw">import java.util.Collections;
class="kw">import java.util.Iterator;
class="kw">import java.util.List;
class="kw">import java.util.concurrent.CompletableFuture;
class="kw">import java.util.concurrent.TimeUnit;
class="kw">import java.util.concurrent.locks.StampedLock;
class="kw">import java.util.function.Supplier;
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 ChunkTracker class="kw">implements Component<EntityStore> {
   @Nonnull
   class="kw">public class="kw">static class="kw">final MetricsRegistry<ChunkTracker> METRICS_REGISTRY = new MetricsRegistry<ChunkTracker>()
      .register("ViewRadius", var0 -> var0.sectionViewRadius, Codec.INTEGER)
      .register("SentViewRadiusSq", var0 -> var0.sentViewRadiusSq, Codec.INTEGER)
      .register("HotRadiusSq", var0 -> var0.hotRadiusSq, Codec.INTEGER)
      .register("LoadedSectionsCount", ChunkTracker::getLoadedSectionsCount, Codec.INTEGER)
      .register("LoadingSectionsCount", ChunkTracker::getLoadingSectionsCount, Codec.INTEGER)
      .register("MaxSectionsPerSecond", ChunkTracker::getMaxSectionsPerSecond, Codec.INTEGER)
      .register("MaxSectionsPerTick", ChunkTracker::getMaxSectionsPerTick, Codec.INTEGER)
      .register("ReadyForChunks", ChunkTracker::isReadyForChunks, Codec.BOOLEAN)
      .register("LastChunkX", var0 -> var0.lastChunkX, Codec.INTEGER)
      .register("LastChunkY", var0 -> var0.lastChunkY, Codec.INTEGER)
      .register("LastChunkZ", var0 -> var0.lastChunkZ, Codec.INTEGER);
   class="kw">public class="kw">static class="kw">final int MAX_SECTIONS_PER_SECOND_LOCAL = 2560;
   class="kw">public class="kw">static class="kw">final int MAX_SECTIONS_PER_SECOND_LAN = 1280;
   class="kw">public class="kw">static class="kw">final int MAX_SECTIONS_PER_SECOND = 360;
   class="kw">public class="kw">static class="kw">final int MAX_SECTIONS_PER_TICK = 40;
   class="kw">public class="kw">static class="kw">final int MAX_UNLOAD_SECTION_INTS = 12288;
   class="kw">public class="kw">static class="kw">final int MAX_UNLOAD_COLUMN_INTS = 8192;
   class="kw">public class="kw">static class="kw">final int MAX_ABSENT_Y_INTS = 128;
   class="kw">public class="kw">static class="kw">final int MIN_LOADED_RADIUS = 2;
   class="kw">public class="kw">static class="kw">final int MAX_HOT_LOADED_RADIUS = 8;
   class="kw">public class="kw">static class="kw">final long MAX_FAILURE_BACKOFF_NANOS = TimeUnit.SECONDS.toNanos(10L);
   @Nullable
   class="kw">private TransformComponent transformComponent;
   class="kw">private int sectionViewRadius;
   @Nonnull
   class="kw">private class="kw">final Supplier<SphereOffsets> sphereOffsetsSupplier;
   @Nonnull
   class="kw">private class="kw">volatile SphereSpiralIterator spiralIterator;
   @Nonnull
   class="kw">private class="kw">final StampedLock lock = new StampedLock();
   class="kw">private class="kw">final Long2ObjectMap<ChunkTracker.TrackedColumn> trackedColumns = new Long2ObjectOpenHashMap();
   class="kw">private class="kw">final Long2ObjectMap<IntArrayList> pendingAbsentByColumn = new Long2ObjectOpenHashMap();
   class="kw">private class="kw">volatile boolean hasPendingAbsent;
   class="kw">private class="kw">final IntArrayList unloadSectionScratch = new IntArrayList();
   class="kw">private class="kw">final IntArrayList unloadColumnScratch = new IntArrayList();
   class="kw">private int loadingSections;
   class="kw">private class="kw">final Int3OpenHashSet reloadingSections = new Int3OpenHashSet();
   class="kw">private class="kw">final ChunkTracker.ReloadContext reloadContext = new ChunkTracker.ReloadContext();
   class="kw">private int maxSectionsPerSecond;
   class="kw">private float inverseMaxSectionsPerSecond;
   class="kw">private int maxSectionsPerTick;
   class="kw">private int minLoadedRadius;
   class="kw">private int maxHotLoadedRadius;
   class="kw">private int maxHotLoadedRadiusSq;
   class="kw">private float accumulatorSeconds;
   class="kw">private int sentViewRadiusSq;
   class="kw">private int hotRadiusSq;
   class="kw">private int lastChunkX;
   class="kw">private int lastChunkY;
   class="kw">private int lastChunkZ;
   class="kw">private boolean readyForChunks;

   class="kw">public class="kw">static ComponentType<EntityStore, ChunkTracker> getComponentType() {
      class="kw">return EntityModule.get().getChunkTrackerComponentType();
   }

   class="kw">public ChunkTracker() {
      this(() -> HytaleServer.get().getConfig().getMaxViewSphereOffsets());
   }

   class="kw">public ChunkTracker(@Nonnull Supplier<SphereOffsets> var1) {
      this.sphereOffsetsSupplier = var1;
      this.spiralIterator = new SphereSpiralIterator(var1.get());
      this.minLoadedRadius = 2;
      this.maxHotLoadedRadius = 8;
      this.maxHotLoadedRadiusSq = 64;
      this.maxSectionsPerTick = 40;
   }

   class="kw">private ChunkTracker(@Nonnull ChunkTracker var1) {
      this.sphereOffsetsSupplier = var1.sphereOffsetsSupplier;
      this.spiralIterator = new SphereSpiralIterator(this.sphereOffsetsSupplier.get());
      this.copyFrom(var1);
   }

   class="kw">public void clear() {
      long var1 = this.lock.writeLock();

      try {
         this.resetState();
      } class="kw">finally {
         this.lock.unlockWrite(var1);
      }
   }

   class="kw">private void resetState() {
      this.trackedColumns.clear();
      this.reloadingSections.clear();
      this.pendingAbsentByColumn.clear();
      this.hasPendingAbsent = false;
      this.loadingSections = 0;
      this.sentViewRadiusSq = 0;
      this.hotRadiusSq = 0;
   }

   class="kw">private void flushPendingAbsent(@Nonnull PlayerRef var1) {
      if (this.pendingAbsentByColumn.isEmpty()) {
         this.hasPendingAbsent = false;
      } else {
         PacketHandler var2 = var1.getPacketHandler();
         ObjectIterator var3 = Long2ObjectMaps.fastIterator(this.pendingAbsentByColumn);

         while (var3.hasNext()) {
            Entry var4 = (Entry<IntArrayList>)var3.next();
            long var5 = var4.getLongKey();
            if (this.trackedColumns.containsKey(var5)) {
               int var7 = ChunkUtil.xOfChunkIndex(var5);
               int var8 = ChunkUtil.zOfChunkIndex(var5);
               IntArrayList var9 = (IntArrayList)var4.getValue();
               int[] var10 = var9.elements();
               int var11 = var9.size();

               for (int var12 = 0; var12 < var11; var12 += 128) {
                  int var13 = Math.min(var12 + 128, var11);
                  var2.writeNoCache(new SetAbsentChunks(var7, var8, Arrays.copyOfRange(var10, var12, var13)));
               }
            }
         }

         this.pendingAbsentByColumn.clear();
         this.hasPendingAbsent = false;
      }
   }

   class="kw">private void flushUnloads(@Nonnull PlayerRef var1) {
      PacketHandler var2 = var1.getPacketHandler();
      int var3 = this.unloadSectionScratch.size();
      if (var3 > 0) {
         int[] var4 = this.unloadSectionScratch.elements();

         for (int var5 = 0; var5 < var3; var5 += 12288) {
            int var6 = Math.min(var5 + 12288, var3);
            var2.writeNoCache(new UnloadChunks(Arrays.copyOfRange(var4, var5, var6), null));
         }
      }

      int var8 = this.unloadColumnScratch.size();
      if (var8 > 0) {
         int[] var9 = this.unloadColumnScratch.elements();

         for (int var10 = 0; var10 < var8; var10 += 8192) {
            int var7 = Math.min(var10 + 8192, var8);
            var2.writeNoCache(new UnloadChunks(null, Arrays.copyOfRange(var9, var10, var7)));
         }
      }
   }

   class="kw">public void tick(@Nonnull Player var1, @Nonnull PlayerRef var2, @Nonnull TransformComponent var3, float var4, @Nonnull CommandBuffer<EntityStore> var5) {
      if (this.readyForChunks && var2.getPacketHandler().getChannel(NetworkChannel.Chunks).isWritable()) {
         this.transformComponent = var3;
         int var6 = this.sectionViewRadius = var1.getViewRadius();
         Vector3d var7 = var3.getPosition();
         int var8 = MathUtil.floor(var7.x()) >> 5;
         int var9 = MathUtil.floor(var7.y()) >> 5;
         int var10 = MathUtil.floor(var7.z()) >> 5;
         int var11 = var6 * var6;
         int var12 = this.lastChunkX - var8;
         int var13 = this.lastChunkY - var9;
         int var14 = this.lastChunkZ - var10;
         int var15 = (int)Math.ceil(Math.sqrt(var12 * var12 + var13 * var13 + var14 * var14));
         if (var15 > 0) {
            int var16 = Math.min((int)Math.sqrt(this.sentViewRadiusSq), var6);
            int var17 = Math.max(0, var16 - var15);
            this.sentViewRadiusSq = var17 * var17;
            int var18 = Math.min(this.maxHotLoadedRadius, var6);
            int var19 = Math.min((int)Math.sqrt(this.hotRadiusSq), var18);
            int var20 = Math.max(0, var19 - var15);
            this.hotRadiusSq = var20 * var20;
         }

         this.lastChunkX = var8;
         this.lastChunkY = var9;
         this.lastChunkZ = var10;
         int var46 = Math.min(this.maxHotLoadedRadius, var6);
         int var47 = var46 * var46;
         boolean var48 = this.sentViewRadiusSq > var11 + 1;
         if (var48) {
            this.sentViewRadiusSq = var11 + 1;
         }

         if (this.hotRadiusSq > var47 + 1) {
            this.hotRadiusSq = var47 + 1;
         }

         if (var48 || this.sentViewRadiusSq <= var11 || this.hotRadiusSq <= var47 || !this.reloadingSections.isEmpty() || this.hasPendingAbsent) {
            World var49 = var5.getExternalData().getWorld();
            ChunkStore var50 = var49.getChunkStore();
            boolean var21 = var50.supportsCubicSections();
            long var22 = this.lock.writeLock();

            try {
               if (var6 > this.spiralIterator.sharedOffsets().maxR) {
                  SphereSpiralIterator var24 = new SphereSpiralIterator(this.sphereOffsetsSupplier.get());
                  var24.configure(var6);
                  this.spiralIterator = var24;
               } else {
                  this.spiralIterator.configure(var6);
               }

               this.flushPendingAbsent(var2);
               this.unloadSectionScratch.clear();
               this.unloadColumnScratch.clear();
               ObjectIterator var51 = Long2ObjectMaps.fastIterator(this.trackedColumns);

               while (var51.hasNext()) {
                  if (this.tryUnloadColumn((Entry<ChunkTracker.TrackedColumn>)var51.next(), var11, var8, var9, var10, var2)) {
                     var51.remove();
                  }
               }

               this.flushUnloads(var2);
               this.accumulatorSeconds += var4;
               int var25 = Math.min((int)(this.maxSectionsPerSecond * this.accumulatorSeconds), this.maxSectionsPerTick);
               var25 -= this.loadingSections;
               if (var25 > 0 && !this.reloadingSections.isEmpty()) {
                  this.reloadContext.budget = var25;
                  this.reloadContext.chunkStore = var50;
                  this.reloadContext.playerRef = var2;
                  this.reloadContext.transform = var3;
                  this.reloadContext.commandBuffer = var5;
                  this.reloadingSections.removeIf(ChunkTracker::reloadSection, 0, 0, 0, this, this.reloadContext);
                  var25 = this.reloadContext.budget;
                  this.reloadContext.clear();
               }

               if (this.sentViewRadiusSq <= var11) {
                  boolean var26 = true;
                  this.spiralIterator.init(var8, var9, var10, this.sentViewRadiusSq, var11);

                  while (var25 > 0 && this.spiralIterator.advance()) {
                     SpherePosition var27 = this.spiralIterator.position();
                     if (var21 || var27.y >= 0 && var27.y < 10) {
                        long var28 = ChunkUtil.indexChunk(var27.x, var27.z);
                        ChunkTracker.TrackedColumn var30 = (ChunkTracker.TrackedColumn)this.trackedColumns
                           .computeIfAbsent(var28, var0 -> new ChunkTracker.TrackedColumn());
                        if (var30.state == ChunkTracker.ColumnState.NONE) {
                           if (var50.isChunkOnBackoff(var28, MAX_FAILURE_BACKOFF_NANOS)) {
                              var26 = false;
                              class="kw">continue;
                           }

                           this.tryLoadColumnAsync(var50, var2, var28, var3, var5);
                           var30.state = ChunkTracker.ColumnState.LOADING;
                        }

                        if (var30.state == ChunkTracker.ColumnState.LOADING) {
                           var26 = false;
                           if (var30.pendingSections.add(var27.y)) {
                              var25--;
                           }
                        } else if (!var30.loadedSections.contains(var27.y)) {
                           if (var50.isChunkSectionOnBackoff(var27.x, var27.y, var27.z, MAX_FAILURE_BACKOFF_NANOS)) {
                              var26 = false;
                           } else {
                              var26 = false;
                              var30.pendingSections.remove(var27.y);
                              if (var30.loadingSections.add(var27.y)) {
                                 this.loadingSections++;
                                 var25--;
                                 this.accumulatorSeconds = this.accumulatorSeconds - this.inverseMaxSectionsPerSecond;
                                 this.tryLoadSectionAsync(var50, var2, var27.x, var27.y, var27.z, var3, var5);
                              }
                           }
                        }
                     }
                  }

                  if (var26) {
                     this.sentViewRadiusSq = this.spiralIterator.getCompletedDistSq() + 1;
                  }
               }
            } class="kw">finally {
               this.lock.unlockWrite(var22);
            }

            if (this.hotRadiusSq <= var47) {
               ComponentType var52 = ChunkStore.REGISTRY.getNonTickingComponentType();
               ComponentType var54 = WorldChunk.getComponentType();
               Store var55 = var50.getStore();
               long var56 = this.lock.readLock();

               try {
                  this.spiralIterator.init(var8, var9, var10, this.hotRadiusSq, var47);

                  while (this.spiralIterator.advance()) {
                     SpherePosition var29 = this.spiralIterator.position();
                     int var57 = var29.x;
                     int var31 = var29.y;
                     int var32 = var29.z;
                     long var33 = ChunkUtil.indexChunk(var57, var32);
                     ChunkTracker.TrackedColumn var35 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var33);
                     if (var35 != null && var35.loadedSections.contains(var31)) {
                        Ref var36 = var50.getChunkSectionReference(var57, var31, var32);
                        if (var36 != null && var36.isValid()) {
                           if (var55.<NonTicking<ChunkStore>>getComponent(var36, var52) != null) {
                              var5.run(var3x -> var55.tryRemoveComponent(var36, var52));
                           }

                           Ref var37 = var50.getChunkReference(var33);
                           if (var37 != null && var37.isValid()) {
                              WorldChunk var38 = var55.getComponent(var37, var54);
                              if (var38 != null && !var38.is(ChunkFlag.TICKING)) {
                                 var5.run(var1x -> var38.setFlag(ChunkFlag.TICKING, true));
                              }
                           }
                        }
                     }
                  }
               } class="kw">finally {
                  this.lock.unlockRead(var56);
               }

               this.hotRadiusSq = var47 + 1;
            }

            if (this.sentViewRadiusSq > var11) {
               this.accumulatorSeconds = 0.0F;
            }
         }
      }
   }

   class="kw">public boolean isLoaded(long var1) {
      long var3 = this.lock.readLock();

      try {
         ChunkTracker.TrackedColumn var5 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var1);
         class="kw">return var5 != null && var5.state == ChunkTracker.ColumnState.READY;
      } class="kw">finally {
         this.lock.unlockRead(var3);
      }
   }

   class="kw">public boolean isLoaded(int var1, int var2, int var3) {
      long var4 = this.lock.readLock();

      try {
         ChunkTracker.TrackedColumn var6 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(ChunkUtil.indexChunk(var1, var3));
         class="kw">return var6 != null && var6.state == ChunkTracker.ColumnState.READY && var6.loadedSections.contains(var2);
      } class="kw">finally {
         this.lock.unlockRead(var4);
      }
   }

   @Deprecated(forRemoval = true)
   class="kw">public void removeForReload(long var1) {
      long var3 = this.lock.writeLock();

      try {
         ChunkTracker.TrackedColumn var5 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var1);
         if (var5 == null) {
            class="kw">return;
         }

         int var6 = ChunkUtil.xOfChunkIndex(var1);
         int var7 = ChunkUtil.zOfChunkIndex(var1);
         IntIterator var8 = var5.loadedSections.iterator();

         while (var8.hasNext()) {
            Integer var9 = (Integer)var8.next();
            this.reloadingSections.add(var6, var9, var7);
         }
      } class="kw">finally {
         this.lock.unlockWrite(var3);
      }
   }

   class="kw">public void removeForReload(int var1, int var2, int var3) {
      if (this.shouldBeVisible(var1, var2, var3)) {
         long var4 = this.lock.writeLock();

         try {
            this.reloadingSections.add(var1, var2, var3);
         } class="kw">finally {
            this.lock.unlockWrite(var4);
         }
      }
   }

   class="kw">public boolean shouldBeVisible(long var1) {
      if (this.transformComponent == null) {
         class="kw">return false;
      }

      Vector3d var3 = this.transformComponent.getPosition();
      int var4 = MathUtil.floor(var3.x()) >> 5;
      int var5 = MathUtil.floor(var3.z()) >> 5;
      int var6 = ChunkUtil.xOfChunkIndex(var1);
      int var7 = ChunkUtil.zOfChunkIndex(var1);
      int var8 = Math.max(this.minLoadedRadius, this.sectionViewRadius);
      class="kw">return shouldBeVisible(var8 * var8, var4, var5, var6, var7);
   }

   class="kw">public boolean shouldBeVisible(int var1, int var2, int var3) {
      if (this.transformComponent == null) {
         class="kw">return false;
      }

      Vector3d var4 = this.transformComponent.getPosition();
      int var5 = MathUtil.floor(var4.x()) >> 5;
      int var6 = MathUtil.floor(var4.y()) >> 5;
      int var7 = MathUtil.floor(var4.z()) >> 5;
      class="kw">return this.spiralIterator.containsOffset(var1 - var5, var2 - var6, var3 - var7);
   }

   @Nonnull
   class="kw">public ChunkTracker.ChunkVisibility getChunkVisibility(long var1) {
      if (this.transformComponent == null) {
         class="kw">return ChunkTracker.ChunkVisibility.NONE;
      } else {
         Vector3d var3 = this.transformComponent.getPosition();
         int var4 = MathUtil.floor(var3.x()) >> 5;
         int var5 = MathUtil.floor(var3.z()) >> 5;
         int var6 = ChunkUtil.xOfChunkIndex(var1);
         int var7 = ChunkUtil.zOfChunkIndex(var1);
         int var8 = Math.abs(var6 - var4);
         int var9 = Math.abs(var7 - var5);
         int var10 = var8 * var8 + var9 * var9;
         int var11 = Math.max(this.minLoadedRadius, this.sectionViewRadius);
         boolean var12 = var10 <= var11 * var11;
         if (var12) {
            boolean var13 = var10 <= this.maxHotLoadedRadiusSq;
            class="kw">return var13 ? ChunkTracker.ChunkVisibility.HOT : ChunkTracker.ChunkVisibility.COLD;
         } else {
            class="kw">return ChunkTracker.ChunkVisibility.NONE;
         }
      }
   }

   @Nonnull
   class="kw">public ChunkTracker.ChunkVisibility getSectionVisibility(int var1, int var2, int var3) {
      if (this.transformComponent == null) {
         class="kw">return ChunkTracker.ChunkVisibility.NONE;
      }

      Vector3d var4 = this.transformComponent.getPosition();
      int var5 = MathUtil.floor(var4.x()) >> 5;
      int var6 = MathUtil.floor(var4.y()) >> 5;
      int var7 = MathUtil.floor(var4.z()) >> 5;
      int var8 = var1 - var5;
      int var9 = var2 - var6;
      int var10 = var3 - var7;
      if (!this.spiralIterator.containsOffset(var8, var9, var10)) {
         class="kw">return ChunkTracker.ChunkVisibility.NONE;
      }

      int var11 = var8 * var8 + var9 * var9 + var10 * var10;
      class="kw">return var11 <= this.maxHotLoadedRadiusSq ? ChunkTracker.ChunkVisibility.HOT : ChunkTracker.ChunkVisibility.COLD;
   }

   class="kw">public int getMaxSectionsPerSecond() {
      class="kw">return this.maxSectionsPerSecond;
   }

   class="kw">public void setMaxSectionsPerSecond(int var1) {
      this.maxSectionsPerSecond = var1;
      this.inverseMaxSectionsPerSecond = 1.0F / var1;
   }

   class="kw">public void setDefaultMaxSectionsPerSecond(@Nonnull PlayerRef var1) {
      if (var1.getPacketHandler().isLocalConnection()) {
         this.maxSectionsPerSecond = 2560;
      } else if (var1.getPacketHandler().isLANConnection()) {
         this.maxSectionsPerSecond = 1280;
      } else {
         this.maxSectionsPerSecond = 360;
      }

      this.inverseMaxSectionsPerSecond = 1.0F / this.maxSectionsPerSecond;
   }

   class="kw">public int getMaxSectionsPerTick() {
      class="kw">return this.maxSectionsPerTick;
   }

   class="kw">public void setMaxSectionsPerTick(int var1) {
      this.maxSectionsPerTick = var1;
   }

   class="kw">public int getMinLoadedRadius() {
      class="kw">return this.minLoadedRadius;
   }

   class="kw">public void setMinLoadedRadius(int var1) {
      this.minLoadedRadius = var1;
   }

   class="kw">public int getMaxHotLoadedRadius() {
      class="kw">return this.maxHotLoadedRadius;
   }

   class="kw">public void setMaxHotLoadedRadius(int var1) {
      this.maxHotLoadedRadius = var1;
      this.maxHotLoadedRadiusSq = var1 * var1;
   }

   class="kw">public int getLoadedSectionsCount() {
      long var1 = this.lock.readLock();

      try {
         int var3 = 0;
         ObjectIterator var4 = this.trackedColumns.values().iterator();

         while (var4.hasNext()) {
            ChunkTracker.TrackedColumn var5 = (ChunkTracker.TrackedColumn)var4.next();
            var3 += var5.loadedSections.size();
         }

         class="kw">return var3;
      } class="kw">finally {
         this.lock.unlockRead(var1);
      }
   }

   class="kw">public void forEachLoadedSection(@Nonnull TriIntConsumer var1) {
      long var2 = this.lock.readLock();

      try {
         ObjectIterator var4 = Long2ObjectMaps.fastIterator(this.trackedColumns);

         while (var4.hasNext()) {
            Entry var5 = (Entry<ChunkTracker.TrackedColumn>)var4.next();
            ChunkTracker.TrackedColumn var6 = (ChunkTracker.TrackedColumn)var5.getValue();
            if (!var6.loadedSections.isEmpty()) {
               int var7 = ChunkUtil.xOfChunkIndex(var5.getLongKey());
               int var8 = ChunkUtil.zOfChunkIndex(var5.getLongKey());
               IntIterator var9 = var6.loadedSections.iterator();

               while (var9.hasNext()) {
                  var1.accept(var7, var9.nextInt(), var8);
               }
            }
         }
      } class="kw">finally {
         this.lock.unlockRead(var2);
      }
   }

   class="kw">public int getLoadingSectionsCount() {
      long var1 = this.lock.tryOptimisticRead();
      int var3 = this.loadingSections;
      if (this.lock.validate(var1)) {
         class="kw">return var3;
      }

      var1 = this.lock.readLock();

      try {
         class="kw">return this.loadingSections;
      } class="kw">finally {
         this.lock.unlockRead(var1);
      }
   }

   @Nonnull
   class="kw">public String getLoadedChunksDebug() {
      long var1 = this.lock.readLock();

      try {
         StringBuilder var3 = new StringBuilder();
         if (this.transformComponent == null) {
            var3.append("Tracker not yet ticked");
            class="kw">return var3.toString();
         }

         Vector3d var4 = this.transformComponent.getPosition();
         int var5 = MathUtil.floor(var4.x()) >> 5;
         int var6 = MathUtil.floor(var4.y()) >> 5;
         int var7 = MathUtil.floor(var4.z()) >> 5;
         int var8 = 0;
         int var9 = 0;
         ObjectIterator var10 = Long2ObjectMaps.fastIterator(this.trackedColumns);

         while (var10.hasNext()) {
            Entry var11 = (Entry<ChunkTracker.TrackedColumn>)var10.next();
            ChunkTracker.TrackedColumn var12 = (ChunkTracker.TrackedColumn)var11.getValue();
            var8 += var12.loadedSections.size();
            int var13 = ChunkUtil.xOfChunkIndex(var11.getLongKey());
            int var14 = ChunkUtil.zOfChunkIndex(var11.getLongKey());
            IntIterator var15 = var12.loadedSections.iterator();

            while (var15.hasNext()) {
               if (this.getSectionVisibility(var13, var15.nextInt(), var14) == ChunkTracker.ChunkVisibility.HOT) {
                  var9++;
               }
            }
         }

         var3.append("Player chunk: (").append(var5).append(", ").append(var6).append(", ").append(var7).append(")\n");
         var3.append("View radius: ").append(this.sectionViewRadius).append('\n');
         var3.append("Sent radius sq: ").append(this.sentViewRadiusSq).append('\n');
         var3.append("Hot radius sq: ").append(this.hotRadiusSq).append('\n');
         var3.append("Ready for chunks: ").append(this.readyForChunks).append('\n');
         var3.append("Tracked columns: ").append(this.trackedColumns.size()).append('\n');
         var3.append("Loaded sections: ").append(var8).append('\n');
         var3.append("Hot sections: ").append(var9).append('\n');
         var3.append("\nLoaded sections per column (top-down):\n");
         this.appendColumnGrid(var3, var5, var7, false);
         var3.append("\nHot sections per column (top-down):\n");
         this.appendColumnGrid(var3, var5, var7, true);
         class="kw">return var3.toString();
      } class="kw">finally {
         this.lock.unlockRead(var1);
      }
   }

   class="kw">private void appendColumnGrid(@Nonnull StringBuilder var1, int var2, int var3, boolean var4) {
      int var5 = this.sectionViewRadius;

      for (int var6 = var3 - var5; var6 <= var3 + var5; var6++) {
         for (int var7 = var2 - var5; var7 <= var2 + var5; var7++) {
            ChunkTracker.TrackedColumn var8 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(ChunkUtil.indexChunk(var7, var6));
            if (var8 == null) {
               var1.append(" . ");
            } else {
               int var9;
               if (var4) {
                  var9 = 0;
                  IntIterator var10 = var8.loadedSections.iterator();

                  while (var10.hasNext()) {
                     if (this.getSectionVisibility(var7, var10.nextInt(), var6) == ChunkTracker.ChunkVisibility.HOT) {
                        var9++;
                     }
                  }
               } else {
                  var9 = var8.loadedSections.size();
               }

               var1.append(String.format("%2d ", var9));
            }
         }

         var1.append('\n');
      }
   }

   class="kw">public void setReadyForChunks(boolean var1) {
      this.readyForChunks = var1;
   }

   class="kw">public boolean isReadyForChunks() {
      class="kw">return this.readyForChunks;
   }

   class="kw">public void copyFrom(@Nonnull ChunkTracker var1) {
      long var2 = this.lock.writeLock();

      try {
         long var4 = var1.lock.readLock();

         try {
            this.resetState();
            ObjectIterator var6 = var1.trackedColumns.long2ObjectEntrySet().iterator();

            while (var6.hasNext()) {
               Entry var7 = (Entry<ChunkTracker.TrackedColumn>)var6.next();
               ChunkTracker.TrackedColumn var8 = (ChunkTracker.TrackedColumn)var7.getValue();
               if (var8.state == ChunkTracker.ColumnState.READY) {
                  ChunkTracker.TrackedColumn var9 = new ChunkTracker.TrackedColumn();
                  var9.state = ChunkTracker.ColumnState.READY;
                  var9.loadedSections.addAll(var8.loadedSections);
                  this.trackedColumns.put(var7.getLongKey(), var9);
               }
            }

            var1.reloadingSections.forEach((var1x, var2x, var3) -> this.reloadingSections.add(var1x, var2x, var3));
         } class="kw">finally {
            var1.lock.unlockRead(var4);
         }
      } class="kw">finally {
         this.lock.unlockWrite(var2);
      }
   }

   class="kw">private class="kw">static boolean shouldBeVisible(int var0, int var1, int var2, int var3, int var4) {
      int var5 = Math.abs(var3 - var1);
      int var6 = Math.abs(var4 - var2);
      int var7 = var5 * var5 + var6 * var6;
      class="kw">return var7 <= var0;
   }

   class="kw">private boolean tryUnloadColumn(Entry<ChunkTracker.TrackedColumn> var1, int var2, int var3, int var4, int var5, PlayerRef var6) {
      long var7 = var1.getLongKey();
      ChunkTracker.TrackedColumn var9 = (ChunkTracker.TrackedColumn)var1.getValue();
      int var10 = ChunkUtil.xOfChunkIndex(var7);
      int var11 = ChunkUtil.zOfChunkIndex(var7);
      if (!var9.pendingSections.isEmpty()) {
         IntIterator var12 = var9.pendingSections.iterator();

         while (var12.hasNext()) {
            int var13 = var12.nextInt();
            if (!this.spiralIterator.containsOffset(var10 - var3, var13 - var4, var11 - var5)) {
               var12.remove();
            }
         }
      }

      if (!var9.loadingSections.isEmpty()) {
         IntIterator var21 = var9.loadingSections.iterator();

         while (var21.hasNext()) {
            int var24 = var21.nextInt();
            if (!this.spiralIterator.containsOffset(var10 - var3, var24 - var4, var11 - var5)) {
               var21.remove();
               this.loadingSections--;
            }
         }
      }

      if (!var9.loadedSections.isEmpty()) {
         IntIterator var22 = var9.loadedSections.iterator();

         while (var22.hasNext()) {
            int var25 = var22.nextInt();
            if (this.tryUnloadSection(var10, var25, var11, var3, var4, var5, var6)) {
               var22.remove();
            }
         }
      }

      if (shouldBeVisible(var2, var10, var11, var3, var5)) {
         class="kw">return false;
      }

      if (!var9.pendingSections.isEmpty() || !var9.loadingSections.isEmpty() || !var9.loadedSections.isEmpty()) {
         class="kw">return false;
      }

      if (var9.state != ChunkTracker.ColumnState.READY) {
         class="kw">return true;
      }

      Ref var23 = var6.getReference();
      if (var23 != null && var23.isValid()) {
         Store var26 = var23.getStore();
         World var14 = var26.getExternalData().getWorld();
         PacketHandler var15 = var6.getPacketHandler();
         ChunkStore var16 = var14.getChunkStore();
         Ref var17 = var16.getChunkReference(var7);
         if (var17 != null) {
            Store var18 = var16.getStore();
            ObjectArrayList var19 = new ObjectArrayList();
            var18.fetch(Collections.singletonList(var17), ChunkStore.UNLOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE, var6, var19);

            for (int var20 = 0; var20 < var19.size(); var20++) {
               var15.write((ToClientPacket)var19.get(var20));
            }
         }

         this.unloadColumnScratch.add(var10);
         this.unloadColumnScratch.add(var11);
         class="kw">return true;
      } else {
         class="kw">return true;
      }
   }

   class="kw">private boolean tryUnloadSection(int var1, int var2, int var3, int var4, int var5, int var6, @Nonnull PlayerRef var7) {
      if (this.spiralIterator.containsOffset(var1 - var4, var2 - var5, var3 - var6)) {
         class="kw">return false;
      }

      Ref var8 = var7.getReference();
      if (var8 != null && var8.isValid()) {
         Store var9 = var8.getStore();
         World var10 = var9.getExternalData().getWorld();
         PacketHandler var11 = var7.getPacketHandler();
         ChunkStore var12 = var10.getChunkStore();
         Ref var13 = var12.getChunkSectionReference(var1, var2, var3);
         if (var13 != null) {
            Store var14 = var12.getStore();
            ObjectArrayList var15 = new ObjectArrayList();
            var14.fetch(Collections.singletonList(var13), ChunkStore.UNLOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE, var7, var15);

            for (int var16 = 0; var16 < var15.size(); var16++) {
               var11.write((ToClientPacket)var15.get(var16));
            }
         }

         this.unloadSectionScratch.add(var1);
         this.unloadSectionScratch.add(var2);
         this.unloadSectionScratch.add(var3);
         class="kw">return true;
      } else {
         class="kw">return true;
      }
   }

   class="kw">public void tryLoadColumnAsync(
      @Nonnull ChunkStore var1, @Nonnull PlayerRef var2, long var3, @Nonnull TransformComponent var5, @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      World var7 = var6.getExternalData().getWorld();
      Vector3d var8 = var5.getPosition();
      int var9 = MathUtil.floor(var8.x()) >> 5;
      int var10 = MathUtil.floor(var8.z()) >> 5;
      int var11 = ChunkUtil.xOfChunkIndex(var3);
      int var12 = ChunkUtil.zOfChunkIndex(var3);
      boolean var13 = shouldBeVisible(this.maxHotLoadedRadiusSq, var9, var10, var11, var12);
      Ref var14 = var1.getChunkReference(var3);
      if (var14 != null) {
         WorldChunk var15 = var1.getStore().getComponent(var14, WorldChunk.getComponentType());
         assert var15 != null;
         if (var15.is(ChunkFlag.TICKING)) {
            this._loadChunkAsync(var3, var2, var14, var1).exceptionallyAsync(var3x -> this.columnLoadFailed(var3, var3x));
            class="kw">return;
         }
      }

      int var16 = -2147483632;
      if (var13) {
         var16 |= 4;
      }

      var1.getChunkReferenceAsync(var3, var16).thenComposeAsync(var5x -> {
         if (var5x != null && var5x.isValid()) {
            long var17 = this.lock.readLock();

            try {
               if (!this.trackedColumns.containsKey(var3)) {
                  class="kw">return CompletableFuture.completedFuture(null);
               }
            } class="kw">finally {
               this.lock.unlockRead(var17);
            }

            class="kw">return this._loadChunkAsync(var3, var2, (Ref<ChunkStore>)var5x, var1);
         } else {
            long var6 = this.lock.writeLock();

            try {
               ChunkTracker.TrackedColumn var8 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var3);
               if (var8 != null) {
                  var8.state = ChunkTracker.ColumnState.READY;
                  var8.pendingSections.clear();
               }
            } class="kw">finally {
               this.lock.unlockWrite(var6);
            }

            class="kw">return CompletableFuture.completedFuture(null);
         }
      }, var7).exceptionallyAsync(var3x -> this.columnLoadFailed(var3, var3x));
   }

   @Nullable
   class="kw">private Void columnLoadFailed(long var1, @Nonnull Throwable var3) {
      long var4 = this.lock.writeLock();

      try {
         ChunkTracker.TrackedColumn var6 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var1);
         if (var6 != null) {
            var6.state = ChunkTracker.ColumnState.NONE;
         }
      } class="kw">finally {
         this.lock.unlockWrite(var4);
      }

      ((HytaleLogger.Api)HytaleLogger.getLogger().at(Level.SEVERE).withCause(var3))
         .log("Failed to load chunk! %d, %d", ChunkUtil.xOfChunkIndex(var1), ChunkUtil.zOfChunkIndex(var1));
      class="kw">return null;
   }

   @Nonnull
   class="kw">private CompletableFuture<Void> _loadChunkAsync(long var1, @Nonnull PlayerRef var3, @Nonnull Ref<ChunkStore> var4, @Nonnull ChunkStore var5) {
      List var6 = new ObjectArrayList();
      var5.getStore().fetch(Collections.singletonList(var4), ChunkStore.LOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE, var3, var6);
      ObjectArrayList var7 = new ObjectArrayList();
      var5.getStore().fetch(Collections.singletonList(var4), ChunkStore.LOAD_FUTURE_PACKETS_DATA_QUERY_SYSTEM_TYPE, var3, var7);
      class="kw">return CompletableFuture.allOf((CompletableFuture<?>[])var7.toArray(CompletableFuture[]::new)).thenAcceptAsync(var6x -> {
         Iterator var7 = var7.iterator();

         while (var7.hasNext()) {
            CompletableFuture var8 = (CompletableFuture<ToClientPacket>)var7.next();
            ToClientPacket var9 = var8.join();
            if (var9 != null) {
               var6.add(var9);
            }
         }

         long var14 = this.lock.writeLock();

         try {
            ChunkTracker.TrackedColumn var15 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var1);
            if (var15 != null) {
               for (int var10 = 0; var10 < var6.size(); var10++) {
                  var3.getPacketHandler().write(var6.get(var10));
               }

               var15.state = ChunkTracker.ColumnState.READY;
            }
         } class="kw">finally {
            this.lock.unlockWrite(var14);
         }
      });
   }

   class="kw">private class="kw">static boolean reloadSection(
      int var0, int var1, int var2, int var3, int var4, int var5, @Nonnull ChunkTracker var6, @Nonnull ChunkTracker.ReloadContext var7
   ) {
      if (var7.budget <= 0) {
         class="kw">return false;
      }

      long var8 = ChunkUtil.indexChunk(var0, var2);
      ChunkTracker.TrackedColumn var10 = (ChunkTracker.TrackedColumn)var6.trackedColumns.get(var8);
      if (var10 == null) {
         class="kw">return true;
      }

      if (var10.loadingSections.contains(var1) || var10.pendingSections.contains(var1)) {
         class="kw">return true;
      }

      if (!var10.loadedSections.contains(var1)) {
         class="kw">return true;
      }

      var10.loadedSections.remove(var1);
      var10.loadingSections.add(var1);
      var6.loadingSections++;
      var7.budget--;
      var6.accumulatorSeconds = var6.accumulatorSeconds - var6.inverseMaxSectionsPerSecond;
      var6.tryLoadSectionAsync(var7.chunkStore, var7.playerRef, var0, var1, var2, var7.transform, var7.commandBuffer);
      class="kw">return true;
   }

   class="kw">public void tryLoadSectionAsync(
      @Nonnull ChunkStore var1,
      @Nonnull PlayerRef var2,
      int var3,
      int var4,
      int var5,
      @Nonnull TransformComponent var6,
      @Nonnull ComponentAccessor<EntityStore> var7
   ) {
      World var8 = var7.getExternalData().getWorld();
      long var9 = ChunkUtil.indexChunk(var3, var5);
      Vector3d var11 = var6.getPosition();
      int var12 = MathUtil.floor(var11.x()) >> 5;
      int var13 = MathUtil.floor(var11.y()) >> 5;
      int var14 = MathUtil.floor(var11.z()) >> 5;
      int var15 = var3 - var12;
      int var16 = var4 - var13;
      int var17 = var5 - var14;
      boolean var18 = var15 * var15 + var16 * var16 + var17 * var17 <= this.maxHotLoadedRadiusSq;
      Ref var19 = var1.getChunkSectionReference(var3, var4, var5);
      if (var19 != null && var19.isValid()) {
         Store var20 = var1.getStore();
         if (var20.<NonTicking<ChunkStore>>getComponent(var19, ChunkStore.REGISTRY.getNonTickingComponentType()) == null) {
            this._loadSectionAsync(var3, var4, var5, var2, var19, var1).exceptionallyAsync(var6x -> this.sectionLoadFailed(var9, var3, var4, var5, var6x));
            class="kw">return;
         }
      }

      int var21 = -2147483632;
      if (var18) {
         var21 |= 4;
      }

      var1.getChunkSectionReferenceAsync(var3, var4, var5, var21).thenComposeAsync(var8x -> {
         if (var8x != null && var8x.isValid()) {
            long var20 = this.lock.readLock();

            try {
               ChunkTracker.TrackedColumn var21 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var9);
               if (var21 == null || !var21.loadingSections.contains(var4)) {
                  class="kw">return CompletableFuture.completedFuture(null);
               }
            } class="kw">finally {
               this.lock.unlockRead(var20);
            }

            class="kw">return this._loadSectionAsync(var3, var4, var5, var2, (Ref<ChunkStore>)var8x, var1);
         } else {
            long var9 = this.lock.writeLock();

            try {
               ChunkTracker.TrackedColumn var11 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var9);
               if (var11 != null && var11.loadingSections.remove(var4)) {
                  this.loadingSections--;
                  var11.loadedSections.add(var4);
                  ((IntArrayList)this.pendingAbsentByColumn.computeIfAbsent(var9, var0 -> new IntArrayList())).add(var4);
                  this.hasPendingAbsent = true;
               }
            } class="kw">finally {
               this.lock.unlockWrite(var9);
            }

            class="kw">return CompletableFuture.completedFuture(null);
         }
      }, var8).exceptionallyAsync(var6x -> this.sectionLoadFailed(var9, var3, var4, var5, var6x));
   }

   @Nullable
   class="kw">private Void sectionLoadFailed(long var1, int var3, int var4, int var5, @Nonnull Throwable var6) {
      long var7 = this.lock.writeLock();

      try {
         ChunkTracker.TrackedColumn var9 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var1);
         if (var9 != null && var9.loadingSections.remove(var4)) {
            this.loadingSections--;
         }
      } class="kw">finally {
         this.lock.unlockWrite(var7);
      }

      ((HytaleLogger.Api)HytaleLogger.getLogger().at(Level.SEVERE).withCause(var6)).log("Failed to load chunk section! %d, %d, %d", var3, var4, var5);
      class="kw">return null;
   }

   @Nonnull
   class="kw">private CompletableFuture<Void> _loadSectionAsync(
      int var1, int var2, int var3, @Nonnull PlayerRef var4, @Nonnull Ref<ChunkStore> var5, @Nonnull ChunkStore var6
   ) {
      long var7 = ChunkUtil.indexChunk(var1, var3);
      List var9 = new ObjectArrayList();
      var6.getStore().fetch(Collections.singletonList(var5), ChunkStore.LOAD_PACKETS_DATA_QUERY_SYSTEM_TYPE, var4, var9);
      ObjectArrayList var10 = new ObjectArrayList();
      var6.getStore().fetch(Collections.singletonList(var5), ChunkStore.LOAD_FUTURE_PACKETS_DATA_QUERY_SYSTEM_TYPE, var4, var10);
      class="kw">return CompletableFuture.allOf((CompletableFuture<?>[])var10.toArray(CompletableFuture[]::new)).thenAcceptAsync(var7x -> {
         Iterator var8 = var10.iterator();

         while (var8.hasNext()) {
            CompletableFuture var9 = (CompletableFuture<ToClientPacket>)var8.next();
            ToClientPacket var10 = var9.join();
            if (var10 != null) {
               var9.add(var10);
            }
         }

         long var15 = this.lock.writeLock();

         try {
            ChunkTracker.TrackedColumn var16 = (ChunkTracker.TrackedColumn)this.trackedColumns.get(var7);
            if (var16 != null && var16.loadingSections.remove(var2)) {
               this.loadingSections--;

               for (int var11 = 0; var11 < var9.size(); var11++) {
                  var4.getPacketHandler().write(var9.get(var11));
               }

               var16.loadedSections.add(var2);
            }
         } class="kw">finally {
            this.lock.unlockWrite(var15);
         }
      });
   }

   @Nonnull
   @Override
   class="kw">public Component<EntityStore> clone() {
      class="kw">return new ChunkTracker(this);
   }

   class="kw">public float calculateSectionPriority(int var1, int var2, int var3) {
      if (this.transformComponent == null) {
         class="kw">return Float.MAX_VALUE;
      }

      int var4 = ChunkUtil.minBlock(var1) + 16;
      int var5 = ChunkUtil.minBlock(var2) + 16;
      int var6 = ChunkUtil.minBlock(var3) + 16;
      Vector3d var7 = this.transformComponent.getPosition();
      double var8 = var4 - var7.x;
      double var10 = var5 - var7.y;
      double var12 = var6 - var7.z;
      class="kw">return (float)(var8 * var8 + var10 * var10 + var12 * var12);
   }

   class="kw">public float calculateColumnPriority(int var1, int var2) {
      if (this.transformComponent == null) {
         class="kw">return Float.MAX_VALUE;
      }

      int var3 = ChunkUtil.minBlock(var1) + 16;
      int var4 = ChunkUtil.minBlock(var2) + 16;
      Vector3d var5 = this.transformComponent.getPosition();
      double var6 = var3 - var5.x;
      double var8 = var4 - var5.z;
      class="kw">return (float)(var6 * var6 + var8 * var8);
   }

   class="kw">public enum ChunkVisibility {
      NONE,
      HOT,
      COLD;

      ChunkVisibility() {
      }
   }

   class="kw">private enum ColumnState {
      NONE,
      LOADING,
      READY;

      ColumnState() {
      }
   }

   class="kw">private class="kw">static class="kw">final class ReloadContext {
      class="kw">private int budget;
      @Nullable
      class="kw">private ChunkStore chunkStore;
      @Nullable
      class="kw">private PlayerRef playerRef;
      @Nullable
      class="kw">private TransformComponent transform;
      @Nullable
      class="kw">private CommandBuffer<EntityStore> commandBuffer;

      class="kw">private ReloadContext() {
      }

      class="kw">private void clear() {
         this.chunkStore = null;
         this.playerRef = null;
         this.transform = null;
         this.commandBuffer = null;
      }
   }

   class="kw">private class="kw">static class TrackedColumn {
      @Nonnull
      class="kw">private ChunkTracker.ColumnState state = ChunkTracker.ColumnState.NONE;
      @Nonnull
      class="kw">private class="kw">final IntSet pendingSections = new IntOpenHashSet();
      @Nonnull
      class="kw">private class="kw">final IntSet loadingSections = new IntOpenHashSet();
      @Nonnull
      class="kw">private class="kw">final IntSet loadedSections = new IntOpenHashSet();

      class="kw">private TrackedColumn() {
      }
   }
}