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
parent b36d2af7d5
commit 944be7b031

View File

@ -122,11 +122,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ +
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ +
+ 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..00000000000000000000000000000000
+ 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..00000000000000000000000000000000
+ 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;