diff options
Diffstat (limited to 'patches/server/0332-Entity-Activation-Range-2.0.patch')
-rw-r--r-- | patches/server/0332-Entity-Activation-Range-2.0.patch | 815 |
1 files changed, 815 insertions, 0 deletions
diff --git a/patches/server/0332-Entity-Activation-Range-2.0.patch b/patches/server/0332-Entity-Activation-Range-2.0.patch new file mode 100644 index 0000000000..2c2297baeb --- /dev/null +++ b/patches/server/0332-Entity-Activation-Range-2.0.patch @@ -0,0 +1,815 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar <[email protected]> +Date: Fri, 13 May 2016 01:38:06 -0400 +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 + +== AT == +public net.minecraft.world.entity.Entity isInsidePortal +public net.minecraft.world.entity.LivingEntity jumping + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 316f6b2c111b4f8a5ae0fa4dcb9695fa5ec62ede..2a3d4a041345d5478916f4d2c5c3c382fca5758f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -2,7 +2,6 @@ package net.minecraft.server.level; + + import com.google.common.annotations.VisibleForTesting; + import co.aikar.timings.TimingHistory; // Paper +-import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.mojang.datafixers.DataFixer; + import com.mojang.datafixers.util.Pair; +@@ -1207,17 +1206,17 @@ public class ServerLevel extends Level implements WorldGenLevel { + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below + entity.tickCount++; + timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.setOldPosAndRot(); +@@ -1228,9 +1227,13 @@ public class ServerLevel extends Level implements WorldGenLevel { + return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + this.getProfiler().pop(); ++ } finally { timer.stopTiming(); } // Paper - timings + Iterator iterator = entity.getPassengers().iterator(); + + while (iterator.hasNext()) { +@@ -1238,13 +1241,18 @@ public class ServerLevel extends Level implements WorldGenLevel { + + this.tickPassenger(entity, entity1); + } +- } finally { timer.stopTiming(); } // Paper - timings ++ // } finally { timer.stopTiming(); } // Paper - timings - move up + + } + + private void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.entityTickList.contains(passenger)) { ++ // Paper - EAR 2 ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); ++ co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper ++ try { ++ // Paper end + passenger.setOldPosAndRot(); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = this.getProfiler(); +@@ -1253,8 +1261,17 @@ public class ServerLevel extends Level implements WorldGenLevel { + return BuiltInRegistries.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.positionRider(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + Iterator iterator = passenger.getPassengers().iterator(); + +@@ -1264,6 +1281,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + this.tickPassenger(passenger, entity2); + } + ++ } finally { timer.stopTiming(); }// Paper - EAR2 timings + } + } else { + passenger.stopRiding(); +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 5397d84d790c32d369b0726db16571348285d8fb..b65c8b48c3a3dd71cb5945dca104cc67a1f2ce6d 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -395,6 +395,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + public void inactiveTick() { } + // Spigot end + // Paper start ++ public long activatedImmunityTick = Integer.MIN_VALUE; // Paper ++ public boolean isTemporarilyActive = false; // Paper + protected int numCollisions = 0; // Paper + public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one + @javax.annotation.Nullable +@@ -967,6 +969,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + } else { + this.wasOnFire = this.isOnFire(); + if (movementType == MoverType.PISTON) { ++ this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20); // Paper ++ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20); // Paper + movement = this.limitPistonMovement(movement); + if (movement.equals(Vec3.ZERO)) { + return; +@@ -979,6 +983,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S + this.stuckSpeedMultiplier = Vec3.ZERO; + this.setDeltaMovement(Vec3.ZERO); + } ++ // Paper start - ignore movement changes while inactive. ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) { ++ setDeltaMovement(Vec3.ZERO); ++ this.level.getProfiler().pop(); ++ return; ++ } ++ // Paper end + + movement = this.maybeBackOffFromEdge(movement, movementType); + Vec3 vec3d1 = this.collide(movement); +diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java +index efef5df4cf720058c0b07ef795cfa6a567113811..d330b6d291cd2967358e892ccbc480bb3bd8022d 100644 +--- a/src/main/java/net/minecraft/world/entity/Mob.java ++++ b/src/main/java/net/minecraft/world/entity/Mob.java +@@ -221,6 +221,19 @@ public abstract class Mob extends LivingEntity implements Targeting { + return this.lookControl; + } + ++ // Paper start ++ @Override ++ public void inactiveTick() { ++ super.inactiveTick(); ++ if (this.goalSelector.inactiveTick()) { ++ this.goalSelector.tick(); ++ } ++ if (this.targetSelector.inactiveTick()) { ++ this.targetSelector.tick(); ++ } ++ } ++ // Paper end ++ + public MoveControl getMoveControl() { + Entity entity = this.getControlledVehicle(); + +diff --git a/src/main/java/net/minecraft/world/entity/PathfinderMob.java b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +index 5e9cf929674888b3a143a0691dc6936b304467f1..b5964614823059261c28eb2e998ad54249f07e7b 100644 +--- a/src/main/java/net/minecraft/world/entity/PathfinderMob.java ++++ b/src/main/java/net/minecraft/world/entity/PathfinderMob.java +@@ -21,6 +21,7 @@ public abstract class PathfinderMob extends Mob { + } + + public org.bukkit.craftbukkit.entity.CraftCreature getBukkitCreature() { return (org.bukkit.craftbukkit.entity.CraftCreature) super.getBukkitEntity(); } // Paper ++ public BlockPos movingTarget = null; public BlockPos getMovingTarget() { return movingTarget; } // Paper + + public float getWalkTargetValue(BlockPos pos) { + return this.getWalkTargetValue(pos, this.level()); +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +index 07c1ca01c38d5d7d0a95ad5004b5df9f4a222935..e5995d0db5dcfba59a873ff439601894fdacd556 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +@@ -33,6 +33,7 @@ public class GoalSelector { + private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class); + private int tickCount; + private int newGoalRate = 3; ++ private int curRate; + + public GoalSelector(Supplier<ProfilerFiller> profiler) { + this.profiler = profiler; +@@ -49,6 +50,20 @@ public class GoalSelector { + }); + } + ++ // Paper start ++ public boolean inactiveTick() { ++ this.curRate++; ++ return this.curRate % this.newGoalRate == 0; ++ } ++ public boolean hasTasks() { ++ for (WrappedGoal task : this.availableGoals) { ++ if (task.isRunning()) { ++ return true; ++ } ++ } ++ return false; ++ } ++ // Paper end + public void removeGoal(Goal goal) { + this.availableGoals.stream().filter((wrappedGoal) -> { + return wrappedGoal.getGoal() == goal; +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +index 7153e00a640abfeb134ff1dcb93f363b972a4233..4bbc36404b396500df0d9db380cf223b5897662e 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +@@ -14,7 +14,7 @@ public abstract class MoveToBlockGoal extends Goal { + protected int nextStartTick; + protected int tryTicks; + private int maxStayTicks; +- protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos = BlockPos.ZERO; @Deprecated public final BlockPos getTargetPosition() { return this.blockPos; } @Deprecated public void setTargetPosition(BlockPos pos) { this.blockPos = pos; mob.movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER + private boolean reachedTarget; + private final int searchRange; + private final int verticalSearchRange; +@@ -23,6 +23,13 @@ public abstract class MoveToBlockGoal extends Goal { + public MoveToBlockGoal(PathfinderMob mob, double speed, int range) { + this(mob, speed, range, 1); + } ++ // Paper start - activation range improvements ++ @Override ++ public void stop() { ++ super.stop(); ++ setTargetPosition(BlockPos.ZERO); ++ } ++ // Paper end + + public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { + this.mob = mob; +@@ -114,6 +121,7 @@ public abstract class MoveToBlockGoal extends Goal { + mutableBlockPos.setWithOffset(blockPos, m, k - 1, n); + if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) { + this.blockPos = mutableBlockPos; ++ setTargetPosition(mutableBlockPos.immutable()); // Paper + return true; + } + } +diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java +index 0429b927e63ec12f53a6ce1ebe1e64d99bf7e129..c0aa370367856a159412dd141f683b7d51e11c8b 100644 +--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java ++++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java +@@ -227,17 +227,34 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public void inactiveTick() { + // SPIGOT-3874, SPIGOT-3894, SPIGOT-3846, SPIGOT-5286 :( +- if (this.level().spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { +- this.customServerAiStep(); ++ // Paper start ++ if (this.getUnhappyCounter() > 0) { ++ this.setUnhappyCounter(this.getUnhappyCounter() - 1); + } ++ if (this.isEffectiveAi()) { ++ if (this.level().spigotConfig.tickInactiveVillagers) { ++ this.customServerAiStep(); ++ } else { ++ this.customServerAiStep(true); ++ } ++ } ++ maybeDecayGossip(); ++ // Paper end ++ + super.inactiveTick(); + } + // Spigot End + + @Override ++ @Deprecated // Paper + protected void customServerAiStep() { ++ // Paper start ++ this.customServerAiStep(false); ++ } ++ protected void customServerAiStep(final boolean inactive) { ++ // Paper end + this.level().getProfiler().push("villagerBrain"); +- this.getBrain().tick((ServerLevel) this.level(), this); ++ if (!inactive) this.getBrain().tick((ServerLevel) this.level(), this); // Paper + this.level().getProfiler().pop(); + if (this.assignProfessionWhenSpawned) { + this.assignProfessionWhenSpawned = false; +@@ -261,7 +278,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + this.lastTradedPlayer = null; + } + +- if (!this.isNoAi() && this.random.nextInt(100) == 0) { ++ if (!inactive && !this.isNoAi() && this.random.nextInt(100) == 0) { // Paper + Raid raid = ((ServerLevel) this.level()).getRaidAt(this.blockPosition()); + + if (raid != null && raid.isActive() && !raid.isOver()) { +@@ -272,6 +289,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + if (this.getVillagerData().getProfession() == VillagerProfession.NONE && this.isTrading()) { + this.stopTrading(); + } ++ if (inactive) return; // Paper + + super.customServerAiStep(); + } +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +index b149e8bcac034bb3fc118a9adcb0de45e18ed5e9..fc35cfc9d045f3e5b6a50af1d0ba83b6e322091f 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +@@ -52,6 +52,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + if (bl != this.isEnabled()) { + this.setEnabled(bl); + } ++ this.immunize(); // Paper + + } + +@@ -89,10 +90,12 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + + public boolean suckInItems() { + if (HopperBlockEntity.suckInItems(this.level(), this)) { ++ this.immunize(); // Paper + return true; + } else { + for(ItemEntity itemEntity : this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate(0.25D, 0.0D, 0.25D), EntitySelector.ENTITY_STILL_ALIVE)) { + if (HopperBlockEntity.addItem(this, itemEntity)) { ++ this.immunize(); // Paper + return true; + } + } +@@ -122,4 +125,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory) { + return new HopperMenu(syncId, playerInventory, this); + } ++ ++ // Paper start ++ public void immunize() { ++ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, net.minecraft.server.MinecraftServer.currentTick + 20); ++ } ++ // Paper end ++ + } +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index f300b637466b7e591a4d7e19dd7cfefa7f954e6a..2e5b01cc9c438a2bee7eb770e4c266425a9d287f 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -163,6 +163,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public Map<BlockPos, BlockEntity> capturedTileEntities = new HashMap<>(); + public List<ItemEntity> captureDrops; + public final it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<SpawnCategory> ticksPerSpawnCategory = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>(); ++ // 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 + // Paper start +diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index 45f55c79a9d105f732054d61c4cf83eb5db49762..17a6327ab7b26dfab38881bbc0689b0b25f8f025 100644 +--- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -143,6 +143,10 @@ public class PistonMovingBlockEntity extends BlockEntity { + } + + entity.setDeltaMovement(e, g, h); ++ // Paper - EAR items stuck in in slime pushed by a piston ++ entity.activatedTick = Math.max(entity.activatedTick, net.minecraft.server.MinecraftServer.currentTick + 10); ++ entity.activatedImmunityTick = Math.max(entity.activatedImmunityTick, net.minecraft.server.MinecraftServer.currentTick + 10); ++ // Paper end + break; + } + } +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index d5374072a97f791964033d107f023b3cc657b343..f76b3f410fcc756bb34a5fac21b1d7088ac7a9ce 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -1,39 +1,52 @@ + package org.spigotmc; + ++import net.minecraft.core.BlockPos; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerChunkCache; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.ExperienceOrb; ++import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LightningBolt; + import net.minecraft.world.entity.LivingEntity; ++import net.minecraft.world.entity.Mob; + import net.minecraft.world.entity.PathfinderMob; ++import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ambient.AmbientCreature; + import net.minecraft.world.entity.animal.Animal; ++import net.minecraft.world.entity.animal.Bee; + import net.minecraft.world.entity.animal.Sheep; ++import net.minecraft.world.entity.animal.WaterAnimal; ++import net.minecraft.world.entity.animal.horse.Llama; + import net.minecraft.world.entity.boss.EnderDragonPart; + import net.minecraft.world.entity.boss.enderdragon.EndCrystal; + import net.minecraft.world.entity.boss.enderdragon.EnderDragon; + import net.minecraft.world.entity.boss.wither.WitherBoss; + import net.minecraft.world.entity.item.PrimedTnt; + import net.minecraft.world.entity.monster.Creeper; +-import net.minecraft.world.entity.monster.Monster; +-import net.minecraft.world.entity.monster.Slime; ++import net.minecraft.world.entity.monster.Enemy; ++import net.minecraft.world.entity.monster.Pillager; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; ++import net.minecraft.world.entity.projectile.EyeOfEnder; + import net.minecraft.world.entity.projectile.FireworkRocketEntity; + import net.minecraft.world.entity.projectile.ThrowableProjectile; + import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; ++import co.aikar.timings.MinecraftTimings; ++import net.minecraft.world.entity.schedule.Activity; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.AABB; +-import co.aikar.timings.MinecraftTimings; + + public class ActivationRange + { + + public enum ActivationType + { ++ WATER, // Paper ++ FLYING_MONSTER, // Paper ++ VILLAGER, // Paper + MONSTER, + ANIMAL, + RAIDER, +@@ -41,6 +54,43 @@ public class ActivationRange + + AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); + } ++ // Paper start ++ ++ static Activity[] VILLAGER_PANIC_IMMUNITIES = { ++ Activity.HIDE, ++ Activity.PRE_RAID, ++ Activity.RAID, ++ Activity.PANIC ++ }; ++ ++ private static int checkInactiveWakeup(Entity entity) { ++ Level world = entity.level(); ++ 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 AABB maxBB = new AABB( 0, 0, 0, 0, 0, 0 ); + +@@ -53,10 +103,13 @@ public class ActivationRange + */ + public static ActivationType initializeEntityActivationType(Entity entity) + { ++ if (entity instanceof WaterAnimal) { return ActivationType.WATER; } // Paper ++ else if (entity instanceof Villager) { return ActivationType.VILLAGER; } // Paper ++ else if (entity instanceof FlyingMob && entity instanceof Enemy) { return ActivationType.FLYING_MONSTER; } // Paper - doing & Monster incase Flying no longer includes monster in future + if ( entity instanceof Raider ) + { + return ActivationType.RAIDER; +- } else if ( entity instanceof Monster || entity instanceof Slime ) ++ } else if ( entity instanceof Enemy ) // Paper - correct monster check + { + return ActivationType.MONSTER; + } else if ( entity instanceof PathfinderMob || entity instanceof AmbientCreature ) +@@ -77,10 +130,14 @@ public class ActivationRange + */ + 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 EyeOfEnder // Paper + || entity instanceof Player + || entity instanceof ThrowableProjectile + || entity instanceof EnderDragon +@@ -113,10 +170,25 @@ public class ActivationRange + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; + final int monsterActivationRange = world.spigotConfig.monsterActivationRange; ++ // 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 ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); ++ // 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.simulationDistance << 4 ) - 8, maxRange ); + + for ( Player player : world.players() ) +@@ -127,11 +199,17 @@ public class ActivationRange + continue; + } + +- ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, 256, maxRange ); +- ActivationType.MISC.boundingBox = player.getBoundingBox().inflate( miscActivationRange, 256, miscActivationRange ); +- ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, 256, raiderActivationRange ); +- ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, 256, animalActivationRange ); +- ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, 256, monsterActivationRange ); ++ // Paper start ++ int worldHeight = world.getHeight(); ++ ActivationRange.maxBB = player.getBoundingBox().inflate( maxRange, worldHeight, maxRange ); ++ ActivationType.MISC.boundingBox = player.getBoundingBox().inflate( miscActivationRange, worldHeight, miscActivationRange ); ++ ActivationType.RAIDER.boundingBox = player.getBoundingBox().inflate( raiderActivationRange, worldHeight, raiderActivationRange ); ++ ActivationType.ANIMAL.boundingBox = player.getBoundingBox().inflate( animalActivationRange, worldHeight, animalActivationRange ); ++ ActivationType.MONSTER.boundingBox = player.getBoundingBox().inflate( monsterActivationRange, worldHeight, monsterActivationRange ); ++ ActivationType.WATER.boundingBox = player.getBoundingBox().inflate( waterActivationRange, worldHeight, waterActivationRange ); ++ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate( flyingActivationRange, worldHeight, flyingActivationRange ); ++ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, worldHeight, villagerActivationRange ); ++ // Paper end + + // Paper start + java.util.List<Entity> entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); +@@ -172,60 +250,118 @@ public class ActivationRange + * @param entity + * @return + */ +- public static boolean checkEntityImmunities(Entity entity) ++ public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity + { ++ // Paper start ++ SpigotWorldConfig config = entity.level().spigotConfig; ++ int inactiveWakeUpImmunity = checkInactiveWakeup(entity); ++ if (inactiveWakeUpImmunity > -1) { ++ return inactiveWakeUpImmunity; ++ } ++ if (entity.getRemainingFireTicks() > 0) { ++ return 2; ++ } ++ if (entity.activatedImmunityTick >= MinecraftServer.currentTick) { ++ return 1; ++ } ++ long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; ++ // Paper end + // quick checks. +- if ( entity.wasTouchingWater || entity.getRemainingFireTicks() > 0 ) ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper + { +- return true; ++ return 100; // Paper ++ } ++ // Paper start ++ if ( !entity.onGround() || entity.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D ) ++ { ++ return 100; + } ++ // Paper end + if ( !( entity instanceof AbstractArrow ) ) + { +- if ( !entity.onGround() || !entity.passengers.isEmpty() || entity.isPassenger() ) ++ if ( (!entity.onGround() && !(entity instanceof FlyingMob)) ) // Paper - remove passengers logic + { +- return true; ++ return 10; // Paper + } + } else if ( !( (AbstractArrow) entity ).inGround ) + { +- return true; ++ return 1; // Paper + } + // special cases. + if ( entity instanceof LivingEntity ) + { + LivingEntity living = (LivingEntity) entity; +- if ( /*TODO: Missed mapping? living.attackTicks > 0 || */ living.hurtTime > 0 || living.activeEffects.size() > 0 ) ++ if ( living.onClimbable() || living.jumping || living.hurtTime > 0 || living.activeEffects.size() > 0 ) // Paper + { +- return true; ++ return 1; // Paper + } +- if ( entity instanceof PathfinderMob && ( (PathfinderMob) entity ).getTarget() != null ) ++ if ( entity instanceof Mob && ((Mob) entity ).getTarget() != null) // Paper + { +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Bee) { ++ Bee bee = (Bee)entity; ++ BlockPos movingTarget = bee.getMovingTarget(); ++ if (bee.isAngry() || ++ (bee.getHivePos() != null && bee.getHivePos().equals(movingTarget)) || ++ (bee.getSavedFlowerPos() != null && bee.getSavedFlowerPos().equals(movingTarget)) ++ ) { ++ return 20; ++ } ++ } ++ if ( entity instanceof Villager ) { ++ Brain<Villager> behaviorController = ((Villager) entity).getBrain(); ++ ++ if (config.villagersActiveForPanic) { ++ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ if (behaviorController.isActive(activity)) { ++ return 20*5; ++ } ++ } ++ } ++ ++ if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { ++ if (behaviorController.isActive(Activity.WORK)) { ++ return config.villagersWorkImmunityFor; ++ } ++ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) + { +- return true; ++ return 1; + } ++ // Paper end + if ( entity instanceof Animal ) + { + Animal animal = (Animal) entity; + if ( animal.isBaby() || animal.isInLove() ) + { +- return true; ++ return 5; // Paper + } + if ( entity instanceof Sheep && ( (Sheep) entity ).isSheared() ) + { +- return true; ++ return 1; // Paper + } + } + if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive +- return true; ++ return 20; // Paper ++ } ++ // Paper start ++ if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { ++ return 0; + } ++ if (entity instanceof Pillager) { ++ Pillager pillager = (Pillager) entity; ++ // TODO:? ++ } ++ // Paper end + } + // SPIGOT-6644: Otherwise the target refresh tick will be missed + if (entity instanceof ExperienceOrb) { +- return true; ++ return 20; // Paper + } +- return false; ++ return -1; // Paper + } + + /** +@@ -240,8 +376,19 @@ public class ActivationRange + if ( entity instanceof FireworkRocketEntity ) { + return true; + } ++ // Paper start - special case always immunities ++ // immunize brand new entities, dead entities, and portal scenarios ++ if (entity.defaultActivationState || entity.tickCount < 20*10 || !entity.isAlive() || entity.isInsidePortal || entity.portalCooldown > 0) { ++ return true; ++ } ++ // immunize leashed entities ++ if (entity instanceof Mob && ((Mob)entity).getLeashHolder() instanceof Player) { ++ return true; ++ } ++ // Paper end + +- boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick; ++ entity.isTemporarilyActive = false; // Paper + + // Should this entity tick? + if ( !isActive ) +@@ -249,15 +396,19 @@ public class ActivationRange + if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) + { + // Check immunities every 20 ticks. +- if ( ActivationRange.checkEntityImmunities( entity ) ) +- { +- // Triggered some sort of immunity, give 20 full ticks before we check again. +- entity.activatedTick = MinecraftServer.currentTick + 20; ++ // Paper start ++ int immunity = checkEntityImmunities(entity); ++ if (immunity >= 0) { ++ entity.activatedTick = MinecraftServer.currentTick + immunity; ++ } else { ++ entity.isTemporarilyActive = true; + } ++ // Paper end + isActive = true; ++ + } + // Add a little performance juice to active entities. Skip 1/4 if not immune. +- } else if ( !entity.defaultActivationState && (entity.tickCount + entity.getId()) % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) ) // Paper - Ensure checking item movement is offset from Spigot's entity activation range check ++ } else if ( (entity.tickCount + entity.getId()) % 4 == 0 && ActivationRange.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 81c76360e8c7389bafd61f38e6782668e8c65d27..50e57486d49694396816122504028e410ebb602d 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -205,14 +205,60 @@ public class SpigotWorldConfig + public int monsterActivationRange = 32; + public int raiderActivationRange = 48; + public int miscActivationRange = 16; ++ // 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 = 30*20; ++ public int wakeUpInactiveVillagersFor = 5*20; ++ public int wakeUpInactiveFlying = 8; ++ public int wakeUpInactiveFlyingEvery = 10*20; ++ public int wakeUpInactiveFlyingFor = 5*20; ++ public int villagersWorkImmunityAfter = 5*20; ++ public int villagersWorkImmunityFor = 20; ++ public boolean villagersActiveForPanic = true; ++ // Paper end + public boolean tickInactiveVillagers = true; + public boolean ignoreSpectatorActivation = false; + private void activationRange() + { ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", this.animalActivationRange) != this.animalActivationRange; // Paper + this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange ); + this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange ); + this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange ); + this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange ); ++ // Paper start ++ this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange ); ++ this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange ); ++ this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange ); ++ ++ this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals); ++ this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery); ++ this.wakeUpInactiveAnimalsFor = this.getInt("entity-activation-range.wake-up-inactive.animals-for", this.wakeUpInactiveAnimalsFor); ++ ++ this.wakeUpInactiveMonsters = this.getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", this.wakeUpInactiveMonsters); ++ this.wakeUpInactiveMonstersEvery = this.getInt("entity-activation-range.wake-up-inactive.monsters-every", this.wakeUpInactiveMonstersEvery); ++ this.wakeUpInactiveMonstersFor = this.getInt("entity-activation-range.wake-up-inactive.monsters-for", this.wakeUpInactiveMonstersFor); ++ ++ this.wakeUpInactiveVillagers = this.getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", this.wakeUpInactiveVillagers); ++ this.wakeUpInactiveVillagersEvery = this.getInt("entity-activation-range.wake-up-inactive.villagers-every", this.wakeUpInactiveVillagersEvery); ++ this.wakeUpInactiveVillagersFor = this.getInt("entity-activation-range.wake-up-inactive.villagers-for", this.wakeUpInactiveVillagersFor); ++ ++ this.wakeUpInactiveFlying = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", this.wakeUpInactiveFlying); ++ this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery); ++ this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor); ++ ++ this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter ); ++ this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor ); ++ this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic ); ++ // Paper end + this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers ); + this.ignoreSpectatorActivation = this.getBoolean( "entity-activation-range.ignore-spectators", this.ignoreSpectatorActivation ); + this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers + " / Isa " + this.ignoreSpectatorActivation ); |