From 96c6601300176cf5031c2d252f40653f29d5bd86 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Wed, 2 Apr 2025 19:58:38 +0200 Subject: [PATCH] fix :turtle: --- .../features/0153-Async-Block-Finding.patch | 131 ++++++++++++++---- 1 file changed, 101 insertions(+), 30 deletions(-) diff --git a/leaf-server/minecraft-patches/features/0153-Async-Block-Finding.patch b/leaf-server/minecraft-patches/features/0153-Async-Block-Finding.patch index 1c9e14d9..24c4799e 100644 --- a/leaf-server/minecraft-patches/features/0153-Async-Block-Finding.patch +++ b/leaf-server/minecraft-patches/features/0153-Async-Block-Finding.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Async Block Finding diff --git a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -index 3f080b15543bf8c5fa0774b62d7f12e13b82511a..2bc0f19b86067491f33f647d2e387acd83492844 100644 +index 3f080b15543bf8c5fa0774b62d7f12e13b82511a..135506968893cd164c4d416ce4d356e9f0ed3977 100644 --- a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +++ b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -20,6 +20,19 @@ public abstract class MoveToBlockGoal extends Goal { +@@ -20,6 +20,18 @@ public abstract class MoveToBlockGoal extends Goal { private final int verticalSearchRange; protected int verticalSearchStart; @@ -22,64 +22,116 @@ index 3f080b15543bf8c5fa0774b62d7f12e13b82511a..2bc0f19b86067491f33f647d2e387acd + + private final java.util.concurrent.ConcurrentLinkedQueue candidateBlocks = new java.util.concurrent.ConcurrentLinkedQueue<>(); + private boolean asyncSearchInProgress = false; -+ private boolean searchComplete = false; + // Leaf end - Async Block Finding + public MoveToBlockGoal(PathfinderMob mob, double speedModifier, int searchRange) { this(mob, speedModifier, searchRange, 1); } -@@ -109,6 +122,95 @@ public abstract class MoveToBlockGoal extends Goal { +@@ -29,6 +41,10 @@ public abstract class MoveToBlockGoal extends Goal { + super.stop(); + this.blockPos = BlockPos.ZERO; + this.mob.movingTarget = null; ++ // Leaf start - Reset async state on goal stop ++ this.candidateBlocks.clear(); ++ this.asyncSearchInProgress = false; ++ // Leaf end + } + // Paper end + +@@ -53,23 +69,28 @@ public abstract class MoveToBlockGoal extends Goal { + } + + protected int nextStartTick(PathfinderMob creature) { +- return reducedTickDelay(200 + creature.getRandom().nextInt(200)); ++ // Use the static method from the Goal class directly ++ return Goal.reducedTickDelay(200 + creature.getRandom().nextInt(200)); + } + + @Override + public boolean canContinueToUse() { +- return this.tryTicks >= -this.maxStayTicks && this.tryTicks <= 1200 && this.isValidTarget(this.mob.level(), this.blockPos); ++ return this.tryTicks >= -this.maxStayTicks && this.tryTicks <= 1200 && this.blockPos != BlockPos.ZERO && this.isValidTarget(this.mob.level(), this.blockPos); + } + + @Override + public void start() { +- this.moveMobToBlock(); ++ if (this.blockPos != BlockPos.ZERO) { ++ this.moveMobToBlock(); ++ } + this.tryTicks = 0; + this.maxStayTicks = this.mob.getRandom().nextInt(this.mob.getRandom().nextInt(1200) + 1200) + 1200; + } + + protected void moveMobToBlock() { +- this.mob.getNavigation().moveTo(this.blockPos.getX() + 0.5, this.blockPos.getY() + 1, this.blockPos.getZ() + 0.5, this.speedModifier); ++ if (this.blockPos != BlockPos.ZERO) { ++ this.mob.getNavigation().moveTo(this.blockPos.getX() + 0.5, this.blockPos.getY() + 1, this.blockPos.getZ() + 0.5, this.speedModifier); ++ } + } + + public double acceptedDistance() { +@@ -77,7 +98,7 @@ public abstract class MoveToBlockGoal extends Goal { + } + + protected BlockPos getMoveToTarget() { +- return this.blockPos.above(); ++ return this.blockPos != BlockPos.ZERO ? this.blockPos.above() : BlockPos.ZERO; + } + + @Override +@@ -87,7 +108,13 @@ public abstract class MoveToBlockGoal extends Goal { + + @Override + public void tick() { ++ if (this.blockPos == BlockPos.ZERO) { ++ return; ++ } ++ + BlockPos moveToTarget = this.getMoveToTarget(); ++ if (moveToTarget == BlockPos.ZERO) return; ++ + if (!moveToTarget.closerToCenterThan(this.mob.position(), this.acceptedDistance())) { + this.reachedTarget = false; + this.tryTicks++; +@@ -109,20 +136,90 @@ public abstract class MoveToBlockGoal extends Goal { } protected boolean findNearestBlock() { + // Leaf start - Async Block Finding -+ // Check if async is enabled, if not use the original implementation + if (!org.dreeam.leaf.config.modules.async.AsyncBlockFinding.enabled) { + return findNearestBlockSync(); + } + -+ // Check if we're done with the current search -+ if (searchComplete) { -+ searchComplete = false; -+ asyncSearchInProgress = false; -+ candidateBlocks.clear(); -+ return false; -+ } -+ + while (!candidateBlocks.isEmpty()) { + BlockPos pos = candidateBlocks.poll(); -+ + if (pos != null && this.mob.level().hasChunkAt(pos) && + this.mob.isWithinRestriction(pos) && + this.isValidTarget(this.mob.level(), pos)) { + + this.blockPos = pos; + this.mob.movingTarget = pos == BlockPos.ZERO ? null : pos; -+ searchComplete = true; + return true; + } + } + -+ // If no candidates are left and async search is done -+ if (candidateBlocks.isEmpty() && !asyncSearchInProgress) { -+ searchComplete = true; ++ if (asyncSearchInProgress) { + return false; + } + -+ // Start async search if needed -+ if (!asyncSearchInProgress && candidateBlocks.isEmpty()) { ++ // Check again before starting, avoids tiny race condition if canUse is called rapidly ++ if (!asyncSearchInProgress) { + asyncSearchInProgress = true; -+ -+ // Get necessary data from main thread + final BlockPos centerPos = this.mob.blockPosition().immutable(); + final int searchRange = this.searchRange; + final int verticalRange = this.verticalSearchRange; + final int verticalStart = this.verticalSearchStart; ++ + BLOCK_FINDER_EXECUTOR.execute(() -> { + try { + generateCandidateBlocks(centerPos, searchRange, verticalRange, verticalStart); + } catch (Exception e) { -+ e.printStackTrace(); ++ e.printStackTrace(); // Keep basic error logging + } finally { + asyncSearchInProgress = false; + } @@ -87,11 +139,10 @@ index 3f080b15543bf8c5fa0774b62d7f12e13b82511a..2bc0f19b86067491f33f647d2e387acd + } + + return false; ++ // Leaf end - Async Block Finding + } + -+ // Generate candidate blocks in a spiral pattern + private void generateCandidateBlocks(BlockPos center, int searchRange, int verticalRange, int verticalStart) { -+ // Pre-calculate a prioritized list of positions + java.util.List positions = new java.util.ArrayList<>(); + + for (int i2 = verticalStart; i2 <= verticalRange; i2 = i2 > 0 ? -i2 : 1 - i2) { @@ -105,22 +156,42 @@ index 3f080b15543bf8c5fa0774b62d7f12e13b82511a..2bc0f19b86067491f33f647d2e387acd + } + } + -+ // Sort by distance to center (closest first) + positions.sort((p1, p2) -> { + double d1 = p1.distSqr(center); + double d2 = p2.distSqr(center); + return Double.compare(d1, d2); + }); + -+ // Add to candidate queue + for (BlockPos pos : positions) { + candidateBlocks.add(pos); + } + } + -+ // The original method renamed + protected boolean findNearestBlockSync() { -+ // Leaf end - Async Block Finding int i = this.searchRange; int i1 = this.verticalSearchRange; - BlockPos blockPos = this.mob.blockPosition(); +- BlockPos blockPos = this.mob.blockPosition(); ++ BlockPos blockPosOrigin = this.mob.blockPosition(); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + + for (int i2 = this.verticalSearchStart; i2 <= i1; i2 = i2 > 0 ? -i2 : 1 - i2) { + for (int i3 = 0; i3 < i; i3++) { + for (int i4 = 0; i4 <= i3; i4 = i4 > 0 ? -i4 : 1 - i4) { + for (int i5 = i4 < i3 && i4 > -i3 ? i3 : 0; i5 <= i3; i5 = i5 > 0 ? -i5 : 1 - i5) { +- mutableBlockPos.setWithOffset(blockPos, i4, i2 - 1, i5); ++ mutableBlockPos.setWithOffset(blockPosOrigin, i4, i2 - 1, i5); + if (!this.mob.level().hasChunkAt(mutableBlockPos)) continue; // Gale - Airplane - block goal does not load chunks - if this block isn't loaded, continue + if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) { +- this.blockPos = mutableBlockPos; +- this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper ++ this.blockPos = mutableBlockPos.immutable(); ++ this.mob.movingTarget = this.blockPos == BlockPos.ZERO ? null : this.blockPos; // Paper + return true; + } + } +@@ -134,4 +231,5 @@ public abstract class MoveToBlockGoal extends Goal { + } + + protected abstract boolean isValidTarget(LevelReader level, BlockPos pos); ++ + }