LineOfSightEntityBuffer class

Пакет: com.hypixel.hytale.server.npc.role.support

Файл: com/hypixel/hytale/server/npc/role/support/PositionCache.java

Поля (3)

МодификаторыТипИмя
public final Vector3d dir
public final Vector2d minMax
public final Vector3d pos

Исходный код

Показать/скрыть
class="kw">package com.hypixel.hytale.server.npc.role.support;

class="kw">import com.hypixel.hytale.assetstore.map.BlockTypeAssetMap;
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.Ref;
class="kw">import com.hypixel.hytale.function.consumer.DoubleQuadObjectConsumer;
class="kw">import com.hypixel.hytale.function.consumer.QuadConsumer;
class="kw">import com.hypixel.hytale.function.consumer.TriConsumer;
class="kw">import com.hypixel.hytale.function.predicate.QuadPredicate;
class="kw">import com.hypixel.hytale.function.predicate.TriPredicate;
class="kw">import com.hypixel.hytale.math.iterator.BlockIterator;
class="kw">import com.hypixel.hytale.math.random.RandomExtra;
class="kw">import com.hypixel.hytale.math.shape.Box;
class="kw">import com.hypixel.hytale.math.util.ChunkUtil;
class="kw">import com.hypixel.hytale.math.util.MathUtil;
class="kw">import com.hypixel.hytale.protocol.Opacity;
class="kw">import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType;
class="kw">import com.hypixel.hytale.server.core.entity.entities.Player;
class="kw">import com.hypixel.hytale.server.core.modules.blockset.BlockSetModule;
class="kw">import com.hypixel.hytale.server.core.modules.collision.CollisionMath;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.BoundingBox;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.ModelComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
class="kw">import com.hypixel.hytale.server.core.modules.entity.item.ItemComponent;
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.EntityStore;
class="kw">import com.hypixel.hytale.server.npc.NPCPlugin;
class="kw">import com.hypixel.hytale.server.npc.entities.NPCEntity;
class="kw">import com.hypixel.hytale.server.npc.instructions.ExecutionSupport;
class="kw">import com.hypixel.hytale.server.npc.util.EntityDetectionUtil;
class="kw">import com.hypixel.hytale.server.npc.util.NPCPhysicsMath;
class="kw">import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
class="kw">import it.unimi.dsi.fastutil.ints.IntSet;
class="kw">import it.unimi.dsi.fastutil.objects.ObjectArrayList;
class="kw">import it.unimi.dsi.fastutil.objects.Reference2ByteMap;
class="kw">import it.unimi.dsi.fastutil.objects.Reference2ByteOpenHashMap;
class="kw">import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
class="kw">import java.util.List;
class="kw">import java.util.Objects;
class="kw">import java.util.Set;
class="kw">import java.util.function.BiPredicate;
class="kw">import java.util.function.Consumer;
class="kw">import java.util.function.Predicate;
class="kw">import javax.annotation.Nonnull;
class="kw">import javax.annotation.Nullable;
class="kw">import org.joml.Vector2d;
class="kw">import org.joml.Vector3d;

