From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Fri, 15 Jan 2021 19:05:01 -0600
Subject: [PATCH] Dynamic activation range

This replaces the current method of ticking an inactive entity's
pathfinder 1/4 times with a new method that's dynamic based off how far
away it is from a player. If an entity is within 32 blocks, it gets
ticked every tick. If it's within 45 blocks, it gets ticked every other
tick. If it's within 55 blocks, it gets ticked once every three ticks.
(these numbers have since been changed, but the idea is the same.)

Airplane
Copyright (C) 2020 Technove LLC

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
index ab019b577002677a4ce788106f8e5a1d7757a2ae..0e452ea9c5d098326d22a20aa67e423f85843db7 100644
--- a/src/main/java/gg/airplane/AirplaneConfig.java
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -47,4 +47,36 @@ public class AirplaneConfig {
         }
     }
 
+
+    public static int startDistance;
+    public static int startDistanceSquared;
+    public static int maximumActivationPrio;
+    public static int activationDistanceMod;
+    public static boolean dynamicVillagerBehavior;
+    public static boolean dynamicPiglinBehavior;
+    public static boolean dynamicHoglinBehavior;
+
+    private static void dynamicActivationRange() {
+        config.setComment("activation-range", "Optimizes how entities act when", "they're far away from the player");
+
+        startDistance = config.getInt("activation-range.start-distance", 12,
+          "This value determines how far away an entity has to be",
+          "from the player to start being effected by DEAR.");
+        startDistanceSquared = startDistance * startDistance;
+        maximumActivationPrio = config.getInt("activation-range.max-tick-freq", 20,
+          "This value defines how often in ticks, the furthest entity",
+          "will get their pathfinders and behaviors ticked. 20 = 1s");
+        activationDistanceMod = config.getInt("activation-range.activation-dist-mod", 8,
+          "This value defines how much distance modifies an entity's",
+          "tick frequency. freq = (distanceToPlayer^2) / (2^value)",
+          "If you want further away entities to tick less often, use 7.",
+          "If you want further away entities to tick more often, try 9.");
+
+        config.setComment("behavior-activation", "A list of entities to use the dynamic activation range", "to modify how often their behaviors are ticked");
+
+        dynamicVillagerBehavior = config.getBoolean("behavior-activation.villager", true);
+        dynamicPiglinBehavior = config.getBoolean("behavior-activation.piglin", true);
+        dynamicHoglinBehavior = config.getBoolean("behavior-activation.hoglin", true);
+    }
+
 }
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index feab0ae1930b5271fe0d06a40c180317dcbc9d1d..c6b4af810fe3bda7797ab94316b2357178c9cd49 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -289,6 +289,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne
     public void inactiveTick() { }
     // Spigot end
     public boolean shouldBeRemoved; // Paper
