mirror of
https://github.com/PaperMC/Paper.git
synced 2025-04-26 22:06:20 +02:00
update Optimize Pathfinder - Remove Streams / Optimized collections
This commit is contained in:
parent
57fce3dca5
commit
ebbfe2749b
161 changed files with 130 additions and 159 deletions
patches
removed/1.17
server
0540-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch0541-Beacon-API-custom-effect-ranges.patch0542-Add-API-for-quit-reason.patch0543-Seed-based-feature-search.patch0544-Add-Wandering-Trader-spawn-rate-config-options.patch0545-Significantly-improve-performance-of-the-end-generat.patch0546-Expose-world-spawn-angle.patch0547-Add-Destroy-Speed-API.patch0548-Fix-Player-spawnParticle-x-y-z-precision-loss.patch0549-Add-LivingEntity-clearActiveItem.patch0550-Add-PlayerItemCooldownEvent.patch0551-More-lightning-API.patch0552-Climbing-should-not-bypass-cramming-gamerule.patch0553-Added-missing-default-perms-for-commands.patch0554-Add-PlayerShearBlockEvent.patch0555-Set-spigots-verbose-world-setting-to-false-by-def.patch0556-Fix-curing-zombie-villager-discount-exploit.patch0557-Limit-recipe-packets.patch0558-Fix-CraftSound-backwards-compatibility.patch0559-MC-4-Fix-item-position-desync.patch0560-Player-Chunk-Load-Unload-Events.patch0561-Optimize-Dynamic-get-Missing-Keys.patch0562-Expose-LivingEntity-hurt-direction.patch0563-Add-OBSTRUCTED-reason-to-BedEnterResult.patch0564-Do-not-crash-from-invalid-ingredient-lists-in-Villag.patch0565-added-PlayerTradeEvent.patch0566-Implement-TargetHitEvent.patch0567-Additional-Block-Material-API-s.patch0568-Fix-harming-potion-dupe.patch0569-Implement-API-to-get-Material-from-Boats-and-Minecar.patch0570-Cache-burn-durations.patch0571-Allow-disabling-mob-spawner-spawn-egg-transformation.patch0572-Implement-PlayerFlowerPotManipulateEvent.patch0573-Fix-interact-event-not-being-called-in-adventure.patch0574-Zombie-API-breaking-doors.patch0575-Fix-nerfed-slime-when-splitting.patch0576-Add-EntityLoadCrossbowEvent.patch0577-Guardian-beam-workaround.patch0578-Added-WorldGameRuleChangeEvent.patch0579-Added-ServerResourcesReloadedEvent.patch0580-Added-world-settings-for-mobs-picking-up-loot.patch0581-Implemented-BlockFailedDispenseEvent.patch0582-Added-PlayerLecternPageChangeEvent.patch0583-Added-PlayerLoomPatternSelectEvent.patch0584-Configurable-door-breaking-difficulty.patch0585-Empty-commands-shall-not-be-dispatched.patch0586-Implement-API-to-expose-exact-interaction-point.patch0587-Remove-stale-POIs.patch0588-Fix-villager-boat-exploit.patch0589-Add-sendOpLevel-API.patch0590-Add-StructureLocateEvent.patch0591-Collision-option-for-requiring-a-player-participant.patch0592-Remove-ProjectileHitEvent-call-when-fireballs-dead.patch0593-Return-chat-component-with-empty-text-instead-of-thr.patch0594-Make-schedule-command-per-world.patch0595-Configurable-max-leash-distance.patch0596-Implement-BlockPreDispenseEvent.patch0597-Added-Vanilla-Entity-Tags.patch0598-added-Wither-API.patch0599-Added-firing-of-PlayerChangeBeaconEffectEvent.patch0600-Fix-console-spam-when-removing-chests-in-water.patch0601-Add-toggle-for-always-placing-the-dragon-egg.patch0602-Added-PlayerStonecutterRecipeSelectEvent.patch0603-Add-dropLeash-variable-to-EntityUnleashEvent.patch0604-Skip-distance-map-update-when-spawning-disabled.patch0605-Reset-shield-blocking-on-dimension-change.patch0606-add-DragonEggFormEvent.patch0607-EntityMoveEvent.patch0608-added-option-to-disable-pathfinding-updates-on-block.patch0609-Inline-shift-direction-fields.patch0610-Allow-adding-items-to-BlockDropItemEvent.patch0611-Add-getMainThreadExecutor-to-BukkitScheduler.patch0612-living-entity-allow-attribute-registration.patch0613-fix-dead-slime-setSize-invincibility.patch0614-Merchant-getRecipes-should-return-an-immutable-list.patch0615-misc-debugging-dumps.patch0616-Add-support-for-hex-color-codes-in-console.patch0617-Expose-Tracked-Players.patch0618-Remove-streams-from-SensorNearest.patch0619-MC-29274-Fix-Wither-hostility-towards-players.patch0620-Throw-proper-exception-on-empty-JsonList-file.patch0621-Improve-ServerGUI.patch0622-stop-firing-pressure-plate-EntityInteractEvent-for-i.patch0623-fix-converting-txt-to-json-file.patch0624-Add-worldborder-events.patch0625-added-PlayerNameEntityEvent.patch0626-Prevent-grindstones-from-overstacking-items.patch0627-Add-recipe-to-cook-events.patch0628-Add-Block-isValidTool.patch0629-Allow-using-signs-inside-spawn-protection.patch0630-Implement-Keyed-on-World.patch0631-Add-fast-alternative-constructor-for-Rotations.patch0632-Item-Rarity-API.patch0633-Only-set-despawnTimer-for-Wandering-Traders-spawned-.patch0634-copy-TESign-isEditable-from-snapshots.patch0635-Drop-carried-item-when-player-has-disconnected.patch0636-forced-whitelist-use-configurable-kick-message.patch0637-Don-t-ignore-result-of-PlayerEditBookEvent.patch0638-fix-cancelling-block-falling-causing-client-desync.patch
|
@ -1,159 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 4 Aug 2020 22:24:15 +0200
|
||||
Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections
|
||||
1.17 Update: Please do this k thx bb
|
||||
I utilized the IDE to convert streams to non streams code, so shouldn't
|
||||
be any risk of behavior change. Only did minor optimization of the
|
||||
generated code set to remove unnecessary things.
|
||||
|
||||
I expect us to just drop this patch on next major update and re-apply
|
||||
it with the IDE again and re-apply the collections optimization.
|
||||
|
||||
Optimize collection by creating a list instead of a set of the key and value.
|
||||
|
||||
This lets us get faster foreach iteration, as well as avoids map lookups on
|
||||
the values when needed.
|
||||
|
||||
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 ba8ee93032aabe7ec4ecf52d452e1a580d6ebc20..2ef0e04af771e14f8d71aef4ccb81d3b81db7df5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
@@ -33,28 +33,31 @@ public class PathFinder {
|
||||
this.openSet.a();
|
||||
this.nodeEvaluator.prepare(world, mob);
|
||||
Node pathpoint = this.nodeEvaluator.getStart();
|
||||
- Map<Target, BlockPos> map = (Map) positions.stream().collect(Collectors.toMap((blockposition) -> {
|
||||
- return this.nodeEvaluator.getGoal((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
|
||||
- }, Function.identity()));
|
||||
- Path pathentity = this.findPath(pathpoint, map, followRange, distance, rangeMultiplier);
|
||||
+ // Paper start - remove streams - and optimize collection
|
||||
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
|
||||
+ for (BlockPos blockposition : positions) {
|
||||
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal((double) blockposition.getX(), blockposition.getY(), blockposition.getZ()), blockposition));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ Path pathentity = this.a(pathpoint, map, followRange, distance, rangeMultiplier);
|
||||
|
||||
this.nodeEvaluator.done();
|
||||
return pathentity;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- private Path findPath(Node startNode, Map<Target, BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
|
||||
- Set<Target> set = positions.keySet();
|
||||
+ private Path a(Node pathpoint, List<Map.Entry<Target, BlockPos>> list, float f, int i, float f1) { // Paper - optimize collection
|
||||
+ //Set<PathDestination> set = map.keySet(); // Paper
|
||||
|
||||
- startNode.g = 0.0F;
|
||||
- startNode.h = this.getBestH(startNode, set);
|
||||
- startNode.f = startNode.h;
|
||||
+ pathpoint.g = 0.0F;
|
||||
+ pathpoint.h = this.a(pathpoint, list); // Paper - optimize collection
|
||||
+ pathpoint.f = pathpoint.h;
|
||||
this.openSet.a();
|
||||
- this.openSet.a(startNode);
|
||||
+ this.openSet.a(pathpoint);
|
||||
Set<Node> set1 = ImmutableSet.of();
|
||||
int j = 0;
|
||||
- Set<Target> set2 = Sets.newHashSetWithExpectedSize(set.size());
|
||||
- int k = (int) ((float) this.maxVisitedNodes * rangeMultiplier);
|
||||
+ List<Map.Entry<Target, BlockPos>> set2 = Lists.newArrayListWithExpectedSize(list.size()); // Paper - optimize collection
|
||||
+ int k = (int) ((float) this.maxVisitedNodes * f1);
|
||||
|
||||
while (!this.openSet.e()) {
|
||||
++j;
|
||||
@@ -65,14 +68,15 @@ public class PathFinder {
|
||||
Node pathpoint1 = this.openSet.c();
|
||||
|
||||
pathpoint1.closed = true;
|
||||
- Iterator iterator = set.iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- Target pathdestination = (Target) iterator.next();
|
||||
+ // Paper start - optimize collection
|
||||
+ for (int i1 = 0; i1 < list.size(); i1++) {
|
||||
+ Map.Entry<Target, BlockPos> entry = list.get(i1);
|
||||
+ Target pathdestination = entry.getKey();
|
||||
|
||||
- if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) distance) {
|
||||
+ if (pathpoint1.distanceManhattan((Node) pathdestination) <= (float) i) {
|
||||
pathdestination.setReached();
|
||||
- set2.add(pathdestination);
|
||||
+ set2.add(entry);
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +84,7 @@ public class PathFinder {
|
||||
break;
|
||||
}
|
||||
|
||||
- if (pathpoint1.distanceTo(startNode) < followRange) {
|
||||
+ if (pathpoint1.distanceTo(pathpoint) < f) {
|
||||
int l = this.nodeEvaluator.getNeighbors(this.neighbors, pathpoint1);
|
||||
|
||||
for (int i1 = 0; i1 < l; ++i1) {
|
||||
@@ -90,10 +94,10 @@ public class PathFinder {
|
||||
pathpoint2.walkedDistance = pathpoint1.walkedDistance + f2;
|
||||
float f3 = pathpoint1.g + f2 + pathpoint2.costMalus;
|
||||
|
||||
- if (pathpoint2.walkedDistance < followRange && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) {
|
||||
+ if (pathpoint2.walkedDistance < f && (!pathpoint2.inOpenSet() || f3 < pathpoint2.g)) {
|
||||
pathpoint2.cameFrom = pathpoint1;
|
||||
pathpoint2.g = f3;
|
||||
- pathpoint2.h = this.getBestH(pathpoint2, set) * 1.5F;
|
||||
+ pathpoint2.h = this.a(pathpoint2, list) * 1.5F; // Paper - list instead of set
|
||||
if (pathpoint2.inOpenSet()) {
|
||||
this.openSet.a(pathpoint2, pathpoint2.g + pathpoint2.h);
|
||||
} else {
|
||||
@@ -105,31 +109,32 @@ public class PathFinder {
|
||||
}
|
||||
}
|
||||
|
||||
- Optional<Path> optional = !set2.isEmpty() ? set2.stream().map((pathdestination1) -> {
|
||||
- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), true);
|
||||
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((pathdestination1) -> {
|
||||
- return this.reconstructPath(pathdestination1.getBestNode(), (BlockPos) positions.get(pathdestination1), false);
|
||||
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
|
||||
-
|
||||
- if (!optional.isPresent()) {
|
||||
- return null;
|
||||
- } else {
|
||||
- Path pathentity = (Path) optional.get();
|
||||
-
|
||||
- return pathentity;
|
||||
+ // Paper start - remove streams - and optimize collection
|
||||
+ Path best = null;
|
||||
+ boolean useSet1 = set2.isEmpty();
|
||||
+ Comparator<Path> comparator = useSet1 ? Comparator.comparingInt(Path::getNodeCount)
|
||||
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
|
||||
+ for (Map.Entry<Target, BlockPos> entry : useSet1 ? list : set2) {
|
||||
+ Path pathEntity = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !useSet1);
|
||||
+ if (best == null || comparator.compare(pathEntity, best) < 0)
|
||||
+ best = pathEntity;
|
||||
}
|
||||
+ return best;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
- private float getBestH(Node node, Set<Target> targets) {
|
||||
+ private float a(Node pathpoint, List<Map.Entry<Target, BlockPos>> list) { // Paper - optimize collection
|
||||
float f = Float.MAX_VALUE;
|
||||
|
||||
float f1;
|
||||
|
||||
- for (Iterator iterator = targets.iterator(); iterator.hasNext(); f = Math.min(f1, f)) {
|
||||
- Target pathdestination = (Target) iterator.next();
|
||||
+ // Paper start - optimize collection
|
||||
+ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper
|
||||
+ Target pathdestination = list.get(i).getKey(); // Paper
|
||||
+ // Paper end
|
||||
|
||||
- f1 = node.distanceTo(pathdestination);
|
||||
- pathdestination.updateBest(f1, node);
|
||||
+ f1 = pathpoint.distanceTo(pathdestination);
|
||||
+ pathdestination.updateBest(f1, pathpoint);
|
||||
}
|
||||
|
||||
return f;
|
|
@ -0,0 +1,130 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 4 Aug 2020 22:24:15 +0200
|
||||
Subject: [PATCH] Optimize Pathfinder - Remove Streams / Optimized collections
|
||||
|
||||
1.17 Update: Please do this k thx bb
|
||||
I utilized the IDE to convert streams to non streams code, so shouldn't
|
||||
be any risk of behavior change. Only did minor optimization of the
|
||||
generated code set to remove unnecessary things.
|
||||
|
||||
I expect us to just drop this patch on next major update and re-apply
|
||||
it with the IDE again and re-apply the collections optimization.
|
||||
|
||||
Optimize collection by creating a list instead of a set of the key and value.
|
||||
|
||||
This lets us get faster foreach iteration, as well as avoids map lookups on
|
||||
the values when needed.
|
||||
|
||||
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 800d464207026d145056b39b298045121342b899..6062f5154c55179e1cf3b280e6dc56d2f561987d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
@@ -35,27 +35,31 @@ public class PathFinder {
|
||||
this.openSet.clear();
|
||||
this.nodeEvaluator.prepare(world, mob);
|
||||
Node node = this.nodeEvaluator.getStart();
|
||||
- Map<Target, BlockPos> map = positions.stream().collect(Collectors.toMap((blockPos) -> {
|
||||
- return this.nodeEvaluator.getGoal((double)blockPos.getX(), (double)blockPos.getY(), (double)blockPos.getZ());
|
||||
- }, Function.identity()));
|
||||
+ // Paper start - remove streams - and optimize collection
|
||||
+ List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
|
||||
+ for (BlockPos blockPos : positions) {
|
||||
+ map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getGoal(blockPos.getX(), blockPos.getY(), blockPos.getZ()), blockPos));
|
||||
+ }
|
||||
+ // Paper end
|
||||
Path path = this.findPath(world.getProfiler(), node, map, followRange, distance, rangeMultiplier);
|
||||
this.nodeEvaluator.done();
|
||||
return path;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
- private Path findPath(ProfilerFiller profiler, Node startNode, Map<Target, BlockPos> positions, float followRange, int distance, float rangeMultiplier) {
|
||||
+ // Paper start - optimize collection
|
||||
+ private Path findPath(ProfilerFiller profiler, Node startNode, List<Map.Entry<Target, BlockPos>> positions, float followRange, int distance, float rangeMultiplier) {
|
||||
profiler.push("find_path");
|
||||
profiler.markForCharting(MetricCategory.PATH_FINDING);
|
||||
- Set<Target> set = positions.keySet();
|
||||
+ //Set<Target> set = positions.keySet();
|
||||
startNode.g = 0.0F;
|
||||
- startNode.h = this.getBestH(startNode, set);
|
||||
+ startNode.h = this.getBestH(startNode, positions); // Paper - optimize collection
|
||||
startNode.f = startNode.h;
|
||||
this.openSet.clear();
|
||||
this.openSet.insert(startNode);
|
||||
- Set<Node> set2 = ImmutableSet.of();
|
||||
+ //Set<Node> set2 = ImmutableSet.of(); // Paper - unused - diff on change
|
||||
int i = 0;
|
||||
- Set<Target> set3 = Sets.newHashSetWithExpectedSize(set.size());
|
||||
+ List<Map.Entry<Target, BlockPos>> entryList = Lists.newArrayListWithExpectedSize(positions.size()); // Paper - optimize collection
|
||||
int j = (int)((float)this.maxVisitedNodes * rangeMultiplier);
|
||||
|
||||
while(!this.openSet.isEmpty()) {
|
||||
@@ -67,14 +71,18 @@ public class PathFinder {
|
||||
Node node = this.openSet.pop();
|
||||
node.closed = true;
|
||||
|
||||
- for(Target target : set) {
|
||||
+ // Paper start - optimize collection
|
||||
+ for(int i1 = 0; i1 < positions.size(); i1++) {
|
||||
+ final Map.Entry<Target, BlockPos> entry = positions.get(i1);
|
||||
+ Target target = entry.getKey();
|
||||
if (node.distanceManhattan(target) <= (float)distance) {
|
||||
target.setReached();
|
||||
- set3.add(target);
|
||||
+ entryList.add(entry);
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
- if (!set3.isEmpty()) {
|
||||
+ if (!entryList.isEmpty()) { // Paper - rename variable
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -89,7 +97,7 @@ public class PathFinder {
|
||||
if (node2.walkedDistance < followRange && (!node2.inOpenSet() || g < node2.g)) {
|
||||
node2.cameFrom = node;
|
||||
node2.g = g;
|
||||
- node2.h = this.getBestH(node2, set) * 1.5F;
|
||||
+ node2.h = this.getBestH(node2, positions) * 1.5F; // Paper - list instead of set
|
||||
if (node2.inOpenSet()) {
|
||||
this.openSet.changeCost(node2, node2.g + node2.h);
|
||||
} else {
|
||||
@@ -101,19 +109,27 @@ public class PathFinder {
|
||||
}
|
||||
}
|
||||
|
||||
- Optional<Path> optional = !set3.isEmpty() ? set3.stream().map((target) -> {
|
||||
- return this.reconstructPath(target.getBestNode(), positions.get(target), true);
|
||||
- }).min(Comparator.comparingInt(Path::getNodeCount)) : set.stream().map((target) -> {
|
||||
- return this.reconstructPath(target.getBestNode(), positions.get(target), false);
|
||||
- }).min(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount));
|
||||
- profiler.pop();
|
||||
- return !optional.isPresent() ? null : optional.get();
|
||||
+ // Paper start - remove streams - and optimize collection
|
||||
+ Path best = null;
|
||||
+ boolean entryListIsEmpty = entryList.isEmpty();
|
||||
+ Comparator<Path> comparator = entryListIsEmpty ? Comparator.comparingInt(Path::getNodeCount)
|
||||
+ : Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount);
|
||||
+ for (Map.Entry<Target, BlockPos> entry : entryListIsEmpty ? positions : entryList) {
|
||||
+ Path path = this.reconstructPath(entry.getKey().getBestNode(), entry.getValue(), !entryListIsEmpty);
|
||||
+ if (best == null || comparator.compare(path, best) < 0)
|
||||
+ best = path;
|
||||
+ }
|
||||
+ return best;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
- private float getBestH(Node node, Set<Target> targets) {
|
||||
+ private float getBestH(Node node, List<Map.Entry<Target, BlockPos>> targets) { // Paper - optimize collection - Set<Target> -> List<Map.Entry<Target, BlockPos>>
|
||||
float f = Float.MAX_VALUE;
|
||||
|
||||
- for(Target target : targets) {
|
||||
+ // Paper start - optimize collection
|
||||
+ for (int i = 0, targetsSize = targets.size(); i < targetsSize; i++) {
|
||||
+ final Target target = targets.get(i).getKey();
|
||||
+ // Paper end
|
||||
float g = node.distanceTo(target);
|
||||
target.updateBest(g, node);
|
||||
f = Math.min(g, f);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue