diff --git a/leaf-server/minecraft-patches/features/0153-Async-target-finding.patch b/leaf-server/minecraft-patches/features/0153-Async-target-finding.patch index 684ffe8b..c714bf57 100644 --- a/leaf-server/minecraft-patches/features/0153-Async-target-finding.patch +++ b/leaf-server/minecraft-patches/features/0153-Async-target-finding.patch @@ -307,14 +307,14 @@ index 05d5cde42b7011091ef4ee874c0d9d5586ae3f10..88809afe30bb970a7de8bdfd26926880 this.navigation.tick(); this.customServerAiStep((ServerLevel)this.level()); diff --git a/net/minecraft/world/entity/ai/goal/AvoidEntityGoal.java b/net/minecraft/world/entity/ai/goal/AvoidEntityGoal.java -index 4b24bb47a53a46586a642f3fb2656b1b8b670bf2..9abb8e7b0dea2cb63dad234812d773403d0716f6 100644 +index 4b24bb47a53a46586a642f3fb2656b1b8b670bf2..22f052d02ccf22f22894a0b236af1b95c8d65e97 100644 --- a/net/minecraft/world/entity/ai/goal/AvoidEntityGoal.java +++ b/net/minecraft/world/entity/ai/goal/AvoidEntityGoal.java @@ -67,15 +67,24 @@ public class AvoidEntityGoal extends Goal { @Override public boolean canUse() { -+ // Leaf start - Async Avoid Entity Finding ++ // Leaf start - Async target finding + if (org.dreeam.leaf.config.modules.async.AsyncTargetFinding.searchEntity) { + if (!poll()) { + getNearestEntityAsync(); @@ -328,11 +328,11 @@ index 4b24bb47a53a46586a642f3fb2656b1b8b670bf2..9abb8e7b0dea2cb63dad234812d77340 this.mob, this.mob.getX(), - this.mob.getY(), -+ this.mob.getEyeY(), // Leaf - Async Avoid Entity Finding ++ this.mob.getEyeY(), // Leaf - Async target finding this.mob.getZ() ); + } -+ // Leaf end - Async Avoid Entity Finding ++ // Leaf end - Async target finding if (this.toAvoid == null) { return false; } else { @@ -340,7 +340,7 @@ index 4b24bb47a53a46586a642f3fb2656b1b8b670bf2..9abb8e7b0dea2cb63dad234812d77340 } } -+ // Leaf start - Async Avoid Entity Finding ++ // Leaf start - Async target finding + private boolean poll() { + if (!(this.mob.getGoalCtx().result() instanceof LivingEntity target)) return false; + var serverLevel = getServerLevel(this.mob); @@ -368,25 +368,25 @@ index 4b24bb47a53a46586a642f3fb2656b1b8b670bf2..9abb8e7b0dea2cb63dad234812d77340 + z + ); + } -+ // Leaf end - Async Avoid Entity Finding ++ // Leaf end - Async target finding + @Override public boolean canContinueToUse() { return !this.pathNav.isDone(); diff --git a/net/minecraft/world/entity/ai/goal/BegGoal.java b/net/minecraft/world/entity/ai/goal/BegGoal.java -index 28ef40e8a645989ea181297069cf2bbe571f3082..d011e4735cb8fd65a39a6b7a66386375b12aca78 100644 +index 28ef40e8a645989ea181297069cf2bbe571f3082..1c128f60adf6a72bed0ca40b98dc579cdf9d0e21 100644 --- a/net/minecraft/world/entity/ai/goal/BegGoal.java +++ b/net/minecraft/world/entity/ai/goal/BegGoal.java @@ -27,8 +27,43 @@ public class BegGoal extends Goal { this.setFlags(EnumSet.of(Goal.Flag.LOOK)); } -+ // Leaf start - Async Target Finding ++ // Leaf start - Async target finding + protected boolean poll() { + if (!(this.wolf.getGoalCtx().result() instanceof Player target)) return false; + if (target == null) return false; + ServerLevel serverLevel = getServerLevel(this.wolf); -+ if (serverLevel == null || !target.isAlive() || !playerHoldingInteresting(target)) return false; ++ if (serverLevel == null || !target.isAlive() || !playerHoldingInteresting0(target)) return false; + this.player = target; + return true; + } @@ -399,17 +399,17 @@ index 28ef40e8a645989ea181297069cf2bbe571f3082..d011e4735cb8fd65a39a6b7a66386375 + final TargetingConditions begTargeting = this.begTargeting; + ctx.wake = () -> { + var player = serverLevel.getNearestPlayer(begTargeting, wolf); -+ if (player != null && playerHoldingInteresting(player)) { ++ if (player != null && playerHoldingInteresting0(player)) { + return player; + } + return null; + }; + } -+ // Leaf end - Async Target Finding ++ // Leaf end - Async target finding + @Override public boolean canUse() { -+ // Leaf start - Async Target Finding ++ // Leaf start - Async target finding + if (poll()) { + return true; + } @@ -417,23 +417,28 @@ index 28ef40e8a645989ea181297069cf2bbe571f3082..d011e4735cb8fd65a39a6b7a66386375 + findTargetAsync(); + return false; + } -+ // Leaf end - Async Target Finding ++ // Leaf end - Async target finding this.player = this.level.getNearestPlayer(this.begTargeting, this.wolf); return this.player != null && this.playerHoldingInteresting(this.player); } -@@ -59,10 +94,10 @@ public class BegGoal extends Goal { - this.lookTime--; - } +@@ -69,4 +104,17 @@ public class BegGoal extends Goal { -- private boolean playerHoldingInteresting(Player player) { -+ private static boolean playerHoldingInteresting(Player player) { // Leaf start - Async Target Finding - static - for (InteractionHand interactionHand : InteractionHand.values()) { - ItemStack itemInHand = player.getItemInHand(interactionHand); -- if (itemInHand.is(Items.BONE) || this.wolf.isFood(itemInHand)) { -+ if (itemInHand.is(Items.BONE) || itemInHand.is(net.minecraft.tags.ItemTags.WOLF_FOOD)) { // Leaf end - Async Target Finding - return true; - } - } + return false; + } ++ ++ // Leaf start - Async target finding - static impl ++ private static boolean playerHoldingInteresting0(Player player) { ++ for (InteractionHand interactionHand : InteractionHand.values()) { ++ ItemStack itemInHand = player.getItemInHand(interactionHand); ++ if (itemInHand.is(Items.BONE) || itemInHand.is(net.minecraft.tags.ItemTags.WOLF_FOOD)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Leaf end - Async target finding - static impl + } diff --git a/net/minecraft/world/entity/ai/goal/CatLieOnBedGoal.java b/net/minecraft/world/entity/ai/goal/CatLieOnBedGoal.java index 4c46cd105cde3cbcde65a02ff691c3a8edd56c76..b3205c9f35687bc37124876198ec2d657ccaa96c 100644 --- a/net/minecraft/world/entity/ai/goal/CatLieOnBedGoal.java @@ -669,7 +674,7 @@ index 3093f03d4f298bf39fec8bad2b6c22518774aea8..0a41797fd7beddce0b93d42bac6e0270 } else { this.parent = animal; diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java -index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba25e300a8 100644 +index e82e32407cec6109b9c3b0106295217f4a3f4aa2..852393af4013178562940f6a0d07e5364758ec21 100644 --- a/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java @@ -26,13 +26,23 @@ public class GoalSelector { @@ -718,7 +723,7 @@ index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator); // Paper end - Perf: optimize goal types if (!flag.getOrDefault(flag1, NO_GOAL).canBeReplacedBy(goal)) { -@@ -85,7 +96,131 @@ public class GoalSelector { +@@ -85,7 +96,136 @@ public class GoalSelector { return true; } @@ -743,7 +748,12 @@ index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba + ctx.state = true; + } + -+ this.lockedFlags.entrySet().removeIf(entry -> !entry.getValue().isRunning()); ++ for (Goal.Flag flag : GOAL_FLAG_VALUES) { ++ WrappedGoal goal = this.lockedFlags.get(flag); ++ if (goal != null && !goal.isRunning()) { ++ this.lockedFlags.remove(flag); ++ } ++ } + + ctxIndex = 0; + ctx.state = true; @@ -791,7 +801,7 @@ index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba + if (!ctx.state) { + switch (goal.getGoal()) { + case net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal t -> t.poll(); -+ case net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal t -> t.poll(); ++ case net.minecraft.world.entity.ai.goal.target.ResetUniversalAngerTargetGoal t -> t.poll(); + default -> {} + } + } @@ -850,7 +860,7 @@ index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba for (WrappedGoal wrappedGoal : this.availableGoals) { if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams wrappedGoal.stop(); -@@ -116,6 +251,24 @@ public class GoalSelector { +@@ -116,6 +256,24 @@ public class GoalSelector { } public void tickRunningGoals(boolean tickAllRunning) { @@ -863,7 +873,7 @@ index e82e32407cec6109b9c3b0106295217f4a3f4aa2..f522125d19e31ec3fd3d38d1fdb307ba + } + ctxState = tickAllRunning ? 2 : 3; + } else { -+ for (WrappedGoal wrappedGoal : this.ctxGoals) { ++ for (WrappedGoal wrappedGoal : java.util.Objects.requireNonNull(this.ctxGoals)) { + if (wrappedGoal.isRunning() && (tickAllRunning || wrappedGoal.requiresUpdateEveryTick())) { + wrappedGoal.tick(); + } @@ -1390,10 +1400,10 @@ index c67a88c9c77ece7c85ffb169ac96da4f28291228..93bf51c9299354be2a581618bd31d2c4 + // Leaf end - Async search block } diff --git a/net/minecraft/world/entity/ai/goal/TemptGoal.java b/net/minecraft/world/entity/ai/goal/TemptGoal.java -index f88f618d34fb343b31de3af1a875d6633703df71..754c379b42cf65c1d2278b474cdfbe50e9e62b34 100644 +index f88f618d34fb343b31de3af1a875d6633703df71..22656c9ef08a65e23cabdd9f6af84f3d2279b075 100644 --- a/net/minecraft/world/entity/ai/goal/TemptGoal.java +++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java -@@ -36,12 +36,51 @@ public class TemptGoal extends Goal { +@@ -36,14 +36,43 @@ public class TemptGoal extends Goal { this.targetingConditions = TEMPT_TARGETING.copy().selector((entity, level) -> this.shouldFollow(entity)); } @@ -1423,28 +1433,22 @@ index f88f618d34fb343b31de3af1a875d6633703df71..754c379b42cf65c1d2278b474cdfbe50 this.calmDown--; return false; } else { +- this.player = getServerLevel(this.mob) +- .getNearestPlayer(this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE)), this.mob); + // Leaf start - Async Tempt Finding + if (org.dreeam.leaf.config.modules.async.AsyncTargetFinding.searchEntity) { -+ if (poll()) { -+ if (this.player != null) { -+ org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TEMPT); -+ if (event.isCancelled()) { -+ return false; -+ } -+ this.player = (event.getTarget() == null) ? null : ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getTarget()).getHandle(); -+ } -+ if (this.player != null) { -+ return true; -+ } -+ } else { ++ if (!poll()) { + getNearestPlayerAsync(); + return false; + } ++ } else { ++ this.player = getServerLevel(this.mob) ++ .getNearestPlayer(this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE)), this.mob); + } + // Leaf end - Async Tempt Finding - this.player = getServerLevel(this.mob) - .getNearestPlayer(this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE)), this.mob); // CraftBukkit start + if (this.player != null) { + org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TEMPT); diff --git a/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java b/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java index 4644f3f7af89623ca6218c0dd24bb6cd67db553b..c9750ad322ddaa9c457f0e652d87c7abf8559358 100644 --- a/net/minecraft/world/entity/ai/goal/target/DefendVillageTargetGoal.java