+    // Airplane start
+    public int activatedPriority = gg.airplane.AirplaneConfig.maximumActivationPrio; // golf score
+    // Airplane end
 
     public float getBukkitYaw() {
         return this.yaw;
diff --git a/src/main/java/net/minecraft/world/entity/EntityInsentient.java b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
index aae13c2e6c2a30b69c33417932c6a4d0aefeb7f5..f4440a5c4aedb1d7d303517f86a07c856dd1309b 100644
--- a/src/main/java/net/minecraft/world/entity/EntityInsentient.java
+++ b/src/main/java/net/minecraft/world/entity/EntityInsentient.java
@@ -201,10 +201,10 @@ public abstract class EntityInsentient extends EntityLiving {
     @Override
     public void inactiveTick() {
         super.inactiveTick();
-        if (this.goalSelector.inactiveTick()) {
+        if (this.goalSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priroity
             this.goalSelector.doTick();
         }
-        if (this.targetSelector.inactiveTick()) {
+        if (this.targetSelector.inactiveTick(this.activatedPriority)) { // Airplane - pass activated priority
             this.targetSelector.doTick();
         }
     }
@@ -829,9 +829,11 @@ public abstract class EntityInsentient extends EntityLiving {
         this.bo.a();
         this.world.getMethodProfiler().exit();
         this.world.getMethodProfiler().enter("targetSelector");
+        if (this.targetSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking
         this.targetSelector.doTick();
         this.world.getMethodProfiler().exit();
         this.world.getMethodProfiler().enter("goalSelector");
+        if (this.goalSelector.inactiveTick(this.activatedPriority)) // Airplane - use this to alternate ticking
         this.goalSelector.doTick();
         this.world.getMethodProfiler().exit();
         this.world.getMethodProfiler().enter("navigation");
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
index 637928664f8c7b1c694a234e507c20724294e450..02e8288473138dcea008d6157318758e8d7ee3be 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
@@ -44,9 +44,14 @@ public class PathfinderGoalSelector {
     }
 
     // Paper start
-    public boolean inactiveTick() {
-        incRate();
-        return getCurRate() % getTickRate() == 0;
+    public boolean inactiveTick(int tickRate) { // Airplane - take tick rate
+        tickRate = Math.min(tickRate, getTickRate()); // Airplane
+        if (this.curRate++ % tickRate != 0) { // Airplane - use tick rate / increment curRate every tick
+            //incRate();
+            return false;
+        } else {
+            return true;
+        }
     }
     public boolean hasTasks() {
         for (PathfinderGoalWrapped task : getTasks()) {
diff --git a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
index ab692de8a5b1411e37251fb545e6f579a9929f91..9aa4850e021076fde306eea7eec104c31086c57f 100644
--- a/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/hoglin/EntityHoglin.java
@@ -121,12 +121,17 @@ public class EntityHoglin extends EntityAnimal implements IMonster, IOglin {
         return (BehaviorController<EntityHoglin>) super.getBehaviorController(); // Airplane - decompile error
     }
 
+    private int behaviorTick; // Airplane
     @Override
     protected void mobTick() {
+        // Airplane - dynamic tick
+        if (!gg.airplane.AirplaneConfig.dynamicHoglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
         this.world.getMethodProfiler().enter("hoglinBrain");
         this.getBehaviorController().a((WorldServer) this.world, (EntityHoglin) this); // Airplane - decompile error
         this.world.getMethodProfiler().exit();
         HoglinAI.a(this);
+        }
+        // Airplane end
         if (this.isConverting()) {
             ++this.conversionTicks;
             if (this.conversionTicks > 300) {
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
index d100b39c420e2326e869aa4059fc800d4c2fc0e4..48acef830eb1d919499e9b79dc6a9af4bdf8a17b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/EntityPiglin.java
@@ -244,12 +244,17 @@ public class EntityPiglin extends EntityPiglinAbstract implements ICrossbow {
         return !this.cannotHunt;
     }
 
+    private int behaviorTick; // Airplane
     @Override
     protected void mobTick() {
+        // Airplane - dynamic tick
+        if (!gg.airplane.AirplaneConfig.dynamicPiglinBehavior || this.behaviorTick++ % this.activatedPriority == 0) {
         this.world.getMethodProfiler().enter("piglinBrain");
         this.getBehaviorController().a((WorldServer) this.world, (EntityPiglin) this); // Airplane - compile error
         this.world.getMethodProfiler().exit();
         PiglinAI.b(this);
+        }
+        // Airplane end
         super.mobTick();
     }
 
diff --git a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
index 2d0b83923d58cc7b6918b4e2ff2bece13ca26899..d8028675fc82883d716bcfb44431ca6ac7dfda36 100644
--- a/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/EntityVillager.java
@@ -231,11 +231,17 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
     }
     // Spigot End
 
+    private int behaviorTick = 0;
+
     @Override
     protected void mobTick() { mobTick(false); }
     protected void mobTick(boolean inactive) {
         this.world.getMethodProfiler().enter("villagerBrain");
-        if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+        if (!inactive) {
+            if (!gg.airplane.AirplaneConfig.dynamicVillagerBehavior || behaviorTick++ % this.activatedPriority == 0) {
+                this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+            }
+        }
         this.world.getMethodProfiler().exit();
         if (this.bF) {
             this.bF = false;
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
index 5c2eaca0bc63c7880ee928aba6a24761737aa649..8b36ca5062f8e0e8bd58aa506e91704a747de81b 100644
--- a/src/main/java/org/spigotmc/ActivationRange.java
+++ b/src/main/java/org/spigotmc/ActivationRange.java
@@ -47,6 +47,9 @@ import net.minecraft.world.entity.schedule.Activity;
 import net.minecraft.world.entity.item.EntityFallingBlock;
 import net.minecraft.world.entity.projectile.EntityEnderSignal;
 // Paper end
+// Airplane start
+import net.minecraft.world.phys.Vec3D;
+// Airplane end
 
 public class ActivationRange
 {
@@ -227,7 +230,7 @@ public class ActivationRange
                     Chunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper
                     if ( chunk != null )
                     {
-                        activateChunkEntities( chunk );
+                        activateChunkEntities( chunk, player.getPositionVector() ); // Airplane
                     }
                 }
             }
@@ -240,7 +243,7 @@ public class ActivationRange
      *
      * @param chunk
      */
-    private static void activateChunkEntities(Chunk chunk)
+    private static void activateChunkEntities(Chunk chunk, Vec3D playerVec) // Airplane - add player location
     {
         // Paper start
         Entity[] rawData = chunk.entities.getRawData();
@@ -249,6 +252,15 @@ public class ActivationRange
             //for ( Entity entity : (Collection<Entity>) slice )
             // Paper end
             {
+                // Airplane start
+                Vec3D entityVec = entity.getPositionVector();
+                double diffX = playerVec.x - entityVec.x, diffY = playerVec.y - entityVec.y, diffZ = playerVec.z - entityVec.z;
+                int squaredDistance = (int) (diffX * diffX + diffY * diffY + diffZ * diffZ);
+                entity.activatedPriority = squaredDistance > gg.airplane.AirplaneConfig.startDistanceSquared ?
+                  Math.max(1, Math.min(squaredDistance >> gg.airplane.AirplaneConfig.activationDistanceMod, gg.airplane.AirplaneConfig.maximumActivationPrio)) :
+                  1;
+                // Airplane end
+
                 if (MinecraftServer.currentTick > entity.activatedTick) {
                     if (entity.defaultActivationState || entity.activationType.boundingBox.c(entity.getBoundingBox())) { // Paper
                         entity.activatedTick = MinecraftServer.currentTick;
