Avoid a cubed max search distance for POIs (#8576)

The max search distance used to get the closest Poi data on X/Z axis is cubed
instead of squared (one time in the parameter and another time in the function)
for almost all search.
Generally this has been hidden by another check that already does a pre
distance check between the poi pos and the source pos for individual
component but the issue still happens for diagonal distance search.
Discovered by Samsuik
This commit is contained in:
Lulu13022002 2022-11-21 16:02:21 +01:00 committed by GitHub
parent a7df847aad
commit 3ab194e185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -32,10 +32,10 @@ had to be specifically modified.
diff --git a/src/main/java/io/papermc/paper/util/PoiAccess.java b/src/main/java/io/papermc/paper/util/PoiAccess.java diff --git a/src/main/java/io/papermc/paper/util/PoiAccess.java b/src/main/java/io/papermc/paper/util/PoiAccess.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b6dd54b32 index 0000000000000000000000000000000000000000..05640f5f70e81833530e8098d30c400fed7ba6e1
--- /dev/null --- /dev/null
+++ b/src/main/java/io/papermc/paper/util/PoiAccess.java +++ b/src/main/java/io/papermc/paper/util/PoiAccess.java
@@ -0,0 +1,801 @@ @@ -0,0 +1,800 @@
+package io.papermc.paper.util; +package io.papermc.paper.util;
+ +
+import com.mojang.datafixers.util.Pair; +import com.mojang.datafixers.util.Pair;
@ -122,11 +122,11 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final PoiRecord ret = findClosestPoiDataRecord( + final PoiRecord ret = findClosestPoiDataRecord(
+ poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistance, occupancy, load + poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load
+ ); + );
+ +
+ return ret == null ? null : ret.getPos(); + return ret == null ? null : ret.getPos();
@ -140,11 +140,11 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final PoiRecord ret = findClosestPoiDataRecord( + final PoiRecord ret = findClosestPoiDataRecord(
+ poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistance, occupancy, load + poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load
+ ); + );
+ +
+ return ret == null ? null : Pair.of(ret.getPoiType(), ret.getPos()); + return ret == null ? null : Pair.of(ret.getPoiType(), ret.getPos());
@ -158,7 +158,7 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load, + final boolean load,
+ final Set<BlockPos> ret) { + final Set<BlockPos> ret) {
@ -173,7 +173,7 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ +
+ final List<PoiRecord> toConvert = new ArrayList<>(); + final List<PoiRecord> toConvert = new ArrayList<>();
+ findClosestPoiDataRecords( + findClosestPoiDataRecords(
+ poiStorage, villagePlaceType, newPredicate, sourcePosition, range, maxDistance, occupancy, load, toConvert + poiStorage, villagePlaceType, newPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load, toConvert
+ ); + );
+ +
+ for (final PoiRecord record : toConvert) { + for (final PoiRecord record : toConvert) {
@ -189,12 +189,12 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final List<PoiRecord> ret = new ArrayList<>(); + final List<PoiRecord> ret = new ArrayList<>();
+ findClosestPoiDataRecords( + findClosestPoiDataRecords(
+ poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistance, occupancy, load, ret + poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load, ret
+ ); + );
+ return ret.isEmpty() ? null : ret.get(0); + return ret.isEmpty() ? null : ret.get(0);
+ } + }
@ -207,12 +207,12 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final BiPredicate<Holder<PoiType>, BlockPos> predicate, + final BiPredicate<Holder<PoiType>, BlockPos> predicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final List<PoiRecord> ret = new ArrayList<>(); + final List<PoiRecord> ret = new ArrayList<>();
+ findClosestPoiDataRecords( + findClosestPoiDataRecords(
+ poiStorage, villagePlaceType, predicate, sourcePosition, range, maxDistance, occupancy, load, ret + poiStorage, villagePlaceType, predicate, sourcePosition, range, maxDistanceSquared, occupancy, load, ret
+ ); + );
+ return ret.isEmpty() ? null : ret.get(0); + return ret.isEmpty() ? null : ret.get(0);
+ } + }
@ -225,12 +225,12 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load, + final boolean load,
+ final List<PoiRecord> ret) { + final List<PoiRecord> ret) {
+ final BiPredicate<Holder<PoiType>, BlockPos> predicate = positionPredicate != null ? (type, pos) -> positionPredicate.test(pos) : null; + final BiPredicate<Holder<PoiType>, BlockPos> predicate = positionPredicate != null ? (type, pos) -> positionPredicate.test(pos) : null;
+ findClosestPoiDataRecords(poiStorage, villagePlaceType, predicate, sourcePosition, range, maxDistance, occupancy, load, ret); + findClosestPoiDataRecords(poiStorage, villagePlaceType, predicate, sourcePosition, range, maxDistanceSquared, occupancy, load, ret);
+ } + }
+ +
+ public static void findClosestPoiDataRecords(final PoiManager poiStorage, + public static void findClosestPoiDataRecords(final PoiManager poiStorage,
@ -239,14 +239,14 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final BiPredicate<Holder<PoiType>, BlockPos> predicate, + final BiPredicate<Holder<PoiType>, BlockPos> predicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load, + final boolean load,
+ final List<PoiRecord> ret) { + final List<PoiRecord> ret) {
+ final Predicate<? super PoiRecord> occupancyFilter = occupancy.getTest(); + final Predicate<? super PoiRecord> occupancyFilter = occupancy.getTest();
+ +
+ final List<PoiRecord> closestRecords = new ArrayList<>(); + final List<PoiRecord> closestRecords = new ArrayList<>();
+ double closestDistanceSquared = maxDistance * maxDistance; + double closestDistanceSquared = maxDistanceSquared;
+ +
+ final int lowerX = Mth.floor(sourcePosition.getX() - range) >> 4; + final int lowerX = Mth.floor(sourcePosition.getX() - range) >> 4;
+ final int lowerY = WorldUtil.getMinSection(poiStorage.world); + final int lowerY = WorldUtil.getMinSection(poiStorage.world);
@ -413,11 +413,11 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final PoiRecord ret = findNearestPoiRecord( + final PoiRecord ret = findNearestPoiRecord(
+ poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistance, occupancy, load + poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load
+ ); + );
+ return ret == null ? null : ret.getPos(); + return ret == null ? null : ret.getPos();
+ } + }
@ -429,7 +429,7 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load, + final boolean load,
+ final int max, + final int max,
@ -445,7 +445,7 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ +
+ final List<PoiRecord> toConvert = new ArrayList<>(); + final List<PoiRecord> toConvert = new ArrayList<>();
+ findNearestPoiRecords( + findNearestPoiRecords(
+ poiStorage, villagePlaceType, newPredicate, sourcePosition, range, maxDistance, occupancy, load, max, toConvert + poiStorage, villagePlaceType, newPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load, max, toConvert
+ ); + );
+ +
+ for (final PoiRecord record : toConvert) { + for (final PoiRecord record : toConvert) {
@ -460,12 +460,12 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load) { + final boolean load) {
+ final List<PoiRecord> ret = new ArrayList<>(); + final List<PoiRecord> ret = new ArrayList<>();
+ findNearestPoiRecords( + findNearestPoiRecords(
+ poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistance, occupancy, load, + poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, maxDistanceSquared, occupancy, load,
+ 1, ret + 1, ret
+ ); + );
+ return ret.isEmpty() ? null : ret.get(0); + return ret.isEmpty() ? null : ret.get(0);
@ -478,14 +478,13 @@ index 0000000000000000000000000000000000000000..1e7be5da4907616ad9e1e01a2227d29b
+ final Predicate<BlockPos> positionPredicate, + final Predicate<BlockPos> positionPredicate,
+ final BlockPos sourcePosition, + final BlockPos sourcePosition,
+ final int range, // distance on x y z axis + final int range, // distance on x y z axis
+ final double maxDistance, + final double maxDistanceSquared,
+ final PoiManager.Occupancy occupancy, + final PoiManager.Occupancy occupancy,
+ final boolean load, + final boolean load,
+ final int max, + final int max,
+ final List<PoiRecord> ret) { + final List<PoiRecord> ret) {
+ final Predicate<? super PoiRecord> occupancyFilter = occupancy.getTest(); + final Predicate<? super PoiRecord> occupancyFilter = occupancy.getTest();
+ +
+ final double maxDistanceSquared = maxDistance * maxDistance;
+ final Double2ObjectRBTreeMap<List<PoiRecord>> closestRecords = new Double2ObjectRBTreeMap<>(); + final Double2ObjectRBTreeMap<List<PoiRecord>> closestRecords = new Double2ObjectRBTreeMap<>();
+ int totalRecords = 0; + int totalRecords = 0;
+ double furthestDistanceSquared = maxDistanceSquared; + double furthestDistanceSquared = maxDistanceSquared;
@ -876,7 +875,7 @@ index 33fbf72b440e0d164ecd4fb0fdec72e2394d0a1e..8db20db72cd51046213625fac46c3585
BlockPos blockPos = path.getTarget(); BlockPos blockPos = path.getTarget();
Optional<Holder<PoiType>> optional = poiManager.getType(blockPos); Optional<Holder<PoiType>> optional = poiManager.getType(blockPos);
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
index a98f4315b82919e4d90d74f5cd0e6f21e49353dc..8849ae489ebdafef6836425729d7714d7e136986 100644 index 6d9ccb87265bcb5c2aecf2e5a0a043ac3c4cbefd..291af79b754ba1a78556f5c8b7b004268761a768 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java
@@ -127,43 +127,62 @@ public class PoiManager extends SectionStorage<PoiSection> { @@ -127,43 +127,62 @@ public class PoiManager extends SectionStorage<PoiSection> {
@ -962,7 +961,7 @@ index a98f4315b82919e4d90d74f5cd0e6f21e49353dc..8849ae489ebdafef6836425729d7714d
public boolean release(BlockPos pos) { public boolean release(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
index d0ce7b14d29459e276961c38cfc5b5da1cd15634..2e410b21564a067ed04f4179908fba8389062f4c 100644 index e921e3cce8c746e28d73e1a7e67a7efe656ec09f..8241320f5f01d0b093024ca27f6d8bdbac487ab3 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiSection.java
@@ -26,7 +26,7 @@ import org.slf4j.Logger; @@ -26,7 +26,7 @@ import org.slf4j.Logger;