9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-22 00:19:20 +00:00
Files
Leaf/patches/server/0042-Hearse-Pathfinding-Fixes.patch
2023-01-04 19:27:51 -05:00

273 lines
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BuildTools <unconfigured@null.spigotmc.org>
Date: Wed, 4 Jan 2023 15:19:31 +0800
Subject: [PATCH] Hearse: Pathfinding Fixes
Original license:
Original project: https://github.com/NaturalCodeClub/Hearse
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/BinaryHeap.java b/src/main/java/net/minecraft/world/level/pathfinder/BinaryHeap.java
index 27b9cefc172b391824ead382a712b8b9b1ddfe45..c949325dc9b21d8a75ee639210911c61616949c8 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/BinaryHeap.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/BinaryHeap.java
@@ -4,10 +4,8 @@ public class BinaryHeap {
private Node[] heap = new Node[128];
private int size;
- public Node insert(Node node) {
- if (node.heapIdx >= 0) {
- throw new IllegalStateException("OW KNOWS!");
- } else {
+ public synchronized Node insert(Node node) {
+ if (node.heapIdx < 0) {
if (this.size == this.heap.length) {
Node[] nodes = new Node[this.size << 1];
System.arraycopy(this.heap, 0, nodes, 0, this.size);
@@ -17,19 +15,19 @@ public class BinaryHeap {
this.heap[this.size] = node;
node.heapIdx = this.size;
this.upHeap(this.size++);
- return node;
}
+ return node;
}
- public void clear() {
+ public synchronized void clear() {
this.size = 0;
}
- public Node peek() {
+ public synchronized Node peek() {
return this.heap[0];
}
- public Node pop() {
+ public synchronized Node pop() {
Node node = this.heap[0];
this.heap[0] = this.heap[--this.size];
this.heap[this.size] = null;
@@ -41,7 +39,7 @@ public class BinaryHeap {
return node;
}
- public void remove(Node node) {
+ public synchronized void remove(Node node) {
this.heap[node.heapIdx] = this.heap[--this.size];
this.heap[this.size] = null;
if (this.size > node.heapIdx) {
@@ -55,7 +53,7 @@ public class BinaryHeap {
node.heapIdx = -1;
}
- public void changeCost(Node node, float weight) {
+ public synchronized void changeCost(Node node, float weight) {
float f = node.f;
node.f = weight;
if (weight < f) {
@@ -66,7 +64,7 @@ public class BinaryHeap {
}
- public int size() {
+ public synchronized int size() {
return this.size;
}
@@ -135,11 +133,11 @@ public class BinaryHeap {
node.heapIdx = index;
}
- public boolean isEmpty() {
+ public synchronized boolean isEmpty() {
return this.size == 0;
}
- public Node[] getHeap() {
+ public synchronized Node[] getHeap() {
Node[] nodes = new Node[this.size()];
System.arraycopy(this.heap, 0, nodes, 0, this.size());
return nodes;
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/FlyNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/FlyNodeEvaluator.java
index b0bae04ab5a93dd4cf1eeeb02bed1e508e1f2913..d427735eff0056c171591709829d0bb76f7bb6f3 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/FlyNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/FlyNodeEvaluator.java
@@ -1,6 +1,7 @@
package net.minecraft.world.level.pathfinder;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.EnumSet;
import java.util.List;
@@ -15,7 +16,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
public class FlyNodeEvaluator extends WalkNodeEvaluator {
- private final Long2ObjectMap<BlockPathTypes> pathTypeByPosCache = new Long2ObjectOpenHashMap<>();
+ private final Long2ObjectMap<BlockPathTypes> pathTypeByPosCache = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
private static final float SMALL_MOB_INFLATED_START_NODE_BOUNDING_BOX = 1.5F;
private static final int MAX_START_NODE_CANDIDATES = 10;
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
index a8a2594b8f5b3ebf6a1f918c7d822ad35b051b17..7de3c41e036ddb91d951cefbd2ea093918150680 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/NodeEvaluator.java
@@ -1,6 +1,7 @@
package net.minecraft.world.level.pathfinder;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
@@ -11,7 +12,7 @@ import net.minecraft.world.level.PathNavigationRegion;
public abstract class NodeEvaluator {
protected PathNavigationRegion level;
protected Mob mob;
- protected final Int2ObjectMap<Node> nodes = new Int2ObjectOpenHashMap<>();
+ protected final Int2ObjectMap<Node> nodes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
protected int entityWidth;
protected int entityHeight;
protected int entityDepth;
@@ -39,9 +40,7 @@ public abstract class NodeEvaluator {
}
protected Node getNode(int x, int y, int z) {
- return this.nodes.computeIfAbsent(Node.createHash(x, y, z), (l) -> {
- return new Node(x, y, z);
- });
+ return this.nodes.computeIfAbsent(Node.createHash(x, y, z), (l) -> new Node(x, y, z));
}
public abstract Node getStart();
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
index a8af51a25b0f99c3a64d9150fdfcd6b818aa7581..919f8c1aa52aa8c468427e850d1d4764a915320f 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
@@ -8,6 +8,8 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -20,6 +22,7 @@ import net.minecraft.world.level.PathNavigationRegion;
public class PathFinder {
private static final float FUDGING = 1.5F;
private final Node[] neighbors = new Node[32];
+ private final ReadWriteLock evaluatorLock = new ReentrantReadWriteLock();
private final int maxVisitedNodes;
public final NodeEvaluator nodeEvaluator;
private static final boolean DEBUG = false;
@@ -33,19 +36,40 @@ public class PathFinder {
@Nullable
public Path findPath(PathNavigationRegion world, Mob mob, Set<BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
this.openSet.clear();
- this.nodeEvaluator.prepare(world, mob);
- Node node = this.nodeEvaluator.getStart();
+ this.evaluatorLock.writeLock().lock();
+ try {
+ this.nodeEvaluator.prepare(world, mob);
+ }finally {
+ this.evaluatorLock.writeLock().unlock();
+ }
+ Node node;
+ this.evaluatorLock.readLock().lock();
+ try{
+ node = this.nodeEvaluator.getStart();
+ }finally {
+ this.evaluatorLock.readLock().unlock();
+ }
if (node == null) {
return null;
} else {
// Paper start - remove streams - and optimize collection
List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
- for (BlockPos pos : positions) {
- map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos));
+ this.evaluatorLock.readLock().lock();
+ try {
+ for (BlockPos pos : positions) {
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(pos.getX(), pos.getY(), pos.getZ()), pos));
+ }
+ }finally {
+ this.evaluatorLock.readLock().unlock();
}
// Paper end
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
- this.nodeEvaluator.done();
+ this.evaluatorLock.writeLock().lock();
+ try {
+ this.nodeEvaluator.done();
+ }finally {
+ this.evaluatorLock.writeLock().unlock();;
+ }
return path;
}
}
@@ -91,7 +115,13 @@ public class PathFinder {
}
if (!(node.distanceTo(startNode) >= followRange)) {
- int k = this.nodeEvaluator.getNeighbors(this.neighbors, node);
+ int k;
+ this.evaluatorLock.readLock().lock();
+ try {
+ k = this.nodeEvaluator.getNeighbors(this.neighbors, node);
+ }finally {
+ this.evaluatorLock.readLock().unlock();
+ }
for(int l = 0; l < k; ++l) {
Node node2 = this.neighbors[l];
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java
index 6084631b5b502279b84f190dc62fc76b770e368e..f526adbd31e65fc74af48f6137d293a7a7ceafbb 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/SwimNodeEvaluator.java
@@ -2,6 +2,7 @@ package net.minecraft.world.level.pathfinder;
import com.google.common.collect.Maps;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Map;
import javax.annotation.Nullable;
@@ -17,7 +18,7 @@ import net.minecraft.world.level.material.FluidState;
public class SwimNodeEvaluator extends NodeEvaluator {
private final boolean allowBreaching;
- private final Long2ObjectMap<BlockPathTypes> pathTypesByPosCache = new Long2ObjectOpenHashMap<>();
+ private final Long2ObjectMap<BlockPathTypes> pathTypesByPosCache = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
public SwimNodeEvaluator(boolean canJumpOutOfWater) {
this.allowBreaching = canJumpOutOfWater;
diff --git a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
index 894881018c659d874f28f5744f0b8247cfecb1c1..ae06f7ef9c4b8147508984f8b46176de46171285 100644
--- a/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/src/main/java/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -1,8 +1,10 @@
package net.minecraft.world.level.pathfinder;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
+import it.unimi.dsi.fastutil.objects.Object2BooleanMaps;
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap;
import java.util.EnumSet;
import javax.annotation.Nullable;
@@ -33,8 +35,8 @@ public class WalkNodeEvaluator extends NodeEvaluator {
public static final double SPACE_BETWEEN_WALL_POSTS = 0.5D;
private static final double DEFAULT_MOB_JUMP_HEIGHT = 1.125D;
protected float oldWaterCost;
- private final Long2ObjectMap<BlockPathTypes> pathTypesByPosCache = new Long2ObjectOpenHashMap<>();
- private final Object2BooleanMap<AABB> collisionCache = new Object2BooleanOpenHashMap<>();
+ private final Long2ObjectMap<BlockPathTypes> pathTypesByPosCache = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
+ private final Object2BooleanMap<AABB> collisionCache = Object2BooleanMaps.synchronize(new Object2BooleanOpenHashMap<>());
@Override
public void prepare(PathNavigationRegion cachedWorld, Mob entity) {