From 7111fef5590e6cdca7397e5fecc275397ab476bb Mon Sep 17 00:00:00 2001 From: PiggyPiglet Date: Sat, 24 Jan 2026 19:05:58 +0800 Subject: [PATCH] Use PlayerRef instead of Player, finalise expansion/replace api --- build.gradle.kts | 6 +- .../helpch/placeholderapi/PlaceholderAPI.java | 74 ++--- .../placeholderapi/PlaceholderHook.java | 16 +- .../expansion/PlaceholderExpansion.java | 266 ++++++++++-------- .../replacer/CharsReplacer.java | 3 +- .../replacer/MessageReplacer.java | 50 ++++ .../placeholderapi/replacer/Replacer.java | 2 +- 7 files changed, 252 insertions(+), 165 deletions(-) create mode 100644 src/main/java/at/helpch/placeholderapi/replacer/MessageReplacer.java diff --git a/build.gradle.kts b/build.gradle.kts index eec54f2..56933b0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,12 +14,16 @@ description = "An awesome placeholder provider!" repositories { mavenCentral() mavenLocal() + + maven { + url = uri("https://repo.codemc.io/repository/hytale/") + } } dependencies { implementation("org.yaml:snakeyaml:2.5") - compileOnly(files("libs/HytaleServer.jar")) + compileOnly("com.hypixel.hytale:Server:2026.01.17-4b0f30090") compileOnlyApi("org.jetbrains:annotations:23.0.0") } diff --git a/src/main/java/at/helpch/placeholderapi/PlaceholderAPI.java b/src/main/java/at/helpch/placeholderapi/PlaceholderAPI.java index 62f5cb8..499fade 100644 --- a/src/main/java/at/helpch/placeholderapi/PlaceholderAPI.java +++ b/src/main/java/at/helpch/placeholderapi/PlaceholderAPI.java @@ -31,10 +31,12 @@ import java.util.stream.Collectors; import at.helpch.placeholderapi.expansion.PlaceholderExpansion; import at.helpch.placeholderapi.expansion.Relational; import at.helpch.placeholderapi.replacer.CharsReplacer; +import at.helpch.placeholderapi.replacer.MessageReplacer; import at.helpch.placeholderapi.replacer.Replacer; import at.helpch.placeholderapi.replacer.Replacer.Closure; import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.universe.PlayerRef; import org.jetbrains.annotations.NotNull; public final class PlaceholderAPI { @@ -62,48 +64,26 @@ public final class PlaceholderAPI { * @return String containing all translated placeholders */ @NotNull - public static String setPlaceholders(final Player player, + public static String setPlaceholders(final PlayerRef player, @NotNull final String text) { return REPLACER_PERCENT.apply(text, player, PlaceholderAPIPlugin.instance().localExpansionManager()::getExpansion); } - public static Message setPlaceholders(final Player player, + /** + * Translates all placeholders into their corresponding values. + *
The pattern of a valid placeholder is {@literal %_%}. + * + * @param player Player to parse the placeholders against + * @param original Message to set the placeholder values in + * @return Message containing all translated placeholders + */ + @NotNull + public static Message setPlaceholders(final PlayerRef player, @NotNull final Message original) { - String replaced = setPlaceholders(player, original.getFormattedMessage().rawText); - String link = original.getFormattedMessage().link == null ? null : PlaceholderAPI.setPlaceholders(player, original.getFormattedMessage().link); - - List newChildren = original.getChildren().stream() - .filter(Objects::nonNull) - .map(child -> setPlaceholders(player, child)) - .toList(); - - Message message = Message.raw(replaced) - .color(original.getColor()); - - if (link != null) { - message = message.link(link); - } - - int bold = original.getFormattedMessage().bold.getValue(); - if (bold != 0) { - message = message.bold(bold != 1); - } - - int italic = original.getFormattedMessage().italic.getValue(); - if (italic != 0) { - message = message.italic(italic != 1); - } - - return message.insertAll(newChildren); + return MessageReplacer.replace(original, str -> setPlaceholders(player, str)); } -// @NotNull -// public static Message setPlaceholders(final Player player, -// @NotNull final Message message) { -// -// } - /** * Translates all placeholders into their corresponding values. *
The pattern of a valid placeholder is {@literal %_%}. @@ -113,11 +93,25 @@ public final class PlaceholderAPI { * @return String containing all translated placeholders */ @NotNull - public static List setPlaceholders(final Player player, + public static List setPlaceholders(final PlayerRef player, @NotNull final List text) { return text.stream().map(line -> setPlaceholders(player, line)).collect(Collectors.toList()); } +// /** +// * Translates all placeholders into their corresponding values. +// *
The pattern of a valid placeholder is {@literal %_%}. +// * +// * @param player Player to parse the placeholders against +// * @param original List of Messages to set the placeholder values in +// * @return List of Message containing all translated placeholders +// */ +// @NotNull +// public static List setPlaceholders(final Player player, +// @NotNull final List original) { +// return original.stream().map(msg -> setPlaceholders(player, msg)).collect(Collectors.toList()); +// } + // /** // * Translates all placeholders into their corresponding values. // *
The pattern of a valid placeholder is {@literal %_%}. @@ -153,12 +147,18 @@ public final class PlaceholderAPI { * @return String containing all translated placeholders */ @NotNull - public static String setBracketPlaceholders(final Player player, + public static String setBracketPlaceholders(final PlayerRef player, @NotNull final String text) { return REPLACER_BRACKET.apply(text, player, PlaceholderAPIPlugin.instance().localExpansionManager()::getExpansion); } + @NotNull + public static Message setBracketPlaceholders(final PlayerRef player, + @NotNull final Message original) { + return MessageReplacer.replace(original, str -> setBracketPlaceholders(player, str)); + } + /** * Translates all placeholders into their corresponding values. *
The pattern of a valid placeholder is {@literal {_}}. @@ -168,7 +168,7 @@ public final class PlaceholderAPI { * @return String containing all translated placeholders */ @NotNull - public static List<@NotNull String> setBracketPlaceholders(final Player player, + public static List<@NotNull String> setBracketPlaceholders(final PlayerRef player, @NotNull final List<@NotNull String> text) { return text.stream().map(line -> setBracketPlaceholders(player, line)) .collect(Collectors.toList()); diff --git a/src/main/java/at/helpch/placeholderapi/PlaceholderHook.java b/src/main/java/at/helpch/placeholderapi/PlaceholderHook.java index 3776a7a..292249c 100644 --- a/src/main/java/at/helpch/placeholderapi/PlaceholderHook.java +++ b/src/main/java/at/helpch/placeholderapi/PlaceholderHook.java @@ -25,19 +25,7 @@ import com.hypixel.hytale.server.core.universe.PlayerRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class PlaceholderHook { +public interface PlaceholderHook { @Nullable - public String onRequest(final Player player, @NotNull final String params) { -// Player player2; -// if (player != null && player.isOnline()) { -// return onPlaceholderRequest(player.getPlayer(), params); -// } - - return onPlaceholderRequest(player, params); - } - - @Nullable - public String onPlaceholderRequest(final Player player, @NotNull final String params) { - return null; - } + String onPlaceholderRequest(final PlayerRef player, @NotNull final String params); } diff --git a/src/main/java/at/helpch/placeholderapi/expansion/PlaceholderExpansion.java b/src/main/java/at/helpch/placeholderapi/expansion/PlaceholderExpansion.java index 4566bbf..0975d06 100644 --- a/src/main/java/at/helpch/placeholderapi/expansion/PlaceholderExpansion.java +++ b/src/main/java/at/helpch/placeholderapi/expansion/PlaceholderExpansion.java @@ -20,17 +20,16 @@ package at.helpch.placeholderapi.expansion; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.logging.Level; +import java.util.regex.Pattern; import at.helpch.placeholderapi.PlaceholderAPIPlugin; import at.helpch.placeholderapi.PlaceholderHook; import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.plugin.PluginBase; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,7 +39,8 @@ import org.jetbrains.annotations.Nullable; * class extending this one is located under the {@code PlaceholderAPI/expansions} * directory or when the {@link #register()} method is called by said class. */ -public abstract class PlaceholderExpansion extends PlaceholderHook { +public abstract class PlaceholderExpansion implements PlaceholderHook { + private static final Pattern PATH_DELIMITER = Pattern.compile("."); /** * The type is {@link Type#INTERNAL} by default. @@ -224,113 +224,157 @@ public abstract class PlaceholderExpansion extends PlaceholderHook { // return section == null ? null : section.getConfigurationSection(path); // } -// /** -// * Gets the Object relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the provided Default Object, when the default ConfigurationSection is null -// * -// * @param path The path to get the Object from. This is relative to the default section -// * @param def The default Object to return when the ConfigurationSection returns null -// * @return Object from the provided path or the default one provided -// */ -// @Nullable -// @Contract("_, !null -> !null") -// public final Object get(@NotNull final String path, final Object def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.get(path, def); -// } + /** + * Gets the Object relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the provided Default Object, when the default ConfigurationSection is null + * + * @param path The path to get the Object from. This is relative to the default section + * @param def The default Object to return when the ConfigurationSection returns null + * @return Object from the provided path or the default one provided + */ + @Nullable + @Contract("_, !null -> !null") + public final Object get(@NotNull final String path, final Object def) { + return get(new ArrayDeque<>(Arrays.asList(PATH_DELIMITER.split(path))), def, getExpansionConfig()); + } -// /** -// * Gets the int relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the provided Default int, when the default ConfigurationSection is null -// * -// * @param path The path to get the int from. This is relative to the default section -// * @param def The default int to return when the ConfigurationSection returns null -// * @return int from the provided path or the default one provided -// */ -// public final int getInt(@NotNull final String path, final int def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.getInt(path, def); -// } -// -// /** -// * Gets the long relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the provided Default long, when the default ConfigurationSection is null -// * -// * @param path The path to get the long from. This is relative to the default section -// * @param def The default long to return when the ConfigurationSection returns null -// * @return long from the provided path or the default one provided -// */ -// public final long getLong(@NotNull final String path, final long def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.getLong(path, def); -// } -// -// /** -// * Gets the double relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the provided Default double, when the default ConfigurationSection is null -// * -// * @param path The path to get the double from. This is relative to the default section -// * @param def The default double to return when the ConfigurationSection returns null -// * @return double from the provided path or the default one provided -// */ -// public final double getDouble(@NotNull final String path, final double def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.getDouble(path, def); -// } -// -// /** -// * Gets the String relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the provided Default String, when the default ConfigurationSection is null -// * -// * @param path The path to get the String from. This is relative to the default section -// * @param def The default String to return when the ConfigurationSection returns null. Can be null -// * @return String from the provided path or the default one provided -// */ -// @Nullable -// @Contract("_, !null -> !null") -// public final String getString(@NotNull final String path, @Nullable final String def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.getString(path, def); -// } -// -// /** -// * Gets a String List relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or an empty List, when the default ConfigurationSection is null -// * -// * @param path The path to get the String list from. This is relative to the default section -// * @return String list from the provided path or an empty list -// */ -// @NotNull -// public final List getStringList(@NotNull final String path) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? Collections.emptyList() : section.getStringList(path); -// } -// -// /** -// * Gets the boolean relative to the {@link #getConfigSection() default ConfigurationSection} set -// * by the expansion or the default boolean, when the default ConfigurationSection is null -// * -// * @param path The path to get the boolean from. This is relative to the default section -// * @param def The default boolean to return when the ConfigurationSection is null -// * @return boolean from the provided path or the default one provided -// */ -// public final boolean getBoolean(@NotNull final String path, final boolean def) { -// final ConfigurationSection section = getConfigSection(); -// return section == null ? def : section.getBoolean(path, def); -// } -// -// /** -// * Whether the {@link #getConfigSection() default ConfigurationSection} contains the provided path -// * or not. This will return {@code false} when either the default section is null, or doesn't -// * contain the provided path -// * -// * @param path The path to check -// * @return true when the default ConfigurationSection is not null and contains the path, false otherwise -// */ -// public final boolean configurationContains(@NotNull final String path) { -// final ConfigurationSection section = getConfigSection(); -// return section != null && section.contains(path); -// } + private Object get(@NotNull final Queue path, final Object def, @NotNull final Map map) { + if (path.size() == 1) { + return map.getOrDefault(path.poll(), def); + } + + Object obj = map.get(path.poll()); + + if (!(obj instanceof Map)) { + return def; + } + + return get(path, def, (Map) obj); + } + + /** + * Gets the int relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the provided Default int, when the default ConfigurationSection is null + * + * @param path The path to get the int from. This is relative to the default section + * @param def The default int to return when the ConfigurationSection returns null + * @return int from the provided path or the default one provided + */ + public final int getInt(@NotNull final String path, final int def) { + final Object obj = get(path, def); + + if (!(obj instanceof Integer)) { + return def; + } + + return (Integer) obj; + } + + /** + * Gets the long relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the provided Default long, when the default ConfigurationSection is null + * + * @param path The path to get the long from. This is relative to the default section + * @param def The default long to return when the ConfigurationSection returns null + * @return long from the provided path or the default one provided + */ + public final long getLong(@NotNull final String path, final long def) { + final Object obj = get(path, def); + + if (!(obj instanceof Long) ) { + return def; + } + + return (Long) obj; + } + + /** + * Gets the double relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the provided Default double, when the default ConfigurationSection is null + * + * @param path The path to get the double from. This is relative to the default section + * @param def The default double to return when the ConfigurationSection returns null + * @return double from the provided path or the default one provided + */ + public final double getDouble(@NotNull final String path, final double def) { + final Object obj = get(path, def); + + if (!(obj instanceof Double) ) { + return def; + } + + return (Double) obj; + } + + /** + * Gets the String relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the provided Default String, when the default ConfigurationSection is null + * + * @param path The path to get the String from. This is relative to the default section + * @param def The default String to return when the ConfigurationSection returns null. Can be null + * @return String from the provided path or the default one provided + */ + @Nullable + @Contract("_, !null -> !null") + public final String getString(@NotNull final String path, @Nullable final String def) { + final Object obj = get(path, def); + + if (!(obj instanceof String)) { + return def; + } + + return (String) obj; + } + + /** + * Gets a String List relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or an empty List, when the default ConfigurationSection is null + * + * @param path The path to get the String list from. This is relative to the default section + * @return String list from the provided path or an empty list + */ + @NotNull + public final List getStringList(@NotNull final String path) { + final Object obj = get(path, new ArrayList<>()); + + if (!(obj instanceof List)) { + return new ArrayList<>(); + } + + return (List) obj; + } + + /** + * Gets the boolean relative to the {@link #getConfigSection() default ConfigurationSection} set + * by the expansion or the default boolean, when the default ConfigurationSection is null + * + * @param path The path to get the boolean from. This is relative to the default section + * @param def The default boolean to return when the ConfigurationSection is null + * @return boolean from the provided path or the default one provided + */ + public final boolean getBoolean(@NotNull final String path, final boolean def) { + final Object obj = get(path, def); + + if (!(obj instanceof Boolean)) { + return def; + } + + return (Boolean) obj; + } + + /** + * Whether the {@link #getConfigSection() default ConfigurationSection} contains the provided path + * or not. This will return {@code false} when either the default section is null, or doesn't + * contain the provided path + * + * @param path The path to check + * @return true when the default ConfigurationSection is not null and contains the path, false otherwise + */ + public final boolean configurationContains(@NotNull final String path) { + final Object obj = get(path, null); + + return obj == null; + } /** * Logs the provided message with the provided Level in the console. diff --git a/src/main/java/at/helpch/placeholderapi/replacer/CharsReplacer.java b/src/main/java/at/helpch/placeholderapi/replacer/CharsReplacer.java index 1c8ef06..d0bfed8 100644 --- a/src/main/java/at/helpch/placeholderapi/replacer/CharsReplacer.java +++ b/src/main/java/at/helpch/placeholderapi/replacer/CharsReplacer.java @@ -25,6 +25,7 @@ import java.util.function.Function; import at.helpch.placeholderapi.expansion.PlaceholderExpansion; import com.hypixel.hytale.server.core.entity.entities.Player; +import com.hypixel.hytale.server.core.universe.PlayerRef; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,7 +41,7 @@ public final class CharsReplacer implements Replacer { @NotNull @Override - public String apply(@NotNull final String text, @Nullable final Player player, + public String apply(@NotNull final String text, @Nullable final PlayerRef player, @NotNull final Function lookup) { final char[] chars = text.toCharArray(); final StringBuilder builder = new StringBuilder(text.length()); diff --git a/src/main/java/at/helpch/placeholderapi/replacer/MessageReplacer.java b/src/main/java/at/helpch/placeholderapi/replacer/MessageReplacer.java new file mode 100644 index 0000000..83f32a6 --- /dev/null +++ b/src/main/java/at/helpch/placeholderapi/replacer/MessageReplacer.java @@ -0,0 +1,50 @@ +package at.helpch.placeholderapi.replacer; + +import at.helpch.placeholderapi.PlaceholderAPI; +import com.hypixel.hytale.server.core.Message; +import com.hypixel.hytale.server.core.entity.entities.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +public final class MessageReplacer { + @NotNull + public static Message replace(@NotNull final Message original, @NotNull final Function setPlaceholders) { + if (original.getFormattedMessage().rawText == null) { + return original; + } + + String replaced = setPlaceholders.apply(original.getFormattedMessage().rawText); + String link = original.getFormattedMessage().link == null ? null : setPlaceholders.apply(original.getFormattedMessage().link); + + List newChildren = original.getChildren().stream() + .filter(Objects::nonNull) + .map(child -> replace(child, setPlaceholders)) + .toList(); + + Message message = Message.raw(replaced); + + if (original.getColor() != null) { + message = message.color(original.getColor()); + } + + if (link != null) { + message = message.link(link); + } + + int bold = original.getFormattedMessage().bold.getValue(); + if (bold != 0) { + message = message.bold(bold != 1); + } + + int italic = original.getFormattedMessage().italic.getValue(); + if (italic != 0) { + message = message.italic(italic != 1); + } + + return message.insertAll(newChildren); + } +} diff --git a/src/main/java/at/helpch/placeholderapi/replacer/Replacer.java b/src/main/java/at/helpch/placeholderapi/replacer/Replacer.java index f1bbeb8..9f455a5 100644 --- a/src/main/java/at/helpch/placeholderapi/replacer/Replacer.java +++ b/src/main/java/at/helpch/placeholderapi/replacer/Replacer.java @@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable; public interface Replacer { @NotNull - String apply(@NotNull final String text, @Nullable final Player player, + String apply(@NotNull final String text, @Nullable final PlayerRef player, @NotNull final Function lookup);