From 9258faff3f2e976202c4cbc653c94d3477b7c7fe Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au>
Date: Mon, 11 Feb 2013 19:32:14 +1100
Subject: [PATCH] Apply entity activation range, the most over hyped commit
 ever.

---
 CraftBukkit-Patches/0002-Spigot-changes.patch |   8 +-
 ...n-Range-This-feature-gives-3-new-con.patch | 340 ++++++++++++++++++
 2 files changed, 344 insertions(+), 4 deletions(-)
 create mode 100644 CraftBukkit-Patches/0027-Entity-Activation-Range-This-feature-gives-3-new-con.patch

diff --git a/CraftBukkit-Patches/0002-Spigot-changes.patch b/CraftBukkit-Patches/0002-Spigot-changes.patch
index 207ff2823b..230a33fcb2 100644
--- a/CraftBukkit-Patches/0002-Spigot-changes.patch
+++ b/CraftBukkit-Patches/0002-Spigot-changes.patch
@@ -1,4 +1,4 @@
-From 80afd7d84a7d9092281b41183190bff1bc84480e Mon Sep 17 00:00:00 2001
+From dcdcd6631d28acb723e1086a142210b3e77001fd Mon Sep 17 00:00:00 2001
 From: md_5 <md_5@live.com.au>
 Date: Sun, 3 Feb 2013 12:21:52 +1100
 Subject: [PATCH] Spigot changes.
@@ -448,7 +448,7 @@ index fac9ea5..43a24f5 100644
                      }
                  }
 diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
-index b0bb672..b650f55 100644
+index e857612..d13fa19 100644
 --- a/src/main/java/net/minecraft/server/PlayerList.java
 +++ b/src/main/java/net/minecraft/server/PlayerList.java
 @@ -253,7 +253,7 @@ public abstract class PlayerList {
@@ -460,7 +460,7 @@ index b0bb672..b650f55 100644
          } else {
              String s2 = socketaddress.toString();
  
-@@ -921,7 +921,13 @@ public abstract class PlayerList {
+@@ -924,7 +924,13 @@ public abstract class PlayerList {
  
      public void r() {
          while (!this.players.isEmpty()) {
@@ -1417,7 +1417,7 @@ index 0000000..fba4b4a
 +}
 \ No newline at end of file
 diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
-index b0c23a0..747a88e 100644
+index f8dbbee..c79f352 100644
 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
 +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
 @@ -212,10 +212,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
diff --git a/CraftBukkit-Patches/0027-Entity-Activation-Range-This-feature-gives-3-new-con.patch b/CraftBukkit-Patches/0027-Entity-Activation-Range-This-feature-gives-3-new-con.patch
new file mode 100644
index 0000000000..4472b2ec60
--- /dev/null
+++ b/CraftBukkit-Patches/0027-Entity-Activation-Range-This-feature-gives-3-new-con.patch
@@ -0,0 +1,340 @@
+From fee453c7c632f95685e96ff767e28d6f2b9efae9 Mon Sep 17 00:00:00 2001
+From: Aikar <aikar@aikar.co>
+Date: Sun, 3 Feb 2013 05:10:21 -0500
+Subject: [PATCH] Entity Activation Range# This feature gives 3 new
+ configurable ranges that if an entity of the matching type is outside of this
+ radius of any player, will tick at 5% of its normal rate.
+
+This will drastically cut down on tick timings for entities that are not in range of a user to actually be "used".
+This change can have dramatic impact on gameplay if configured too low. Balance according to your servers desired gameplay.
+---
+ src/main/java/net/minecraft/server/Entity.java     |   8 ++
+ .../java/net/minecraft/server/EntityArrow.java     |   2 +-
+ src/main/java/net/minecraft/server/World.java      |  10 +-
+ .../java/org/bukkit/craftbukkit/CraftWorld.java    |  13 ++
+ src/main/java/org/bukkit/craftbukkit/Spigot.java   | 148 +++++++++++++++++++++
+ .../java/org/bukkit/event/WorldTimingsHandler.java |   2 +
+ src/main/resources/configurations/bukkit.yml       |   3 +
+ 7 files changed, 184 insertions(+), 2 deletions(-)
+
+diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
+index d0a58f8..9da5035 100644
+--- a/src/main/java/net/minecraft/server/Entity.java
++++ b/src/main/java/net/minecraft/server/Entity.java
+@@ -111,6 +111,13 @@ public abstract class Entity {
+     public UUID uniqueId = UUID.randomUUID(); // CraftBukkit
+     public boolean valid = false; // CraftBukkit
+ 
++    // Spigot start
++    public boolean inWater = false;
++    public final byte activationType = org.bukkit.craftbukkit.Spigot.initializeEntityActivationType(this);
++    public final boolean defaultActivationState = org.bukkit.craftbukkit.Spigot.initializeEntityActivationState(this);
++    public boolean isActivated = defaultActivationState;
++    // Spigot end
++
+     public Entity(World world) {
+         this.id = entityCount++;
+         this.l = 1.0D;
+@@ -862,6 +869,7 @@ public abstract class Entity {
+             this.ad = false;
+         }
+ 
++        this.inWater = this.ad; // Spigot
+         return this.ad;
+     }
+ 
+diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
+index 916b9dc..bdd18f6 100644
+--- a/src/main/java/net/minecraft/server/EntityArrow.java
++++ b/src/main/java/net/minecraft/server/EntityArrow.java
+@@ -16,7 +16,7 @@ public class EntityArrow extends Entity implements IProjectile {
+     private int f = -1;
+     private int g = 0;
+     private int h = 0;
+-    private boolean inGround = false;
++    public boolean inGround = false; // Spigot - private -> public
+     public int fromPlayer = 0;
+     public int shake = 0;
+     public Entity shooter;
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index cd7ad64..53834a9 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -1241,6 +1241,7 @@ public abstract class World implements IBlockAccess {
+         this.methodProfiler.c("regular");
+         timings.entityBaseTick.stopTiming(); // Spigot
+ 
++        org.bukkit.craftbukkit.Spigot.activateEntities(this); // Spigot
+         timings.entityTick.startTiming(); // Spigot
+         for (i = 0; i < this.entityList.size(); ++i) {
+             entity = (Entity) this.entityList.get(i);
+@@ -1405,6 +1406,13 @@ public abstract class World implements IBlockAccess {
+         if (entity == null) {
+             return;
+         }
++        if (!entity.isActivated && !org.bukkit.craftbukkit.Spigot.checkIfActive(entity)) {
++            if (entity.vehicle == null) {
++                entity.ticksLived++;
++            }
++            return;
++        }
++        entity.isActivated = entity.defaultActivationState;
+         try {
+             tickEntity(entity, flag);
+         } catch (Exception e) {
+@@ -1434,7 +1442,7 @@ public abstract class World implements IBlockAccess {
+         int j = MathHelper.floor(entity.locZ);
+         byte b0 = 32;
+ 
+-        if (!flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) {
++        if (entity instanceof EntityFireworks || !flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) { // Spigot - Not safe to skip a firework.
+             entity.T = entity.locX;
+             entity.U = entity.locY;
+             entity.V = entity.locZ;
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+index 21bd64a..a083ae4 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+@@ -100,6 +100,10 @@ public class CraftWorld implements World {
+         treeGrowthModifier = configuration.getInt("world-settings.default.tree-growth-modifier", treeGrowthModifier);
+         mushroomGrowthModifier = configuration.getInt("world-settings.default.mushroom-growth-modifier", mushroomGrowthModifier);
+ 
++        miscEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-misc", miscEntityActivationRange);
++        animalEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-animals", animalEntityActivationRange);
++        monsterEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-monsters", monsterEntityActivationRange);
++
+         //override defaults with world specific, if they exist
+         growthPerTick = configuration.getInt("world-settings." + name + ".growth-chunks-per-tick", growthPerTick);
+         itemMergeRadius = configuration.getDouble("world-settings." + name + ".item-merge-radius", itemMergeRadius);
+@@ -121,6 +125,10 @@ public class CraftWorld implements World {
+ 
+         obfuscated = !world.getServer().orebfuscatorDisabledWorlds.contains(name);
+ 
++        miscEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-misc", miscEntityActivationRange);
++        animalEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-animals", animalEntityActivationRange);
++        monsterEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-monsters", monsterEntityActivationRange);
++
+         server.getLogger().info("-------------- Spigot ----------------");
+         server.getLogger().info("-------- World Settings For [" + name + "] --------");
+         server.getLogger().info("Growth Per Chunk: " + growthPerTick);
+@@ -138,6 +146,7 @@ public class CraftWorld implements World {
+         server.getLogger().info("Mushroom Growth Modifier: " + mushroomGrowthModifier);
+         server.getLogger().info("View distance: " + viewDistance);
+         server.getLogger().info("Oreobfuscator: " + obfuscated);
++        server.getLogger().info("Entity Activation Range: An " + animalEntityActivationRange + " / Mo " + monsterEntityActivationRange + " / Mi " + miscEntityActivationRange);
+         server.getLogger().info("-------------------------------------------------");
+         // Spigot end
+     }
+@@ -158,6 +167,10 @@ public class CraftWorld implements World {
+     public int sugarGrowthModifier = 100;
+     public int treeGrowthModifier = 100;
+     public int mushroomGrowthModifier = 100;
++
++    public int miscEntityActivationRange = 0;
++    public int animalEntityActivationRange = 0;
++    public int monsterEntityActivationRange = 0;
+     // Spigot end
+ 
+     public Block getBlockAt(int x, int y, int z) {
+diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java
+index 83988c3..be77320 100644
+--- a/src/main/java/org/bukkit/craftbukkit/Spigot.java
++++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java
+@@ -1,7 +1,9 @@
+ package org.bukkit.craftbukkit;
+ 
++import net.minecraft.server.*;
+ import org.bukkit.command.SimpleCommandMap;
+ import org.bukkit.configuration.file.YamlConfiguration;
++import java.util.List;
+ 
+ public class Spigot {
+     public static void initialize(CraftServer server, SimpleCommandMap commandMap, YamlConfiguration configuration) {
+@@ -32,5 +34,151 @@ public class Spigot {
+             server.getLogger().severe("[Spigot] You should not disable chunk-gc. Resetting period-in-ticks to 600 ticks.");
+             server.chunkGCPeriod = 600;
+         }
++
++    }
++
++    /**
++     * Initializes an entities type on construction to specify what group this
++     * entity is in for activation ranges.
++     *
++     * @param entity
++     * @return group id
++     */
++    public static byte initializeEntityActivationType(Entity entity) {
++        if (entity instanceof EntityMonster || entity instanceof EntitySlime) {
++            return 1; // Monster
++        } else if (entity instanceof EntityCreature || entity instanceof EntityAmbient) {
++            return 2; // Animal
++        } else {
++            return 3; // Misc
++        }
++    }
++
++    /**
++     * These entities are excluded from Activation range checks.
++     *
++     * @param entity
++     * @return boolean If it should always tick.
++     */
++    public static boolean initializeEntityActivationState(Entity entity) {
++        if (entity instanceof EntityHuman
++                || entity instanceof EntityArrow
++                || entity instanceof EntityProjectile
++                || entity instanceof EntityEnderDragon
++                || entity instanceof EntityComplexPart
++                || entity instanceof EntityWither
++                || entity instanceof EntityFireball
++                || entity instanceof EntityWeather
++                || entity instanceof EntityTNTPrimed
++                || entity instanceof EntityEnderCrystal
++                || entity instanceof EntityFireworks) {
++            return true;
++        }
++        return false;
++    }
++
++    /**
++     * Utility method to grow an AABB without creating a new AABB or touching
++     * the pool, so we can re-use ones we have.
++     *
++     * @param target
++     * @param source
++     * @param x
++     * @param y
++     * @param z
++     */
++    public static void growBB(AxisAlignedBB target, AxisAlignedBB source, int x, int y, int z) {
++        target.a = source.a - x;
++        target.b = source.b - y;
++        target.c = source.c - z;
++        target.d = source.d + x;
++        target.e = source.e + y;
++        target.f = source.f + z;
++    }
++
++    /**
++     * Find what entities are in range of the players in the world and set
++     * active if in range.
++     *
++     * @param world
++     */
++    public static void activateEntities(World world) {
++        final int miscActivationRange = world.getWorld().miscEntityActivationRange;
++        final int animalActivationRange = world.getWorld().animalEntityActivationRange;
++        final int monsterActivationRange = world.getWorld().monsterEntityActivationRange;
++
++
++        world.timings.activationCheck.startTiming();
++        int maxRange = Math.max(monsterActivationRange, animalActivationRange);
++        maxRange = Math.max(maxRange, miscActivationRange);
++        if (miscActivationRange == 0 || animalActivationRange == 0 || monsterActivationRange == 0) {
++            // One of them is disabled, set to view-distance
++            maxRange = world.getWorld().viewDistance << 4;
++        } else {
++            maxRange = Math.min(world.getWorld().viewDistance << 4, maxRange); // Do not tick on edge of unloaded chunks - vanilla behavior.
++        }
++
++        AxisAlignedBB maxBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
++        AxisAlignedBB miscBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
++        AxisAlignedBB animalBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
++        AxisAlignedBB monsterBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0);
++
++        for (Entity player : (List<Entity>) world.players) {
++            growBB(maxBB, player.boundingBox, maxRange, 256, maxRange);
++            growBB(miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange);
++            growBB(animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange);
++            growBB(monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange);
++
++            final List<Entity> list = world.getEntities(player, maxBB);
++            for (Entity entity : list) {
++                if (!entity.defaultActivationState) {
++                    boolean isInRange = false;
++                    switch (entity.activationType) {
++                        case 1:
++                            if (monsterActivationRange == 0 || monsterBB.a(entity.boundingBox)) {
++                                isInRange = true;
++                            }
++                            break;
++                        case 2:
++                            if (animalActivationRange == 0 || animalBB.a(entity.boundingBox)) {
++                                isInRange = true;
++                            }
++                            break;
++                        case 3:
++                        default:
++                            if (miscActivationRange == 0 || miscBB.a(entity.boundingBox)) {
++                                isInRange = true;
++                            }
++                    }
++
++                    entity.isActivated = isInRange;
++                }
++            }
++        }
++        world.timings.activationCheck.stopTiming();
++    }
++
++    /**
++     * If an entity is not in range, do some more checks to see if we should
++     * give it a shot.
++     *
++     * @param entity
++     * @return
++     */
++    public static boolean checkIfActive(Entity entity) {
++        // quick checks.
++        if (entity.ticksLived % 20 == 0 || !entity.onGround || entity.inWater || entity.passenger != null || entity.vehicle != null) {
++            return true;
++        }
++        // special cases.
++        if (entity instanceof EntityAnimal) {
++            EntityAnimal animal = (EntityAnimal) entity;
++            if (animal.isBaby() || animal.r() /*love*/) {
++                return true;
++            }
++            return (entity instanceof EntitySheep && ((EntitySheep) entity).isSheared());
++        }
++        return (entity instanceof EntityArrow && !((EntityArrow) entity).inGround);
++
+     }
+ }
+diff --git a/src/main/java/org/bukkit/event/WorldTimingsHandler.java b/src/main/java/org/bukkit/event/WorldTimingsHandler.java
+index bb0c191..6a4a05e 100644
+--- a/src/main/java/org/bukkit/event/WorldTimingsHandler.java
++++ b/src/main/java/org/bukkit/event/WorldTimingsHandler.java
+@@ -8,6 +8,7 @@ public class WorldTimingsHandler {
+     public CustomTimingsHandler entityBaseTick;
+     public CustomTimingsHandler entityTick;
+     public CustomTimingsHandler tileEntityTick;
++    public CustomTimingsHandler activationCheck;
+     public WorldTimingsHandler(World server) {
+         String name = server.worldData.getName() +" - ";
+ 
+@@ -16,5 +17,6 @@ public class WorldTimingsHandler {
+         entityBaseTick = new CustomTimingsHandler(name + "entityBaseTick");
+         entityTick     = new CustomTimingsHandler(name + "entityTick");
+         tileEntityTick = new CustomTimingsHandler(name + "tileEntityTick");
++        activationCheck = new CustomTimingsHandler("** " + name + "activateEntities");
+     }
+ }
+diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml
+index 6931712..06ac168 100644
+--- a/src/main/resources/configurations/bukkit.yml
++++ b/src/main/resources/configurations/bukkit.yml
+@@ -49,6 +49,9 @@ world-settings:
+         sugar-growth-modifier: 100
+         tree-growth-modifier: 100
+         mushroom-growth-modifier: 100
++        entity-activation-range-animals: 48
++        entity-activation-range-monsters: 48
++        entity-activation-range-misc: 16
+     world:
+         growth-chunks-per-tick: 1000
+     world_nether:
+-- 
+1.8.1-rc2
+