diff --git a/eco-api/src/main/java/com/willfp/eco/core/config/interfaces/Config.java b/eco-api/src/main/java/com/willfp/eco/core/config/interfaces/Config.java index c9515dc8..b466a119 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/config/interfaces/Config.java +++ b/eco-api/src/main/java/com/willfp/eco/core/config/interfaces/Config.java @@ -3,8 +3,8 @@ package com.willfp.eco.core.config.interfaces; import com.willfp.eco.core.config.BuildableConfig; import com.willfp.eco.core.config.ConfigType; import com.willfp.eco.core.config.TransientConfig; +import com.willfp.eco.core.placeholder.InjectablePlaceholder; import com.willfp.eco.core.placeholder.PlaceholderInjectable; -import com.willfp.eco.core.placeholder.StaticPlaceholder; import com.willfp.eco.util.NumberUtils; import com.willfp.eco.util.StringUtils; import org.bukkit.configuration.ConfigurationSection; @@ -471,7 +471,7 @@ public interface Config extends Cloneable, PlaceholderInjectable { */ default double getDoubleFromExpression(@NotNull String path, @Nullable Player player) { - return NumberUtils.evaluateExpression(this.getString(path), player, this.getInjectedPlaceholders()); + return NumberUtils.evaluateExpression(this.getString(path), player, this); } /** @@ -539,12 +539,12 @@ public interface Config extends Cloneable, PlaceholderInjectable { Config clone(); @Override - default void injectPlaceholders(@NotNull Iterable placeholders) { + default void addInjectablePlaceholder(@NotNull Iterable placeholders) { // Do nothing. } @Override - default List getInjectedPlaceholders() { + default @NotNull List getPlaceholderInjections() { return Collections.emptyList(); } diff --git a/eco-api/src/main/java/com/willfp/eco/core/config/wrapper/ConfigWrapper.java b/eco-api/src/main/java/com/willfp/eco/core/config/wrapper/ConfigWrapper.java index 77ec4ebd..42b309e0 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/config/wrapper/ConfigWrapper.java +++ b/eco-api/src/main/java/com/willfp/eco/core/config/wrapper/ConfigWrapper.java @@ -2,7 +2,7 @@ package com.willfp.eco.core.config.wrapper; import com.willfp.eco.core.config.ConfigType; import com.willfp.eco.core.config.interfaces.Config; -import com.willfp.eco.core.placeholder.StaticPlaceholder; +import com.willfp.eco.core.placeholder.InjectablePlaceholder; import com.willfp.eco.util.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -145,18 +145,13 @@ public abstract class ConfigWrapper implements Config { } @Override - public void injectPlaceholders(@NotNull final StaticPlaceholder... placeholders) { - handle.injectPlaceholders(placeholders); + public void addInjectablePlaceholder(@NotNull final Iterable placeholders) { + handle.addInjectablePlaceholder(placeholders); } @Override - public void injectPlaceholders(@NotNull final Iterable placeholders) { - handle.injectPlaceholders(placeholders); - } - - @Override - public List getInjectedPlaceholders() { - return handle.getInjectedPlaceholders(); + public @NotNull List getPlaceholderInjections() { + return handle.getPlaceholderInjections(); } @Override diff --git a/eco-api/src/main/java/com/willfp/eco/core/integrations/placeholder/PlaceholderManager.java b/eco-api/src/main/java/com/willfp/eco/core/integrations/placeholder/PlaceholderManager.java index cd3913fd..17d445f0 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/integrations/placeholder/PlaceholderManager.java +++ b/eco-api/src/main/java/com/willfp/eco/core/integrations/placeholder/PlaceholderManager.java @@ -4,8 +4,11 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.willfp.eco.core.Eco; import com.willfp.eco.core.EcoPlugin; +import com.willfp.eco.core.placeholder.InjectablePlaceholder; import com.willfp.eco.core.placeholder.Placeholder; +import com.willfp.eco.core.placeholder.PlaceholderInjectable; import com.willfp.eco.core.placeholder.PlayerPlaceholder; +import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder; import com.willfp.eco.core.placeholder.PlayerlessPlaceholder; import com.willfp.eco.core.placeholder.StaticPlaceholder; import org.bukkit.entity.Player; @@ -154,17 +157,47 @@ public final class PlaceholderManager { * @param player The player to translate the placeholders with respect to. * @param statics Extra static placeholders. * @return The text, translated. + * @deprecated Use new static system. */ + @Deprecated(since = "6.35.0", forRemoval = true) public static String translatePlaceholders(@NotNull final String text, @Nullable final Player player, @NotNull final List statics) { + return translatePlaceholders(text, player, new PlaceholderInjectable() { + @Override + public void clearInjectedPlaceholders() { + // Do nothing. + } + + @Override + public @NotNull List getPlaceholderInjections() { + return new ArrayList<>(statics); + } + }); + } + + /** + * Translate all placeholders with respect to a player. + * + * @param text The text that may contain placeholders to translate. + * @param player The player to translate the placeholders with respect to. + * @param context The injectable context. + * @return The text, translated. + */ + public static String translatePlaceholders(@NotNull final String text, + @Nullable final Player player, + @NotNull final PlaceholderInjectable context) { String processed = text; for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) { processed = integration.translate(processed, player); } - for (StaticPlaceholder placeholder : statics) { + for (InjectablePlaceholder injection : context.getPlaceholderInjections()) { // Do I know this is a bad way of doing this? Yes. - processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue()); + if (injection instanceof StaticPlaceholder placeholder) { + processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue()); + } else if (injection instanceof PlayerStaticPlaceholder placeholder && player != null) { + processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue(player)); + } } return processed; } diff --git a/eco-api/src/main/java/com/willfp/eco/core/placeholder/InjectablePlaceholder.java b/eco-api/src/main/java/com/willfp/eco/core/placeholder/InjectablePlaceholder.java new file mode 100644 index 00000000..cfd51de8 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/placeholder/InjectablePlaceholder.java @@ -0,0 +1,14 @@ +package com.willfp.eco.core.placeholder; + +import com.willfp.eco.core.Eco; +import com.willfp.eco.core.EcoPlugin; + +/** + * Placeholders that can be injected into {@link PlaceholderInjectable} objects. + */ +public sealed interface InjectablePlaceholder extends Placeholder permits PlayerStaticPlaceholder, StaticPlaceholder { + @Override + default EcoPlugin getPlugin() { + return Eco.getHandler().getEcoPlugin(); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/placeholder/Placeholder.java b/eco-api/src/main/java/com/willfp/eco/core/placeholder/Placeholder.java index 66ff163b..19f810e5 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/placeholder/Placeholder.java +++ b/eco-api/src/main/java/com/willfp/eco/core/placeholder/Placeholder.java @@ -5,7 +5,7 @@ import com.willfp.eco.core.EcoPlugin; /** * A placeholder represents a string that can hold a value. */ -public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder, StaticPlaceholder { +public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder, InjectablePlaceholder { /** * Get the plugin that holds the placeholder. * diff --git a/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlaceholderInjectable.java b/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlaceholderInjectable.java index ddf4f09a..28897257 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlaceholderInjectable.java +++ b/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlaceholderInjectable.java @@ -2,6 +2,7 @@ package com.willfp.eco.core.placeholder; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; /** @@ -22,7 +23,40 @@ public interface PlaceholderInjectable { * * @param placeholders The placeholders. */ - void injectPlaceholders(@NotNull Iterable placeholders); + default void injectPlaceholders(@NotNull InjectablePlaceholder... placeholders) { + this.addInjectablePlaceholder(List.of(placeholders)); + } + + /** + * Inject placeholder. + * + * @param placeholders The placeholders. + */ + @Deprecated(since = "6.35.0", forRemoval = true) + default void injectPlaceholders(@NotNull Iterable placeholders) { + List toInject = new ArrayList<>(); + for (StaticPlaceholder placeholder : placeholders) { + toInject.add(placeholder); + } + this.addInjectablePlaceholder(toInject); + } + + /** + * Inject placeholders. + *

+ * When implementing a PlaceholderInjectable object, override this method. + * + * @param placeholders The placeholders. + */ + default void addInjectablePlaceholder(@NotNull Iterable placeholders) { + List toInject = new ArrayList<>(); + for (InjectablePlaceholder placeholder : placeholders) { + if (placeholder instanceof StaticPlaceholder staticPlaceholder) { + toInject.add(staticPlaceholder); + } + } + this.injectPlaceholders(toInject); + } /** * Clear injected placeholders. @@ -33,6 +67,31 @@ public interface PlaceholderInjectable { * Get injected placeholders. * * @return Injected placeholders. + * @deprecated Use getPlaceholderInjections. */ - List getInjectedPlaceholders(); + @Deprecated(since = "6.35.0", forRemoval = true) + @NotNull + default List getInjectedPlaceholders() { + List found = new ArrayList<>(); + + for (InjectablePlaceholder placeholder : getPlaceholderInjections()) { + if (placeholder instanceof StaticPlaceholder staticPlaceholder) { + found.add(staticPlaceholder); + } + } + + return found; + } + + /** + * Get injected placeholders. + *

+ * Override this method in implementations. + * + * @return Injected placeholders. + */ + @NotNull + default List getPlaceholderInjections() { + return new ArrayList<>(getInjectedPlaceholders()); + } } diff --git a/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlayerStaticPlaceholder.java b/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlayerStaticPlaceholder.java new file mode 100644 index 00000000..f4fbcb45 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/placeholder/PlayerStaticPlaceholder.java @@ -0,0 +1,66 @@ +package com.willfp.eco.core.placeholder; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.function.Function; + +/** + * A placeholder that cannot be registered, and exists purely in injection. + */ +public final class PlayerStaticPlaceholder implements InjectablePlaceholder { + /** + * The name of the placeholder. + */ + private final String identifier; + + /** + * The function to retrieve the output of the placeholder. + */ + private final Function function; + + /** + * Create a new player placeholder. + * + * @param identifier The identifier. + * @param function The function to retrieve the value. + */ + public PlayerStaticPlaceholder(@NotNull final String identifier, + @NotNull final Function function) { + this.identifier = identifier; + this.function = function; + } + + /** + * Get the value of the placeholder. + * + * @param player The player. + * @return The value. + */ + public String getValue(@NotNull final Player player) { + return function.apply(player); + } + + @Override + public String getIdentifier() { + return this.identifier; + } + + @Override + public boolean equals(@Nullable final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PlayerStaticPlaceholder that)) { + return false; + } + return Objects.equals(this.getIdentifier(), that.getIdentifier()); + } + + @Override + public int hashCode() { + return Objects.hash(this.getIdentifier()); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/placeholder/StaticPlaceholder.java b/eco-api/src/main/java/com/willfp/eco/core/placeholder/StaticPlaceholder.java index a108fbd4..0f004373 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/placeholder/StaticPlaceholder.java +++ b/eco-api/src/main/java/com/willfp/eco/core/placeholder/StaticPlaceholder.java @@ -1,7 +1,5 @@ package com.willfp.eco.core.placeholder; -import com.willfp.eco.core.Eco; -import com.willfp.eco.core.EcoPlugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,7 +9,7 @@ import java.util.function.Supplier; /** * A placeholder that cannot be registered, and exists purely in injection. */ -public final class StaticPlaceholder implements Placeholder { +public final class StaticPlaceholder implements InjectablePlaceholder { /** * The name of the placeholder. */ @@ -43,11 +41,6 @@ public final class StaticPlaceholder implements Placeholder { return function.get(); } - @Override - public EcoPlugin getPlugin() { - return Eco.getHandler().getEcoPlugin(); - } - @Override public String getIdentifier() { return this.identifier; diff --git a/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java b/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java index cea2265b..b6f6b80e 100644 --- a/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java +++ b/eco-api/src/main/java/com/willfp/eco/util/NumberUtils.java @@ -1,5 +1,7 @@ package com.willfp.eco.util; +import com.willfp.eco.core.placeholder.InjectablePlaceholder; +import com.willfp.eco.core.placeholder.PlaceholderInjectable; import com.willfp.eco.core.placeholder.StaticPlaceholder; import org.apache.commons.lang.Validate; import org.bukkit.entity.Player; @@ -8,7 +10,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ThreadLocalRandom; @@ -252,7 +256,17 @@ public final class NumberUtils { */ public static double evaluateExpression(@NotNull final String expression, @Nullable final Player player) { - return evaluateExpression(expression, player, Collections.emptyList()); + return evaluateExpression(expression, player, new PlaceholderInjectable() { + @Override + public void clearInjectedPlaceholders() { + // Nothing. + } + + @Override + public @NotNull List getPlaceholderInjections() { + return Collections.emptyList(); + } + }); } /** @@ -262,11 +276,41 @@ public final class NumberUtils { * @param player The player. * @param statics The static placeholders. * @return The value of the expression, or zero if invalid. + * @deprecated Use new statics system. */ + @Deprecated(since = "6.35.0", forRemoval = true) public static double evaluateExpression(@NotNull final String expression, @Nullable final Player player, @NotNull final Iterable statics) { - return crunch.evaluate(expression, player, statics); + return crunch.evaluate(expression, player, new PlaceholderInjectable() { + @Override + public void clearInjectedPlaceholders() { + // Do nothing. + } + + @Override + public @NotNull List getPlaceholderInjections() { + List injections = new ArrayList<>(); + for (StaticPlaceholder placeholder : statics) { + injections.add(placeholder); + } + return injections; + } + }); + } + + /** + * Evaluate an expression with respect to a player (for placeholders). + * + * @param expression The expression. + * @param player The player. + * @param context The injectable placeholders. + * @return The value of the expression, or zero if invalid. + */ + public static double evaluateExpression(@NotNull final String expression, + @Nullable final Player player, + @NotNull final PlaceholderInjectable context) { + return crunch.evaluate(expression, player, context); } /** @@ -290,12 +334,12 @@ public final class NumberUtils { * * @param expression The expression. * @param player The player. - * @param statics The statics. + * @param injectable The injectable placeholders. * @return The value of the expression, or zero if invalid. */ double evaluate(@NotNull String expression, @Nullable Player player, - @NotNull Iterable statics); + @NotNull PlaceholderInjectable injectable); } private NumberUtils() { diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfig.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfig.kt index b443a865..74bf424c 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfig.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfig.kt @@ -2,7 +2,7 @@ package com.willfp.eco.internal.config import com.willfp.eco.core.config.ConfigType import com.willfp.eco.core.config.interfaces.Config -import com.willfp.eco.core.placeholder.StaticPlaceholder +import com.willfp.eco.core.placeholder.InjectablePlaceholder import com.willfp.eco.util.StringUtils import org.bukkit.configuration.file.YamlConfiguration import java.util.concurrent.ConcurrentHashMap @@ -14,7 +14,7 @@ open class EcoConfig( private val values = ConcurrentHashMap() @Transient - var injections = mutableListOf() + var injections = mutableListOf() fun init(values: Map) { this.values.clear() @@ -156,13 +156,13 @@ open class EcoConfig( return (get(path) as? Iterable)?.map { it.toDouble() } } - override fun injectPlaceholders(placeholders: Iterable) { + override fun addInjectablePlaceholder(placeholders: Iterable) { injections.removeIf { placeholders.any { placeholder -> it.identifier == placeholder.identifier } } injections.addAll(placeholders) } - override fun getInjectedPlaceholders(): List { - return injections.toList() + override fun getPlaceholderInjections(): List { + return injections.toList(); } override fun clearInjectedPlaceholders() { diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt index e04c25cd..083cb565 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/config/EcoConfigSection.kt @@ -1,13 +1,13 @@ package com.willfp.eco.internal.config import com.willfp.eco.core.config.ConfigType -import com.willfp.eco.core.placeholder.StaticPlaceholder +import com.willfp.eco.core.placeholder.InjectablePlaceholder @Suppress("UNCHECKED_CAST") class EcoConfigSection( type: ConfigType, values: Map = emptyMap(), - injections: Collection = emptyList() + injections: Collection = emptyList() ) : EcoConfig(type) { init { this.init(values) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoHandler.kt index 8bfc105d..d25b17b2 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoHandler.kt @@ -61,13 +61,9 @@ class EcoHandler : EcoSpigotPlugin(), Handler { if (this.configYml.getBool("use-safer-namespacedkey-creation")) SafeInternalNamespacedKeyFactory() else FastInternalNamespacedKeyFactory() - override fun createScheduler(plugin: EcoPlugin): EcoScheduler { - return EcoScheduler(plugin) - } + override fun createScheduler(plugin: EcoPlugin): EcoScheduler = EcoScheduler(plugin) - override fun createEventManager(plugin: EcoPlugin): EcoEventManager { - return EcoEventManager(plugin) - } + override fun createEventManager(plugin: EcoPlugin) = EcoEventManager(plugin) override fun createNamespacedKeyFactory(plugin: EcoPlugin): EcoNamespacedKeyFactory { return EcoNamespacedKeyFactory(plugin) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index f3fb36b8..f9f36603 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -176,7 +176,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() { val tpsProxy = getProxy(TPSProxy::class.java) ServerUtils.initialize { tpsProxy.getTPS() } - NumberUtils.initCrunch { expression, player, statics -> evaluateExpression(expression, player, statics) } + NumberUtils.initCrunch { expression, player, context -> evaluateExpression(expression, player, context) } CustomItemsManager.registerProviders() diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/CrunchHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/CrunchHandler.kt index 16f397ab..31514a14 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/CrunchHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/math/CrunchHandler.kt @@ -3,7 +3,7 @@ package com.willfp.eco.internal.spigot.math import com.github.benmanes.caffeine.cache.Cache import com.github.benmanes.caffeine.cache.Caffeine import com.willfp.eco.core.integrations.placeholder.PlaceholderManager -import com.willfp.eco.core.placeholder.StaticPlaceholder +import com.willfp.eco.core.placeholder.PlaceholderInjectable import org.bukkit.entity.Player import redempt.crunch.CompiledExpression import redempt.crunch.Crunch @@ -13,9 +13,9 @@ import redempt.crunch.functional.EvaluationEnvironment private val cache: Cache = Caffeine.newBuilder().build() private val goToZero = Crunch.compileExpression("0") -fun evaluateExpression(expression: String, player: Player?, statics: Iterable): Double { +fun evaluateExpression(expression: String, player: Player?, context: PlaceholderInjectable): Double { val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression) - .map { PlaceholderManager.translatePlaceholders(it, player, statics.toList()) } + .map { PlaceholderManager.translatePlaceholders(it, player, context) } .map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) } .toDoubleArray()