From 544cae4eca921628d254bf6a15c3bdec69410cb6 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 27 Apr 2020 00:34:51 -0400 Subject: [PATCH] Entity Activation Range 2.0! Major improvements to restoring behavior Calling this 2.0 as it's a pretty major improvement with more knobs to twist. This update fixes many things. The goal here is to restore vanilla behavior to some degree. Instead of permanent inactive pools of animals, let them show some signs of life some.... Yes this may reduce performance compared to before, but I hope it is minimal. Got to find a balance. Previous EAR logic really compromised vanilla behavior of mobs. This tries to restore it. Changes: 1) All monsters are now classed as Monster. Mojang has an interface, we should use it. - This now includes Shulker, Slimes, see #2 for Phantom and Ghast 2) Villagers and Flying Monsters now have their own separate activation range configs. - Villagers will default to your Animals config 3) Added a bunch of more immunities - Brand new entities are immune for a few seconds - Entities that recently traveled by portal are immune for few seconds - Entities that are leashed to a player are immune - Ender Signals are immune - Entities that are jumping, climbing, dying (lol) are immune - Minecarts are now always immune to the movement restriction 4) Villagers immunity received major overhaul... - Now has many immunities for Villager activities to let them do their work then go back inactive - Such as interacting with doors and workstations should be more normal now - Raids will trigger immunities, in that villagers will run and hide when bell rings. - Raid should keep the entire village immune during the raid to keep gameplay mechanics You can disable raids by game rule if you dont want raids Then the big one..... Wake Up Inactive Entities: One issue plagueing "farms" is that we no longer even let entities move now. Entities become lifeless. A new system has been introduced to wake up inactive entities every so often, to let them stretch their legs, eat some food, play with each other and experience the good entity life. Animals, Villagers, Monsters (Includes Pillagers), and Flying Monsters will now wake up every so often after staying inactive for a very long. This grants them a temporary immunity, that the goal is they will then find "stuff to do" by having a longer activity window. How many to wake up, how often they wake up, and for how long they wake up are all configurable. Current EAR Immunities really don't give some entities enough of a window to find work to then keep them immune for the work to even start. This system should help that. We will only wake up a few entities per tick on the first wave, restoring 1 per type per world per tick. So say you have 10 monsters qualify for inactive wake up, all 8 will wake up on the first eligible tick, and then the 9th will wake up on next tick, 10th on next tick. If for 5 ticks no more inactive wake up, our buffer will have built back up to 5, and then 5 can go next needed tick. This basically incrementally wakes them up, preventing too many from waking up in a single tick, to reduce impact to TPS. --- ...atch => Entity-Activation-Range-2.0.patch} | 310 +++++++++++++++--- Spigot-Server-Patches/Entity-Jump-API.patch | 15 +- ...Crash-support-and-Improve-Async-Shut.patch | 4 +- ...imise-entity-hard-collision-checking.patch | 6 +- ...e-getChunkAt-calls-for-loaded-chunks.patch | 4 +- .../Optimise-random-block-ticking.patch | 4 +- ...-Villager-AI-optimizations-DROP-1.16.patch | 2 +- .../Seed-based-feature-search.patch | 10 +- .../Tracking-Range-Improvements.patch | 4 +- 9 files changed, 287 insertions(+), 72 deletions(-) rename Spigot-Server-Patches/{Activation-Range-Improvements.patch => Entity-Activation-Range-2.0.patch} (60%) diff --git a/Spigot-Server-Patches/Activation-Range-Improvements.patch b/Spigot-Server-Patches/Entity-Activation-Range-2.0.patch similarity index 60% rename from Spigot-Server-Patches/Activation-Range-Improvements.patch rename to Spigot-Server-Patches/Entity-Activation-Range-2.0.patch index 6bbe58756..b2e2e48f1 100644 --- a/Spigot-Server-Patches/Activation-Range-Improvements.patch +++ b/Spigot-Server-Patches/Entity-Activation-Range-2.0.patch @@ -1,16 +1,32 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 13 May 2016 01:38:06 -0400 -Subject: [PATCH] Activation Range Improvements +Subject: [PATCH] Entity Activation Range 2.0 Optimizes performance of Activation Range +Adds many new configurations and a new wake up inactive system + Fixes and adds new Immunities to improve gameplay behavior Adds water Mobs to activation range config and nerfs fish +Adds flying monsters to control ghast and phantoms +Adds villagers as separate config +diff --git a/src/main/java/net/minecraft/server/BehaviorController.java b/src/main/java/net/minecraft/server/BehaviorController.java +index a1883eba63..7c6e687707 100644 +--- a/src/main/java/net/minecraft/server/BehaviorController.java ++++ b/src/main/java/net/minecraft/server/BehaviorController.java +@@ -0,0 +0,0 @@ public class BehaviorController implements MinecraftSeri + }); + } + ++ public boolean hasActivity(Activity activity) { return c(activity); } // Paper - OBFHELPER + public boolean c(Activity activity) { + return this.g.contains(activity); + } diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 0900db05..6509463e 100644 +index 0900db052d..57c289bab9 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -34,7 +50,7 @@ index 0900db05..6509463e 100644 this.setMot(Vec3D.a); } + // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof EntityItem) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { ++ if (isTemporarilyActive && !(this instanceof EntityItem || this instanceof EntityMinecartAbstract) && vec3d == getMot() && enummovetype == EnumMoveType.SELF) { + setMot(Vec3D.a); + this.world.getMethodProfiler().exit(); + return; @@ -52,7 +68,7 @@ index 0900db05..6509463e 100644 // Paper start return this.pushedByWater(); diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java -index b40c8d2f..4eda1307 100644 +index b40c8d2f83..4eda130750 100644 --- a/src/main/java/net/minecraft/server/EntityCreature.java +++ b/src/main/java/net/minecraft/server/EntityCreature.java @@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityUnleashEvent; @@ -64,9 +80,18 @@ index b40c8d2f..4eda1307 100644 protected EntityCreature(EntityTypes entitytypes, World world) { super(entitytypes, world); diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java -index 6d53254f..1991cee4 100644 +index 6d53254f83..5aca7a9131 100644 --- a/src/main/java/net/minecraft/server/EntityInsentient.java +++ b/src/main/java/net/minecraft/server/EntityInsentient.java +@@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { + public MinecraftKey lootTableKey; + public long lootTableSeed; + @Nullable +- private Entity leashHolder; ++ public Entity leashHolder; // Paper + private int bF; + @Nullable + private NBTTagCompound bG; @@ -0,0 +0,0 @@ public abstract class EntityInsentient extends EntityLiving { return this.lookController; } @@ -85,8 +110,21 @@ index 6d53254f..1991cee4 100644 public ControllerMove getControllerMove() { if (this.isPassenger() && this.getVehicle() instanceof EntityInsentient) { EntityInsentient entityinsentient = (EntityInsentient) this.getVehicle(); +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 1b9551ae09..158ae4ff68 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { + protected float aV; + protected int aW; protected int getKillCount() { return this.aW; } // Paper - OBFHELPER + public float lastDamage; +- protected boolean jumping; ++ public boolean jumping; // Paper + public float aZ; + public float ba; + public float bb; diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java -index 6d4d41c8..193dbfc5 100644 +index 6d4d41c88c..193dbfc5f6 100644 --- a/src/main/java/net/minecraft/server/EntityLlama.java +++ b/src/main/java/net/minecraft/server/EntityLlama.java @@ -0,0 +0,0 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn @@ -98,7 +136,7 @@ index 6d4d41c8..193dbfc5 100644 return this.bJ != null; } diff --git a/src/main/java/net/minecraft/server/PathfinderGoal.java b/src/main/java/net/minecraft/server/PathfinderGoal.java -index f22f12ee..bdb90a34 100644 +index f22f12eeb0..bdb90a3466 100644 --- a/src/main/java/net/minecraft/server/PathfinderGoal.java +++ b/src/main/java/net/minecraft/server/PathfinderGoal.java @@ -0,0 +0,0 @@ public abstract class PathfinderGoal { @@ -114,7 +152,7 @@ index f22f12ee..bdb90a34 100644 public void e() {} diff --git a/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java -index 41fb166c..e93129f0 100644 +index 41fb166ce0..e93129f0b2 100644 --- a/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java +++ b/src/main/java/net/minecraft/server/PathfinderGoalGotoTarget.java @@ -0,0 +0,0 @@ import java.util.EnumSet; @@ -155,7 +193,7 @@ index 41fb166c..e93129f0 100644 } } diff --git a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java -index 44bb18c5..93513677 100644 +index 44bb18c594..935136771e 100644 --- a/src/main/java/net/minecraft/server/PathfinderGoalSelector.java +++ b/src/main/java/net/minecraft/server/PathfinderGoalSelector.java @@ -0,0 +0,0 @@ public class PathfinderGoalSelector { @@ -199,7 +237,7 @@ index 44bb18c5..93513677 100644 this.d.stream().filter((pathfindergoalwrapped) -> { return pathfindergoalwrapped.j() == pathfindergoal; diff --git a/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java -index 5a8c60ad..29657fed 100644 +index 5a8c60ad90..29657fed75 100644 --- a/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java +++ b/src/main/java/net/minecraft/server/PathfinderGoalWrapped.java @@ -0,0 +0,0 @@ public class PathfinderGoalWrapped extends PathfinderGoal { @@ -210,13 +248,33 @@ index 5a8c60ad..29657fed 100644 public boolean g() { return this.c; } +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 9e161746f2..228e6e9ab9 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { + public long ticksPerMonsterSpawns; + public long ticksPerWaterSpawns; + public long ticksPerAmbientSpawns; ++ // Paper start ++ public int wakeupInactiveRemainingAnimals; ++ public int wakeupInactiveRemainingFlying; ++ public int wakeupInactiveRemainingMonsters; ++ public int wakeupInactiveRemainingVillagers; ++ // Paper end + public boolean populating; + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 92601c58..79581717 100644 +index 92601c581c..92f19fcbb1 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java @@ -0,0 +0,0 @@ package org.spigotmc; + import java.util.Collection; import java.util.List; ++ ++import net.minecraft.server.Activity; import net.minecraft.server.AxisAlignedBB; +import net.minecraft.server.BehaviorController; +import net.minecraft.server.BlockPosition; @@ -230,7 +288,9 @@ index 92601c58..79581717 100644 import net.minecraft.server.EntityComplexPart; import net.minecraft.server.EntityCreature; import net.minecraft.server.EntityCreeper; -@@ -0,0 +0,0 @@ import net.minecraft.server.EntityEnderDragon; + import net.minecraft.server.EntityEnderCrystal; + import net.minecraft.server.EntityEnderDragon; ++import net.minecraft.server.EntityEnderSignal; import net.minecraft.server.EntityFallingBlock; // Paper import net.minecraft.server.EntityFireball; import net.minecraft.server.EntityFireworks; @@ -244,9 +304,11 @@ index 92601c58..79581717 100644 import net.minecraft.server.EntityProjectile; import net.minecraft.server.EntityRaider; import net.minecraft.server.EntitySheep; -@@ -0,0 +0,0 @@ import net.minecraft.server.EntityThrownTrident; +@@ -0,0 +0,0 @@ import net.minecraft.server.EntityTNTPrimed; + import net.minecraft.server.EntityThrownTrident; import net.minecraft.server.EntityVillager; import net.minecraft.server.EntityWither; ++import net.minecraft.server.IMonster; import net.minecraft.server.MathHelper; +import net.minecraft.server.MemoryModuleType; import net.minecraft.server.MinecraftServer; @@ -264,22 +326,95 @@ index 92601c58..79581717 100644 public enum ActivationType { + WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper MONSTER, ANIMAL, RAIDER, +@@ -0,0 +0,0 @@ public class ActivationRange + + AxisAlignedBB boundingBox = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); + } ++ // Paper start ++ static MemoryModuleType[] VILLAGER_IMMUNITIES = { ++ MemoryModuleType.LOOK_TARGET, ++ MemoryModuleType.INTERACTION_TARGET, ++ MemoryModuleType.WALK_TARGET, ++ MemoryModuleType.HIDING_PLACE, ++ MemoryModuleType.PATH, ++ MemoryModuleType.SECONDARY_JOB_SITE ++ }; ++ ++ static Activity[] VILLAGER_ACTIVITY_IMMUNITIES = { ++ Activity.HIDE, ++ Activity.PRE_RAID, ++ Activity.RAID, ++ Activity.WORK, ++ Activity.PANIC ++ }; ++ ++ private static int checkInactiveWakeup(Entity entity) { ++ World world = entity.world; ++ SpigotWorldConfig config = world.spigotConfig; ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ if (entity.activationType == ActivationType.VILLAGER) { ++ if (inactiveFor > config.wakeUpInactiveVillagersEvery && world.wakeupInactiveRemainingVillagers > 0) { ++ world.wakeupInactiveRemainingVillagers--; ++ return config.wakeUpInactiveVillagersFor; ++ } ++ } else if (entity.activationType == ActivationType.ANIMAL) { ++ if (inactiveFor > config.wakeUpInactiveAnimalsEvery && world.wakeupInactiveRemainingAnimals > 0) { ++ world.wakeupInactiveRemainingAnimals--; ++ return config.wakeUpInactiveAnimalsFor; ++ } ++ } else if (entity.activationType == ActivationType.FLYING_MONSTER) { ++ if (inactiveFor > config.wakeUpInactiveFlyingEvery && world.wakeupInactiveRemainingFlying > 0) { ++ world.wakeupInactiveRemainingFlying--; ++ return config.wakeUpInactiveFlyingFor; ++ } ++ } else if (entity.activationType == ActivationType.MONSTER || entity.activationType == ActivationType.RAIDER) { ++ if (inactiveFor > config.wakeUpInactiveMonstersEvery && world.wakeupInactiveRemainingMonsters > 0) { ++ world.wakeupInactiveRemainingMonsters--; ++ return config.wakeUpInactiveMonstersFor; ++ } ++ } ++ return -1; ++ } ++ // Paper end + + static AxisAlignedBB maxBB = new AxisAlignedBB( 0, 0, 0, 0, 0, 0 ); + @@ -0,0 +0,0 @@ public class ActivationRange */ public static ActivationType initializeEntityActivationType(Entity entity) { + if (entity instanceof EntityWaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof EntityVillager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof EntityFlying && entity instanceof IMonster) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future if ( entity instanceof EntityRaider ) { return ActivationType.RAIDER; +- } else if ( entity instanceof EntityMonster || entity instanceof EntitySlime ) ++ } else if ( entity instanceof IMonster ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof EntityCreature || entity instanceof EntityAmbient ) @@ -0,0 +0,0 @@ public class ActivationRange - || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) - || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) - || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) -+ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange == 0 ) // Paper + */ + public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) + { +- if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange == 0 ) +- || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange == 0 ) +- || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange == 0 ) +- || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange == 0 ) ++ if ( ( entity.activationType == ActivationType.MISC && config.miscActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.RAIDER && config.raiderActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.ANIMAL && config.animalActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.MONSTER && config.monsterActivationRange <= 0 ) ++ || ( entity.activationType == ActivationType.VILLAGER && config.villagerActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.WATER && config.waterActivationRange <= 0 ) // Paper ++ || ( entity.activationType == ActivationType.FLYING_MONSTER && config.flyingMonsterActivationRange <= 0 ) // Paper ++ || entity instanceof EntityEnderSignal // Paper || entity instanceof EntityHuman || entity instanceof EntityProjectile || entity instanceof EntityEnderDragon @@ -287,17 +422,37 @@ index 92601c58..79581717 100644 final int raiderActivationRange = world.spigotConfig.raiderActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; final int monsterActivationRange = world.spigotConfig.monsterActivationRange; -+ final int waterActivationRange = world.spigotConfig.waterActivationRange; // Paper -+ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); // Paper ++ // Paper start ++ final int waterActivationRange = world.spigotConfig.waterActivationRange; ++ final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; ++ final int villagerActivationRange = world.spigotConfig.villagerActivationRange; ++ world.wakeupInactiveRemainingAnimals = Math.min(world.wakeupInactiveRemainingAnimals + 1, world.spigotConfig.wakeUpInactiveAnimals); ++ world.wakeupInactiveRemainingVillagers = Math.min(world.wakeupInactiveRemainingVillagers + 1, world.spigotConfig.wakeUpInactiveVillagers); ++ world.wakeupInactiveRemainingMonsters = Math.min(world.wakeupInactiveRemainingMonsters + 1, world.spigotConfig.wakeUpInactiveMonsters); ++ world.wakeupInactiveRemainingFlying = Math.min(world.wakeupInactiveRemainingFlying + 1, world.spigotConfig.wakeUpInactiveFlying); ++ final ChunkProviderServer chunkProvider = (ChunkProviderServer) world.getChunkProvider(); ++ // Paper end int maxRange = Math.max( monsterActivationRange, animalActivationRange ); maxRange = Math.max( maxRange, raiderActivationRange ); + maxRange = Math.max( maxRange, miscActivationRange ); ++ // Paper start ++ maxRange = Math.max( maxRange, flyingActivationRange ); ++ maxRange = Math.max( maxRange, waterActivationRange ); ++ maxRange = Math.max( maxRange, villagerActivationRange ); ++ // Paper end + maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); + + for ( EntityHuman player : world.getPlayers() ) @@ -0,0 +0,0 @@ public class ActivationRange ActivationType.RAIDER.boundingBox = player.getBoundingBox().grow( raiderActivationRange, 256, raiderActivationRange ); ActivationType.ANIMAL.boundingBox = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange ); ActivationType.MONSTER.boundingBox = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange ); -+ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); // Paper -+ ++ // Paper start ++ ActivationType.WATER.boundingBox = player.getBoundingBox().grow( waterActivationRange, 256, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().grow( flyingActivationRange, 256, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().grow( villagerActivationRange, 256, waterActivationRange ); ++ // Paper end int i = MathHelper.floor( maxBB.minX / 16.0D ); int j = MathHelper.floor( maxBB.maxX / 16.0D ); @@ -345,9 +500,18 @@ index 92601c58..79581717 100644 - public static boolean checkEntityImmunities(Entity entity) + public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity { ++ // Paper start ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.fireTicks > 0) { ++ return 2; ++ } ++ // Paper end // quick checks. - if ( entity.inWater || entity.fireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.pushedByWater()) || entity.fireTicks > 0 ) // Paper ++ if ( (entity.activationType != ActivationType.WATER && entity.inWater && entity.isPushedByWater()) ) // Paper { - return true; + return 100; // Paper @@ -367,9 +531,10 @@ index 92601c58..79581717 100644 } // special cases. if ( entity instanceof EntityLiving ) -@@ -0,0 +0,0 @@ public class ActivationRange + { EntityLiving living = (EntityLiving) entity; - if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTicks > 0 || living.effects.size() > 0 ) ++ if ( living.isClimbing() || living.jumping || living.hurtTicks > 0 || living.effects.size() > 0 ) // Paper { - return true; + return 1; // Paper @@ -389,22 +554,28 @@ index 92601c58..79581717 100644 + (bee.getFlowerPos() != null && bee.getFlowerPos().equals(movingTarget)) + ) { + return 20; ++ } ++ } ++ if ( entity instanceof EntityVillager ) { ++ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); ++ ++ for (Activity activity : VILLAGER_ACTIVITY_IMMUNITIES) { ++ if (behaviorController.hasActivity(activity)) { ++ return 5; ++ } ++ } ++ for (MemoryModuleType type : VILLAGER_IMMUNITIES) { ++ if (behaviorController.hasMemory(type)) { ++ return 5; ++ } + } } - if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) +- if ( entity instanceof EntityVillager && ( (EntityVillager) entity ).canBreed() ) ++ if ( entity instanceof EntityLlama && ( (EntityLlama ) entity ).inCaravan() ) { - return true; -+ BehaviorController behaviorController = ((EntityVillager) entity).getBehaviorController(); -+ if (behaviorController.hasMemory(MemoryModuleType.BREED_TARGET)) { -+ return 1; -+ } -+ // Paper end ++ return 1; } -+ // Paper start -+ if ( entity instanceof EntityLlama && ( (EntityLlama ) entity ).inCaravan() ) -+ { -+ return 0; -+ } + // Paper end if ( entity instanceof EntityAnimal ) { @@ -412,7 +583,7 @@ index 92601c58..79581717 100644 if ( animal.isBaby() || animal.isInLove() ) { - return true; -+ return 1; // Paper ++ return 5; // Paper } if ( entity instanceof EntitySheep && ( (EntitySheep) entity ).isSheared() ) { @@ -423,11 +594,11 @@ index 92601c58..79581717 100644 if (entity instanceof EntityCreeper && ((EntityCreeper) entity).isIgnited()) { // isExplosive - return true; + return 20; // Paper -+ } + } + // Paper start + if (entity instanceof EntityInsentient && ((EntityInsentient) entity).targetSelector.hasTasks() ) { + return 0; - } ++ } + if (entity instanceof EntityPillager) { + EntityPillager pillager = (EntityPillager) entity; + // TODO:? @@ -440,9 +611,22 @@ index 92601c58..79581717 100644 /** @@ -0,0 +0,0 @@ public class ActivationRange + if ( !entity.inChunk || entity instanceof EntityFireworks ) { + return true; } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.ticksLived < 20*10 || !entity.isAlive() || entity.inPortal() || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof EntityInsentient && ((EntityInsentient)entity).leashHolder instanceof EntityHuman) { ++ return true; ++ } ++ // Paper end - boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; +- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; + entity.isTemporarilyActive = false; // Paper // Should this entity tick? @@ -468,27 +652,65 @@ index 92601c58..79581717 100644 } // Add a little performance juice to active entities. Skip 1/4 if not immune. - } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if ( !entity.defaultActivationState && entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper ++ } else if (entity.ticksLived % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper { isActive = false; } diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index 5e932a5d..1b42ba94 100644 +index 5e932a5d97..5a704c60fd 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -0,0 +0,0 @@ public class SpigotWorldConfig public int monsterActivationRange = 32; public int raiderActivationRange = 48; public int miscActivationRange = 16; -+ public int waterActivationRange = 16; // Paper ++ // Paper start ++ public int flyingMonsterActivationRange = 32; ++ public int waterActivationRange = 16; ++ public int villagerActivationRange = 32; ++ public int wakeUpInactiveAnimals = 4; ++ public int wakeUpInactiveAnimalsEvery = 60*20; ++ public int wakeUpInactiveAnimalsFor = 5*20; ++ public int wakeUpInactiveMonsters = 8; ++ public int wakeUpInactiveMonstersEvery = 20*20; ++ public int wakeUpInactiveMonstersFor = 5*20; ++ public int wakeUpInactiveVillagers = 4; ++ public int wakeUpInactiveVillagersEvery = 15*20; ++ public int wakeUpInactiveVillagersFor = 5*20; ++ public int wakeUpInactiveFlying = 8; ++ public int wakeUpInactiveFlyingEvery = 10*20; ++ public int wakeUpInactiveFlyingFor = 5*20; ++ // Paper end public boolean tickInactiveVillagers = true; private void activationRange() { -@@ -0,0 +0,0 @@ public class SpigotWorldConfig ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper + animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); // Paper ++ // Paper start ++ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); ++ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); ++ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ ++ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); ++ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); ++ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ ++ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); ++ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); ++ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ ++ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); ++ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); ++ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ ++ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); ++ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); ++ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ ++ // Paper end tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); } diff --git a/Spigot-Server-Patches/Entity-Jump-API.patch b/Spigot-Server-Patches/Entity-Jump-API.patch index ef8124546..c60d7df5e 100644 --- a/Spigot-Server-Patches/Entity-Jump-API.patch +++ b/Spigot-Server-Patches/Entity-Jump-API.patch @@ -5,18 +5,9 @@ Subject: [PATCH] Entity Jump API diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 1b9551ae..ad474500 100644 +index 158ae4ff68..1e6106f2ba 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { - protected float aV; - protected int aW; protected int getKillCount() { return this.aW; } // Paper - OBFHELPER - public float lastDamage; -- protected boolean jumping; -+ public boolean jumping; // Paper - protected -> public - public float aZ; - public float ba; - public float bb; @@ -0,0 +0,0 @@ public abstract class EntityLiving extends Entity { } else if (this.aH()) { this.c(TagsFluid.LAVA); @@ -29,7 +20,7 @@ index 1b9551ae..ad474500 100644 } else { this.jumpTicks = 0; diff --git a/src/main/java/net/minecraft/server/EntityPanda.java b/src/main/java/net/minecraft/server/EntityPanda.java -index cd41c80f..f50ed190 100644 +index cd41c80f19..f50ed19080 100644 --- a/src/main/java/net/minecraft/server/EntityPanda.java +++ b/src/main/java/net/minecraft/server/EntityPanda.java @@ -0,0 +0,0 @@ public class EntityPanda extends EntityAnimal { @@ -43,7 +34,7 @@ index cd41c80f..f50ed190 100644 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 6de01e4f..8ffa3cb0 100644 +index 6de01e4f0e..8ffa3cb059 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { diff --git a/Spigot-Server-Patches/Forced-Watchdog-Crash-support-and-Improve-Async-Shut.patch b/Spigot-Server-Patches/Forced-Watchdog-Crash-support-and-Improve-Async-Shut.patch index 1aa860769..25f84e357 100644 --- a/Spigot-Server-Patches/Forced-Watchdog-Crash-support-and-Improve-Async-Shut.patch +++ b/Spigot-Server-Patches/Forced-Watchdog-Crash-support-and-Improve-Async-Shut.patch @@ -73,7 +73,7 @@ index cfe43e882e..2632c7c3ec 100644 } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 01534d19d4..94daf684b1 100644 +index 5f57a9e1c8..98f0398348 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant implements MinecraftSeri diff --git a/Spigot-Server-Patches/Seed-based-feature-search.patch b/Spigot-Server-Patches/Seed-based-feature-search.patch index 8da1d81b8..a6511a977 100644 --- a/Spigot-Server-Patches/Seed-based-feature-search.patch +++ b/Spigot-Server-Patches/Seed-based-feature-search.patch @@ -15,7 +15,7 @@ changes but this should usually not happen. A config option to disable this improvement is added though in case that should ever be necessary. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3b8488d3..bce50218 100644 +index 3b8488d3ff..bce502181f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -0,0 +0,0 @@ public class PaperWorldConfig { @@ -32,7 +32,7 @@ index 3b8488d3..bce50218 100644 private void maxEntityCollision() { maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) ); diff --git a/src/main/java/net/minecraft/server/BiomeManager.java b/src/main/java/net/minecraft/server/BiomeManager.java -index e96f544f..68423645 100644 +index e96f544f12..68423645df 100644 --- a/src/main/java/net/minecraft/server/BiomeManager.java +++ b/src/main/java/net/minecraft/server/BiomeManager.java @@ -0,0 +0,0 @@ public class BiomeManager { @@ -49,7 +49,7 @@ index e96f544f..68423645 100644 return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a); } diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java -index f2a19acd..09f1308b 100644 +index f2a19acd84..09f1308b0d 100644 --- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java +++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java @@ -0,0 +0,0 @@ public class ChunkCoordIntPair { @@ -66,7 +66,7 @@ index f2a19acd..09f1308b 100644 return this.z << 4; } diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java -index e8ce2ecf..acfe732a 100644 +index e8ce2ecf23..acfe732af5 100644 --- a/src/main/java/net/minecraft/server/StructureGenerator.java +++ b/src/main/java/net/minecraft/server/StructureGenerator.java @@ -0,0 +0,0 @@ public abstract class StructureGenerator @@ -94,7 +94,7 @@ index e8ce2ecf..acfe732a 100644 public abstract StructureGenerator.a a(); diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 48c75af8..79d8c7ba 100644 +index 228e6e9ab9..f1d072a39c 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java @@ -0,0 +0,0 @@ public abstract class World implements GeneratorAccess, AutoCloseable { diff --git a/Spigot-Server-Patches/Tracking-Range-Improvements.patch b/Spigot-Server-Patches/Tracking-Range-Improvements.patch index fe4d5907d..a1d3ce7bc 100644 --- a/Spigot-Server-Patches/Tracking-Range-Improvements.patch +++ b/Spigot-Server-Patches/Tracking-Range-Improvements.patch @@ -20,7 +20,7 @@ index a7b981f299..043ba702d7 100644 if (j > i) { i = j; diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java -index 6f8e6c1d07..46c33e6917 100644 +index 6f8e6c1d07..765bdaf9b5 100644 --- a/src/main/java/org/spigotmc/TrackingRange.java +++ b/src/main/java/org/spigotmc/TrackingRange.java @@ -0,0 +0,0 @@ @@ -47,6 +47,7 @@ index 6f8e6c1d07..46c33e6917 100644 + switch (entity.activationType) { + case RAIDER: + case MONSTER: ++ case FLYING_MONSTER: return config.monsterTrackingRange; - } else - { @@ -57,6 +58,7 @@ index 6f8e6c1d07..46c33e6917 100644 - return config.animalTrackingRange; - } else if ( entity instanceof EntityItemFrame || entity instanceof EntityPainting || entity instanceof EntityItem || entity instanceof EntityExperienceOrb ) + case WATER: ++ case VILLAGER: + case ANIMAL: + return config.animalTrackingRange; + case MISC: