aboutsummaryrefslogtreecommitdiffhomepage
path: root/CraftBukkit-Patches/0016-Entity-Activation-Range.patch
diff options
context:
space:
mode:
Diffstat (limited to 'CraftBukkit-Patches/0016-Entity-Activation-Range.patch')
-rw-r--r--CraftBukkit-Patches/0016-Entity-Activation-Range.patch522
1 files changed, 522 insertions, 0 deletions
diff --git a/CraftBukkit-Patches/0016-Entity-Activation-Range.patch b/CraftBukkit-Patches/0016-Entity-Activation-Range.patch
new file mode 100644
index 0000000000..afb1768c66
--- /dev/null
+++ b/CraftBukkit-Patches/0016-Entity-Activation-Range.patch
@@ -0,0 +1,522 @@
+From 72e1c5a2f9954a7dafbf3ccfc9477330df7bc861 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+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.
+
+diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
+index a7d9c11..33798d8 100644
+--- a/src/main/java/net/minecraft/server/Entity.java
++++ b/src/main/java/net/minecraft/server/Entity.java
+@@ -90,7 +90,7 @@ public abstract class Entity {
+ public int ticksLived;
+ public int maxFireTicks;
+ public int fireTicks; // CraftBukkit - private -> public
+- protected boolean inWater;
++ public boolean inWater; // Spigot - protected -> public
+ public int noDamageTicks;
+ private boolean justCreated;
+ protected boolean fireProof;
+@@ -114,7 +114,13 @@ public abstract class Entity {
+ public boolean valid; // CraftBukkit
+ public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only
+
++ // Spigot start
+ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot
++ public final byte activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this);
++ public final boolean defaultActivationState;
++ public long activatedTick = 0;
++ public void inactiveTick() { }
++ // Spigot end
+
+ public int getId() {
+ return this.id;
+@@ -141,7 +147,12 @@ public abstract class Entity {
+ this.setPosition(0.0D, 0.0D, 0.0D);
+ if (world != null) {
+ this.dimension = world.worldProvider.dimension;
++ // Spigot start
++ this.defaultActivationState = org.spigotmc.ActivationRange.initializeEntityActivationState(this, world.spigotConfig);
++ } else {
++ this.defaultActivationState = false;
+ }
++ // Spigot end
+
+ this.datawatcher = new DataWatcher(this);
+ this.datawatcher.a(0, Byte.valueOf((byte) 0));
+diff --git a/src/main/java/net/minecraft/server/EntityAgeable.java b/src/main/java/net/minecraft/server/EntityAgeable.java
+index 36ed831..7ddca48 100644
+--- a/src/main/java/net/minecraft/server/EntityAgeable.java
++++ b/src/main/java/net/minecraft/server/EntityAgeable.java
+@@ -6,6 +6,31 @@ public abstract class EntityAgeable extends EntityCreature {
+ private float bq;
+ public boolean ageLocked = false; // CraftBukkit
+
++ // Spigot start
++ @Override
++ public void inactiveTick()
++ {
++ super.inactiveTick();
++ if ( this.world.isStatic || this.ageLocked )
++ { // CraftBukkit
++ this.a( this.isBaby() );
++ } else
++ {
++ int i = this.getAge();
++
++ if ( i < 0 )
++ {
++ ++i;
++ this.setAge( i );
++ } else if ( i > 0 )
++ {
++ --i;
++ this.setAge( i );
++ }
++ }
++ }
++ // Spigot end
++
+ public EntityAgeable(World world) {
+ super(world);
+ }
+diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
+index 88b0751..ac5d5d2 100644
+--- a/src/main/java/net/minecraft/server/EntityArrow.java
++++ b/src/main/java/net/minecraft/server/EntityArrow.java
+@@ -15,7 +15,7 @@ public class EntityArrow extends Entity implements IProjectile {
+ private int f = -1;
+ private Block g;
+ private int h;
+- private boolean inGround;
++ public boolean inGround = false; // Spigot - private -> public
+ public int fromPlayer;
+ public int shake;
+ public Entity shooter;
+@@ -24,6 +24,18 @@ public class EntityArrow extends Entity implements IProjectile {
+ private double damage = 2.0D;
+ public int knockbackStrength; // CraftBukkit - private -> public
+
++ // Spigot Start
++ @Override
++ public void inactiveTick()
++ {
++ if ( this.inGround )
++ {
++ this.at += 19; // Despawn counter. First int after shooter
++ }
++ super.inactiveTick();
++ }
++ // Spigot End
++
+ public EntityArrow(World world) {
+ super(world);
+ this.j = 10.0D;
+diff --git a/src/main/java/net/minecraft/server/EntityFireworks.java b/src/main/java/net/minecraft/server/EntityFireworks.java
+index 759d46c..b977cf7 100644
+--- a/src/main/java/net/minecraft/server/EntityFireworks.java
++++ b/src/main/java/net/minecraft/server/EntityFireworks.java
+@@ -5,6 +5,15 @@ public class EntityFireworks extends Entity {
+ private int ticksFlown;
+ public int expectedLifespan; // CraftBukkit - private -> public
+
++ // Spigot Start
++ @Override
++ public void inactiveTick()
++ {
++ this.ticksFlown += 19;
++ super.inactiveTick();
++ }
++ // Spigot End
++
+ public EntityFireworks(World world) {
+ super(world);
+ this.a(0.25F, 0.25F);
+diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
+index 6a0bee6..92ad5c7 100644
+--- a/src/main/java/net/minecraft/server/EntityLiving.java
++++ b/src/main/java/net/minecraft/server/EntityLiving.java
+@@ -84,6 +84,13 @@ public abstract class EntityLiving extends Entity {
+ public int maxAirTicks = 300;
+ ArrayList<org.bukkit.inventory.ItemStack> drops = null;
+ // CraftBukkit end
++ // Spigot start
++ public void inactiveTick()
++ {
++ super.inactiveTick();
++ ++this.aU; // Above all the floats
++ }
++ // Spigot end
+
+ public EntityLiving(World world) {
+ super(world);
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index e03712a..e876b66 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -1317,6 +1317,7 @@ public abstract class World implements IBlockAccess {
+ this.f.clear();
+ this.methodProfiler.c("regular");
+
++ org.spigotmc.ActivationRange.activateEntities(this); // Spigot
+ timings.entityTick.startTiming(); // Spigot
+ // CraftBukkit start - Use field for loop variable
+ for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) {
+@@ -1473,9 +1474,11 @@ public abstract class World implements IBlockAccess {
+ int j = MathHelper.floor(entity.locZ);
+ byte b0 = 32;
+
+- // CraftBukkit start - Use neighbor cache instead of looking up
+- Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4);
+- if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.b(i - b0, 0, j - b0, i + b0, 0, j + b0) */) {
++ // Spigot start
++ if (!org.spigotmc.ActivationRange.checkIfActive(entity)) {
++ entity.ticksLived++;
++ entity.inactiveTick();
++ } else {
+ entity.tickTimer.startTiming(); // Spigot
+ // CraftBukkit end
+ entity.S = entity.locX;
+diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java
+index 558574f..41d2d87 100644
+--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java
++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java
+@@ -39,6 +39,9 @@ public class SpigotTimings {
+
+ public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand");
+
++ public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck");
++ public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive");
++
+ public static final HashMap<String, CustomTimingsHandler> entityTypeTimingMap = new HashMap<String, CustomTimingsHandler>();
+ public static final HashMap<String, CustomTimingsHandler> tileEntityTypeTimingMap = new HashMap<String, CustomTimingsHandler>();
+ public static final HashMap<String, CustomTimingsHandler> pluginTaskTimingMap = new HashMap<String, CustomTimingsHandler>();
+diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
+new file mode 100644
+index 0000000..84a7dd6
+--- /dev/null
++++ b/src/main/java/org/spigotmc/ActivationRange.java
+@@ -0,0 +1,296 @@
++package org.spigotmc;
++
++import java.util.ArrayList;
++import java.util.List;
++import net.minecraft.server.AxisAlignedBB;
++import net.minecraft.server.Chunk;
++import net.minecraft.server.Entity;
++import net.minecraft.server.EntityAmbient;
++import net.minecraft.server.EntityAnimal;
++import net.minecraft.server.EntityArrow;
++import net.minecraft.server.EntityComplexPart;
++import net.minecraft.server.EntityCreature;
++import net.minecraft.server.EntityEnderCrystal;
++import net.minecraft.server.EntityEnderDragon;
++import net.minecraft.server.EntityFireball;
++import net.minecraft.server.EntityFireworks;
++import net.minecraft.server.EntityHuman;
++import net.minecraft.server.EntityLiving;
++import net.minecraft.server.EntityMonster;
++import net.minecraft.server.EntityProjectile;
++import net.minecraft.server.EntitySheep;
++import net.minecraft.server.EntitySlime;
++import net.minecraft.server.EntityTNTPrimed;
++import net.minecraft.server.EntityVillager;
++import net.minecraft.server.EntityWeather;
++import net.minecraft.server.EntityWither;
++import net.minecraft.server.MathHelper;
++import net.minecraft.server.MinecraftServer;
++import net.minecraft.server.World;
++import org.bukkit.craftbukkit.SpigotTimings;
++
++public class ActivationRange
++{
++
++ static AxisAlignedBB maxBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 );
++ static AxisAlignedBB miscBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 );
++ static AxisAlignedBB animalBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 );
++ static AxisAlignedBB monsterBB = AxisAlignedBB.a( 0, 0, 0, 0, 0, 0 );
++
++ /**
++ * 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
++ * @param world
++ * @return boolean If it should always tick.
++ */
++ public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config)
++ {
++ if ( ( entity.activationType == 3 && config.miscActivationRange == 0 )
++ || ( entity.activationType == 2 && config.animalActivationRange == 0 )
++ || ( entity.activationType == 1 && config.monsterActivationRange == 0 )
++ || entity instanceof EntityHuman
++ || 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)
++ {
++ SpigotTimings.entityActivationCheckTimer.startTiming();
++ final int miscActivationRange = world.spigotConfig.miscActivationRange;
++ final int animalActivationRange = world.spigotConfig.animalActivationRange;
++ final int monsterActivationRange = world.spigotConfig.monsterActivationRange;
++
++ int maxRange = Math.max( monsterActivationRange, animalActivationRange );
++ maxRange = Math.max( maxRange, miscActivationRange );
++ maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange );
++
++ for ( Entity player : new ArrayList<Entity>( world.players ) )
++ {
++
++ player.activatedTick = MinecraftServer.currentTick;
++ 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 );
++
++ int i = MathHelper.floor( maxBB.a / 16.0D );
++ int j = MathHelper.floor( maxBB.d / 16.0D );
++ int k = MathHelper.floor( maxBB.c / 16.0D );
++ int l = MathHelper.floor( maxBB.f / 16.0D );
++
++ for ( int i1 = i; i1 <= j; ++i1 )
++ {
++ for ( int j1 = k; j1 <= l; ++j1 )
++ {
++ if ( world.getWorld().isChunkLoaded( i1, j1 ) )
++ {
++ activateChunkEntities( world.getChunkAt( i1, j1 ) );
++ }
++ }
++ }
++ }
++ SpigotTimings.entityActivationCheckTimer.stopTiming();
++ }
++
++ /**
++ * Checks for the activation state of all entities in this chunk.
++ *
++ * @param chunk
++ */
++ private static void activateChunkEntities(Chunk chunk)
++ {
++ for ( List<Entity> slice : chunk.entitySlices )
++ {
++ for ( Entity entity : slice )
++ {
++ if ( MinecraftServer.currentTick > entity.activatedTick )
++ {
++ if ( entity.defaultActivationState )
++ {
++ entity.activatedTick = MinecraftServer.currentTick;
++ continue;
++ }
++ switch ( entity.activationType )
++ {
++ case 1:
++ if ( monsterBB.b( entity.boundingBox ) )
++ {
++ entity.activatedTick = MinecraftServer.currentTick;
++ }
++ break;
++ case 2:
++ if ( animalBB.b( entity.boundingBox ) )
++ {
++ entity.activatedTick = MinecraftServer.currentTick;
++ }
++ break;
++ case 3:
++ default:
++ if ( miscBB.b( entity.boundingBox ) )
++ {
++ entity.activatedTick = MinecraftServer.currentTick;
++ }
++ }
++ }
++ }
++ }
++ }
++
++ /**
++ * 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 checkEntityImmunities(Entity entity)
++ {
++ // quick checks.
++ if ( entity.inWater /* isInWater */ || entity.fireTicks > 0 )
++ {
++ return true;
++ }
++ if ( !( entity instanceof EntityArrow ) )
++ {
++ if ( !entity.onGround || entity.passenger != null
++ || entity.vehicle != null )
++ {
++ return true;
++ }
++ } else if ( !( (EntityArrow) entity ).inGround )
++ {
++ return true;
++ }
++ // special cases.
++ if ( entity instanceof EntityLiving )
++ {
++ EntityLiving living = (EntityLiving) entity;
++ if ( living.attackTicks > 0 || living.hurtTicks > 0 || living.effects.size() > 0 )
++ {
++ return true;
++ }
++ if ( entity instanceof EntityCreature && ( (EntityCreature) entity ).target != null )
++ {
++ return true;
++ }
++ if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).bY() /* Getter for first boolean */ )
++ {
++ return true;
++ }
++ if ( entity instanceof EntityAnimal )
++ {
++ EntityAnimal animal = (EntityAnimal) entity;
++ if ( animal.isBaby() || animal.ce() /*love*/ )
++ {
++ return true;
++ }
++ if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() )
++ {
++ return true;
++ }
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Checks if the entity is active for this tick.
++ *
++ * @param entity
++ * @return
++ */
++ public static boolean checkIfActive(Entity entity)
++ {
++ SpigotTimings.checkIfActiveTimer.startTiming();
++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState;
++
++ // Should this entity tick?
++ if ( !isActive )
++ {
++ if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 )
++ {
++ // Check immunities every 20 ticks.
++ if ( checkEntityImmunities( entity ) )
++ {
++ // Triggered some sort of immunity, give 20 full ticks before we check again.
++ entity.activatedTick = MinecraftServer.currentTick + 20;
++ }
++ isActive = true;
++ }
++ // Add a little performance juice to active entities. Skip 1/4 if not immune.
++ } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) )
++ {
++ isActive = false;
++ }
++ int x = MathHelper.floor( entity.locX );
++ int z = MathHelper.floor( entity.locZ );
++ // Make sure not on edge of unloaded chunk
++ Chunk chunk = entity.world.getChunkIfLoaded( x >> 4, z >> 4 );
++ if ( isActive && !( chunk != null && chunk.areNeighborsLoaded( 1 ) ) )
++ {
++ isActive = false;
++ }
++ SpigotTimings.checkIfActiveTimer.stopTiming();
++ return isActive;
++ }
++}
+diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
+index 46249d7..ed2836a 100644
+--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
+@@ -138,4 +138,15 @@ public class SpigotWorldConfig
+ mobSpawnRange = (byte) getInt( "mob-spawn-range", 4 );
+ log( "Mob Spawn Range: " + mobSpawnRange );
+ }
++
++ public int animalActivationRange = 32;
++ public int monsterActivationRange = 32;
++ public int miscActivationRange = 16;
++ private void activationRange()
++ {
++ animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange );
++ monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange );
++ miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange );
++ log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Mi " + miscActivationRange );
++ }
+ }
+--
+1.9.1
+