class="kw">public class PositionCache class="kw">implements Component<EntityStore> {
   class="kw">public class="kw">static class="kw">final BiPredicate<Ref<EntityStore>, ComponentAccessor<EntityStore>> IS_VALID_PLAYER = (var0, var1) -> {
      Player var2 = var1.getComponent(var0, Player.getComponentType());
      class="kw">return var2 != null && !var2.isWaitingForClientReady() ? EntityDetectionUtil.isDetectableByNPCs(var0, var1, var2) : false;
   };
   class="kw">public class="kw">static class="kw">final BiPredicate<Ref<EntityStore>, ComponentAccessor<EntityStore>> IS_VALID_NPC = (var0, var1) -> var1.getArchetype(var0)
      .contains(NPCEntity.getComponentType());
   class="kw">public class="kw">static class="kw">final double MIN_LOS_BLOCKING_DISTANCE_SQUARED = 1.0E-6;
   class="kw">public class="kw">static class="kw">final String FUNCTION_CAN_BE_ONLY_CALLED_WHILE_CONFIGURING_POSITION_CACHE = "function can be only called while configuring PositionCache";
   class="kw">private class="kw">static class="kw">final float LOS_CACHE_TTL_MIN_SECONDS = 0.09F;
   class="kw">private class="kw">static class="kw">final float LOS_CACHE_TTL_MAX_SECONDS = 0.11F;
   class="kw">public class="kw">static class="kw">final float POSITION_CACHE_TTL_SECONDS = 0.2F;
   class="kw">private class="kw">static class="kw">final ComponentType<EntityStore, TransformComponent> TRANSFORM_COMPONENT_TYPE = TransformComponent.getComponentType();
   class="kw">private class="kw">static class="kw">final ComponentType<EntityStore, ItemComponent> ITEM_COMPONENT_TYPE = ItemComponent.getComponentType();
   class="kw">private class="kw">static class="kw">final ComponentType<EntityStore, ModelComponent> MODEL_COMPONENT_TYPE = ModelComponent.getComponentType();
   class="kw">protected class="kw">static class="kw">final ComponentType<EntityStore, BoundingBox> BOUNDING_BOX_COMPONENT_TYPE = BoundingBox.getComponentType();
   class="kw">private double maxDroppedItemDistance;
   class="kw">private double maxSpawnMarkerDistance;
   class="kw">private int maxSpawnBeaconDistance;
   @Nullable
   class="kw">private class="kw">final RoleStats roleStats;
   class="kw">private int roleIndex = -1;
   class="kw">private int opaqueBlockSet;
   class="kw">protected EntityList players;
   class="kw">protected EntityList npcs;
   class="kw">protected class="kw">final List<Consumer<ExecutionSupport>> externalRegistrations = new ObjectArrayList();
   class="kw">private class="kw">final List<Ref<EntityStore>> droppedItems = new ReferenceArrayList();
   class="kw">private class="kw">final List<Ref<EntityStore>> spawnMarkers = new ReferenceArrayList();
   class="kw">private class="kw">final List<Ref<EntityStore>> spawnBeacons = new ReferenceArrayList();
   class="kw">private class="kw">final Reference2ByteMap<Ref<EntityStore>> lineOfSightCache = new Reference2ByteOpenHashMap();
   class="kw">private class="kw">final Reference2ByteMap<Ref<EntityStore>> inverseLineOfSightCache = new Reference2ByteOpenHashMap();
   class="kw">private class="kw">final Reference2ByteMap<Ref<EntityStore>> friendlyFireCache = new Reference2ByteOpenHashMap();
   class="kw">protected class="kw">final PositionCache.LineOfSightBuffer lineOfSightComputeBuffer = new PositionCache.LineOfSightBuffer();
   class="kw">protected class="kw">final PositionCache.LineOfSightEntityBuffer lineOfSightEntityComputeBuffer = new PositionCache.LineOfSightEntityBuffer();
   class="kw">private float cacheTTL = 0.09F;
   class="kw">private float positionCacheNextUpdate;
   class="kw">private boolean isBenchmarking;
   class="kw">private boolean isConfiguring;
   class="kw">private boolean couldBreathe = true;

   @Nonnull
   class="kw">public class="kw">static ComponentType<EntityStore, PositionCache> getComponentType() {
      class="kw">return NPCPlugin.get().getPositionCacheComponentType();
   }

   @Nonnull
   class="kw">public class="kw">static PositionCache get(@Nonnull Ref<EntityStore> var0, @Nonnull ComponentAccessor<EntityStore> var1) {
      PositionCache var2 = var1.getComponent(var0, getComponentType());
      assert var2 != null : "Missing PositionCache on entity " + var0;
      class="kw">return var2;
   }

   class="kw">public PositionCache(@Nullable RoleStats var1) {
      this.roleStats = var1;
      this.players = new EntityList(null, IS_VALID_PLAYER);
      this.npcs = new EntityList(null, IS_VALID_NPC);
   }

   class="kw">public PositionCache() {
      this(null);
   }

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

   class="kw">public int getRoleIndex() {
      class="kw">return this.roleIndex;
   }

