From 32d16facab307ea9640e3398c28f51d8610a8fef Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Sun, 26 Nov 2023 00:49:10 -0800 Subject: [PATCH 1/5] Better Location Comparison --- .../classes/data/DefaultComparators.java | 27 ++++++- .../ch/njol/skript/util/LocationUtils.java | 80 +++++++++++++++++++ 2 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/main/java/ch/njol/skript/util/LocationUtils.java diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index 7f96bab14d8..4372c4adb1f 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -24,27 +24,27 @@ import ch.njol.skript.aliases.ItemData; import ch.njol.skript.aliases.ItemType; import ch.njol.skript.classes.ClassInfo; -import org.skriptlang.skript.lang.comparator.Comparator; import ch.njol.skript.entity.BoatChestData; import ch.njol.skript.entity.BoatData; import ch.njol.skript.entity.EntityData; import ch.njol.skript.entity.RabbitData; -import org.skriptlang.skript.lang.comparator.Comparators; import ch.njol.skript.util.BlockUtils; import ch.njol.skript.util.Date; import ch.njol.skript.util.EnchantmentType; import ch.njol.skript.util.Experience; -import ch.njol.skript.util.WeatherType; import ch.njol.skript.util.GameruleValue; +import ch.njol.skript.util.LocationUtils; import ch.njol.skript.util.StructureType; import ch.njol.skript.util.Time; import ch.njol.skript.util.Timeperiod; import ch.njol.skript.util.Timespan; +import ch.njol.skript.util.WeatherType; import ch.njol.skript.util.slot.EquipmentSlot; import ch.njol.skript.util.slot.Slot; import ch.njol.skript.util.slot.SlotWithIndex; import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.World; @@ -61,6 +61,8 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.skriptlang.skript.lang.comparator.Comparator; +import org.skriptlang.skript.lang.comparator.Comparators; import org.skriptlang.skript.lang.comparator.Relation; import java.util.Objects; @@ -630,6 +632,25 @@ public boolean supportsOrdering() { return false; } }); + + // Location - Location + Comparators.registerComparator(Location.class, Location.class, new Comparator() { + @Override + public Relation compare(Location location1, Location location2) { + // check normal equality first + if (location1.equals(location2)) return Relation.EQUAL; + // if not, standardize values + Location normalizedLocation1 = LocationUtils.normalize(location1.clone()); + Location normalizedLocation2 = LocationUtils.normalize(location2.clone()); + // check if they are equal now + return Relation.get(normalizedLocation1.equals(normalizedLocation2)); + } + + @Override + public boolean supportsOrdering() { + return false; + } + }); } } diff --git a/src/main/java/ch/njol/skript/util/LocationUtils.java b/src/main/java/ch/njol/skript/util/LocationUtils.java new file mode 100644 index 00000000000..a92348ac98c --- /dev/null +++ b/src/main/java/ch/njol/skript/util/LocationUtils.java @@ -0,0 +1,80 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package ch.njol.skript.util; + +import org.bukkit.Location; + +/** + * A class that contains methods based around + * making it easier to deal with {@link Location} + * objects. + */ +public class LocationUtils { + + /** + * Normalizes the location by ensuring that the pitch is between -90 and 90, the yaw is between -180 and 180, + * and all -0.0 values are converted to 0.0. + * + * @param location The location to normalize + * @return The same location with normalized values. + */ + public static Location normalize(Location location) { + location.setPitch(Location.normalizePitch(location.getPitch())); + location.setYaw(Location.normalizeYaw(location.getYaw())); + + if (location.getYaw() == -0.0) location.setYaw(0); + if (location.getPitch() == -0.0) location.setPitch(0); + if (location.getX() == -0.0) location.setX(0); + if (location.getY() == -0.0) location.setY(0); + if (location.getZ() == -0.0) location.setZ(0); + + return location; + } + + /** + * Compares two locations without taking into account their yaw or pitch. + * + * @param loc1 The first location + * @param loc2 The second location + * @return Whether the x, y, z, and world of the two locations are the same. + */ + public static boolean compareWithoutDirection(Location loc1, Location loc2) { + return compareWithoutDirection(loc1, loc2, 0.0); + } + + /** + * Compares two locations without taking into account their yaw or pitch, with a tolerance for the difference + * between the x, y, and z values. This essentially checks if loc2 is within a cube of side length 2*epsilon centered + * around loc1. + *

