Reworked placeholder system
This commit is contained in:
@@ -2,6 +2,8 @@ package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.TransientConfig;
|
||||
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.entity.Player;
|
||||
@@ -9,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -18,7 +21,7 @@ import java.util.Objects;
|
||||
* Contains all methods that must exist in yaml and json configurations.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Config extends Cloneable {
|
||||
public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
/**
|
||||
* Clears cache.
|
||||
*/
|
||||
@@ -563,7 +566,7 @@ public interface Config extends Cloneable {
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@Nullable Player player) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player);
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player, this.getInjectedPlaceholders());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,4 +632,14 @@ public interface Config extends Cloneable {
|
||||
* @return The clone.
|
||||
*/
|
||||
Config clone();
|
||||
|
||||
@Override
|
||||
default void injectPlaceholders(@NotNull StaticPlaceholder... placeholders) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
default List<StaticPlaceholder> getInjectedPlaceholders() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.willfp.eco.core.integrations.placeholder;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.Placeholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -10,10 +14,13 @@ import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A {@link PlaceholderEntry} is a placeholder in and of itself.
|
||||
* A placeholder entry is a placeholder in and of itself.
|
||||
* <p>
|
||||
* It should be fairly straightforward.
|
||||
*
|
||||
* @deprecated Confusing functionality with inconsistent nullability and poor naming.
|
||||
*/
|
||||
@Deprecated(since = "6.28.0", forRemoval = true)
|
||||
public class PlaceholderEntry {
|
||||
/**
|
||||
* The name of the placeholder, used in lookups.
|
||||
@@ -140,7 +147,28 @@ public class PlaceholderEntry {
|
||||
* Register the placeholder.
|
||||
*/
|
||||
public void register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
PlaceholderManager.registerPlaceholder(this.toModernPlaceholder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the placeholder to a modern placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
Placeholder toModernPlaceholder() {
|
||||
if (this.requiresPlayer) {
|
||||
return new PlayerPlaceholder(
|
||||
Objects.requireNonNullElse(plugin, Eco.getHandler().getEcoPlugin()),
|
||||
identifier,
|
||||
function
|
||||
);
|
||||
} else {
|
||||
return new PlayerlessPlaceholder(
|
||||
Objects.requireNonNullElse(plugin, Eco.getHandler().getEcoPlugin()),
|
||||
identifier,
|
||||
() -> function.apply(null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,11 +4,16 @@ 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.Placeholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -19,11 +24,12 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Class to handle placeholder integrations.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public final class PlaceholderManager {
|
||||
/**
|
||||
* All registered placeholders.
|
||||
*/
|
||||
private static final Map<EcoPlugin, Map<String, PlaceholderEntry>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
private static final Map<EcoPlugin, Map<String, Placeholder>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* All registered placeholder integrations.
|
||||
@@ -35,7 +41,7 @@ public final class PlaceholderManager {
|
||||
*/
|
||||
private static final LoadingCache<EntryWithPlayer, String> PLACEHOLDER_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(key -> key.entry.getResult(key.player));
|
||||
.build(key -> key.entry.getValue(key.player));
|
||||
|
||||
/**
|
||||
* Register a new placeholder integration.
|
||||
@@ -50,16 +56,31 @@ public final class PlaceholderManager {
|
||||
/**
|
||||
* Register a placeholder.
|
||||
*
|
||||
* @param expansion The {@link com.willfp.eco.core.integrations.placeholder.PlaceholderEntry} to register.
|
||||
* @param placeholder The placeholder to register.
|
||||
*/
|
||||
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
|
||||
EcoPlugin plugin = expansion.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : expansion.getPlugin();
|
||||
Map<String, PlaceholderEntry> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
public static void registerPlaceholder(@NotNull final Placeholder placeholder) {
|
||||
if (placeholder instanceof StaticPlaceholder) {
|
||||
throw new IllegalArgumentException("Static placeholders cannot be registered!");
|
||||
}
|
||||
|
||||
EcoPlugin plugin = placeholder.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : placeholder.getPlugin();
|
||||
Map<String, Placeholder> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
.getOrDefault(plugin, new HashMap<>());
|
||||
pluginPlaceholders.put(expansion.getIdentifier(), expansion);
|
||||
pluginPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
REGISTERED_PLACEHOLDERS.put(plugin, pluginPlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a placeholder.
|
||||
*
|
||||
* @param placeholder The placeholder to register.
|
||||
* @deprecated Uses old placeholder system.
|
||||
*/
|
||||
@Deprecated(since = "6.28.0", forRemoval = true)
|
||||
public static void registerPlaceholder(@NotNull final PlaceholderEntry placeholder) {
|
||||
registerPlaceholder(placeholder.toModernPlaceholder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of a placeholder with respect to a player.
|
||||
*
|
||||
@@ -82,29 +103,36 @@ public final class PlaceholderManager {
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @return The value of the placeholder.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier,
|
||||
@Nullable final EcoPlugin plugin) {
|
||||
EcoPlugin owner = plugin == null ? Eco.getHandler().getEcoPlugin() : plugin;
|
||||
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
|
||||
Placeholder placeholder = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
|
||||
|
||||
if (entry == null && plugin != null) {
|
||||
PlaceholderEntry alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
|
||||
if (placeholder == null && plugin != null) {
|
||||
Placeholder alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
|
||||
.get(identifier.toLowerCase());
|
||||
if (alternate != null) {
|
||||
entry = alternate;
|
||||
placeholder = alternate;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
if (placeholder == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (player == null && entry.requiresPlayer()) {
|
||||
if (placeholder instanceof PlayerPlaceholder playerPlaceholder) {
|
||||
if (player == null) {
|
||||
return "";
|
||||
} else {
|
||||
return PLACEHOLDER_CACHE.get(new EntryWithPlayer(playerPlaceholder, player));
|
||||
}
|
||||
} else if (placeholder instanceof PlayerlessPlaceholder playerlessPlaceholder) {
|
||||
return playerlessPlaceholder.getValue();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
return PLACEHOLDER_CACHE.get(new EntryWithPlayer(entry, player));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,10 +144,28 @@ public final class PlaceholderManager {
|
||||
*/
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player) {
|
||||
return translatePlaceholders(text, player, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 statics Extra static placeholders.
|
||||
* @return The text, translated.
|
||||
*/
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player,
|
||||
@NotNull final List<StaticPlaceholder> statics) {
|
||||
String processed = text;
|
||||
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
|
||||
processed = integration.translate(processed, player);
|
||||
}
|
||||
for (StaticPlaceholder placeholder : statics) {
|
||||
// Do I know this is a bad way of doing this? Yes.
|
||||
processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue());
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
@@ -138,8 +184,8 @@ public final class PlaceholderManager {
|
||||
return found;
|
||||
}
|
||||
|
||||
private static record EntryWithPlayer(@NotNull PlaceholderEntry entry,
|
||||
@Nullable Player player) {
|
||||
private record EntryWithPlayer(@NotNull PlayerPlaceholder entry,
|
||||
@NotNull Player player) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
|
||||
/**
|
||||
* A placeholder represents a string that can hold a value.
|
||||
*/
|
||||
public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder, StaticPlaceholder {
|
||||
/**
|
||||
* Get the plugin that holds the placeholder.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
EcoPlugin getPlugin();
|
||||
|
||||
/**
|
||||
* Get the identifier for the placeholder.
|
||||
*
|
||||
* @return The identifier.
|
||||
*/
|
||||
String getIdentifier();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a class that can have placeholders injected into it.
|
||||
*/
|
||||
public interface PlaceholderInjectable {
|
||||
/**
|
||||
* Inject placeholder.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
void injectPlaceholders(@NotNull StaticPlaceholder... placeholders);
|
||||
|
||||
/**
|
||||
* Get injected placeholders.
|
||||
*
|
||||
* @return Injected placeholders.
|
||||
*/
|
||||
List<StaticPlaceholder> getInjectedPlaceholders();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A placeholder that requires a player.
|
||||
*/
|
||||
public final class PlayerPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder given a player.
|
||||
*/
|
||||
private final Function<Player, String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public PlayerPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder for a given player.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue(@NotNull final Player player) {
|
||||
return function.apply(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
public PlayerPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A placeholder that does not require a player.
|
||||
*/
|
||||
public final class PlayerlessPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public PlayerlessPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Supplier<String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
public PlayerlessPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A placeholder that cannot be registered, and exists purely in injection.
|
||||
*/
|
||||
public final class StaticPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public StaticPlaceholder(@NotNull final String identifier,
|
||||
@NotNull final Supplier<String> function) {
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return Eco.getHandler().getEcoPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.recipe.recipes;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
@@ -24,6 +25,7 @@ import java.util.Optional;
|
||||
/**
|
||||
* Shapeless crafting recipe.
|
||||
*/
|
||||
@Beta
|
||||
public final class ShapelessCraftingRecipe extends PluginDependent<EcoPlugin> implements CraftingRecipe {
|
||||
/**
|
||||
* Recipe parts.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -7,10 +8,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for numbers.
|
||||
@@ -24,7 +25,7 @@ public final class NumberUtils {
|
||||
/**
|
||||
* Crunch handler.
|
||||
*/
|
||||
private static BiFunction<String, Player, Double> crunch = null;
|
||||
private static CrunchHandler crunch = null;
|
||||
|
||||
/**
|
||||
* Set of roman numerals to look up.
|
||||
@@ -251,7 +252,21 @@ public final class NumberUtils {
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@Nullable final Player player) {
|
||||
return crunch.apply(expression, player);
|
||||
return evaluateExpression(expression, player, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression with respect to a player (for placeholders).
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param statics The static 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 Iterable<StaticPlaceholder> statics) {
|
||||
return crunch.evaluate(expression, player, statics);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,11 +275,29 @@ public final class NumberUtils {
|
||||
* @param handler The handler.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void initCrunch(@NotNull final BiFunction<String, Player, Double> handler) {
|
||||
public static void initCrunch(@NotNull final CrunchHandler handler) {
|
||||
Validate.isTrue(crunch == null, "Already initialized!");
|
||||
crunch = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bridge component for crunch.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface CrunchHandler {
|
||||
/**
|
||||
* Evaluate an expression.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param statics The statics.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
double evaluate(@NotNull String expression,
|
||||
@Nullable Player player,
|
||||
@NotNull Iterable<StaticPlaceholder> statics);
|
||||
}
|
||||
|
||||
private NumberUtils() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user