   @Nullable
   class="kw">public RoleStats getRoleStats() {
      class="kw">return this.roleStats;
   }

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

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

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

   class="kw">public EntityList getPlayers() {
      class="kw">return this.players;
   }

   class="kw">public EntityList getNpcs() {
      class="kw">return this.npcs;
   }

   class="kw">public boolean tickPositionCacheNextUpdate(float var1) {
      class="kw">return (this.positionCacheNextUpdate -= var1) <= 0.0F;
   }

   class="kw">public void resetPositionCacheNextUpdate() {
      this.positionCacheNextUpdate = 0.2F;
   }

   class="kw">public double getMaxDroppedItemDistance() {
      class="kw">return this.maxDroppedItemDistance;
   }

   class="kw">public double getMaxSpawnMarkerDistance() {
      class="kw">return this.maxSpawnMarkerDistance;
   }

   class="kw">public int getMaxSpawnBeaconDistance() {
      class="kw">return this.maxSpawnBeaconDistance;
   }

   class="kw">public void addExternalPositionCacheRegistration(Consumer<ExecutionSupport> var1) {
      this.externalRegistrations.add(var1);
   }

   @Nonnull
   class="kw">public List<Consumer<ExecutionSupport>> getExternalRegistrations() {
      class="kw">return this.externalRegistrations;
   }

   class="kw">public void reset(boolean var1) {
      this.players.reset();
      this.npcs.reset();
      this.maxDroppedItemDistance = 0.0;
      this.droppedItems.clear();
      this.spawnMarkers.clear();
      this.spawnBeacons.clear();
      this.positionCacheNextUpdate = RandomExtra.randomRange(0.0F, 0.2F);
      this.clearLineOfSightCache();
      this.isConfiguring = var1;
   }

   class="kw">public void finalizeConfiguration() {
      this.isConfiguring = false;
      this.npcs.finalizeConfiguration();
      this.players.finalizeConfiguration();
      if (this.roleStats != null) {
         this.roleStats.trackBuckets(false, this.npcs.getBucketRanges());
         this.roleStats.trackBuckets(true, this.players.getBucketRanges());
      }
   }

   class="kw">public void clear(double var1) {
      this.clearLineOfSightCache(var1);
      if (this.isBenchmarking && this.roleIndex >= 0) {
         NPCPlugin.get().collectSensorSupportTickDone(this.roleIndex);
      }

      this.isBenchmarking = false;
   }

   class="kw">public boolean couldBreatheCached() {
      class="kw">return this.couldBreathe;
   }

   class="kw">public <T, U, V> void forEachPlayer(
      @Nonnull DoubleQuadObjectConsumer<Ref<EntityStore>, T, U, V> var1, T var2, U var3, V var4, double var5, ComponentAccessor<EntityStore> var7
   ) {
      this.players.forEachEntity(var1, var2, var3, var4, var5, var7);
   }

   @Nullable
   class="kw">public Ref<EntityStore> getClosestPlayerInRange(double var1, double var3, @Nonnull ComponentAccessor<EntityStore> var5) {
      class="kw">return this.getClosestPlayerInRange(var1, var3, var0 -> true, var5);
   }

   @Nullable
   class="kw">public Ref<EntityStore> getClosestPlayerInRange(
      double var1, double var3, @Nonnull Predicate<Ref<EntityStore>> var5, @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      class="kw">return this.players.getClosestEntityInRange(var1, var3, var5, var6);
   }

   @Nullable
   class="kw">public Ref<EntityStore> getClosestNPCInRange(
      double var1, double var3, @Nonnull Predicate<Ref<EntityStore>> var5, @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      class="kw">return this.npcs.getClosestEntityInRange(var1, var3, var5, var6);
   }

   class="kw">public <S, T> void processNPCsInRange(
      @Nonnull Ref<EntityStore> var1,
      double var2,
      double var4,
      boolean var6,
      Ref<EntityStore> var7,
      @Nonnull ExecutionSupport var8,
      @Nonnull QuadPredicate<S, Ref<EntityStore>, ExecutionSupport, T> var9,
      S var10,
      T var11,
      @Nonnull ComponentAccessor<EntityStore> var12
   ) {
      this.processEntitiesInRange(var1, this.npcs, var2, var4, var6, var7, var8, var9, var10, var11, var12);
   }