+ * Intended for rough comparisons of locations in the future. + * + * @param loc1 The first location + * @param loc2 The second location + * @param epsilon The maximum difference between each of the x, y, and z values of the two locations. + * @return Whether the x, y, z, and world of the two locations are the same. + */ + public static boolean compareWithoutDirection(Location loc1, Location loc2, double epsilon) { + return loc1.getWorld().equals(loc2.getWorld()) && + Math.abs(loc1.getX() - loc2.getX()) <= epsilon && + Math.abs(loc1.getY() - loc2.getY()) <= epsilon && + Math.abs(loc1.getZ() - loc2.getZ()) <= epsilon; + } + +} From 242387b9ffdb401e1a613a47b7bb50ba02ad68a1 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Sun, 26 Nov 2023 01:16:28 -0800 Subject: [PATCH 2/5] Update src/main/java/ch/njol/skript/util/LocationUtils.java Co-authored-by: Fusezion --- .../java/ch/njol/skript/util/LocationUtils.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/ch/njol/skript/util/LocationUtils.java b/src/main/java/ch/njol/skript/util/LocationUtils.java index a92348ac98c..877206e8fc0 100644 --- a/src/main/java/ch/njol/skript/util/LocationUtils.java +++ b/src/main/java/ch/njol/skript/util/LocationUtils.java @@ -38,11 +38,16 @@ public static Location normalize(Location location) { location.setPitch(Location.normalizePitch(location.getPitch())); location.setYaw(Location.normalizeYaw(location.getYaw())); - if (location.getYaw() == -0.0) location.setYaw(0); - if (location.getPitch() == -0.0) location.setPitch(0); - if (location.getX() == -0.0) location.setX(0); - if (location.getY() == -0.0) location.setY(0); - if (location.getZ() == -0.0) location.setZ(0); + if (location.getYaw() == -0.0) + location.setYaw(0); + if (location.getPitch() == -0.0) + location.setPitch(0); + if (location.getX() == -0.0) + location.setX(0); + if (location.getY() == -0.0) + location.setY(0); + if (location.getZ() == -0.0) + location.setZ(0); return location; } From 529031d460fd5a3faad776d0831dda08d9044c1a Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Sun, 26 Nov 2023 11:29:55 -0800 Subject: [PATCH 3/5] Update src/main/java/ch/njol/skript/classes/data/DefaultComparators.java Co-authored-by: Ayham Al Ali <20037329+AyhamAl-Ali@users.noreply.github.com> --- .../java/ch/njol/skript/classes/data/DefaultComparators.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index 4372c4adb1f..57cdca611b2 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -638,7 +638,8 @@ public boolean supportsOrdering() { @Override public Relation compare(Location location1, Location location2) { // check normal equality first - if (location1.equals(location2)) return Relation.EQUAL; + if (location1.equals(location2)) + return Relation.EQUAL; // if not, standardize values Location normalizedLocation1 = LocationUtils.normalize(location1.clone()); Location normalizedLocation2 = LocationUtils.normalize(location2.clone()); From 65214bc178f15f660ac7f46b766a688f50c7b844 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:40:13 -0800 Subject: [PATCH 4/5] better comparsion --- .../classes/data/DefaultComparators.java | 21 ++--- .../ch/njol/skript/util/LocationUtils.java | 85 ------------------- 2 files changed, 11 insertions(+), 95 deletions(-) delete mode 100644 src/main/java/ch/njol/skript/util/LocationUtils.java diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java index 57cdca611b2..e59a5678403 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -33,7 +33,6 @@ import ch.njol.skript.util.EnchantmentType; import ch.njol.skript.util.Experience; import ch.njol.skript.util.GameruleValue; -import ch.njol.skript.util.LocationUtils; import ch.njol.skript.util.StructureType; import ch.njol.skript.util.Time; import ch.njol.skript.util.Timeperiod; @@ -636,15 +635,17 @@ public boolean supportsOrdering() { // Location - Location Comparators.registerComparator(Location.class, Location.class, new Comparator() { @Override - public Relation compare(Location location1, Location location2) { - // check normal equality first - if (location1.equals(location2)) - return Relation.EQUAL; - // if not, standardize values - Location normalizedLocation1 = LocationUtils.normalize(location1.clone()); - Location normalizedLocation2 = LocationUtils.normalize(location2.clone()); - // check if they are equal now - return Relation.get(normalizedLocation1.equals(normalizedLocation2)); + public Relation compare(Location first, Location second) { + return Relation.get( + // compare worlds + Objects.equals(first.getWorld(), second.getWorld()) && + // compare xyz coords + first.toVector().equals(second.toVector()) && + // normalize yaw and pitch to [-180, 180) and [-90, 90] respectively + // before comparing them + Location.normalizeYaw(first.getYaw()) == Location.normalizeYaw(second.getYaw()) && + Location.normalizePitch(first.getPitch()) == Location.normalizePitch(second.getPitch()) + ); } @Override diff --git a/src/main/java/ch/njol/skript/util/LocationUtils.java b/src/main/java/ch/njol/skript/util/LocationUtils.java deleted file mode 100644 index 877206e8fc0..00000000000 --- a/src/main/java/ch/njol/skript/util/LocationUtils.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * This file is part of Skript. - * - * Skript is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Skript is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Skript. If not, see . - * - * Copyright Peter Güttinger, SkriptLang team and contributors - */ -package ch.njol.skript.util; - -import org.bukkit.Location; - -/** - * A class that contains methods based around - * making it easier to deal with {@link Location} - * objects. - */ -public class LocationUtils { - - /** - * Normalizes the location by ensuring that the pitch is between -90 and 90, the yaw is between -180 and 180, - * and all -0.0 values are converted to 0.0. - * - * @param location The location to normalize - * @return The same location with normalized values. - */ - public static Location normalize(Location location) { - location.setPitch(Location.normalizePitch(location.getPitch())); - location.setYaw(Location.normalizeYaw(location.getYaw())); - - if (location.getYaw() == -0.0) - location.setYaw(0); - if (location.getPitch() == -0.0) - location.setPitch(0); - if (location.getX() == -0.0) - location.setX(0); - if (location.getY() == -0.0) - location.setY(0); - if (location.getZ() == -0.0) - location.setZ(0); - - return location; - } - - /** - * Compares two locations without taking into account their yaw or pitch. - * - * @param loc1 The first location - * @param loc2 The second location - * @return Whether the x, y, z, and world of the two locations are the same. - */ - public static boolean compareWithoutDirection(Location loc1, Location loc2) { - return compareWithoutDirection(loc1, loc2, 0.0); - } - - /** - * Compares two locations without taking into account their yaw or pitch, with a tolerance for the difference - * between the x, y, and z values. This essentially checks if loc2 is within a cube of side length 2*epsilon centered - * around loc1. - *

- * Intended for rough comparisons of locations in the future. - * - * @param loc1 The first location - * @param loc2 The second location - * @param epsilon The maximum difference between each of the x, y, and z values of the two locations. - * @return Whether the x, y, z, and world of the two locations are the same. - */ - public static boolean compareWithoutDirection(Location loc1, Location loc2, double epsilon) { - return loc1.getWorld().equals(loc2.getWorld()) && - Math.abs(loc1.getX() - loc2.getX()) <= epsilon && - Math.abs(loc1.getY() - loc2.getY()) <= epsilon && - Math.abs(loc1.getZ() - loc2.getZ()) <= epsilon; - } - -} From 8e43948a74b7fbf05616cbec23d378dfa3f4dd10 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Thu, 30 Nov 2023 23:33:58 -0800 Subject: [PATCH 5/5] test! --- .../skript/tests/regressions/6205-location comparison.sk | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/test/skript/tests/regressions/6205-location comparison.sk diff --git a/src/test/skript/tests/regressions/6205-location comparison.sk b/src/test/skript/tests/regressions/6205-location comparison.sk new file mode 100644 index 00000000000..9e9df7cf30f --- /dev/null +++ b/src/test/skript/tests/regressions/6205-location comparison.sk @@ -0,0 +1,9 @@ +test "compare similar locations": + set {_world} to world "world" + assert location(1, 2, 3, {_world}, 4, 5) = location(1, 2, 3, {_world}, 4, 5) with "basic location comparison failed" + + assert location(1, 2, 3, {_world}, 270, 0) = location(1, 2, 3, {_world}, -90, 0) with "yaw normalization failed when comparing locations" + assert location(1, 2, 3, {_world}, 0, 270) = location(1, 2, 3, {_world}, 0, 90) with "pitch normalization failed when comparing locations" + assert location(1, 2, 3, {_world}, 270, 270) = location(1, 2, 3, {_world}, -90, 90) with "yaw and pitch normalization failed when comparing locations" + + assert location(1, (-1/infinity value), 3, {_world}, (-1/infinity value), (-1/infinity value)) = location(1, 0, 3, {_world}, 0, 0) with "0 and -0.0 are not equal when comparing locations"