Use PlayerRef instead of Player, finalise expansion/replace api

This commit is contained in:
PiggyPiglet
2026-01-24 19:05:58 +08:00
parent 722279308a
commit 7111fef559
7 changed files with 252 additions and 165 deletions

View File

@@ -14,12 +14,16 @@ description = "An awesome placeholder provider!"
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal() mavenLocal()
maven {
url = uri("https://repo.codemc.io/repository/hytale/")
}
} }
dependencies { dependencies {
implementation("org.yaml:snakeyaml:2.5") 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") compileOnlyApi("org.jetbrains:annotations:23.0.0")
} }

View File

@@ -31,10 +31,12 @@ import java.util.stream.Collectors;
import at.helpch.placeholderapi.expansion.PlaceholderExpansion; import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
import at.helpch.placeholderapi.expansion.Relational; import at.helpch.placeholderapi.expansion.Relational;
import at.helpch.placeholderapi.replacer.CharsReplacer; import at.helpch.placeholderapi.replacer.CharsReplacer;
import at.helpch.placeholderapi.replacer.MessageReplacer;
import at.helpch.placeholderapi.replacer.Replacer; import at.helpch.placeholderapi.replacer.Replacer;
import at.helpch.placeholderapi.replacer.Replacer.Closure; import at.helpch.placeholderapi.replacer.Replacer.Closure;
import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.entity.entities.Player; 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.NotNull;
public final class PlaceholderAPI { public final class PlaceholderAPI {
@@ -62,48 +64,26 @@ public final class PlaceholderAPI {
* @return String containing all translated placeholders * @return String containing all translated placeholders
*/ */
@NotNull @NotNull
public static String setPlaceholders(final Player player, public static String setPlaceholders(final PlayerRef player,
@NotNull final String text) { @NotNull final String text) {
return REPLACER_PERCENT.apply(text, player, return REPLACER_PERCENT.apply(text, player,
PlaceholderAPIPlugin.instance().localExpansionManager()::getExpansion); PlaceholderAPIPlugin.instance().localExpansionManager()::getExpansion);
} }
public static Message setPlaceholders(final Player player, /**
* Translates all placeholders into their corresponding values.
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
*
* @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) { @NotNull final Message original) {
String replaced = setPlaceholders(player, original.getFormattedMessage().rawText); return MessageReplacer.replace(original, str -> setPlaceholders(player, str));
String link = original.getFormattedMessage().link == null ? null : PlaceholderAPI.setPlaceholders(player, original.getFormattedMessage().link);
List<Message> 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);
}
// @NotNull
// public static Message setPlaceholders(final Player player,
// @NotNull final Message message) {
//
// }
/** /**
* Translates all placeholders into their corresponding values. * Translates all placeholders into their corresponding values.
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}. * <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
@@ -113,11 +93,25 @@ public final class PlaceholderAPI {
* @return String containing all translated placeholders * @return String containing all translated placeholders
*/ */
@NotNull @NotNull
public static List<String> setPlaceholders(final Player player, public static List<String> setPlaceholders(final PlayerRef player,
@NotNull final List<String> text) { @NotNull final List<String> text) {
return text.stream().map(line -> setPlaceholders(player, line)).collect(Collectors.toList()); return text.stream().map(line -> setPlaceholders(player, line)).collect(Collectors.toList());
} }
// /**
// * Translates all placeholders into their corresponding values.
// * <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
// *
// * @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<Message> setPlaceholders(final Player player,
// @NotNull final List<Message> original) {
// return original.stream().map(msg -> setPlaceholders(player, msg)).collect(Collectors.toList());
// }
// /** // /**
// * Translates all placeholders into their corresponding values. // * Translates all placeholders into their corresponding values.
// * <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}. // * <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
@@ -153,12 +147,18 @@ public final class PlaceholderAPI {
* @return String containing all translated placeholders * @return String containing all translated placeholders
*/ */
@NotNull @NotNull
public static String setBracketPlaceholders(final Player player, public static String setBracketPlaceholders(final PlayerRef player,
@NotNull final String text) { @NotNull final String text) {
return REPLACER_BRACKET.apply(text, player, return REPLACER_BRACKET.apply(text, player,
PlaceholderAPIPlugin.instance().localExpansionManager()::getExpansion); 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. * Translates all placeholders into their corresponding values.
* <br>The pattern of a valid placeholder is {@literal {<identifier>_<params>}}. * <br>The pattern of a valid placeholder is {@literal {<identifier>_<params>}}.
@@ -168,7 +168,7 @@ public final class PlaceholderAPI {
* @return String containing all translated placeholders * @return String containing all translated placeholders
*/ */
@NotNull @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) { @NotNull final List<@NotNull String> text) {
return text.stream().map(line -> setBracketPlaceholders(player, line)) return text.stream().map(line -> setBracketPlaceholders(player, line))
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@@ -25,19 +25,7 @@ import com.hypixel.hytale.server.core.universe.PlayerRef;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public abstract class PlaceholderHook { public interface PlaceholderHook {
@Nullable @Nullable
public String onRequest(final Player player, @NotNull final String params) { String onPlaceholderRequest(final PlayerRef 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;
}
} }

View File

@@ -20,17 +20,16 @@
package at.helpch.placeholderapi.expansion; package at.helpch.placeholderapi.expansion;
import java.util.Collections; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Pattern;
import at.helpch.placeholderapi.PlaceholderAPIPlugin; import at.helpch.placeholderapi.PlaceholderAPIPlugin;
import at.helpch.placeholderapi.PlaceholderHook; import at.helpch.placeholderapi.PlaceholderHook;
import com.hypixel.hytale.server.core.HytaleServer; import com.hypixel.hytale.server.core.HytaleServer;
import com.hypixel.hytale.server.core.plugin.PluginBase; import com.hypixel.hytale.server.core.plugin.PluginBase;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; 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} * class extending this one is located under the {@code PlaceholderAPI/expansions}
* directory or when the {@link #register()} method is called by said class. * 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. * 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); // return section == null ? null : section.getConfigurationSection(path);
// } // }
// /** /**
// * Gets the Object relative to the {@link #getConfigSection() default ConfigurationSection} set * 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 * 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 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 * @param def The default Object to return when the ConfigurationSection returns null
// * @return Object from the provided path or the default one provided * @return Object from the provided path or the default one provided
// */ */
// @Nullable @Nullable
// @Contract("_, !null -> !null") @Contract("_, !null -> !null")
// public final Object get(@NotNull final String path, final Object def) { public final Object get(@NotNull final String path, final Object def) {
// final ConfigurationSection section = getConfigSection(); return get(new ArrayDeque<>(Arrays.asList(PATH_DELIMITER.split(path))), def, getExpansionConfig());
// return section == null ? def : section.get(path, def); }
// }
// /** private Object get(@NotNull final Queue<String> path, final Object def, @NotNull final Map<String, Object> map) {
// * Gets the int relative to the {@link #getConfigSection() default ConfigurationSection} set if (path.size() == 1) {
// * by the expansion or the provided Default int, when the default ConfigurationSection is null return map.getOrDefault(path.poll(), def);
// * }
// * @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 Object obj = map.get(path.poll());
// * @return int from the provided path or the default one provided
// */ if (!(obj instanceof Map<?, ?>)) {
// public final int getInt(@NotNull final String path, final int def) { return def;
// final ConfigurationSection section = getConfigSection(); }
// return section == null ? def : section.getInt(path, def);
// } return get(path, def, (Map<String, Object>) 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 * 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 long from. This is relative to the default section *
// * @param def The default long to return when the ConfigurationSection returns null * @param path The path to get the int from. This is relative to the default section
// * @return long from the provided path or the default one provided * @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 long getLong(@NotNull final String path, final long def) { */
// final ConfigurationSection section = getConfigSection(); public final int getInt(@NotNull final String path, final int def) {
// return section == null ? def : section.getLong(path, def); final Object obj = get(path, def);
// }
// if (!(obj instanceof Integer)) {
// /** return 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
// * return (Integer) obj;
// * @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 /**
// */ * Gets the long relative to the {@link #getConfigSection() default ConfigurationSection} set
// public final double getDouble(@NotNull final String path, final double def) { * by the expansion or the provided Default long, when the default ConfigurationSection is null
// final ConfigurationSection section = getConfigSection(); *
// return section == null ? def : section.getDouble(path, def); * @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
// /** */
// * Gets the String relative to the {@link #getConfigSection() default ConfigurationSection} set public final long getLong(@NotNull final String path, final long def) {
// * by the expansion or the provided Default String, when the default ConfigurationSection is null final Object obj = get(path, def);
// *
// * @param path The path to get the String from. This is relative to the default section if (!(obj instanceof Long) ) {
// * @param def The default String to return when the ConfigurationSection returns null. Can be null return def;
// * @return String from the provided path or the default one provided }
// */
// @Nullable return (Long) obj;
// @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 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
// * Gets a String List relative to the {@link #getConfigSection() default ConfigurationSection} set * @param def The default double to return when the ConfigurationSection returns null
// * by the expansion or an empty List, when the default ConfigurationSection is null * @return double from the provided path or the default one provided
// * */
// * @param path The path to get the String list from. This is relative to the default section public final double getDouble(@NotNull final String path, final double def) {
// * @return String list from the provided path or an empty list final Object obj = get(path, def);
// */
// @NotNull if (!(obj instanceof Double) ) {
// public final List<String> getStringList(@NotNull final String path) { return def;
// final ConfigurationSection section = getConfigSection(); }
// return section == null ? Collections.emptyList() : section.getStringList(path);
// } return (Double) 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 * 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 boolean from. This is relative to the default section *
// * @param def The default boolean to return when the ConfigurationSection is null * @param path The path to get the String from. This is relative to the default section
// * @return boolean from the provided path or the default one provided * @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
// public final boolean getBoolean(@NotNull final String path, final boolean def) { */
// final ConfigurationSection section = getConfigSection(); @Nullable
// return section == null ? def : section.getBoolean(path, def); @Contract("_, !null -> !null")
// } public final String getString(@NotNull final String path, @Nullable final String def) {
// final Object obj = get(path, def);
// /**
// * Whether the {@link #getConfigSection() default ConfigurationSection} contains the provided path if (!(obj instanceof String)) {
// * or not. This will return {@code false} when either the default section is null, or doesn't return def;
// * contain the provided path }
// *
// * @param path The path to check return (String) obj;
// * @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(); * Gets a String List relative to the {@link #getConfigSection() default ConfigurationSection} set
// return section != null && section.contains(path); * 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<String> getStringList(@NotNull final String path) {
final Object obj = get(path, new ArrayList<>());
if (!(obj instanceof List<?>)) {
return new ArrayList<>();
}
return (List<String>) 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. * Logs the provided message with the provided Level in the console.

View File

@@ -25,6 +25,7 @@ import java.util.function.Function;
import at.helpch.placeholderapi.expansion.PlaceholderExpansion; import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
import com.hypixel.hytale.server.core.entity.entities.Player; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -40,7 +41,7 @@ public final class CharsReplacer implements Replacer {
@NotNull @NotNull
@Override @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<String, @Nullable PlaceholderExpansion> lookup) { @NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
final char[] chars = text.toCharArray(); final char[] chars = text.toCharArray();
final StringBuilder builder = new StringBuilder(text.length()); final StringBuilder builder = new StringBuilder(text.length());

View File

@@ -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<String, String> 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<Message> 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);
}
}

View File

@@ -31,7 +31,7 @@ import org.jetbrains.annotations.Nullable;
public interface Replacer { public interface Replacer {
@NotNull @NotNull
String apply(@NotNull final String text, @Nullable final Player player, String apply(@NotNull final String text, @Nullable final PlayerRef player,
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup); @NotNull final Function<String, @Nullable PlaceholderExpansion> lookup);