   class="kw">public <S, T> void processPlayersInRange(
      @Nonnull Ref<EntityStore> var1,
      double var2,
      double var4,
      boolean var6,
      Ref<EntityStore> var7,
      @Nonnull ExecutionSupport var8,
      @Nonnull QuadPredicate<S, Ref<EntityStore>, ExecutionSupport, T> var9,
      S var10,
      T var11,
      @Nonnull ComponentAccessor<EntityStore> var12
   ) {
      this.processEntitiesInRange(var1, this.players, var2, var4, var6, var7, var8, var9, var10, var11, var12);
   }

   class="kw">public <S, T> void processEntitiesInRange(
      @Nonnull Ref<EntityStore> var1,
      @Nonnull EntityList var2,
      double var3,
      double var5,
      boolean var7,
      Ref<EntityStore> var8,
      @Nonnull ExecutionSupport var9,
      @Nonnull QuadPredicate<S, Ref<EntityStore>, ExecutionSupport, T> var10,
      S var11,
      T var12,
      @Nonnull ComponentAccessor<EntityStore> var13
   ) {
      if (var7) {
         MotionContextSupport var14 = var9.getMotionContextSupport();
         var2.getClosestEntityInRangeProjected(var1, var8, var14.getActiveMotionController(), var3, var5, var10, var9, var11, var12, var13);
      } else {
         var2.getClosestEntityInRange(var8, var3, var5, var10, var9, var11, var12, var13);
      }
   }

   @Nullable
   class="kw">public <S> Ref<EntityStore> getClosestDroppedItemInRange(
      @Nonnull Ref<EntityStore> var1,
      double var2,
      double var4,
      @Nonnull TriPredicate<S, Ref<EntityStore>, ComponentAccessor<EntityStore>> var6,
      S var7,
      @Nonnull ComponentAccessor<EntityStore> var8
   ) {
      int var9 = this.droppedItems.size();
      if (var9 == 0) {
         class="kw">return null;
      }

      TransformComponent var10 = var8.getComponent(var1, TRANSFORM_COMPONENT_TYPE);
      assert var10 != null;
      Vector3d var11 = var10.getPosition();
      var2 *= var2;
      var4 *= var4;

      for (int var12 = 0; var12 < var9; var12++) {
         Ref var13 = this.droppedItems.get(var12);
         if (var13.isValid()) {
            ItemComponent var14 = var8.getComponent(var13, ITEM_COMPONENT_TYPE);
            if (var14 != null) {
               TransformComponent var15 = var8.getComponent(var13, TRANSFORM_COMPONENT_TYPE);
               assert var15 != null;
               double var16 = var15.getPosition().distanceSquared(var11);
               if (!(var16 < var2)) {
                  if (var16 >= var4) {
                     break;
                  }

                  if (var6.test(var7, var13, var8)) {
                     class="kw">return var13;
                  }
               }
            }
         }
      }

      class="kw">return null;
   }

   class="kw">public <S> boolean isEntityCountInRange(
      double var1,
      double var3,
      int var5,
      int var6,
      boolean var7,
      int var8,
      @Nonnull QuadPredicate<S, Ref<EntityStore>, Integer, ComponentAccessor<EntityStore>> var9,
      S var10,
      ComponentAccessor<EntityStore> var11
   ) {
      int var12 = 0;
      if (var7) {
         var12 = this.players.countEntitiesInRange(var1, var3, var6 + 1, var9, var10, var8, var11);
         if (var12 > var6) {
            class="kw">return false;
         }
      }

      var12 += this.npcs.countEntitiesInRange(var1, var3, var6 - var12 + 1, var9, var10, var8, var11);
      class="kw">return var12 >= var5 && var12 <= var6;
   }

