From 7d997d204455f698e1733159e669b3e6556e42c6 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Tue, 21 Jan 2025 17:54:58 +0200 Subject: [PATCH 01/11] init commit --- .../skript/classes/data/BukkitClasses.java | 42 +++-------- .../classes/data/DefaultConverters.java | 5 ++ .../njol/skript/classes/data/JavaClasses.java | 31 ++++++++ .../expressions/ExprPlayerFromUUID.java | 74 +++++++++++++++++++ .../skript/expressions/ExprRandomUUID.java | 12 +-- .../ch/njol/skript/expressions/ExprUUID.java | 20 ++--- src/main/java/ch/njol/skript/util/Utils.java | 18 +++++ src/main/resources/lang/default.lang | 1 + 8 files changed, 156 insertions(+), 47 deletions(-) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index c6c6fe3b86c..bff2dbf768b 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -21,6 +21,7 @@ import ch.njol.skript.util.BlockUtils; import ch.njol.skript.util.PotionEffectUtils; import ch.njol.skript.util.StringMode; +import ch.njol.skript.util.Utils; import ch.njol.util.StringUtils; import ch.njol.yggdrasil.Fields; import io.papermc.paper.world.MoonPhase; @@ -71,10 +72,7 @@ public class BukkitClasses { public BukkitClasses() {} - public static final Pattern UUID_PATTERN = Pattern.compile("(?i)[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}"); - static { - final boolean GET_ENTITY_METHOD_EXISTS = Skript.methodExists(Bukkit.class, "getEntity", UUID.class); Classes.registerClass(new ClassInfo<>(Entity.class, "entity") .user("entit(y|ies)") .name("Entity") @@ -91,26 +89,11 @@ public BukkitClasses() {} .defaultExpression(new EventValueExpression<>(Entity.class)) .parser(new Parser() { @Override - @Nullable - public Entity parse(final String s, final ParseContext context) { - UUID uuid; - try { - uuid = UUID.fromString(s); - } catch (IllegalArgumentException iae) { + public @Nullable Entity parse(final String s, final ParseContext context) { + if (!Utils.isValidUUID(s)) return null; - } - if (GET_ENTITY_METHOD_EXISTS) { - return Bukkit.getEntity(uuid); - } else { - for (World world : Bukkit.getWorlds()) { - for (Entity entity : world.getEntities()) { - if (entity.getUniqueId().equals(uuid)) { - return entity; - } - } - } - } - return null; + + return Bukkit.getEntity(UUID.fromString(s)); } @Override @@ -643,7 +626,7 @@ public Player parse(String string, ParseContext context) { if (context == ParseContext.COMMAND || context == ParseContext.PARSE) { if (string.isEmpty()) return null; - if (UUID_PATTERN.matcher(string).matches()) + if (Utils.isValidUUID(string)) return Bukkit.getPlayer(UUID.fromString(string)); String name = string.toLowerCase(Locale.ENGLISH); int nameLength = name.length(); // caching @@ -709,16 +692,11 @@ public String getDebugMessage(final Player p) { .after("string", "world") .parser(new Parser() { @Override - @Nullable - public OfflinePlayer parse(final String s, final ParseContext context) { - if (context == ParseContext.COMMAND || context == ParseContext.PARSE) { - if (UUID_PATTERN.matcher(s).matches()) - return Bukkit.getOfflinePlayer(UUID.fromString(s)); - else if (!SkriptConfig.playerNameRegexPattern.value().matcher(s).matches()) - return null; + public @Nullable OfflinePlayer parse(final String s, final ParseContext context) { + if (Utils.isValidUUID(s)) + return Bukkit.getOfflinePlayer(UUID.fromString(s)); + else if (!SkriptConfig.playerNameRegexPattern.value().matcher(s).matches()) return Bukkit.getOfflinePlayer(s); - } - assert false; return null; } diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index f43258f2970..427c3b0a8ff 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -39,6 +39,8 @@ import org.skriptlang.skript.lang.converter.Converters; import org.skriptlang.skript.lang.script.Script; +import java.util.UUID; + public class DefaultConverters { public DefaultConverters() {} @@ -275,6 +277,9 @@ public void setAmount(Number amount) { Converters.registerConverter(Script.class, Config.class, Script::getConfig); Converters.registerConverter(Config.class, Node.class, Config::getMainNode); + // UUID -> String + Converters.registerConverter(UUID.class, String.class, UUID::toString); + // // Entity - String (UUID) // Very slow, thus disabled for now // Converters.registerConverter(String.class, Entity.class, new Converter() { // diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index 8d9bbea8603..eb56c314c96 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; +import java.util.UUID; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -325,6 +326,36 @@ public String toVariableNameString(Quaternionf quaternion) { return null; } })); + + Classes.registerClass(new ClassInfo<>(UUID.class, "uuid") + .user("(uuid|universal(ly)? unique identifier)s?") + .name("UUID") + .description( + "A UUID is a universally unique identifier, which is a 128-bit number that is unique to each entity. " + + "They are usually encoded as 36-character strings, which include 32 hexadecimal digits and " + + "four hyphens, typically in this format: \"123e4567-e89b-12d3-a456-426614174000\"", + "In minecraft, it is used to identify entities (like players) in a way " + + "that is unique across all entities, regardless of the entity's state.") + .since("INSERT VERSION") + .parser(new Parser<>() { + @Override + public @Nullable UUID parse(String s, ParseContext context) { + if (Utils.isValidUUID(s)) + return UUID.fromString(s); + return null; + } + + @Override + public String toString(UUID uuid, int flags) { + return "uuid \"" + uuid.toString() + "\""; + } + + @Override + public String toVariableNameString(UUID uuid) { + return "uuid:" + uuid.toString(); + } + }) + ); } /** diff --git a/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java new file mode 100644 index 00000000000..5d821061f1a --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java @@ -0,0 +1,74 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ExprPlayerFromUUID extends SimpleExpression { + + static { + Skript.registerExpression(ExprPlayerFromUUID.class, Object.class, ExpressionType.SIMPLE, + "[:offline[ ]]player[s] from %uuids%"); + } + + private Expression uuids; + private boolean offline; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked + uuids = (Expression) expressions[0]; + offline = parseResult.hasTag("offline"); + return true; + } + + @Override + protected Object @Nullable [] get(Event event) { + List players = new ArrayList<>(); + + for (UUID uuid : uuids.getArray(event)) { + if (offline) { + players.add(Bukkit.getOfflinePlayer(uuid)); + continue; + } + + Player player = Bukkit.getPlayer(uuid); + if (player != null) + players.add(player); + } + + if (offline) + return players.toArray(new OfflinePlayer[0]); + return players.toArray(new Player[0]); + } + + @Override + public boolean isSingle() { + return uuids.isSingle(); + } + + @Override + public Class getReturnType() { + if (offline) + return OfflinePlayer.class; + return Player.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return (offline ? "offline " : "") + "player from " + uuids.toString(event, debug); + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java index 8a75a30e5ad..68fdee27b3c 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java @@ -20,10 +20,10 @@ @Description("Returns a random UUID.") @Examples("set {_uuid} to random uuid") @Since("2.5.1") -public class ExprRandomUUID extends SimpleExpression { +public class ExprRandomUUID extends SimpleExpression { static { - Skript.registerExpression(ExprRandomUUID.class, String.class, ExpressionType.SIMPLE, "[a] random uuid"); + Skript.registerExpression(ExprRandomUUID.class, UUID.class, ExpressionType.SIMPLE, "[a] random uuid"); } @Override @@ -33,8 +33,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye @Override @Nullable - protected String[] get(Event e) { - return new String[] {UUID.randomUUID().toString()}; + protected UUID[] get(Event e) { + return new UUID[]{ UUID.randomUUID() }; } @Override @@ -43,8 +43,8 @@ public boolean isSingle() { } @Override - public Class getReturnType() { - return String.class; + public Class getReturnType() { + return UUID.class; } @Override diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index 4f0a0022a26..52b4dcd6809 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -13,6 +13,8 @@ import ch.njol.skript.doc.Since; import ch.njol.skript.expressions.base.SimplePropertyExpression; +import java.util.UUID; + /** * @author Peter Güttinger */ @@ -29,19 +31,19 @@ " kick player due to \"Someone with your name has played on this server before\"", " else:", " set {uuid::%name of player%} to uuid of player"}) -@Since("2.1.2, 2.2 (offline players' UUIDs), 2.2-dev24 (other entities' UUIDs)") -public class ExprUUID extends SimplePropertyExpression { +@Since("2.1.2, 2.2 (offline players' UUIDs), 2.2-dev24 (other entities' UUIDs), INSERT VERSION (return UUIDs)") +public class ExprUUID extends SimplePropertyExpression { static { - register(ExprUUID.class, String.class, "UUID", "offlineplayers/worlds/entities"); + register(ExprUUID.class, UUID.class, "UUID", "offlineplayers/worlds/entities"); } @Override @Nullable - public String convert(final Object o) { + public UUID convert(final Object o) { if (o instanceof OfflinePlayer) { try { - return ((OfflinePlayer) o).getUniqueId().toString(); + return ((OfflinePlayer) o).getUniqueId(); } catch (UnsupportedOperationException e) { // Some plugins (ProtocolLib) try to emulate offline players, but fail miserably // They will throw this exception... and somehow server may freeze when this happens @@ -50,16 +52,16 @@ public String convert(final Object o) { return null; } } else if (o instanceof Entity) { - return ((Entity)o).getUniqueId().toString(); + return ((Entity)o).getUniqueId(); } else if (o instanceof World) { - return ((World) o).getUID().toString(); + return ((World) o).getUID(); } return null; } @Override - public Class getReturnType() { - return String.class; + public Class getReturnType() { + return UUID.class; } @Override diff --git a/src/main/java/ch/njol/skript/util/Utils.java b/src/main/java/ch/njol/skript/util/Utils.java index 6a2db700ae3..d606ce2518b 100644 --- a/src/main/java/ch/njol/skript/util/Utils.java +++ b/src/main/java/ch/njol/skript/util/Utils.java @@ -840,4 +840,22 @@ public int hashCode() { } + public static boolean isValidUUID(String uuid) { + if (uuid == null || uuid.length() != 36) return false; + + if (uuid.charAt(8) != '-' || uuid.charAt(13) != '-' || uuid.charAt(18) != '-' || uuid.charAt(23) != '-') { + return false; + } + + for (int i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) continue; + char c = uuid.charAt(i); + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { + return false; + } + } + + return true; + } + } diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 999c0f394bd..41eeab269a1 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2586,6 +2586,7 @@ types: boolean: boolean¦ (yes/no)¦s (yes/no) @a string: text¦s @a chunk: chunk¦s @a + uuid: uuid¦s @a # Bukkit entity: entit¦y¦ies @an From 95df13d9fd87cf2aebd29cfc03879240cdd6ce2b Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Tue, 21 Jan 2025 18:05:03 +0200 Subject: [PATCH 02/11] optimize imports --- src/main/java/ch/njol/skript/expressions/ExprUUID.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index 52b4dcd6809..3d8821f545c 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -3,7 +3,6 @@ import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; import ch.njol.skript.Skript; From fc1629a0ed4f03caaf1656a769055d12e50f37c8 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Tue, 21 Jan 2025 22:23:16 +0200 Subject: [PATCH 03/11] replace try/catches with isValidUUID method, final changes --- .../skript/classes/data/BukkitClasses.java | 8 +- .../classes/data/DefaultComparators.java | 4 + .../classes/data/DefaultConverters.java | 14 ++- .../skript/classes/data/DefaultFunctions.java | 12 +- .../njol/skript/classes/data/JavaClasses.java | 8 +- .../expressions/ExprEntityFromUUID.java | 116 ++++++++++++++++++ .../expressions/ExprPlayerFromUUID.java | 74 ----------- .../skript/expressions/ExprRandomUUID.java | 2 +- .../ch/njol/skript/expressions/ExprUUID.java | 37 +++--- src/main/java/ch/njol/skript/util/Utils.java | 25 ++++ 10 files changed, 189 insertions(+), 111 deletions(-) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java delete mode 100644 src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index d61abab8ad6..ab44a9cc98c 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -90,10 +90,10 @@ public BukkitClasses() {} .parser(new Parser() { @Override public @Nullable Entity parse(final String s, final ParseContext context) { - if (!Utils.isValidUUID(s)) - return null; + if (Utils.isValidUUID(s)) + return Bukkit.getEntity(UUID.fromString(s)); - return Bukkit.getEntity(UUID.fromString(s)); + return null; } @Override @@ -626,8 +626,10 @@ public Player parse(String string, ParseContext context) { if (context == ParseContext.COMMAND || context == ParseContext.PARSE) { if (string.isEmpty()) return null; + if (Utils.isValidUUID(string)) return Bukkit.getPlayer(UUID.fromString(string)); + String name = string.toLowerCase(Locale.ENGLISH); int nameLength = name.length(); // caching List players = new ArrayList<>(); 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 f6a2759c201..4bfc7b332cf 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -45,6 +45,7 @@ import org.skriptlang.skript.lang.comparator.Relation; import java.util.Objects; +import java.util.UUID; @SuppressWarnings({"rawtypes"}) public class DefaultComparators { @@ -665,6 +666,9 @@ public Relation compare(EntitySnapshot snap1, EntitySnapshot snap2) { } }); } + + // UUID - UUID + Comparators.registerComparator(UUID.class, UUID.class, (one, two) -> Relation.get(one.equals(two))); } } diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index 427c3b0a8ff..9e7aad4ed13 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -11,6 +11,7 @@ import ch.njol.skript.entity.XpOrbData; import ch.njol.skript.lang.util.common.AnyAmount; import ch.njol.skript.lang.util.common.AnyNamed; +import ch.njol.skript.lang.util.common.AnyValued; import ch.njol.skript.util.*; import ch.njol.skript.util.slot.Slot; import org.bukkit.*; @@ -277,8 +278,19 @@ public void setAmount(Number amount) { Converters.registerConverter(Script.class, Config.class, Script::getConfig); Converters.registerConverter(Config.class, Node.class, Config::getMainNode); - // UUID -> String + // UUID -> String & AnyValued Converters.registerConverter(UUID.class, String.class, UUID::toString); + Converters.registerConverter(UUID.class, AnyValued.class, uuid -> new AnyValued() { + @Override + public String value() { + return uuid.toString(); + } + + @Override + public Class valueType() { + return String.class; + } + }); // // Entity - String (UUID) // Very slow, thus disabled for now // Converters.registerConverter(String.class, Entity.class, new Converter() { diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java index 69a142d4827..24d110aaa5e 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java @@ -11,10 +11,7 @@ import ch.njol.skript.lang.util.SimpleLiteral; import ch.njol.skript.registrations.Classes; import ch.njol.skript.registrations.DefaultClasses; -import ch.njol.skript.util.Color; -import ch.njol.skript.util.ColorRGB; -import ch.njol.skript.util.Contract; -import ch.njol.skript.util.Date; +import ch.njol.skript.util.*; import ch.njol.util.Math2; import ch.njol.util.StringUtils; import ch.njol.util.coll.CollectionUtils; @@ -544,9 +541,8 @@ public Player[] executeSimple(Object[][] params) { boolean isExact = (boolean) params[1][0]; UUID uuid = null; if (name.length() > 16 || name.contains("-")) { // shortcut - try { + if (Utils.isValidUUID(name)) uuid = UUID.fromString(name); - } catch (IllegalArgumentException ignored) {} } return CollectionUtils.array(uuid != null ? Bukkit.getPlayer(uuid) : (isExact ? Bukkit.getPlayerExact(name) : Bukkit.getPlayer(name))); } @@ -569,10 +565,8 @@ public OfflinePlayer[] executeSimple(Object[][] params) { String name = (String) params[0][0]; UUID uuid = null; if (name.length() > 16 || name.contains("-")) { // shortcut - try { + if (Utils.isValidUUID(name)) uuid = UUID.fromString(name); - } catch (IllegalArgumentException ignored) { - } } OfflinePlayer result; diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index eb56c314c96..4a343494f8b 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -339,9 +339,9 @@ public String toVariableNameString(Quaternionf quaternion) { .since("INSERT VERSION") .parser(new Parser<>() { @Override - public @Nullable UUID parse(String s, ParseContext context) { - if (Utils.isValidUUID(s)) - return UUID.fromString(s); + public @Nullable UUID parse(String string, ParseContext context) { + if (Utils.isValidUUID(string)) + return UUID.fromString(string); return null; } @@ -352,7 +352,7 @@ public String toString(UUID uuid, int flags) { @Override public String toVariableNameString(UUID uuid) { - return "uuid:" + uuid.toString(); + return uuid.toString(); } }) ); diff --git a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java new file mode 100644 index 00000000000..53ef48d5744 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java @@ -0,0 +1,116 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Name("Entity/Player from UUID") +@Description({ + "Get an entity or player from a UUID.", + "Use 'offline' to get an offline player." +}) +@Examples({ + "set {_player} to player from \"a0789aeb-7b46-43f6-86fb-cb671fed5775\" parsed as uuid", + "set {_offline player} to offline player from {_some uuid}", + "set {_entity} to entity from {_some uuid}" +}) +@Since("INSERT VERSION") +public class ExprEntityFromUUID extends SimpleExpression { + + static { + Skript.registerExpression(ExprEntityFromUUID.class, Object.class, ExpressionType.SIMPLE, + "[:offline[ ]]player[s] from %uuids%", + "entit(y|ies) from %uuids%" + ); + } + + private Expression uuids; + private boolean offline, entity; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked + uuids = (Expression) expressions[0]; + offline = parseResult.hasTag("offline"); + entity = matchedPattern == 1; + return true; + } + + @Override + protected Object @Nullable [] get(Event event) { + List entities = new ArrayList<>(); + + for (UUID uuid : uuids.getArray(event)) { + if (!entity) { + if (offline) { + entities.add(Bukkit.getOfflinePlayer(uuid)); + continue; + } + + Player player = Bukkit.getPlayer(uuid); + if (player != null) + entities.add(player); + + } else { + Entity entity = Bukkit.getEntity(uuid); + if (entity != null) + entities.add(entity); + + } + } + + if (offline) + return entities.toArray(new OfflinePlayer[0]); + return entities.toArray(new Player[0]); + } + + @Override + public boolean isSingle() { + return uuids.isSingle(); + } + + @Override + public Class getReturnType() { + if (entity) + return Entity.class; + else if (offline) + return OfflinePlayer.class; + return Player.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); + + if (entity) { + builder.append("entities"); + } else { + if (offline) + builder.append("offline"); + builder.append("players"); + } + + builder.append("from", uuids); + + return builder.toString(); + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java deleted file mode 100644 index 5d821061f1a..00000000000 --- a/src/main/java/ch/njol/skript/expressions/ExprPlayerFromUUID.java +++ /dev/null @@ -1,74 +0,0 @@ -package ch.njol.skript.expressions; - -import ch.njol.skript.Skript; -import ch.njol.skript.lang.Expression; -import ch.njol.skript.lang.ExpressionType; -import ch.njol.skript.lang.SkriptParser.ParseResult; -import ch.njol.skript.lang.util.SimpleExpression; -import ch.njol.util.Kleenean; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -public class ExprPlayerFromUUID extends SimpleExpression { - - static { - Skript.registerExpression(ExprPlayerFromUUID.class, Object.class, ExpressionType.SIMPLE, - "[:offline[ ]]player[s] from %uuids%"); - } - - private Expression uuids; - private boolean offline; - - @Override - public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - //noinspection unchecked - uuids = (Expression) expressions[0]; - offline = parseResult.hasTag("offline"); - return true; - } - - @Override - protected Object @Nullable [] get(Event event) { - List players = new ArrayList<>(); - - for (UUID uuid : uuids.getArray(event)) { - if (offline) { - players.add(Bukkit.getOfflinePlayer(uuid)); - continue; - } - - Player player = Bukkit.getPlayer(uuid); - if (player != null) - players.add(player); - } - - if (offline) - return players.toArray(new OfflinePlayer[0]); - return players.toArray(new Player[0]); - } - - @Override - public boolean isSingle() { - return uuids.isSingle(); - } - - @Override - public Class getReturnType() { - if (offline) - return OfflinePlayer.class; - return Player.class; - } - - @Override - public String toString(@Nullable Event event, boolean debug) { - return (offline ? "offline " : "") + "player from " + uuids.toString(event, debug); - } - -} diff --git a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java index 68fdee27b3c..86ee65e8463 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java @@ -19,7 +19,7 @@ @Name("Random UUID") @Description("Returns a random UUID.") @Examples("set {_uuid} to random uuid") -@Since("2.5.1") +@Since("2.5.1, INSERT VERSION (return UUIDs)") public class ExprRandomUUID extends SimpleExpression { static { diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index 3d8821f545c..7dc872c8793 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -18,18 +18,17 @@ * @author Peter Güttinger */ @Name("UUID") -@Description({"The UUID of a player, entity or world.", - "In the future there will be an option to use a player's UUID instead of the name in variable names (i.e. when %player% is used), but for now this can be used.", - "Please note that this expression does not work for offline players if you are under 1.8!"}) -// TODO [UUID] update documentation after release. Add note about requiring Bukkit 1.7.(9/10)? -@Examples({"# prevents people from joining the server if they use the name of a player", - "# who has played on this server at least once since this script has been added", - "on login:", - " if {uuid::%name of player%} exists:", - " {uuid::%name of player%} is not uuid of player", - " kick player due to \"Someone with your name has played on this server before\"", - " else:", - " set {uuid::%name of player%} to uuid of player"}) +@Description("The UUID of a player, entity or world.") +@Examples({ + "# prevents people from joining the server if they use the name of a player", + "# who has played on this server at least once since this script has been added", + "on login:", + "\tif {uuid::%name of player%} exists:", + "\t\t{uuid::%name of player%} is not uuid of player", + "\t\tkick player due to \"Someone with your name has played on this server before\"", + "\telse:", + "\t\tset {uuid::%name of player%} to uuid of player" +}) @Since("2.1.2, 2.2 (offline players' UUIDs), 2.2-dev24 (other entities' UUIDs), INSERT VERSION (return UUIDs)") public class ExprUUID extends SimplePropertyExpression { @@ -39,10 +38,10 @@ public class ExprUUID extends SimplePropertyExpression { @Override @Nullable - public UUID convert(final Object o) { - if (o instanceof OfflinePlayer) { + public UUID convert(final Object object) { + if (object instanceof OfflinePlayer player) { try { - return ((OfflinePlayer) o).getUniqueId(); + return player.getUniqueId(); } catch (UnsupportedOperationException e) { // Some plugins (ProtocolLib) try to emulate offline players, but fail miserably // They will throw this exception... and somehow server may freeze when this happens @@ -50,10 +49,10 @@ public UUID convert(final Object o) { e.printStackTrace(); return null; } - } else if (o instanceof Entity) { - return ((Entity)o).getUniqueId(); - } else if (o instanceof World) { - return ((World) o).getUID(); + } else if (object instanceof Entity entity) { + return entity.getUniqueId(); + } else if (object instanceof World world) { + return world.getUID(); } return null; } diff --git a/src/main/java/ch/njol/skript/util/Utils.java b/src/main/java/ch/njol/skript/util/Utils.java index 100c488cb95..df1eb7047a9 100644 --- a/src/main/java/ch/njol/skript/util/Utils.java +++ b/src/main/java/ch/njol/skript/util/Utils.java @@ -903,4 +903,29 @@ If there are no supported versions, you should contact the author(s): %s, and as return 0; } + /** + * @param uuid the string + * @return whether the given string is a valid UUID + */ + public static boolean isValidUUID(String uuid) { + if (uuid == null || uuid.length() != 36) + return false; + + if (uuid.charAt(8) != '-' || uuid.charAt(13) != '-' || uuid.charAt(18) != '-' || uuid.charAt(23) != '-') { + return false; + } + + for (int i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) + continue; + + char c = uuid.charAt(i); + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { + return false; + } + } + + return true; + } + } From 1309525bdf7be75e2afa78bd89cd5e5237edf714 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Tue, 21 Jan 2025 22:44:26 +0200 Subject: [PATCH 04/11] Final changes --- .../expressions/ExprEntityFromUUID.java | 59 +++++++++++++------ .../ch/njol/skript/expressions/ExprUUID.java | 7 ++- .../expressions/ExprEntityFromUUID.sk | 18 ++++++ 3 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk diff --git a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java index 53ef48d5744..1c6e396ba95 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java @@ -13,6 +13,7 @@ import ch.njol.util.Kleenean; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Event; @@ -22,15 +23,16 @@ import java.util.List; import java.util.UUID; -@Name("Entity/Player from UUID") +@Name("Entity/Player/World from UUID") @Description({ - "Get an entity or player from a UUID.", - "Use 'offline' to get an offline player." + "Get an entity, player or world from a UUID.", + "Use 'offline player' to get an offline player." }) @Examples({ "set {_player} to player from \"a0789aeb-7b46-43f6-86fb-cb671fed5775\" parsed as uuid", "set {_offline player} to offline player from {_some uuid}", - "set {_entity} to entity from {_some uuid}" + "set {_entity} to entity from {_some uuid}", + "set {_world} to world from {_some uuid}" }) @Since("INSERT VERSION") public class ExprEntityFromUUID extends SimpleExpression { @@ -38,19 +40,20 @@ public class ExprEntityFromUUID extends SimpleExpression { static { Skript.registerExpression(ExprEntityFromUUID.class, Object.class, ExpressionType.SIMPLE, "[:offline[ ]]player[s] from %uuids%", - "entit(y|ies) from %uuids%" + "(entit(y|ies)|:world[s]) from %uuids%" ); } private Expression uuids; - private boolean offline, entity; + private boolean offline, player, world; @Override public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { //noinspection unchecked uuids = (Expression) expressions[0]; offline = parseResult.hasTag("offline"); - entity = matchedPattern == 1; + player = matchedPattern == 0; + world = parseResult.hasTag("world"); return true; } @@ -59,7 +62,7 @@ public boolean init(Expression[] expressions, int matchedPattern, Kleenean is List entities = new ArrayList<>(); for (UUID uuid : uuids.getArray(event)) { - if (!entity) { + if (player) { if (offline) { entities.add(Bukkit.getOfflinePlayer(uuid)); continue; @@ -69,17 +72,31 @@ public boolean init(Expression[] expressions, int matchedPattern, Kleenean is if (player != null) entities.add(player); - } else { + } else if (!world) { Entity entity = Bukkit.getEntity(uuid); if (entity != null) entities.add(entity); + } else { + World world = Bukkit.getWorld(uuid); + if (world != null) + entities.add(world); } } - if (offline) - return entities.toArray(new OfflinePlayer[0]); - return entities.toArray(new Player[0]); + if (player) { + if (offline) + //noinspection SuspiciousToArrayCall + return entities.toArray(new OfflinePlayer[0]); + //noinspection SuspiciousToArrayCall + return entities.toArray(new Player[0]); + } + + if (world) + //noinspection SuspiciousToArrayCall + return entities.toArray(new World[0]); + //noinspection SuspiciousToArrayCall + return entities.toArray(new Entity[0]); } @Override @@ -89,18 +106,24 @@ public boolean isSingle() { @Override public Class getReturnType() { - if (entity) - return Entity.class; - else if (offline) - return OfflinePlayer.class; - return Player.class; + if (world) { + return World.class; + } else if (player) { + if (offline) + return OfflinePlayer.class; + return Player.class; + } + + return Entity.class; } @Override public String toString(@Nullable Event event, boolean debug) { SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); - if (entity) { + if (world) { + builder.append("worlds"); + } else if (!player) { builder.append("entities"); } else { if (offline) diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index 7dc872c8793..cd3c4d72dbe 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -27,7 +27,12 @@ "\t\t{uuid::%name of player%} is not uuid of player", "\t\tkick player due to \"Someone with your name has played on this server before\"", "\telse:", - "\t\tset {uuid::%name of player%} to uuid of player" + "\t\tset {uuid::%name of player%} to uuid of player", + "", + "command /what-is-my-uuid:", + "\ttrigger:", + "\t\tset {_uuid} to uuid of player", + "\t\tsend \"Your UUID is '%string within {_uuid}%'\"", }) @Since("2.1.2, 2.2 (offline players' UUIDs), 2.2-dev24 (other entities' UUIDs), INSERT VERSION (return UUIDs)") public class ExprUUID extends SimplePropertyExpression { diff --git a/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk new file mode 100644 index 00000000000..f0e6b9ce913 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk @@ -0,0 +1,18 @@ +test "entity from uuid": + set {_lookup} to offline player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) + assert {_lookup} is set with "Failed to look up offline player" + + spawn a pig at test-location + set {_pig} to last spawned pig + + set {_lookup} to entity from (uuid of {_pig}) + assert {_lookup} is set with "Failed to look up entity" + + delete entity within {_pig} + + set {_lookup} to entity from ("blah" parsed as uuid) + assert {_lookup} is set to fail with "entity is set without a valid uuid" + + # because im not online, should fail + set {_lookup} to player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) + assert {_lookup} is set to fail with "player is set without being online" From 3d7e1205fd0b06db84b28790ddc9ed5b4e7255be Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Tue, 21 Jan 2025 22:45:26 +0200 Subject: [PATCH 05/11] tiny change --- .../java/ch/njol/skript/expressions/ExprEntityFromUUID.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java index 1c6e396ba95..a5f72f39aeb 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java @@ -48,9 +48,9 @@ public class ExprEntityFromUUID extends SimpleExpression { private boolean offline, player, world; @Override - public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { //noinspection unchecked - uuids = (Expression) expressions[0]; + uuids = (Expression) exprs[0]; offline = parseResult.hasTag("offline"); player = matchedPattern == 0; world = parseResult.hasTag("world"); From 11a0b4343b1336f8b131c0c7b0e42080bc9a38e9 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Wed, 22 Jan 2025 17:05:42 +0200 Subject: [PATCH 06/11] Tests and changes --- .../skript/classes/data/BukkitClasses.java | 2 +- .../classes/data/DefaultComparators.java | 3 +- .../njol/skript/classes/data/JavaClasses.java | 90 ++++++++++++++----- ...rEntityFromUUID.java => ExprFromUUID.java} | 47 +++++----- .../ch/njol/skript/expressions/ExprUUID.java | 2 +- src/main/java/ch/njol/skript/util/Utils.java | 1 + .../expressions/ExprEntityFromUUID.sk | 18 ---- .../tests/syntaxes/expressions/ExprUUID.sk | 31 +++++++ 8 files changed, 126 insertions(+), 68 deletions(-) rename src/main/java/ch/njol/skript/expressions/{ExprEntityFromUUID.java => ExprFromUUID.java} (80%) delete mode 100644 src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprUUID.sk diff --git a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java index ab44a9cc98c..c547add7ab5 100644 --- a/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/BukkitClasses.java @@ -697,7 +697,7 @@ public String getDebugMessage(final Player p) { public @Nullable OfflinePlayer parse(final String s, final ParseContext context) { if (Utils.isValidUUID(s)) return Bukkit.getOfflinePlayer(UUID.fromString(s)); - else if (!SkriptConfig.playerNameRegexPattern.value().matcher(s).matches()) + else if (SkriptConfig.playerNameRegexPattern.value().matcher(s).matches()) return Bukkit.getOfflinePlayer(s); return null; } 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 4bfc7b332cf..fd8f6ecb8fd 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultComparators.java @@ -667,8 +667,9 @@ public Relation compare(EntitySnapshot snap1, EntitySnapshot snap2) { }); } - // UUID - UUID + // UUID Comparators.registerComparator(UUID.class, UUID.class, (one, two) -> Relation.get(one.equals(two))); + Comparators.registerComparator(UUID.class, String.class, (one, two) -> Relation.get(one.toString().equals(two))); } } diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index 4a343494f8b..5361ab4403b 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -19,6 +19,8 @@ import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; +import java.io.NotSerializableException; +import java.io.StreamCorruptedException; import java.util.UUID; import java.util.function.Function; import java.util.regex.Matcher; @@ -328,33 +330,16 @@ public String toVariableNameString(Quaternionf quaternion) { })); Classes.registerClass(new ClassInfo<>(UUID.class, "uuid") - .user("(uuid|universal(ly)? unique identifier)s?") + .user("uuids?") .name("UUID") .description( - "A UUID is a universally unique identifier, which is a 128-bit number that is unique to each entity. " - + "They are usually encoded as 36-character strings, which include 32 hexadecimal digits and " - + "four hyphens, typically in this format: \"123e4567-e89b-12d3-a456-426614174000\"", - "In minecraft, it is used to identify entities (like players) in a way " - + "that is unique across all entities, regardless of the entity's state.") + "UUIDs are unique identifiers that ensure things can be reliably distinguished from each other. " + + "They're generated in a way that makes it practically impossible for duplicates to occur.", + "Read more about UUIDs and how they are used in Minecraft " + + "in the UUID wiki.") .since("INSERT VERSION") - .parser(new Parser<>() { - @Override - public @Nullable UUID parse(String string, ParseContext context) { - if (Utils.isValidUUID(string)) - return UUID.fromString(string); - return null; - } - - @Override - public String toString(UUID uuid, int flags) { - return "uuid \"" + uuid.toString() + "\""; - } - - @Override - public String toVariableNameString(UUID uuid) { - return uuid.toString(); - } - }) + .parser(new UUIDParser()) + .serializer(new UUIDSerializer()) ); } @@ -824,4 +809,61 @@ public boolean mustSyncDeserialization() { } + private static class UUIDParser extends Parser { + + @Override + public @Nullable UUID parse(String string, ParseContext context) { + if (Utils.isValidUUID(string)) + return UUID.fromString(string); + return null; + } + + @Override + public String toString(UUID uuid, int flags) { + return uuid.toString(); + } + + @Override + public String toVariableNameString(UUID uuid) { + return uuid.toString(); + } + + } + + private static class UUIDSerializer extends Serializer { + + @Override + public Fields serialize(UUID uuid) { + Fields fields = new Fields(); + + fields.putPrimitive("mostsignificantbits", uuid.getMostSignificantBits()); + fields.putPrimitive("leastsignificantbits", uuid.getLeastSignificantBits()); + + return fields; + } + + @Override + public void deserialize(UUID o, Fields f) throws NotSerializableException { + throw new NotSerializableException(); + } + + @Override + protected UUID deserialize(Fields fields) throws StreamCorruptedException { + long mostSignificantBits = fields.getAndRemovePrimitive("mostsignificantbits", long.class); + long leastSignificantBits = fields.getAndRemovePrimitive("leastsignificantbits", long.class); + return new UUID(mostSignificantBits, leastSignificantBits); + } + + @Override + public boolean mustSyncDeserialization() { + return false; + } + + @Override + protected boolean canBeInstantiated() { + return false; + } + + } + } diff --git a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java similarity index 80% rename from src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java rename to src/main/java/ch/njol/skript/expressions/ExprFromUUID.java index a5f72f39aeb..aeca0e01e48 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprEntityFromUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java @@ -24,10 +24,10 @@ import java.util.UUID; @Name("Entity/Player/World from UUID") -@Description({ - "Get an entity, player or world from a UUID.", - "Use 'offline player' to get an offline player." -}) +@Description( + "Get an entity, player, offline player or world from a UUID. " + + "Unloaded entities or players that are offline (when using 'player from %uuid%') will return nothing." +) @Examples({ "set {_player} to player from \"a0789aeb-7b46-43f6-86fb-cb671fed5775\" parsed as uuid", "set {_offline player} to offline player from {_some uuid}", @@ -35,25 +35,26 @@ "set {_world} to world from {_some uuid}" }) @Since("INSERT VERSION") -public class ExprEntityFromUUID extends SimpleExpression { +public class ExprFromUUID extends SimpleExpression { static { - Skript.registerExpression(ExprEntityFromUUID.class, Object.class, ExpressionType.SIMPLE, + Skript.registerExpression(ExprFromUUID.class, Object.class, ExpressionType.SIMPLE, "[:offline[ ]]player[s] from %uuids%", - "(entit(y|ies)|:world[s]) from %uuids%" + "entit(y|ies) from %uuids%", + "world[s] from %uuids%" ); } private Expression uuids; - private boolean offline, player, world; + private boolean player, offline, world; @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { //noinspection unchecked uuids = (Expression) exprs[0]; - offline = parseResult.hasTag("offline"); player = matchedPattern == 0; - world = parseResult.hasTag("world"); + offline = parseResult.hasTag("offline"); + world = matchedPattern == 2; return true; } @@ -72,31 +73,31 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye if (player != null) entities.add(player); - } else if (!world) { - Entity entity = Bukkit.getEntity(uuid); - if (entity != null) - entities.add(entity); - - } else { + } else if (world) { World world = Bukkit.getWorld(uuid); if (world != null) entities.add(world); + + } else { + Entity entity = Bukkit.getEntity(uuid); + if (entity != null) + entities.add(entity); } } if (player) { if (offline) //noinspection SuspiciousToArrayCall - return entities.toArray(new OfflinePlayer[0]); + return entities.toArray(OfflinePlayer[]::new); //noinspection SuspiciousToArrayCall - return entities.toArray(new Player[0]); + return entities.toArray(Player[]::new); } if (world) //noinspection SuspiciousToArrayCall - return entities.toArray(new World[0]); + return entities.toArray(World[]::new); //noinspection SuspiciousToArrayCall - return entities.toArray(new Entity[0]); + return entities.toArray(Entity[]::new); } @Override @@ -123,12 +124,12 @@ public String toString(@Nullable Event event, boolean debug) { if (world) { builder.append("worlds"); - } else if (!player) { - builder.append("entities"); - } else { + } else if (player) { if (offline) builder.append("offline"); builder.append("players"); + } else { + builder.append("entities"); } builder.append("from", uuids); diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index cd3c4d72dbe..5b15b0a5c54 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -34,7 +34,7 @@ "\t\tset {_uuid} to uuid of player", "\t\tsend \"Your UUID is '%string within {_uuid}%'\"", }) -@Since("2.1.2, 2.2 (offline players' UUIDs), 2.2-dev24 (other entities' UUIDs), INSERT VERSION (return UUIDs)") +@Since("2.1.2, 2.2 (offline players' uuids), 2.2-dev24 (other entities' uuids)") public class ExprUUID extends SimplePropertyExpression { static { diff --git a/src/main/java/ch/njol/skript/util/Utils.java b/src/main/java/ch/njol/skript/util/Utils.java index df1eb7047a9..362ea97e70f 100644 --- a/src/main/java/ch/njol/skript/util/Utils.java +++ b/src/main/java/ch/njol/skript/util/Utils.java @@ -904,6 +904,7 @@ If there are no supported versions, you should contact the author(s): %s, and as } /** + * Checks if the provided string is a valid {@link UUID}. * @param uuid the string * @return whether the given string is a valid UUID */ diff --git a/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk deleted file mode 100644 index f0e6b9ce913..00000000000 --- a/src/test/skript/tests/syntaxes/expressions/ExprEntityFromUUID.sk +++ /dev/null @@ -1,18 +0,0 @@ -test "entity from uuid": - set {_lookup} to offline player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) - assert {_lookup} is set with "Failed to look up offline player" - - spawn a pig at test-location - set {_pig} to last spawned pig - - set {_lookup} to entity from (uuid of {_pig}) - assert {_lookup} is set with "Failed to look up entity" - - delete entity within {_pig} - - set {_lookup} to entity from ("blah" parsed as uuid) - assert {_lookup} is set to fail with "entity is set without a valid uuid" - - # because im not online, should fail - set {_lookup} to player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) - assert {_lookup} is set to fail with "player is set without being online" diff --git a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk new file mode 100644 index 00000000000..e054c0dea7f --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk @@ -0,0 +1,31 @@ +test "uuid": + set {_lookup} to offline player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) + assert {_lookup} is "Burbulinis" with "Failed to look up offline player from uuid" + + set {_uuid} to ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) + assert {_uuid} is "a0789aeb-7b46-43f6-86fb-cb671fed5775" with "failed to compare uuid and string" + assert "a0789aeb-7b46-43f6-86fb-cb671fed5775" is {_uuid} with "failed to compare string and uuid" + + spawn a pig at test-location + set {_pig} to last spawned pig + + set {_lookup} to entity from (uuid of {_pig}) + assert {_lookup} is set with "Failed to look up entity" + + delete entity within {_pig} + + set {_lookup} to entity from ("blah" parsed as uuid) + assert {_lookup} is set to fail with "entity is set without a valid uuid" + + # because im not online, should fail + set {_lookup} to player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) + assert {_lookup} is "Burbulinis" to fail with "player is set without being online" + + set {_lookup} to "Njol" parsed as offline player + assert {_lookup} is "Njol" with "failed to look up offline player from name" + + set {_uuid} to uuid of world of test-location + assert {_uuid} is set with "Failed to get world uuid" + + set {_world} to world from {_uuid} + assert {_world} is set with "Failed to get world from uuid" From 2bd510768e2fb6fa7753fc1905de9318ade9bf42 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Wed, 22 Jan 2025 17:13:17 +0200 Subject: [PATCH 07/11] fix test --- src/test/skript/tests/syntaxes/expressions/ExprUUID.sk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk index e054c0dea7f..a43639c4317 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk @@ -1,6 +1,6 @@ test "uuid": set {_lookup} to offline player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) - assert {_lookup} is "Burbulinis" with "Failed to look up offline player from uuid" + assert {_lookup} is set with "Failed to look up offline player from uuid" set {_uuid} to ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) assert {_uuid} is "a0789aeb-7b46-43f6-86fb-cb671fed5775" with "failed to compare uuid and string" From 7d0664c144f07061f0e93f7857d50d6701502974 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Wed, 22 Jan 2025 20:34:05 +0200 Subject: [PATCH 08/11] Add a uuid function and final changes --- .../skript/classes/data/DefaultFunctions.java | 16 ++++++++++++++++ .../ch/njol/skript/classes/data/JavaClasses.java | 4 ++-- .../ch/njol/skript/expressions/ExprFromUUID.java | 8 ++++---- .../tests/syntaxes/expressions/ExprUUID.sk | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java index 24d110aaa5e..50fc0619e13 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java @@ -705,6 +705,22 @@ public String[] executeSimple(Object[][] params) { "\t\tset {_money} to formatNumber({money::%sender's uuid%})", "\t\tsend \"Your balance: %{_money}%\" to sender") .since("2.10"); + + Functions.registerFunction(new SimpleJavaFunction<>("uuid", new Parameter[]{ + new Parameter<>("uuid", DefaultClasses.STRING, true, null) + }, Classes.getExactClassInfo(UUID.class), true) { + @Override + public UUID[] executeSimple(Object[][] params) { + String uuid = (String) params[0][0]; + if (Utils.isValidUUID(uuid)) + return CollectionUtils.array(UUID.fromString(uuid)); + return new UUID[0]; + } + } + .description("Returns a UUID from the given string. The string must be in the format of a UUID.") + .examples("uuid(\"069a79f4-44e9-4726-a5be-fca90e38aaf5\")") + .since("INSERT VERSION") + ); } } diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index 5361ab4403b..6ad2c4d9db7 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -334,9 +334,9 @@ public String toVariableNameString(Quaternionf quaternion) { .name("UUID") .description( "UUIDs are unique identifiers that ensure things can be reliably distinguished from each other. " - + "They're generated in a way that makes it practically impossible for duplicates to occur.", + + "They are generated in a way that makes it practically impossible for duplicates to occur.", "Read more about UUIDs and how they are used in Minecraft " - + "in the UUID wiki.") + + "in the wiki entry about UUIDs.") .since("INSERT VERSION") .parser(new UUIDParser()) .serializer(new UUIDSerializer()) diff --git a/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java index aeca0e01e48..980cc52035d 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java @@ -24,10 +24,10 @@ import java.util.UUID; @Name("Entity/Player/World from UUID") -@Description( - "Get an entity, player, offline player or world from a UUID. " - + "Unloaded entities or players that are offline (when using 'player from %uuid%') will return nothing." -) +@Description({ + "Get an entity, player, offline player or world from a UUID.", + "Unloaded entities or players that are offline (when using 'player from %uuid%') will return nothing." +}) @Examples({ "set {_player} to player from \"a0789aeb-7b46-43f6-86fb-cb671fed5775\" parsed as uuid", "set {_offline player} to offline player from {_some uuid}", diff --git a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk index a43639c4317..98466146958 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk @@ -17,7 +17,7 @@ test "uuid": set {_lookup} to entity from ("blah" parsed as uuid) assert {_lookup} is set to fail with "entity is set without a valid uuid" - # because im not online, should fail + # because this player is not online, should fail set {_lookup} to player from ("a0789aeb-7b46-43f6-86fb-cb671fed5775" parsed as uuid) assert {_lookup} is "Burbulinis" to fail with "player is set without being online" From 636d9fd4c68ebb7958b8e1d2164f6bd36d0c0a99 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Wed, 22 Jan 2025 21:51:48 +0200 Subject: [PATCH 09/11] Remove the AnyValued for UUIDs and tests for parsing uuids --- .../njol/skript/classes/data/DefaultConverters.java | 13 +------------ .../skript/tests/syntaxes/expressions/ExprUUID.sk | 9 +++++++-- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index 9e7aad4ed13..c327fcbc9a5 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -278,19 +278,8 @@ public void setAmount(Number amount) { Converters.registerConverter(Script.class, Config.class, Script::getConfig); Converters.registerConverter(Config.class, Node.class, Config::getMainNode); - // UUID -> String & AnyValued + // UUID -> String Converters.registerConverter(UUID.class, String.class, UUID::toString); - Converters.registerConverter(UUID.class, AnyValued.class, uuid -> new AnyValued() { - @Override - public String value() { - return uuid.toString(); - } - - @Override - public Class valueType() { - return String.class; - } - }); // // Entity - String (UUID) // Very slow, thus disabled for now // Converters.registerConverter(String.class, Entity.class, new Converter() { diff --git a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk index 98466146958..eac3cbaf1f5 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk +++ b/src/test/skript/tests/syntaxes/expressions/ExprUUID.sk @@ -9,8 +9,13 @@ test "uuid": spawn a pig at test-location set {_pig} to last spawned pig - set {_lookup} to entity from (uuid of {_pig}) - assert {_lookup} is set with "Failed to look up entity" + set {_uuid} to uuid of {_pig} + + set {_lookup} to entity from {_uuid} + assert {_lookup} is {_pig} with "Failed to look up pig" + + set {_le pig} to {_uuid} parsed as entity + assert {_le pig} is {_pig} with "failed to parse uuid as entity" delete entity within {_pig} From 8aae8272396e1e558370115cddb6e032cf66c434 Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Wed, 22 Jan 2025 22:44:45 +0200 Subject: [PATCH 10/11] Change throwing an exception to asserting false when deserializing --- src/main/java/ch/njol/skript/classes/data/JavaClasses.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index 6ad2c4d9db7..b2af31d3bc5 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -843,8 +843,8 @@ public Fields serialize(UUID uuid) { } @Override - public void deserialize(UUID o, Fields f) throws NotSerializableException { - throw new NotSerializableException(); + public void deserialize(UUID o, Fields f) { + assert false; } @Override From 91add7f5768bf407b5eed04534b758e5a34e318c Mon Sep 17 00:00:00 2001 From: Burbulinis Date: Sun, 2 Feb 2025 12:58:01 +0200 Subject: [PATCH 11/11] Clean up --- .../skript/classes/data/DefaultConverters.java | 1 - .../njol/skript/classes/data/JavaClasses.java | 1 - .../njol/skript/expressions/ExprFromUUID.java | 2 +- .../njol/skript/expressions/ExprRandomUUID.java | 17 ++++++++--------- .../ch/njol/skript/expressions/ExprUUID.java | 12 ++++-------- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java index c327fcbc9a5..427c3b0a8ff 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultConverters.java @@ -11,7 +11,6 @@ import ch.njol.skript.entity.XpOrbData; import ch.njol.skript.lang.util.common.AnyAmount; import ch.njol.skript.lang.util.common.AnyNamed; -import ch.njol.skript.lang.util.common.AnyValued; import ch.njol.skript.util.*; import ch.njol.skript.util.slot.Slot; import org.bukkit.*; diff --git a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java index b2af31d3bc5..f9608f9aae6 100644 --- a/src/main/java/ch/njol/skript/classes/data/JavaClasses.java +++ b/src/main/java/ch/njol/skript/classes/data/JavaClasses.java @@ -19,7 +19,6 @@ import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; -import java.io.NotSerializableException; import java.io.StreamCorruptedException; import java.util.UUID; import java.util.function.Function; diff --git a/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java index 980cc52035d..61de09b630a 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprFromUUID.java @@ -38,7 +38,7 @@ public class ExprFromUUID extends SimpleExpression { static { - Skript.registerExpression(ExprFromUUID.class, Object.class, ExpressionType.SIMPLE, + Skript.registerExpression(ExprFromUUID.class, Object.class, ExpressionType.PROPERTY, "[:offline[ ]]player[s] from %uuids%", "entit(y|ies) from %uuids%", "world[s] from %uuids%" diff --git a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java index 86ee65e8463..eebb120ef75 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprRandomUUID.java @@ -21,35 +21,34 @@ @Examples("set {_uuid} to random uuid") @Since("2.5.1, INSERT VERSION (return UUIDs)") public class ExprRandomUUID extends SimpleExpression { - + static { Skript.registerExpression(ExprRandomUUID.class, UUID.class, ExpressionType.SIMPLE, "[a] random uuid"); } - + @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { return true; } - + @Override - @Nullable - protected UUID[] get(Event e) { + protected UUID @Nullable [] get(Event e) { return new UUID[]{ UUID.randomUUID() }; } - + @Override public boolean isSingle() { return true; } - + @Override public Class getReturnType() { return UUID.class; } - + @Override public String toString(@Nullable Event e, boolean debug) { return "random uuid"; } - + } diff --git a/src/main/java/ch/njol/skript/expressions/ExprUUID.java b/src/main/java/ch/njol/skript/expressions/ExprUUID.java index 5b15b0a5c54..8419dc10aa9 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprUUID.java +++ b/src/main/java/ch/njol/skript/expressions/ExprUUID.java @@ -14,9 +14,6 @@ import java.util.UUID; -/** - * @author Peter Güttinger - */ @Name("UUID") @Description("The UUID of a player, entity or world.") @Examples({ @@ -42,8 +39,7 @@ public class ExprUUID extends SimplePropertyExpression { } @Override - @Nullable - public UUID convert(final Object object) { + public @Nullable UUID convert(Object object) { if (object instanceof OfflinePlayer player) { try { return player.getUniqueId(); @@ -61,15 +57,15 @@ public UUID convert(final Object object) { } return null; } - + @Override public Class getReturnType() { return UUID.class; } - + @Override protected String getPropertyName() { return "UUID"; } - + }