diff --git a/leaf-server/minecraft-patches/features/0294-cache-entity-isAlive.patch b/leaf-server/minecraft-patches/features/0294-cache-entity-isAlive.patch new file mode 100644 index 000000000..d0c949e91 --- /dev/null +++ b/leaf-server/minecraft-patches/features/0294-cache-entity-isAlive.patch @@ -0,0 +1,1130 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hayanesuru +Date: Sun, 25 Jan 2026 20:50:27 +0900 +Subject: [PATCH] cache entity isAlive + + +diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java +index 45b17a4fbb7f4941f23f5bf4983f9eccf425b73f..22b7ebbd61bf259ccf01eb115fff902580579e2c 100644 +--- a/io/papermc/paper/entity/activation/ActivationRange.java ++++ b/io/papermc/paper/entity/activation/ActivationRange.java +@@ -327,7 +327,7 @@ public final class ActivationRange { + } + // special case always immunities + // immunize brand-new entities, dead entities, and portal scenarios +- if (entity.defaultActivationState || entity.tickCount < 20 * 10 || !entity.isAlive() || (entity.portalProcess != null && !entity.portalProcess.hasExpired()) || entity.portalCooldown > 0) { ++ if (entity.defaultActivationState || entity.tickCount < 20 * 10 || !entity.leaf$isAlive || (entity.portalProcess != null && !entity.portalProcess.hasExpired()) || entity.portalCooldown > 0) { // Leaf - cache entity isAlive + return true; + } + // immunize leashed entities +diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java +index cf2a365bcbb1a278e5553c16ffef6d9ae81f4d41..9fe393a6e408c95a907e4f72aca97d2aacf5f580 100644 +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -1336,7 +1336,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } else { + AABB aabb = AABB.encapsulatingFullBlocks(heightmapPos, heightmapPos.atY(this.getMaxY() + 1)).inflate(3.0); + List entitiesOfClass = this.getEntitiesOfClass( +- LivingEntity.class, aabb, entity -> entity.isAlive() && this.canSeeSky(entity.blockPosition()) && !entity.isSpectator() // Paper - Fix lightning being able to hit spectators (MC-262422) ++ LivingEntity.class, aabb, entity -> entity.leaf$isAlive && this.canSeeSky(entity.blockPosition()) && !entity.isSpectator() // Paper - Fix lightning being able to hit spectators (MC-262422) // Leaf - cache entity isAlive + ); + if (!entitiesOfClass.isEmpty()) { + return entitiesOfClass.get(this.random.nextInt(entitiesOfClass.size())).blockPosition(); +@@ -1767,7 +1767,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + + public List getDragons() { +- return this.getEntities(EntityType.ENDER_DRAGON, LivingEntity::isAlive); ++ return this.getEntities(EntityType.ENDER_DRAGON, enderDragon -> enderDragon.leaf$isAlive); // Leaf - cache entity isAlive + } + + public List getPlayers(Predicate predicate) { +@@ -1790,7 +1790,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + + public @Nullable ServerPlayer getRandomPlayer() { +- List players = this.getPlayers(LivingEntity::isAlive); ++ List players = this.getPlayers(serverPlayer -> serverPlayer.leaf$isAlive); // Leaf - cache entity isAlive + return players.isEmpty() ? null : players.get(this.random.nextInt(players.size())); + } + +diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java +index cf22a560c331f08f7c1729ad5a40d966e1726a96..761ed01cafb61694f9d8b8e2575d49cb58851653 100644 +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -834,7 +834,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + this.awardStat(Stats.PLAY_TIME, increaseTimeStatisticsInterval); + this.awardStat(Stats.TOTAL_WORLD_TIME, increaseTimeStatisticsInterval); + // Gale end - Hydrinity - increase time statistics in intervals +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + this.awardStat(Stats.TIME_SINCE_DEATH, increaseTimeStatisticsInterval); // Gale - Hydrinity - increase time statistics in intervals + } + +diff --git a/net/minecraft/world/damagesource/CombatTracker.java b/net/minecraft/world/damagesource/CombatTracker.java +index 30d0807d7adf46a6cd23b81b979e06f943a2bca1..6c99439ffda4d34f14e3180361c3642f45bfdc22 100644 +--- a/net/minecraft/world/damagesource/CombatTracker.java ++++ b/net/minecraft/world/damagesource/CombatTracker.java +@@ -50,7 +50,7 @@ public class CombatTracker { + this.entries.add(combatEntry); + this.lastDamageTime = this.mob.tickCount; + this.takingDamage = true; +- if (!this.inCombat && this.mob.isAlive() && shouldEnterCombat(source)) { ++ if (!this.inCombat && this.mob.leaf$isAlive && shouldEnterCombat(source)) { // Leaf - cache entity isAlive + this.inCombat = true; + this.combatStartTime = this.mob.tickCount; + this.combatEndTime = this.combatStartTime; +@@ -162,7 +162,7 @@ public class CombatTracker { + + public void recheckStatus() { + int i = this.inCombat ? 300 : 100; +- if (this.takingDamage && (!this.mob.isAlive() || this.mob.tickCount - this.lastDamageTime > i)) { ++ if (this.takingDamage && (!this.mob.leaf$isAlive || this.mob.tickCount - this.lastDamageTime > i)) { // Leaf - cache entity isAlive + // Paper start - Combat tracker API + resetCombatState(); + } +diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java +index ffe7b73dafa81ab96c24198d83474fd9af542476..d829a8d9f5e68e6875c6d68149b38625accd83d6 100644 +--- a/net/minecraft/world/entity/AgeableMob.java ++++ b/net/minecraft/world/entity/AgeableMob.java +@@ -157,7 +157,7 @@ public abstract class AgeableMob extends PathfinderMob { + + this.forcedAgeTimer--; + } +- } else if (this.isAlive()) { ++ } else if (this.leaf$isAlive) { // Leaf - cache entity isAlive + int age = this.getAge(); + if (age < 0) { + this.setAge(++age); +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 8d092716cdcc48b829a1c0ee2e5416d648143a37..3723e1be24c2dfb91bdb3042347196b5300ee081 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -387,6 +387,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + public boolean isTemporarilyActive; + public long activatedImmunityTick = Integer.MIN_VALUE; + public @Nullable Boolean immuneToFire = null; // Purpur - Fire immune API ++ public boolean leaf$isAlive = true; // Leaf - cache entity isAlive + + public void inactiveTick() { + } +@@ -655,7 +656,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + } + + public boolean canInteractWithLevel() { +- return this.isAlive() && !this.isRemoved() && !this.isSpectator(); ++ return this.leaf$isAlive && !this.isRemoved() && !this.isSpectator(); // Leaf - cache entity isAlive + } + + public final void unRide() { +@@ -948,7 +949,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + // CraftBukkit start + public void postTick() { + // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle +- if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities ++ if (!(this instanceof ServerPlayer) && this.leaf$isAlive) { // Paper - don't attempt to teleport dead entities // Leaf - cache entity isAlive + this.handlePortal(); + } + } +@@ -1831,7 +1832,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + to, + aabb, + (pos, index) -> { +- if (!this.isAlive()) { ++ if (!this.leaf$isAlive) { // Leaf - cache entity isAlive + return false; + } else if (index >= maxSteps) { + return false; +@@ -2274,7 +2275,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + } + + public boolean canSpawnSprintParticle() { +- return this.isSprinting() && !this.isInWater() && !this.isSpectator() && !this.isCrouching() && !this.isInLava() && this.isAlive(); ++ return this.isSprinting() && !this.isInWater() && !this.isSpectator() && !this.isCrouching() && !this.isInLava() && this.leaf$isAlive; // Leaf - cache entity isAlive + } + + protected void spawnSprintParticle() { +@@ -2588,7 +2589,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + } + + public boolean canBeHitByProjectile() { +- return this.isAlive() && this.isPickable(); ++ return this.leaf$isAlive && this.isPickable(); // Leaf - cache entity isAlive + } + + public boolean isPickable() { +@@ -3151,7 +3152,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + && player.isSecondaryUseActive() + && this instanceof Leashable leashable + && leashable.canBeLeashed() +- && this.isAlive() ++ && this.leaf$isAlive // Leaf - cache entity isAlive + && !(this instanceof LivingEntity livingEntity && livingEntity.isBaby())) { + List list = Leashable.leashableInArea(this, leashable3 -> leashable3.getLeashHolder() == player); + if (!list.isEmpty()) { +@@ -3192,7 +3193,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + && this.attemptToShearEquipment(player, hand, itemInHand, mob)) { + return InteractionResult.SUCCESS; + } else { +- if (this.isAlive() && this instanceof Leashable leashable2) { ++ if (this.leaf$isAlive && this instanceof Leashable leashable2) { // Leaf - cache entity isAlive + if (leashable2.getLeashHolder() == player) { + if (!this.level().isClientSide()) { + if (hand == InteractionHand.OFF_HAND && (level().purpurConfig.villagerCanBeLeashed || level().purpurConfig.wanderingTraderCanBeLeashed) && this instanceof net.minecraft.world.entity.npc.villager.AbstractVillager) return InteractionResult.CONSUME; // Purpur - Allow leashing villagers +@@ -4207,7 +4208,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + + public @Nullable Entity teleport(TeleportTransition teleportTransition) { + // Paper start - Fix item duplication and teleport issues +- if ((!this.isAlive() || !this.valid) && (teleportTransition.newLevel() != this.level)) { ++ if ((!this.leaf$isAlive || !this.valid) && (teleportTransition.newLevel() != this.level)) { // Leaf - cache entity isAlive + LOGGER.warn("Illegal Entity Teleport {} to {}:{}", this, teleportTransition.newLevel(), teleportTransition.position(), new Throwable()); + return null; + } +@@ -4435,11 +4436,11 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + } + + public boolean canUsePortal(boolean allowPassengers) { +- return (allowPassengers || !this.isPassenger()) && this.isAlive() && (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer); // Purpur - Entities can use portals ++ return (allowPassengers || !this.isPassenger()) && this.leaf$isAlive && (this.level.purpurConfig.entitiesCanUsePortals || this instanceof ServerPlayer); // Purpur - Entities can use portals // Leaf - cache entity isAlive + } + + public boolean canTeleport(Level fromLevel, Level toLevel) { +- if (!this.isAlive() || !this.valid) return false; // Paper - Fix item duplication and teleport issues ++ if (!this.leaf$isAlive || !this.valid) return false; // Paper - Fix item duplication and teleport issues // Leaf - cache entity isAlive + if (fromLevel.dimension() == Level.END && toLevel.dimension() == Level.OVERWORLD) { + for (Entity entity : this.getPassengers()) { + if (entity instanceof ServerPlayer serverPlayer && !serverPlayer.seenCredits) { +@@ -5428,6 +5429,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + if (this.removalReason == null) { + this.removalReason = removalReason; + } ++ this.leaf$onAliveDirty(); // Leaf - cache entity isAlive + + if (this.removalReason.shouldDestroy()) { + this.stopRiding(); +@@ -5446,6 +5448,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + + public void unsetRemoved() { + this.removalReason = null; ++ this.leaf$onAliveDirty(); // Leaf - cache entity isAlive + } + + // Paper start - Folia schedulers +@@ -5529,11 +5532,11 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + } + + public Vec3 getKnownMovement() { +- return this.getControllingPassenger() instanceof Player player && this.isAlive() ? player.getKnownMovement() : this.getDeltaMovement(); ++ return this.getControllingPassenger() instanceof Player player && this.leaf$isAlive ? player.getKnownMovement() : this.getDeltaMovement(); // Leaf - cache entity isAlive + } + + public Vec3 getKnownSpeed() { +- return this.getControllingPassenger() instanceof Player player && this.isAlive() ? player.getKnownSpeed() : this.lastKnownSpeed; ++ return this.getControllingPassenger() instanceof Player player && this.leaf$isAlive ? player.getKnownSpeed() : this.lastKnownSpeed; // Leaf - cache entity isAlive + } + + public @Nullable ItemStack getWeaponItem() { +@@ -5682,6 +5685,15 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + @Nullable + private Player rider = null; + ++ ++ // Leaf start - cache entity isAlive ++ public final void leaf$onAliveDirty() { ++ if (!(this instanceof ServerPlayer) || this.getBukkitEntityRaw() != null) { ++ this.leaf$isAlive = this.isAlive(); ++ } ++ } ++ // Leaf end - cache entity isAlive ++ + @Nullable + public Player getRider() { + return rider; +diff --git a/net/minecraft/world/entity/EntitySelector.java b/net/minecraft/world/entity/EntitySelector.java +index 6bec4307ca7354f6e6be1a543f51ac8d4350b490..2a056bd77cab0db8be61fc45bb9bd69a784477a6 100644 +--- a/net/minecraft/world/entity/EntitySelector.java ++++ b/net/minecraft/world/entity/EntitySelector.java +@@ -7,10 +7,10 @@ import net.minecraft.world.entity.player.Player; + import net.minecraft.world.scores.Team; + + public final class EntitySelector { +- public static final Predicate ENTITY_STILL_ALIVE = Entity::isAlive; +- public static final Predicate LIVING_ENTITY_STILL_ALIVE = entity -> entity.isAlive() && entity instanceof LivingEntity; +- public static final Predicate ENTITY_NOT_BEING_RIDDEN = entity -> entity.isAlive() && !entity.isVehicle() && !entity.isPassenger(); +- public static final Predicate CONTAINER_ENTITY_SELECTOR = entity -> entity instanceof Container && entity.isAlive(); ++ public static final Predicate ENTITY_STILL_ALIVE = e -> e.leaf$isAlive; // Leaf - cache entity isAlive ++ public static final Predicate LIVING_ENTITY_STILL_ALIVE = entity -> entity.leaf$isAlive && entity instanceof LivingEntity; // Leaf - cache entity isAlive ++ public static final Predicate ENTITY_NOT_BEING_RIDDEN = entity -> entity.leaf$isAlive && !entity.isVehicle() && !entity.isPassenger(); // Leaf - cache entity isAlive ++ public static final Predicate CONTAINER_ENTITY_SELECTOR = entity -> entity instanceof Container && entity.leaf$isAlive; // Leaf - cache entity isAlive + public static final Predicate NO_CREATIVE_OR_SPECTATOR = entity -> !( + entity instanceof Player player && (entity.isSpectator() || player.isCreative()) + ); +@@ -32,7 +32,7 @@ public final class EntitySelector { + + // Paper start - Affects Spawning API + public static final Predicate PLAYER_AFFECTS_SPAWNING = (entity) -> { +- return !entity.isSpectator() && entity.isAlive() && entity instanceof Player player && player.affectsSpawning; // Leaf - Optimize nearby alive players for spawning - diff on change ++ return !entity.isSpectator() && entity.leaf$isAlive && entity instanceof Player player && player.affectsSpawning; // Leaf - Optimize nearby alive players for spawning - diff on change // Leaf - cache entity isAlive + }; + // Paper end - Affects Spawning API + +diff --git a/net/minecraft/world/entity/InsideBlockEffectApplier.java b/net/minecraft/world/entity/InsideBlockEffectApplier.java +index a0fa06529beb3690ff60371c2579df87ad649e5a..62b71bd6f4384cbebfc58effbcbdac63e92babe6 100644 +--- a/net/minecraft/world/entity/InsideBlockEffectApplier.java ++++ b/net/minecraft/world/entity/InsideBlockEffectApplier.java +@@ -69,7 +69,7 @@ public interface InsideBlockEffectApplier { + return; + } + +- if (!entity.isAlive()) { ++ if (!entity.leaf$isAlive) { + effects.clear(); + this.lastStep = -1; + return; +@@ -81,15 +81,15 @@ public interface InsideBlockEffectApplier { + effects.get(i++).accept(entity); + effects.get(i++).accept(entity); + effects.get(i++).accept(entity); +- if (!entity.isAlive()) { ++ if (!entity.leaf$isAlive) { + break; + } + } + +- if (entity.isAlive()) { ++ if (entity.leaf$isAlive) { + for (; i < size; i++) { + effects.get(i).accept(entity); +- if (!entity.isAlive()) { ++ if (!entity.leaf$isAlive) { + break; + } + } +diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java +index 4305ab787419223866303d415b5f940f3f8690ef..db2bdc92368f26becf27d4368a287a7713f2c155 100644 +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -447,7 +447,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + super.baseTick(); + ProfilerFiller profilerFiller = Profiler.get(); + profilerFiller.push("livingEntityBaseTick"); +- if (this.isAlive() && this.level() instanceof ServerLevel serverLevel1) { ++ if (this.leaf$isAlive && this.level() instanceof ServerLevel serverLevel1) { // Leaf - cache entity isAlive + boolean flag = this instanceof Player; + // Gale start - Pufferfish - reduce in wall checks + long checkStuckInWallInterval = this.level().galeConfig().smallOptimizations.reducedIntervals.checkStuckInWall; +@@ -518,13 +518,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + this.lastHurtByPlayer = null; + } + +- if (this.lastHurtMob != null && !this.lastHurtMob.isAlive()) { ++ if (this.lastHurtMob != null && !this.lastHurtMob.leaf$isAlive) { // Leaf - cache entity isAlive + this.lastHurtMob = null; + } + + LivingEntity lastHurtByMob = this.getLastHurtByMob(); + if (lastHurtByMob != null) { +- if (!lastHurtByMob.isAlive()) { ++ if (!lastHurtByMob.leaf$isAlive) { // Leaf - cache entity isAlive + this.setLastHurtByMob(null); + } else if (this.tickCount - this.lastHurtByMobTimestamp > 100) { + this.setLastHurtByMob(null); +@@ -1117,7 +1117,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + } + + public boolean canBeSeenByAnyone() { +- return !this.isSpectator() && this.isAlive(); ++ return !this.isSpectator() && this.leaf$isAlive; // Leaf - cache entity isAlive + } + + public static boolean areAllEffectsAmbient(Collection effects) { +@@ -1939,6 +1939,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + */ // Paper - move down to make death event cancellable - this is the awardKillScore below + + this.dead = true; ++ this.leaf$onAliveDirty(); // Leaf - cache entity isAlive + // Paper - moved into if below + if (this.level() instanceof ServerLevel serverLevel) { + // Paper - move below into if for onKill +@@ -1979,6 +1980,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + if (entity instanceof net.minecraft.world.entity.monster.Creeper creeper && creeper.droppedSkulls) { // Creeper has logic for drops skull and need revert that flag + creeper.droppedSkulls = false; + } ++ this.leaf$onAliveDirty(); // Leaf - cache entity isAlive + } + // Paper end + this.createWitherRose(killCredit); +@@ -3424,7 +3426,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + + public void calculateEntityAnimation(boolean includeHeight) { + float f = (float)Mth.length(this.getX() - this.xo, includeHeight ? this.getY() - this.yo : 0.0, this.getZ() - this.zo); +- if (!this.isPassenger() && this.isAlive()) { ++ if (!this.isPassenger() && this.leaf$isAlive) { // Leaf - cache entity isAlive + this.updateWalkAnimation(f); + } else { + this.walkAnimation.stop(); +@@ -3888,7 +3890,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + this.resetFallDistance(); + } + +- if (this.getControllingPassenger() instanceof Player player && this.isAlive()) { ++ if (this.getControllingPassenger() instanceof Player player && this.leaf$isAlive) { // Leaf - cache entity isAlive + this.travelRidden(player, vec3); + } else if (this.canSimulateMovement() && this.isEffectiveAi()) { + this.travel(vec3); +@@ -3968,7 +3970,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + } + + // Purpur start - copied from Mob - API for any mob to burn daylight +- if (this.getType().is(EntityTypeTags.BURN_IN_DAYLIGHT) && this.isAlive()) { ++ if (this.getType().is(EntityTypeTags.BURN_IN_DAYLIGHT) && this.leaf$isAlive) { // Leaf - cache entity isAlive + boolean flag = this.shouldBurnInDay() && this.isSunBurnTick(); // Paper - shouldBurnInDay API // Purpur - use shouldBurnInDay() method to handle Phantoms properly - API for any mob to burn daylight + if (flag) { + EquipmentSlot equipmentSlot = this.sunProtectionSlot(); +@@ -4299,7 +4301,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + + @Override + public boolean isCollidable(boolean ignoreClimbing) { +- return this.isAlive() && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit ++ return this.leaf$isAlive && !this.isSpectator() && (ignoreClimbing || !this.onClimbable()) && this.collides; // CraftBukkit // Leaf - cache entity isAlive + // Paper end - Climbing should not bypass cramming gamerule + } + +@@ -4498,6 +4500,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + // Paper end - lag compensate eating + } + } ++ else if (DATA_HEALTH_ID.equals(key)) { this.leaf$onAliveDirty(); } // Leaf - cache entity isAlive + } + + @Override +@@ -4943,7 +4946,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + } + + public final boolean canEquipWithDispenser(ItemStack stack) { +- if (this.isAlive() && !this.isSpectator()) { ++ if (this.leaf$isAlive && !this.isSpectator()) { // Leaf - cache entity isAlive + Equippable equippable = stack.get(DataComponents.EQUIPPABLE); + if (equippable != null && equippable.dispensable()) { + EquipmentSlot equipmentSlot = equippable.slot(); +diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java +index 10045bdd3c9692fb0a56f140b4891c67cf64eeea..ef82db8361e6ecb241b7f892dedba840e8ddb278 100644 +--- a/net/minecraft/world/entity/Mob.java ++++ b/net/minecraft/world/entity/Mob.java +@@ -279,7 +279,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + } + if (reason != null) { + if (reason == EntityTargetEvent.TargetReason.UNKNOWN && this.getTarget() != null && target == null) { +- reason = this.getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ reason = this.getTarget().leaf$isAlive ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; // Leaf - cache entity isAlive + } + if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { + this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); +@@ -337,7 +337,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + super.baseTick(); + ProfilerFiller profilerFiller = Profiler.get(); + profilerFiller.push("mobBaseTick"); +- if (this.isAlive() && this.random.nextInt(1000) < this.ambientSoundTime++) { ++ if (this.leaf$isAlive && this.random.nextInt(1000) < this.ambientSoundTime++) { // Leaf - cache entity isAlive + this.resetAmbientSoundTime(); + this.playAmbientSound(); + } +@@ -558,8 +558,8 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + profilerFiller.push("looting"); + if (this.level() instanceof ServerLevel serverLevel + && this.canPickUpLoot() +- && this.isAlive() +- && !this.dead ++ && this.leaf$isAlive // Leaf - cache entity isAlive ++ // && !this.dead // Leaf - cache entity isAlive + && serverLevel.getGameRules().get(GameRules.MOB_GRIEFING, checkEntityPickUpLootOverride())) { // Purpur - Check mobGriefing Overrides + Vec3i pickupReach = this.getPickupReach(); + +@@ -1305,7 +1305,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + + @Override + public InteractionResult interact(Player player, InteractionHand hand) { +- if (!this.isAlive()) { ++ if (!this.leaf$isAlive) { // Leaf - cache entity isAlive + return InteractionResult.PASS; + } else { + InteractionResult interactionResult = this.checkAndHandleImportantInteractions(player, hand); +diff --git a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +index 6deb19ff8ba643cfeb04a76f07567efb703e87aa..37bcaad5c434a334126d9c438a303a1092619c10 100644 +--- a/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java ++++ b/net/minecraft/world/entity/ai/behavior/BehaviorUtils.java +@@ -43,7 +43,7 @@ public class BehaviorUtils { + } + + private static boolean targetIsValid(Brain brain, MemoryModuleType memoryType, Predicate livingPredicate) { +- return brain.getMemory(memoryType).filter(livingPredicate).filter(LivingEntity::isAlive).filter(entity -> entityIsVisible(brain, entity)).isPresent(); ++ return brain.getMemory(memoryType).filter(livingPredicate).filter(livingEntity -> livingEntity.leaf$isAlive).filter(entity -> entityIsVisible(brain, entity)).isPresent(); // Leaf - cache entity isAlive + } + + private static void lookAtEachOther(LivingEntity firstEntity, LivingEntity secondEntity) { +diff --git a/net/minecraft/world/entity/ai/behavior/EntityTracker.java b/net/minecraft/world/entity/ai/behavior/EntityTracker.java +index 091cc074d51ce8ab5bd7e58836519ac1e700679a..ca6da4b799342a79ec14856e02a090cd382699c1 100644 +--- a/net/minecraft/world/entity/ai/behavior/EntityTracker.java ++++ b/net/minecraft/world/entity/ai/behavior/EntityTracker.java +@@ -36,7 +36,7 @@ public class EntityTracker implements PositionTracker { + @Override + public boolean isVisibleBy(LivingEntity entity) { + if (this.entity instanceof LivingEntity livingEntity) { +- if (!livingEntity.isAlive()) { ++ if (!livingEntity.leaf$isAlive) { // Leaf - cache entity isAlive + return false; + } else { + Optional memory = entity.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES); +diff --git a/net/minecraft/world/entity/ai/goal/LookAtPlayerGoal.java b/net/minecraft/world/entity/ai/goal/LookAtPlayerGoal.java +index b732193804c0a73e5ced822d7491c7700696338c..988eed63cfe5a00bfee99066cb0c25e2a4fe3e5f 100644 +--- a/net/minecraft/world/entity/ai/goal/LookAtPlayerGoal.java ++++ b/net/minecraft/world/entity/ai/goal/LookAtPlayerGoal.java +@@ -76,7 +76,7 @@ public class LookAtPlayerGoal extends Goal { + + @Override + public boolean canContinueToUse() { +- return this.lookAt.isAlive() && !(this.mob.distanceToSqr(this.lookAt) > this.lookDistance * this.lookDistance) && this.lookTime > 0; ++ return this.lookAt.leaf$isAlive && !(this.mob.distanceToSqr(this.lookAt) > this.lookDistance * this.lookDistance) && this.lookTime > 0; // Leaf - cache entity isAlive + } + + @Override +@@ -91,7 +91,7 @@ public class LookAtPlayerGoal extends Goal { + + @Override + public void tick() { +- if (this.lookAt.isAlive()) { ++ if (this.lookAt.leaf$isAlive) { // Leaf - cache entity isAlive + double d = this.onlyHorizontal ? this.mob.getEyeY() : this.lookAt.getEyeY(); + this.mob.getLookControl().setLookAt(this.lookAt.getX(), d, this.lookAt.getZ()); + this.lookTime--; +diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +index 51a6302ed5daf512acc6bed915f954ac76559270..540e08218da94fdca9e64d16ac6ab8af414f736c 100644 +--- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java ++++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +@@ -19,7 +19,7 @@ public class NearestLivingEntitySensor extends Sensor + AABB aabb = entity.getBoundingBox().inflate(attributeValue, attributeValue, attributeValue); + // Leaf start - fast bit radix sort + it.unimi.dsi.fastutil.objects.ObjectArrayList entitiesOfClass = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); +- ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel) level).moonrise$getEntityLookup().getEntities(LivingEntity.class, entity, aabb, entitiesOfClass, LivingEntity::isAlive); ++ ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemLevel) level).moonrise$getEntityLookup().getEntities(LivingEntity.class, entity, aabb, entitiesOfClass, e -> e.leaf$isAlive); // Leaf - cache entity isAlive + level.fastBitRadixSort.sort(entitiesOfClass.elements(), entitiesOfClass.size(), entity.position()); + // Leaf end - fast bit radix sort + Brain brain = entity.getBrain(); +diff --git a/net/minecraft/world/entity/animal/AgeableWaterCreature.java b/net/minecraft/world/entity/animal/AgeableWaterCreature.java +index b147020149dfc7ee03dc770a4e041fe5991220ee..ba864e8f7cc45dcfdff5d7c602ceaa20caea7686 100644 +--- a/net/minecraft/world/entity/animal/AgeableWaterCreature.java ++++ b/net/minecraft/world/entity/animal/AgeableWaterCreature.java +@@ -35,7 +35,7 @@ public abstract class AgeableWaterCreature extends AgeableMob { + } + + protected void handleAirSupply(int airSupply) { +- if (this.isAlive() && !this.isInWater()) { ++ if (this.leaf$isAlive && !this.isInWater()) { // Leaf - cache entity isAlive + this.setAirSupply(airSupply - 1); + if (this.shouldTakeDrowningDamage()) { + this.setAirSupply(0); +diff --git a/net/minecraft/world/entity/animal/allay/Allay.java b/net/minecraft/world/entity/animal/allay/Allay.java +index 154a72fbc85431c59dc793041952a69de089055f..e4250f958b3d609baf144b952ff4c4df51197e53 100644 +--- a/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/net/minecraft/world/entity/animal/allay/Allay.java +@@ -302,7 +302,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS + @Override + public void aiStep() { + super.aiStep(); +- if (!this.level().isClientSide() && this.isAlive() && this.tickCount % 10 == 0) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && this.tickCount % 10 == 0) { // Leaf - cache entity isAlive + this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } + +diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java +index ec678479ef33a6f1a832598fa0df5b396d491898..7e08eb5bfaaaa78d65945b80a3ecb49b794e620f 100644 +--- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java ++++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java +@@ -170,7 +170,7 @@ public class Armadillo extends Animal { + profilerFiller.push("armadilloActivityUpdate"); + ArmadilloAi.updateActivity(this); + profilerFiller.pop(); +- if (this.isAlive() && --this.scuteTime <= 0 && this.shouldDropLoot(level)) { ++ if (this.leaf$isAlive && --this.scuteTime <= 0 && this.shouldDropLoot(level)) { // Leaf - cache entity isAlive + this.forceDrops = true; // CraftBukkit + if (this.dropFromGiftLootTable(level, BuiltInLootTables.ARMADILLO_SHED, this::spawnAtLocation)) { + this.playSound(SoundEvents.ARMADILLO_SCUTE_DROP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +index 9d5f4b5f756d84e54e9dbeb0d91eda53c09a6ddc..7ae8be9ef483305f2d1ac2154945e882af0e853e 100644 +--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java ++++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java +@@ -260,7 +260,7 @@ public class Axolotl extends Animal implements Bucketable { + } + + protected void handleAirSupply(ServerLevel level, int airSupply) { +- if (this.isAlive() && !this.isInWaterOrRain()) { ++ if (this.leaf$isAlive && !this.isInWaterOrRain()) { // Leaf - cache entity isAlive + this.setAirSupply(airSupply - 1); + if (this.shouldTakeDrowningDamage()) { + this.setAirSupply(0); +diff --git a/net/minecraft/world/entity/animal/chicken/Chicken.java b/net/minecraft/world/entity/animal/chicken/Chicken.java +index bb3eeea32c5f52192e368ced55b4f4d880c94134..cc8d5f3db2431716509e6ed13a05245ced5f47db 100644 +--- a/net/minecraft/world/entity/animal/chicken/Chicken.java ++++ b/net/minecraft/world/entity/animal/chicken/Chicken.java +@@ -172,7 +172,7 @@ public class Chicken extends Animal { + } + + this.flap = this.flap + this.flapping * 2.0F; +- if (this.level() instanceof ServerLevel serverLevel && this.isAlive() && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { ++ if (this.level() instanceof ServerLevel serverLevel && this.leaf$isAlive && !this.isBaby() && !this.isChickenJockey() && --this.eggTime <= 0) { // Leaf - cache entity isAlive + this.forceDrops = true; // CraftBukkit + if (this.dropFromGiftLootTable(serverLevel, BuiltInLootTables.CHICKEN_LAY, this::spawnAtLocation)) { + this.playSound(SoundEvents.CHICKEN_EGG, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); +diff --git a/net/minecraft/world/entity/animal/equine/AbstractHorse.java b/net/minecraft/world/entity/animal/equine/AbstractHorse.java +index 787a2d344854a75d30b672368cfbf6c329929f5c..9a0bd5152ea93510cfe539ef613ea759bb4b04a3 100644 +--- a/net/minecraft/world/entity/animal/equine/AbstractHorse.java ++++ b/net/minecraft/world/entity/animal/equine/AbstractHorse.java +@@ -588,7 +588,7 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory + } + + super.aiStep(); +- if (this.level() instanceof ServerLevel serverLevel && this.isAlive()) { ++ if (this.level() instanceof ServerLevel serverLevel && this.leaf$isAlive) { // Leaf - cache entity isAlive + if (this.random.nextInt(900) == 0 && this.deathTime == 0) { + this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit + } +diff --git a/net/minecraft/world/entity/animal/fish/Pufferfish.java b/net/minecraft/world/entity/animal/fish/Pufferfish.java +index 681eb25e45cec76f21cea9f77efe71290bdb547a..96b92ea82f2011623e701c1bfbcf6bcf0d3412a8 100644 +--- a/net/minecraft/world/entity/animal/fish/Pufferfish.java ++++ b/net/minecraft/world/entity/animal/fish/Pufferfish.java +@@ -128,7 +128,7 @@ public class Pufferfish extends AbstractFish { + + @Override + public void tick() { +- if (!this.level().isClientSide() && this.isAlive() && this.isEffectiveAi()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && this.isEffectiveAi()) { // Leaf - cache entity isAlive + if (this.inflateCounter > 0) { + boolean increase = true; // Paper - Add PufferFishStateChangeEvent + if (this.getPuffState() == 0) { +@@ -170,10 +170,10 @@ public class Pufferfish extends AbstractFish { + @Override + public void aiStep() { + super.aiStep(); +- if (this.level() instanceof ServerLevel serverLevel && this.isAlive() && this.getPuffState() > 0) { ++ if (this.level() instanceof ServerLevel serverLevel && this.leaf$isAlive && this.getPuffState() > 0) { // Leaf - cache entity isAlive + for (Mob mob : this.level() + .getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(0.3), mob1 -> TARGETING_CONDITIONS.test(serverLevel, this, mob1))) { +- if (mob.isAlive()) { ++ if (mob.leaf$isAlive) { // Leaf - cache entity isAlive + this.touch(serverLevel, mob); + } + } +diff --git a/net/minecraft/world/entity/animal/fish/WaterAnimal.java b/net/minecraft/world/entity/animal/fish/WaterAnimal.java +index 515182d71c892e5379625835d8506c739c1b9610..0d0303b5e785039def447f604d657384f02877fd 100644 +--- a/net/minecraft/world/entity/animal/fish/WaterAnimal.java ++++ b/net/minecraft/world/entity/animal/fish/WaterAnimal.java +@@ -37,7 +37,7 @@ public abstract class WaterAnimal extends PathfinderMob { + } + + protected void handleAirSupply(ServerLevel level, int airSupply) { +- if (this.isAlive() && !this.isInWater()) { ++ if (this.leaf$isAlive && !this.isInWater()) { // Leaf - cache entity isAlive + this.setAirSupply(airSupply - 1); + if (this.shouldTakeDrowningDamage()) { + this.setAirSupply(0); +diff --git a/net/minecraft/world/entity/animal/fox/Fox.java b/net/minecraft/world/entity/animal/fox/Fox.java +index 98937a998f55ee462421a7477cc3e2fbf4e75ba3..01d4da75c25d94b4c2a0a4b04676c1ec3036691b 100644 +--- a/net/minecraft/world/entity/animal/fox/Fox.java ++++ b/net/minecraft/world/entity/animal/fox/Fox.java +@@ -275,7 +275,7 @@ public class Fox extends Animal { + + @Override + public void aiStep() { +- if (!this.level().isClientSide() && this.isAlive() && this.isEffectiveAi()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && this.isEffectiveAi()) { // Leaf - cache entity isAlive + this.ticksSinceEaten++; + ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.MAINHAND); + if (this.canEat(itemBySlot)) { +diff --git a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java +index 29de138dd245dac1491f8edd2c37ba8a7a8b7f49..480fb151f78a7c2fdd7f226f94ad9303bfe608c0 100644 +--- a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java ++++ b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java +@@ -611,7 +611,7 @@ public class HappyGhast extends Animal { + @Override + public boolean canBeCollidedWith(@Nullable Entity entity) { + return !this.isBaby() +- && this.isAlive() ++ && this.leaf$isAlive // Leaf - cache entity isAlive + && ( + this.level().isClientSide() && entity instanceof Player && entity.position().y >= this.getBoundingBox().maxY + || this.isVehicle() && entity instanceof HappyGhast +diff --git a/net/minecraft/world/entity/animal/nautilus/Nautilus.java b/net/minecraft/world/entity/animal/nautilus/Nautilus.java +index ab556f276ed899cde5bcd85246842966bbc586b5..88ad2760c8358b255a306135e95fd85c9b5fdb8c 100644 +--- a/net/minecraft/world/entity/animal/nautilus/Nautilus.java ++++ b/net/minecraft/world/entity/animal/nautilus/Nautilus.java +@@ -146,7 +146,7 @@ public class Nautilus extends AbstractNautilus { + // CraftBukkit end + + protected void handleAirSupply(ServerLevel level, int airSupply) { +- if (this.isAlive() && !this.isInWater()) { ++ if (this.leaf$isAlive && !this.isInWater()) { // Leaf - cache entity isAlive + this.setAirSupply(airSupply - 1); + if (this.getAirSupply() <= -20) { + this.setAirSupply(0); +diff --git a/net/minecraft/world/entity/animal/turtle/Turtle.java b/net/minecraft/world/entity/animal/turtle/Turtle.java +index 4fa4e755955c27c689661774d214f797ffa33697..5473ebb9d747137e93038c6faf726d21e47dd031 100644 +--- a/net/minecraft/world/entity/animal/turtle/Turtle.java ++++ b/net/minecraft/world/entity/animal/turtle/Turtle.java +@@ -290,7 +290,7 @@ public class Turtle extends Animal { + @Override + public void aiStep() { + super.aiStep(); +- if (this.isAlive() && this.isLayingEgg() && this.layEggCounter >= 1 && this.layEggCounter % 5 == 0) { ++ if (this.leaf$isAlive && this.isLayingEgg() && this.layEggCounter >= 1 && this.layEggCounter % 5 == 0) { // Leaf - cache entity isAlive + BlockPos blockPos = this.blockPosition(); + if (TurtleEggBlock.onSand(this.level(), blockPos)) { + this.level().levelEvent(LevelEvent.PARTICLES_DESTROY_BLOCK, blockPos, Block.getId(this.level().getBlockState(blockPos.below()))); +diff --git a/net/minecraft/world/entity/animal/wolf/Wolf.java b/net/minecraft/world/entity/animal/wolf/Wolf.java +index 7fbe841818d08fd930f7ce405e84e5ed4badb614..a8a84d9d5df77dd67927a929bcc24222c543b4e8 100644 +--- a/net/minecraft/world/entity/animal/wolf/Wolf.java ++++ b/net/minecraft/world/entity/animal/wolf/Wolf.java +@@ -443,7 +443,7 @@ public class Wolf extends TamableAnimal implements NeutralMob { + @Override + public void tick() { + super.tick(); +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + // Purpur start - Configurable chance for wolves to spawn rabid + if (this.age % 300 == 0 && this.isRabid()) { + this.addEffect(new net.minecraft.world.effect.MobEffectInstance(net.minecraft.world.effect.MobEffects.NAUSEA, 400)); +diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java +index 419982ecea1e846c997db9d9b35958d1d8dcc0e2..973211bd7d0176964a60f32b29476946f244db57 100644 +--- a/net/minecraft/world/entity/item/FallingBlockEntity.java ++++ b/net/minecraft/world/entity/item/FallingBlockEntity.java +@@ -165,7 +165,7 @@ public class FallingBlockEntity extends Entity { + } + // Paper end - Configurable falling blocks height nerf + this.handlePortal(); +- if (this.level() instanceof ServerLevel serverLevel && (this.isAlive() || this.forceTickAfterTeleportToDuplicate)) { ++ if (this.level() instanceof ServerLevel serverLevel && (this.leaf$isAlive || this.forceTickAfterTeleportToDuplicate)) { // Leaf - cache entity isAlive + BlockPos blockPos = this.blockPosition(); + boolean flag = this.blockState.getBlock() instanceof ConcretePowderBlock; + boolean flag1 = flag && this.level().getFluidState(blockPos).is(FluidTags.WATER); +diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java +index c1e7c04b048099dab7bb4cabdcb53add2201247f..cd8b55feed718d1a094794d3bb17f8654123371d 100644 +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -251,7 +251,7 @@ public class ItemEntity extends Entity implements TraceableEntity { + return; + } + +- if (config.temporaryImmunity.duration > 0 && this.isAlive() && this.onGround && !this.isRemoved() && (config.temporaryImmunity.nearbyItemMaxAge == -1 || this.age <= config.temporaryImmunity.nearbyItemMaxAge) && this.age % Math.max(1, config.temporaryImmunity.checkForMinecartNearItemInterval) == 0 && config.temporaryImmunity.maxItemHorizontalDistance >= 0 && config.temporaryImmunity.maxItemVerticalDistance >= 0) { ++ if (config.temporaryImmunity.duration > 0 && this.leaf$isAlive && this.onGround && !this.isRemoved() && (config.temporaryImmunity.nearbyItemMaxAge == -1 || this.age <= config.temporaryImmunity.nearbyItemMaxAge) && this.age % Math.max(1, config.temporaryImmunity.checkForMinecartNearItemInterval) == 0 && config.temporaryImmunity.maxItemHorizontalDistance >= 0 && config.temporaryImmunity.maxItemVerticalDistance >= 0) { // Leaf - cache entity isAlive + net.minecraft.world.phys.AABB aabb = this.getBoundingBox().inflate(config.temporaryImmunity.maxItemHorizontalDistance, config.temporaryImmunity.maxItemVerticalDistance, config.temporaryImmunity.maxItemHorizontalDistance); + for (Entity entity : this.level().getEntities(this, aabb)) { + if (entity instanceof net.minecraft.world.entity.vehicle.minecart.MinecartHopper hopper) { +@@ -305,7 +305,7 @@ public class ItemEntity extends Entity implements TraceableEntity { + + private boolean isMergable() { + ItemStack item = this.getItem(); +- return this.isAlive() && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate ++ return this.leaf$isAlive && this.pickupDelay != 32767 && this.age != -32768 && this.age < this.despawnRate && item.getCount() < item.getMaxStackSize(); // Paper - Alternative item-despawn-rate // Leaf - cache entity isAlive + } + + private void tryToMerge(ItemEntity itemEntity) { +diff --git a/net/minecraft/world/entity/monster/Creeper.java b/net/minecraft/world/entity/monster/Creeper.java +index 608d787b73dce1726ccece9e0372acf995f261d4..d6ba2d8e841daca1d241f3bc66fd2331f4e521b0 100644 +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -211,7 +211,7 @@ public class Creeper extends Monster { + + @Override + public void tick() { +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + this.oldSwell = this.swell; + if (this.isIgnited()) { + this.setSwellDir(1); +@@ -373,6 +373,7 @@ public class Creeper extends Monster { + if (!event.isCancelled()) { + // CraftBukkit end + this.dead = true; ++ this.leaf$onAliveDirty(); // Leaf - cache entity isAlive + serverLevel.explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), serverLevel.getGameRules().get(net.minecraft.world.level.gamerules.GameRules.MOB_GRIEFING) && level().purpurConfig.creeperAllowGriefing ? Level.ExplosionInteraction.MOB : Level.ExplosionInteraction.NONE); // CraftBukkit // Paper - fix DamageSource API (revert to vanilla, no, just no, don't change this) // Purpur - Add enderman and creeper griefing controls + this.spawnLingeringCloud(); + this.triggerOnDeathMobEffects(serverLevel, Entity.RemovalReason.KILLED); +diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java +index 809933cf4eea9dcedae4195cfecfe392973e96b6..c4ae7ad147af70d0d9a99c28a248fef3fd481669 100644 +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -311,7 +311,7 @@ public class EnderMan extends Monster implements NeutralMob { + } + + public boolean teleport() { +- if (!this.level().isClientSide() && this.isAlive()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive) { // Leaf - cache entity isAlive + double d = this.getX() + (this.random.nextDouble() - 0.5) * 64.0; + double d1 = this.getY() + (this.random.nextInt(64) - 32); + double d2 = this.getZ() + (this.random.nextDouble() - 0.5) * 64.0; +diff --git a/net/minecraft/world/entity/monster/Guardian.java b/net/minecraft/world/entity/monster/Guardian.java +index 60490d0611a352ba0546b39fd41259713a7f18b5..960212feca126be8951af917af1f42ca6946ce03 100644 +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -225,7 +225,7 @@ public class Guardian extends Monster { + + @Override + public void aiStep() { +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + if (this.level().isClientSide()) { + this.clientSideTailAnimationO = this.clientSideTailAnimation; + if (!this.isInWater()) { +diff --git a/net/minecraft/world/entity/monster/Ravager.java b/net/minecraft/world/entity/monster/Ravager.java +index 5e6fd02985eef337f2ff8e48fbd904a064c0560a..3e74ec757482a4598605004a670526a688c46859 100644 +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -184,7 +184,7 @@ public class Ravager extends Raider { + @Override + public void aiStep() { + super.aiStep(); +- if (this.isAlive() && (getRider() == null || !this.isControllable())) { // Purpur - Ridables ++ if (this.leaf$isAlive && (getRider() == null || !this.isControllable())) { // Purpur - Ridables // Leaf - cache entity isAlive + if (this.isImmobile()) { + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0); + } else { +diff --git a/net/minecraft/world/entity/monster/Shulker.java b/net/minecraft/world/entity/monster/Shulker.java +index 12e3ba1a545d5ec208ed33af66429f56fcdbed7f..9da2ab7c4f3018801ad39fde606c3833049f98bc 100644 +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -432,7 +432,7 @@ public class Shulker extends AbstractGolem implements Enemy { + } + + protected boolean teleportSomewhere() { +- if (!this.isNoAi() && this.isAlive()) { ++ if (!this.isNoAi() && this.leaf$isAlive) { // Leaf - cache entity isAlive + BlockPos blockPos = this.blockPosition(); + + for (int i = 0; i < 5; i++) { +@@ -541,7 +541,7 @@ public class Shulker extends AbstractGolem implements Enemy { + + @Override + public boolean canBeCollidedWith(@Nullable Entity entity) { +- return this.isAlive(); ++ return this.leaf$isAlive; // Leaf - cache entity isAlive + } + + public Direction getAttachFace() { +diff --git a/net/minecraft/world/entity/monster/Witch.java b/net/minecraft/world/entity/monster/Witch.java +index 589169495c3d74660b5afa3f3b0be3e18f0d8e8e..7bfb3e0a179a1a2e09ecb4b076e5e7749cea921c 100644 +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -150,7 +150,7 @@ public class Witch extends Raider implements RangedAttackMob { + + @Override + public void aiStep() { +- if (!this.level().isClientSide() && this.isAlive()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive) { // Leaf - cache entity isAlive + this.healRaidersGoal.decrementCooldown(); + if (this.healRaidersGoal.getCooldown() <= 0) { + this.attackPlayersGoal.setCanAttack(true); +diff --git a/net/minecraft/world/entity/monster/skeleton/Skeleton.java b/net/minecraft/world/entity/monster/skeleton/Skeleton.java +index 304e6e23a616ddc3312ef27ae5d94c927a52fb80..7274b751c5c36da12f1c3e8b729e83a372eb9c17 100644 +--- a/net/minecraft/world/entity/monster/skeleton/Skeleton.java ++++ b/net/minecraft/world/entity/monster/skeleton/Skeleton.java +@@ -92,7 +92,7 @@ public class Skeleton extends AbstractSkeleton { + + @Override + public void tick() { +- if (!this.level().isClientSide() && this.isAlive() && !this.isNoAi()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && !this.isNoAi()) { // Leaf - cache entity isAlive + if (this.isInPowderSnow) { + if (this.isFreezeConverting()) { + this.conversionTime--; +diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java +index 823f3f360c53ec627df7fa46e591f490626d0bdd..872bdfdf60802157e703eca49a2aafcf8792f639 100644 +--- a/net/minecraft/world/entity/monster/zombie/Zombie.java ++++ b/net/minecraft/world/entity/monster/zombie/Zombie.java +@@ -287,7 +287,7 @@ public class Zombie extends Monster { + + @Override + public void tick() { +- if (this.level() instanceof ServerLevel serverLevel && this.isAlive() && !this.isNoAi()) { ++ if (this.level() instanceof ServerLevel serverLevel && this.leaf$isAlive && !this.isNoAi()) { // Leaf - cache entity isAlive + if (this.isUnderWaterConverting()) { + this.conversionTime--; + if (this.conversionTime < 0) { +diff --git a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java +index 9249232f8d28ac86578cdf7bd877b54c90e5fd1e..a1ae413ace84255b3b2faa1545f99b415f6fc413 100644 +--- a/net/minecraft/world/entity/monster/zombie/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/zombie/ZombieVillager.java +@@ -212,7 +212,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { + + @Override + public void tick() { +- if (!this.level().isClientSide() && this.isAlive() && this.isConverting()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && this.isConverting()) { // Leaf - cache entity isAlive + int conversionProgress = this.getConversionProgress(); + this.villagerConversionTime -= conversionProgress; + if (this.villagerConversionTime <= 0) { +diff --git a/net/minecraft/world/entity/npc/villager/AbstractVillager.java b/net/minecraft/world/entity/npc/villager/AbstractVillager.java +index 05d1a859e1aee639ad9572f2369e6db3c3d7a111..c9b357886820dd8a783e1455f6090be1ebc8b59d 100644 +--- a/net/minecraft/world/entity/npc/villager/AbstractVillager.java ++++ b/net/minecraft/world/entity/npc/villager/AbstractVillager.java +@@ -286,6 +286,6 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa + + @Override + public boolean stillValid(Player player) { +- return this.getTradingPlayer() == player && this.isAlive() && player.isWithinEntityInteractionRange(this, 4.0); ++ return this.getTradingPlayer() == player && this.leaf$isAlive && player.isWithinEntityInteractionRange(this, 4.0); // Leaf - cache entity isAlive + } + } +diff --git a/net/minecraft/world/entity/npc/villager/Villager.java b/net/minecraft/world/entity/npc/villager/Villager.java +index 03d2cf4145e188bdb9474f6c3a43083170536c45..572517079d7c8653ab0c31cd32ee3ae7c4e96438 100644 +--- a/net/minecraft/world/entity/npc/villager/Villager.java ++++ b/net/minecraft/world/entity/npc/villager/Villager.java +@@ -468,7 +468,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler + @Override + public InteractionResult mobInteract(Player player, InteractionHand hand) { + ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.VILLAGER_SPAWN_EGG) || !this.isAlive() || this.isTrading() || this.isSleeping()) { ++ if (itemInHand.is(Items.VILLAGER_SPAWN_EGG) || !this.leaf$isAlive || this.isTrading() || this.isSleeping()) { // Leaf - cache entity isAlive + return super.mobInteract(player, hand); + } else if (this.isBaby()) { + this.setUnhappy(); +diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +index 426217da3e16ac07caf9c53f4f10fb10cf8018f4..a5d579107ddeb53db6bb59b9af798e18317ffdf5 100644 +--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java ++++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +@@ -178,7 +178,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { + this.setDeltaMovement(handHoldingItemAngle); + } + +- if (!this.noPhysics && this.isAlive() && hitResultOnMoveVector.getType() != HitResult.Type.MISS) { ++ if (!this.noPhysics && this.leaf$isAlive && hitResultOnMoveVector.getType() != HitResult.Type.MISS) { // Leaf - cache entity isAlive + this.preHitTargetOrDeflectSelf(hitResultOnMoveVector); // CraftBukkit - projectile hit event + this.needsSync = true; + } +diff --git a/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java b/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java +index d4c6a68c59b710cd3d158c674df03cbc2f2f307b..890b4c3020b3a212f9be94b266ede252db8cf86b 100644 +--- a/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java ++++ b/net/minecraft/world/entity/projectile/arrow/AbstractArrow.java +@@ -211,7 +211,7 @@ public abstract class AbstractArrow extends Projectile { + } + + this.inGroundTime++; +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + this.applyEffectsFromBlocks(); + } + +@@ -278,7 +278,7 @@ public abstract class AbstractArrow extends Projectile { + } + + private void stepMoveAndHit(BlockHitResult hitResult) { +- while (this.isAlive()) { ++ while (this.leaf$isAlive) { // Leaf - cache entity isAlive + Vec3 vec3 = this.position(); + ArrayList list = new ArrayList<>(this.findHitEntities(vec3, hitResult.getLocation())); + list.sort(Comparator.comparingDouble(entityHitResult1 -> vec3.distanceToSqr(entityHitResult1.getEntity().position()))); +@@ -291,12 +291,12 @@ public abstract class AbstractArrow extends Projectile { + } + + if (list.isEmpty()) { +- if (this.isAlive() && hitResult.getType() != HitResult.Type.MISS) { ++ if (this.leaf$isAlive && hitResult.getType() != HitResult.Type.MISS) { // Leaf - cache entity isAlive + this.preHitTargetOrDeflectSelf(hitResult); // CraftBukkit - projectile hit event + this.needsSync = true; + } + break; +- } else if (this.isAlive() && !this.noPhysics) { ++ } else if (this.leaf$isAlive && !this.noPhysics) { // Leaf - cache entity isAlive + ProjectileDeflection projectileDeflection = this.hitTargetsOrDeflectSelf(list); + this.needsSync = true; + if (this.getPierceLevel() > 0 && projectileDeflection == ProjectileDeflection.NONE) { +@@ -310,7 +310,7 @@ public abstract class AbstractArrow extends Projectile { + private ProjectileDeflection hitTargetsOrDeflectSelf(Collection hitResults) { + for (EntityHitResult entityHitResult : hitResults) { + ProjectileDeflection projectileDeflection = this.preHitTargetOrDeflectSelf(entityHitResult); // CraftBukkit - projectile hit event +- if (!this.isAlive() || projectileDeflection != ProjectileDeflection.NONE) { ++ if (!this.leaf$isAlive || projectileDeflection != ProjectileDeflection.NONE) { // Leaf - cache entity isAlive + return projectileDeflection; + } + } +@@ -509,14 +509,14 @@ public abstract class AbstractArrow extends Projectile { + serverPlayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.PLAY_ARROW_HIT_SOUND, 0.0F)); + } + +- if (!entity.isAlive() && this.piercedAndKilledEntities != null) { ++ if (!entity.leaf$isAlive && this.piercedAndKilledEntities != null) { // Leaf - cache entity isAlive + this.piercedAndKilledEntities.add(livingEntity1); + } + + if (!this.level().isClientSide() && owner instanceof ServerPlayer serverPlayer) { + if (this.piercedAndKilledEntities != null) { + CriteriaTriggers.KILLED_BY_ARROW.trigger(serverPlayer, this.piercedAndKilledEntities, this.firedFromWeapon); +- } else if (!entity.isAlive()) { ++ } else if (!entity.leaf$isAlive) { // Leaf - cache entity isAlive + CriteriaTriggers.KILLED_BY_ARROW.trigger(serverPlayer, List.of(entity), this.firedFromWeapon); + } + } +diff --git a/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java b/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java +index 4d416d3a8402a78b8ad6383d842f589a821ddbe9..e67fbd0914d7b4ce86cd3be01604167fd826302a 100644 +--- a/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java ++++ b/net/minecraft/world/entity/projectile/throwableitemprojectile/ThrownEnderpearl.java +@@ -183,7 +183,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + int sectionPosZ = SectionPos.blockToSectionCoord(this.position().z()); + Entity entity = this.owner != null ? findOwnerIncludingDeadPlayer(serverLevel, this.owner.getUUID()) : null; + if (entity instanceof ServerPlayer serverPlayer +- && !entity.isAlive() ++ && !entity.leaf$isAlive // Leaf - cache entity isAlive + && !serverPlayer.wonGame + && serverPlayer.level().getGameRules().get(GameRules.ENDER_PEARLS_VANISH_ON_DEATH)) { + this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause +@@ -191,7 +191,7 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + super.tick(); + } + +- if (this.isAlive()) { ++ if (this.leaf$isAlive) { // Leaf - cache entity isAlive + BlockPos blockPos = BlockPos.containing(this.position()); + if (( + --this.ticketTimer <= 0L +diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java +index 11e9163097dc1b51efcdec04b4db769ba00caa0b..97c3d1ff65dc53edfd54caece27e50df6c209fa2 100644 +--- a/net/minecraft/world/entity/raid/Raid.java ++++ b/net/minecraft/world/entity/raid/Raid.java +@@ -224,7 +224,7 @@ public class Raid { + private Predicate validPlayer() { + return player -> { + BlockPos blockPos = player.blockPosition(); +- return player.isAlive() && player.level().getRaidAt(blockPos) == this; ++ return player.leaf$isAlive && player.level().getRaidAt(blockPos) == this; // Leaf - cache entity isAlive + }; + } + +diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java +index e9a0372f5a262d13b25875d8c507fba9b5751840..8235a6c496e3644a7dfb3969d800fc45af15c569 100644 +--- a/net/minecraft/world/entity/raid/Raider.java ++++ b/net/minecraft/world/entity/raid/Raider.java +@@ -84,7 +84,7 @@ public abstract class Raider extends PatrollingMonster { + + @Override + public void aiStep() { +- if (this.level() instanceof ServerLevel serverLevel && this.isAlive()) { ++ if (this.level() instanceof ServerLevel serverLevel && this.leaf$isAlive) { // Leaf - cache entity isAlive + Raid currentRaid = this.getCurrentRaid(); + if (this.canJoinRaid()) { + if (currentRaid == null) { +diff --git a/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java b/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java +index 443f2c8cdf2e29838cd867f9594ffeb38faeacef..acfe32da195bf2a08f0f8c564f706c8e37b9f059 100644 +--- a/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java ++++ b/net/minecraft/world/entity/vehicle/minecart/MinecartHopper.java +@@ -96,7 +96,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper + } + + private void tryConsumeItems() { +- if (!this.level().isClientSide() && this.isAlive() && this.isEnabled() && !this.consumedItemThisFrame && this.suckInItems()) { ++ if (!this.level().isClientSide() && this.leaf$isAlive && this.isEnabled() && !this.consumedItemThisFrame && this.suckInItems()) { // Leaf - cache entity isAlive + this.consumedItemThisFrame = true; + this.setChanged(); + } +diff --git a/net/minecraft/world/level/EntityGetter.java b/net/minecraft/world/level/EntityGetter.java +index c0d4c489c05b9fa3888adc9133a0e6eb018a9e91..cc831f09853672f42576aa8f02ce3998066d4683 100644 +--- a/net/minecraft/world/level/EntityGetter.java ++++ b/net/minecraft/world/level/EntityGetter.java +@@ -140,7 +140,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst + final double distanceSqr = player.distanceToSqr(x, y, z); + + if (range < 0.0D || distanceSqr < range * range) { +- if (!player.isSpectator() && player.isAlive() && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check ++ if (!player.isSpectator() && player.leaf$isAlive && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check // Leaf - cache entity isAlive + return true; + } + } +@@ -153,7 +153,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst + for (Player player : this.players()) { + double distanceSqr = player.distanceToSqr(x, y, z); + if (range < 0.0D || distanceSqr < range * range) { +- if (!player.isSpectator() && player.isAlive() && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check ++ if (!player.isSpectator() && player.leaf$isAlive && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check // Leaf - cache entity isAlive + return true; + } + } +@@ -185,7 +185,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst + final double distanceSqr = player.distanceToSqr(x, y, z); + + if (range < 0.0D || distanceSqr < range * range) { +- if (!player.isSpectator() && player.isAlive() && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check ++ if (!player.isSpectator() && player.leaf$isAlive && player.affectsSpawning) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check // Leaf - cache entity isAlive + return true; + } + } +diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java +index 28660d0876403403651ee629d6acfd1232d42562..fd60761ac08fcb32e9a683532170255ee22cb5fe 100644 +--- a/net/minecraft/world/level/ServerExplosion.java ++++ b/net/minecraft/world/level/ServerExplosion.java +@@ -486,7 +486,7 @@ public class ServerExplosion implements Explosion { + int floor3 = Mth.floor(this.center.y + f + 1.0); + int floor4 = Mth.floor(this.center.z - f - 1.0); + int floor5 = Mth.floor(this.center.z + f + 1.0); +- List list = this.level.getEntities(this.excludeSourceFromDamage ? this.source : null, new AABB(floor, floor2, floor4, floor1, floor3, floor5), entity -> entity.isAlive() && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source ++ List list = this.level.getEntities(this.excludeSourceFromDamage ? this.source : null, new AABB(floor, floor2, floor4, floor1, floor3, floor5), entity -> entity.leaf$isAlive && !entity.isSpectator()); // Paper - Fix lag from explosions processing dead entities, Allow explosions to damage source // Leaf - cache entity isAlive + for (Entity entity : list) { // Paper - used in loop + if (!entity.ignoreExplosion(this)) { + double d = Math.sqrt(entity.distanceToSqr(this.center)) / f; +diff --git a/net/minecraft/world/level/block/entity/BellBlockEntity.java b/net/minecraft/world/level/block/entity/BellBlockEntity.java +index 5f742e509bede54066d64350007e442ec7471ea3..45524f405af9b42ec89cf3bf68d10934b7879421 100644 +--- a/net/minecraft/world/level/block/entity/BellBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/BellBlockEntity.java +@@ -114,18 +114,18 @@ public class BellBlockEntity extends BlockEntity { + + if (!this.level.isClientSide()) { + for (LivingEntity livingEntity : this.nearbyEntities) { +- if (livingEntity.isAlive() && !livingEntity.isRemoved() && blockPos.closerToCenterThan(livingEntity.position(), 32.0)) { ++ if (livingEntity.leaf$isAlive && !livingEntity.isRemoved() && blockPos.closerToCenterThan(livingEntity.position(), 32.0)) { // Leaf - cache entity isAlive + livingEntity.getBrain().setMemory(MemoryModuleType.HEARD_BELL_TIME, this.level.getGameTime()); + } + } + } + +- this.nearbyEntities.removeIf(e -> !e.isAlive()); // Paper - Fix bell block entity memory leak ++ this.nearbyEntities.removeIf(e -> !e.leaf$isAlive); // Paper - Fix bell block entity memory leak // Leaf - cache entity isAlive + } + + private static boolean areRaidersNearby(BlockPos pos, List raiders) { + for (LivingEntity livingEntity : raiders) { +- if (livingEntity.isAlive() ++ if (livingEntity.leaf$isAlive // Leaf - cache entity isAlive + && !livingEntity.isRemoved() + && pos.closerToCenterThan(livingEntity.position(), 32.0) + && livingEntity.getType().is(EntityTypeTags.RAIDERS)) { +@@ -167,7 +167,7 @@ public class BellBlockEntity extends BlockEntity { + } + + private static boolean isRaiderWithinRange(BlockPos pos, LivingEntity raider) { +- return raider.isAlive() && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0) && raider.getType().is(EntityTypeTags.RAIDERS); ++ return raider.leaf$isAlive && !raider.isRemoved() && pos.closerToCenterThan(raider.position(), 48.0) && raider.getType().is(EntityTypeTags.RAIDERS); // Leaf - cache entity isAlive + } + + @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add BellRevealRaiderEvent +diff --git a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +index 816d9a0f7f35b95b369ffbfc02e4d1f306b814c5..ebabb5c89e1ea902dcb93d91fe1caf13d152a19c 100644 +--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java ++++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +@@ -222,7 +222,7 @@ public class ConduitBlockEntity extends BlockEntity { + return selectNewTarget(level, pos); + } else { + LivingEntity livingEntity = EntityReference.getLivingEntity(destroyTarget, level); +- return livingEntity != null && livingEntity.isAlive() && pos.closerThan(livingEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? destroyTarget : null; // Purpur - Conduit behavior configuration ++ return livingEntity != null && livingEntity.leaf$isAlive && pos.closerThan(livingEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? destroyTarget : null; // Purpur - Conduit behavior configuration // Leaf - cache entity isAlive + } + } + +diff --git a/net/minecraft/world/scores/Scoreboard.java b/net/minecraft/world/scores/Scoreboard.java +index 8ac6138dbf9299a0253599a57f85138fc7c80bd2..b2a9de7e4c8f9ca11ef4523972117f06f4701b0b 100644 +--- a/net/minecraft/world/scores/Scoreboard.java ++++ b/net/minecraft/world/scores/Scoreboard.java +@@ -342,7 +342,7 @@ public class Scoreboard { + } + + public void entityRemoved(Entity entity) { +- if (!(entity instanceof Player) && !entity.isAlive()) { ++ if (!(entity instanceof Player) && !entity.leaf$isAlive) { // Leaf - cache entity isAlive + this.resetAllPlayerScores(entity); + this.removePlayerFromTeam(entity.getScoreboardName()); + } diff --git a/leaf-server/paper-patches/features/0059-cache-entity-isAlive.patch b/leaf-server/paper-patches/features/0059-cache-entity-isAlive.patch new file mode 100644 index 000000000..30848beb1 --- /dev/null +++ b/leaf-server/paper-patches/features/0059-cache-entity-isAlive.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hayanesuru +Date: Sun, 25 Jan 2026 20:50:29 +0900 +Subject: [PATCH] cache entity isAlive + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 1742395c42d7844ae3b66ca4bfab515a7ef52c08..3296eb75cc3ce0a97ad63337db0041514e056a04 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -2695,6 +2695,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa + public void setRealHealth(double health) { + if (Double.isNaN(health)) return; // Paper - Check for NaN + this.health = health; ++ this.getHandle().leaf$onAliveDirty(); // Leaf - cache entity isAlive + } + + public void updateScaledHealth() { +@@ -2712,6 +2713,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player, PluginMessa + this.getHandle().getEntityData().set(net.minecraft.world.entity.LivingEntity.DATA_HEALTH_ID, (float) this.getScaledHealth()); + + this.getHandle().maxHealthCache = this.getMaxHealth(); ++ this.getHandle().leaf$onAliveDirty(); // Leaf - cache entity isAlive + } + + @Override