   class="kw">public <S, T> int countEntitiesInRange(
      double var1,
      double var3,
      boolean var5,
      @Nonnull QuadPredicate<S, Ref<EntityStore>, T, ComponentAccessor<EntityStore>> var6,
      S var7,
      T var8,
      ComponentAccessor<EntityStore> var9
   ) {
      int var10 = 0;
      if (var5) {
         var10 = this.players.countEntitiesInRange(var1, var3, Integer.MAX_VALUE, var6, var7, var8, var9);
      }

      class="kw">return var10 + this.npcs.countEntitiesInRange(var1, var3, Integer.MAX_VALUE, var6, var7, var8, var9);
   }

   class="kw">public void requirePlayerDistanceSorted(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      this.players.requireDistanceSorted(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(true, RoleStats.RangeType.SORTED, var3);
      }
   }

   class="kw">public void requirePlayerDistanceUnsorted(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      this.players.requireDistanceUnsorted(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(true, RoleStats.RangeType.UNSORTED, var3);
      }
   }

   class="kw">public void requirePlayerDistanceAvoidance(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      this.players.requireDistanceAvoidance(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(true, RoleStats.RangeType.AVOIDANCE, var3);
      }
   }

   class="kw">public void requireEntityDistanceSorted(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      this.npcs.requireDistanceSorted(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(false, RoleStats.RangeType.SORTED, var3);
      }
   }

   class="kw">public void requireEntityDistanceUnsorted(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      this.npcs.requireDistanceUnsorted(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(false, RoleStats.RangeType.UNSORTED, var3);
      }
   }

   class="kw">public void requireEntityDistanceAvoidance(double var1) {
      int var3 = MathUtil.ceil(var1);
      if (!this.isConfiguring) {
         throw new IllegalStateException("function can be only called while configuring PositionCache");
      }

      var3 = this.npcs.requireDistanceAvoidance(var3);
      if (this.roleStats != null) {
         this.roleStats.trackRange(false, RoleStats.RangeType.AVOIDANCE, var3);
      }
   }

   class="kw">public void requireDroppedItemDistance(double var1) {
      if (this.maxDroppedItemDistance < var1) {
         this.maxDroppedItemDistance = var1;
      }
   }

   class="kw">public void requireSpawnMarkerDistance(double var1) {
      if (this.maxSpawnMarkerDistance < var1) {
         this.maxSpawnMarkerDistance = var1;
      }
   }

   class="kw">public void requireSpawnBeaconDistance(int var1) {
      if (this.maxSpawnBeaconDistance < var1) {
         this.maxSpawnBeaconDistance = var1;
      }
   }

   class="kw">public <T, U, V, R> void forEachNPCUnordered(
      double var1,
      @Nonnull QuadPredicate<Ref<EntityStore>, T, U, ComponentAccessor<EntityStore>> var3,
      @Nonnull QuadConsumer<Ref<EntityStore>, T, V, R> var4,
      T var5,
      U var6,
      V var7,
      R var8,
      ComponentAccessor<EntityStore> var9
   ) {
      this.npcs.forEachEntityUnordered(var1, var3, var4, var5, var6, var7, var8, var9);
   }

   class="kw">public <T> void forEachEntityInAvoidanceRange(
      @Nonnull Set<Ref<EntityStore>> var1, @Nonnull TriConsumer<Ref<EntityStore>, T, CommandBuffer<EntityStore>> var2, T var3, CommandBuffer<EntityStore> var4
   ) {
      this.npcs.forEachEntityAvoidance(var1, var2, var3, var4);
      this.players.forEachEntityAvoidance(var1, var2, var3, var4);
   }

   class="kw">public <T, U> void forEachEntityInAvoidanceRange(
      @Nonnull Set<Ref<EntityStore>> var1,
      @Nonnull QuadConsumer<Ref<EntityStore>, T, U, CommandBuffer<EntityStore>> var2,
      T var3,
      U var4,
      CommandBuffer<EntityStore> var5
   ) {
      this.npcs.forEachEntityAvoidance(var1, var2, var3, var4, var5);
      this.players.forEachEntityAvoidance(var1, var2, var3, var4, var5);
   }

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

   class="kw">private class="kw">static <T> boolean testLineOfSightRays(
      @Nonnull Ref<EntityStore> var0,
      @Nonnull Ref<EntityStore> var1,
      @Nonnull PositionCache.RayPredicate<T> var2,
      @Nonnull T var3,
      @Nonnull ComponentAccessor<EntityStore> var4
   ) {
      TransformComponent var5 = var4.getComponent(var0, TRANSFORM_COMPONENT_TYPE);
      assert var5 != null;
      Vector3d var6 = var5.getPosition();
      ModelComponent var7 = var4.getComponent(var0, MODEL_COMPONENT_TYPE);
      float var8 = var7 != null ? var7.getModel().getEyeHeight() : 0.0F;
      double var9 = var6.x();
      double var11 = var6.y() + var8;
      double var13 = var6.z();
      TransformComponent var15 = var4.getComponent(var1, TRANSFORM_COMPONENT_TYPE);
      assert var15 != null;
      Vector3d var16 = var15.getPosition();
      double var17 = var16.x();
      double var19 = var16.y();
      double var21 = var16.z();
      ModelComponent var23 = var4.getComponent(var1, MODEL_COMPONENT_TYPE);
      if (var23 != null) {
         class="kw">return var2.test(var9, var11, var13, var17, var19 + var23.getModel().getEyeHeight(), var21, var3, var4);
      }

      double var24 = 0.0;
      double var26 = 0.0;
      double var28 = 0.0;
      BoundingBox var30 = var4.getComponent(var1, BOUNDING_BOX_COMPONENT_TYPE);
      if (var30 != null) {
         Box var31 = var30.getBoundingBox();
         var24 = (var31.getMax().x() + var31.getMin().x()) / 2.0;
         var26 = (var31.getMax().y() + var31.getMin().y()) / 2.0;
         var28 = (var31.getMax().z() + var31.getMin().z()) / 2.0;
      }

      class="kw">return var2.test(var9, var11, var13, var17 + var24, var19 + var26, var21 + var28, var3, var4);
   }

   class="kw">private boolean hasLineOfSightInternal(@Nonnull Ref<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      if (var1.equals(var2)) {
         class="kw">return false;
      }

      TransformComponent var4 = var3.getComponent(var1, TRANSFORM_COMPONENT_TYPE);
      assert var4 != null;
      TransformComponent var5 = var3.getComponent(var2, TRANSFORM_COMPONENT_TYPE);
      assert var5 != null;
      if (var4.getPosition().distanceSquared(var5.getPosition()) <= 1.0E-12) {
         class="kw">return true;
      }

      World var6 = var3.getExternalData().getWorld();
      Objects.requireNonNull(var6, "World can't be null in isLOS");
      Int2ObjectMap var7 = BlockSetModule.getInstance().getBlockSets();
      IntSet var8 = this.opaqueBlockSet >= 0 && var7 != null ? (IntSet)var7.get(this.opaqueBlockSet) : null;

      try {
         this.lineOfSightComputeBuffer.result = true;
         this.lineOfSightComputeBuffer.assetMap = BlockType.getAssetMap();
         this.lineOfSightComputeBuffer.opaqueSet = var8;
         this.lineOfSightComputeBuffer.world = var6;
         class="kw">return testLineOfSightRays(
            var1,
            var2,
            (var0, var2x, var4x, var6x, var8x, var10, var12x, var13) -> {
               var12x.chunk = var12x.world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(var0, var4x));
               if (var12x.chunk == null) {
                  class="kw">return false;
               }

               BlockIterator.iterateFromTo(
                  var0,
                  var2x,
                  var4x,
                  var6x,
                  var8x,
                  var10,
                  (var0x, var1x, var2xx, var3x, var5x, var7x, var9, var11, var13x, var15) -> {
                     if (!ChunkUtil.isInsideChunk(var15.chunk.getX(), var15.chunk.getZ(), var0x, var2xx)) {
                        var15.chunk = var15.world.getChunkIfInMemory(ChunkUtil.indexChunkFromBlock(var0x, var2xx));
                        if (var15.chunk == null) {
                           var15.result = false;
                           class="kw">return false;
                        }
                     }

                     int var16 = var15.chunk.getBlock(var0x, var1x, var2xx);
                     if (var16 == 0) {
                        class="kw">return true;
                     }

                     BlockType var17 = var15.assetMap.getAsset(var16);
                     if (var17 != BlockType.UNKNOWN
                        && var17.getOpacity() != null
                        && var17.getOpacity() == Opacity.Transparent
                        && (var15.opaqueSet == null || !var15.opaqueSet.contains(var16))) {
                        class="kw">return true;
                     }

                     var15.result = false;
                     class="kw">return false;
                  },
                  var12x
               );
               class="kw">return var12x.result;
            },
            this.lineOfSightComputeBuffer,
            var3
         );
      } class="kw">finally {
         this.lineOfSightComputeBuffer.clearRefs();
      }
   }

   class="kw">public boolean hasLineOfSight(@Nonnull Ref<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      boolean var4 = this.lineOfSightCache.containsKey(var2);
      if (var4) {
         if (this.isBenchmarking && this.roleIndex >= 0) {
            NPCPlugin.get().collectSensorSupportLosTest(this.roleIndex, true, 0L);
         }

         class="kw">return this.lineOfSightCache.getByte(var2) != 0;
      } else {
         boolean var5;
         if (this.isBenchmarking) {
            long var6 = System.nanoTime();
            var5 = this.hasLineOfSightInternal(var1, var2, var3);
            if (this.roleIndex >= 0) {
               NPCPlugin.get().collectSensorSupportLosTest(this.roleIndex, false, System.nanoTime() - var6);
            }
         } else {
            var5 = this.hasLineOfSightInternal(var1, var2, var3);
         }

         this.lineOfSightCache.put(var2, (byte)(var5 ? 1 : 0));
         class="kw">return var5;
      }
   }

   class="kw">public boolean hasInverseLineOfSight(@Nonnull Ref<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      boolean var4 = this.inverseLineOfSightCache.containsKey(var2);
      if (this.isBenchmarking && this.roleIndex >= 0) {
         NPCPlugin.get().collectSensorSupportInverseLosTest(this.roleIndex, var4);
      }

      if (var4) {
         class="kw">return this.inverseLineOfSightCache.getByte(var2) != 0;
      }

      boolean var5 = this.hasLineOfSightInternal(var2, var1, var3);
      this.inverseLineOfSightCache.put(var2, (byte)(var5 ? 1 : 0));
      class="kw">return var5;
   }

   class="kw">public boolean isFriendlyBlockingLineOfSight(@Nonnull Ref<EntityStore> var1, @Nonnull Ref<EntityStore> var2, @Nonnull ComponentAccessor<EntityStore> var3) {
      boolean var4 = this.friendlyFireCache.containsKey(var2);
      if (this.isBenchmarking && this.roleIndex >= 0) {
         NPCPlugin.get().collectSensorSupportFriendlyBlockingTest(this.roleIndex, var4);
      }

      if (var4) {
         class="kw">return this.friendlyFireCache.getByte(var2) != 0;
      }

      boolean var5 = testLineOfSightRays(
         var1,
         var2,
         (var1x, var3x, var5x, var7, var9, var11, var13, var14) -> {
            PositionCache.LineOfSightEntityBuffer var15 = var13.lineOfSightEntityComputeBuffer;
            var15.pos.set(var1x, var3x, var5x);
            var15.dir.set(var7 - var1x, var9 - var3x, var11 - var5x);
            double var16 = var15.dir.lengthSquared();
            class="kw">return var16 < 1.0E-6
               ? false
               : var13.players
                     .testAnyEntityDistanceSquared(
                        var16, (var1xx, var2x, var3xx, var4x, var5xx) -> var1xx.testLineOfSightEntity(var1, var2x, var3xx, var4x, var5xx), var13, var15, var14
                     )
                  || var13.npcs
                     .testAnyEntityDistanceSquared(
                        var16, (var1xx, var2x, var3xx, var4x, var5xx) -> var1xx.testLineOfSightEntity(var1, var2x, var3xx, var4x, var5xx), var13, var15, var14
                     );
         },
         this,
         var3
      );
      this.friendlyFireCache.put(var2, (byte)(var5 ? 1 : 0));
      class="kw">return var5;
   }

   class="kw">private boolean testLineOfSightEntity(
      @Nonnull Ref<EntityStore> var1,
      @Nonnull Ref<EntityStore> var2,
      @Nonnull PositionCache.LineOfSightEntityBuffer var3,
      @Nonnull ComponentAccessor<EntityStore> var4,
      double var5
   ) {
      CombatSupport var7 = var4.getComponent(var1, CombatSupport.getComponentType());
      class="kw">return !var2.equals(var1)
         && var7 != null
         && !var7.getCanCauseDamage(var1, var2, var4)
         && rayIsIntersectingEntity(var2, var3.pos, var3.dir, var3.minMax, var5, var4);
   }

   class="kw">private void clearLineOfSightCache(double var1) {
      this.cacheTTL -= (float)var1;
      if (this.cacheTTL <= 0.0F) {
         this.clearLineOfSightCache();
      }
   }

   class="kw">private void clearLineOfSightCache() {
      this.cacheTTL = RandomExtra.randomRange(0.09F, 0.11F);
      this.lineOfSightCache.clear();
      this.inverseLineOfSightCache.clear();
      this.friendlyFireCache.clear();
   }

   class="kw">protected class="kw">static boolean rayIsIntersectingEntity(
      @Nonnull Ref<EntityStore> var0,
      @Nonnull Vector3d var1,
      @Nonnull Vector3d var2,
      @Nonnull Vector2d var3,
      double var4,
      @Nonnull ComponentAccessor<EntityStore> var6
   ) {
      BoundingBox var7 = var6.getComponent(var0, BOUNDING_BOX_COMPONENT_TYPE);
      if (var7 == null) {
         class="kw">return false;
      }

      TransformComponent var8 = var6.getComponent(var0, TRANSFORM_COMPONENT_TYPE);
      assert var8 != null;
      Vector3d var9 = var8.getPosition();
      double var10 = var9.x();
      double var12 = var9.y();
      double var14 = var9.z();
      double var16 = var10 - var1.x;
      double var18 = var12 - var1.y;
      double var20 = var14 - var1.z;
      double var22 = NPCPhysicsMath.dotProduct(var2.x, var2.y, var2.z, var16, var18, var20);
      if (var22 <= 0.0) {
         class="kw">return false;
      }

      double var24 = NPCPhysicsMath.dotProduct(var16, var18, var20);
      class="kw">return var22 * var22 >= var24 * var4 ? false : CollisionMath.intersectRayAABB(var1, var2, var10, var12, var14, var7.getBoundingBox(), var3);
   }

   @Nonnull
   class="kw">public List<Ref<EntityStore>> getDroppedItemList() {
      class="kw">return this.droppedItems;
   }

   @Nonnull
   class="kw">public List<Ref<EntityStore>> getSpawnMarkerList() {
      class="kw">return this.spawnMarkers;
   }

   @Nonnull
   class="kw">public List<Ref<EntityStore>> getSpawnBeaconList() {
      class="kw">return this.spawnBeacons;
   }

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

   class="kw">private class="kw">static class LineOfSightBuffer {
      @Nullable
      class="kw">public World world;
      @Nullable
      class="kw">public WorldChunk chunk;
      @Nullable
      class="kw">public IntSet opaqueSet;
      @Nullable
      class="kw">public BlockTypeAssetMap<String, BlockType> assetMap;
      class="kw">public boolean result;

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

      class="kw">public void clearRefs() {
         this.world = null;
         this.chunk = null;
         this.opaqueSet = null;
         this.assetMap = null;
      }
   }

   class="kw">private class="kw">static class LineOfSightEntityBuffer {
      class="kw">public class="kw">final Vector3d pos = new Vector3d();
      class="kw">public class="kw">final Vector3d dir = new Vector3d();
      class="kw">public class="kw">final Vector2d minMax = new Vector2d();

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

   @FunctionalInterface
   class="kw">public class="kw">interface RayPredicate<T> {
      boolean test(double var1, double var3, double var5, double var7, double var9, double var11, T var13, @Nonnull ComponentAccessor<EntityStore> var14);
   }
}