Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43b7c393b9 | ||
|
|
714952bc45 | ||
|
|
322e179b81 | ||
|
|
469be73ada | ||
|
|
7eac60146f | ||
|
|
ad0223e1bb | ||
|
|
430117f342 | ||
|
|
fa87cae81e | ||
|
|
5695750fc5 | ||
|
|
45e8a57880 | ||
|
|
17fcd2c1b5 | ||
|
|
0c1e17c351 | ||
|
|
9415515849 | ||
|
|
d0e957ea37 | ||
|
|
69514e2f85 | ||
|
|
259e35c978 | ||
|
|
40aec26f15 | ||
|
|
67b2fdd594 | ||
|
|
83f86983f6 | ||
|
|
3ba98a9a5e | ||
|
|
f19e565fbe | ||
|
|
ee3ecb643b | ||
|
|
3aefb0e481 | ||
|
|
d9eb1e1c26 | ||
|
|
70631e67c5 | ||
|
|
82797e7342 | ||
|
|
d2917341b1 | ||
|
|
760f42be0c | ||
|
|
bb01af2ab2 | ||
|
|
517d890c05 | ||
|
|
f02fc56778 | ||
|
|
4417b09c14 | ||
|
|
6b37fafa90 | ||
|
|
f8c5c9f06d | ||
|
|
0fd6cbaa08 | ||
|
|
81afa32eb0 | ||
|
|
7387fe2332 | ||
|
|
80fa05da98 | ||
|
|
77754249ad | ||
|
|
1843cf0f8a | ||
|
|
05eb5ee993 | ||
|
|
7bc11ee716 | ||
|
|
f566aec00e | ||
|
|
36d47c55a1 | ||
|
|
40463213ac | ||
|
|
6ec80d30ad | ||
|
|
7ccee60a0c | ||
|
|
0805b48763 | ||
|
|
d737322aaa | ||
|
|
4ddc150e1c | ||
|
|
0da119d89d | ||
|
|
fc0a07d1c5 | ||
|
|
4ce2850138 |
@@ -82,6 +82,12 @@ allprojects {
|
||||
|
||||
// UltraEconomy
|
||||
maven("https://repo.techscode.com/repository/maven-releases/")
|
||||
|
||||
// PlayerPoints
|
||||
maven("https://repo.rosewooddev.io/repository/public/")
|
||||
|
||||
// Denizen
|
||||
maven("https://maven.citizensnpcs.co/repo")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -25,8 +25,8 @@ import com.willfp.eco.core.gui.menu.MenuType;
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.packet.Packet;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||
import com.willfp.eco.core.scheduling.Scheduler;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
@@ -531,7 +531,7 @@ public interface Eco {
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
double evaluate(@NotNull String expression,
|
||||
@NotNull MathContext context);
|
||||
@NotNull PlaceholderContext context);
|
||||
|
||||
/**
|
||||
* Get the menu a player currently has open.
|
||||
@@ -563,6 +563,30 @@ public interface Eco {
|
||||
void sendPacket(@NotNull Player player,
|
||||
@NotNull Packet packet);
|
||||
|
||||
/**
|
||||
* Translate placeholders in a string.
|
||||
*
|
||||
* @param text The text.
|
||||
* @param context The context.
|
||||
* @return The translated text.
|
||||
*/
|
||||
@NotNull
|
||||
String translatePlaceholders(@NotNull String text,
|
||||
@NotNull PlaceholderContext context);
|
||||
|
||||
/**
|
||||
* Get the value of a placeholder.
|
||||
*
|
||||
* @param plugin The plugin that owns the placeholder.
|
||||
* @param args The placeholder arguments.
|
||||
* @param context The context.
|
||||
* @return The value, or null if invalid.
|
||||
*/
|
||||
@Nullable
|
||||
String getPlaceholderValue(@Nullable EcoPlugin plugin,
|
||||
@NotNull String args,
|
||||
@NotNull PlaceholderContext context);
|
||||
|
||||
/**
|
||||
* Get the instance of eco; the bridge between the api frontend and the implementation backend.
|
||||
*
|
||||
|
||||
@@ -366,7 +366,6 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
||||
public final void onEnable() {
|
||||
super.onEnable();
|
||||
|
||||
this.getLogger().info("");
|
||||
this.getLogger().info("Loading " + this.getColor() + this.getName());
|
||||
|
||||
if (this.getResourceId() != 0 && !Eco.get().getEcoPlugin().getConfigYml().getBool("no-update-checker")) {
|
||||
@@ -406,7 +405,9 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
||||
|
||||
this.loadedIntegrations.removeIf(pl -> pl.equalsIgnoreCase(this.getName()));
|
||||
|
||||
this.getLogger().info("Loaded integrations: " + String.join(", ", this.getLoadedIntegrations()));
|
||||
if (!this.getLoadedIntegrations().isEmpty()) {
|
||||
this.getLogger().info("Loaded integrations: " + String.join(", ", this.getLoadedIntegrations()));
|
||||
}
|
||||
|
||||
Prerequisite.update();
|
||||
|
||||
@@ -428,17 +429,19 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
||||
if (this.isSupportingExtensions()) {
|
||||
this.getExtensionLoader().loadExtensions();
|
||||
|
||||
if (this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
|
||||
this.getLogger().info("&cNo extensions found");
|
||||
} else {
|
||||
this.getLogger().info("Extensions Loaded:");
|
||||
this.getExtensionLoader().getLoadedExtensions().forEach(extension -> this.getLogger().info("- " + extension.getName() + " v" + extension.getVersion()));
|
||||
if (!this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
|
||||
List<String> loadedExtensions = this.getExtensionLoader().getLoadedExtensions().stream().map(
|
||||
extension -> extension.getName() + " v" + extension.getVersion()
|
||||
).toList();
|
||||
|
||||
this.getLogger().info(
|
||||
"Loaded extensions: " +
|
||||
String.join(", ", loadedExtensions)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.handleLifecycle(this.onEnable, this::handleEnable);
|
||||
|
||||
this.getLogger().info("");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.willfp.eco.core.config.Configs;
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
@@ -134,7 +135,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default int getIntFromExpression(@NotNull String path) {
|
||||
return getIntFromExpression(path, null);
|
||||
return getIntFromExpression(path, PlaceholderContext.of(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +164,18 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
return Double.valueOf(getDoubleFromExpression(path, player, additionalPlayers)).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default int getIntFromExpression(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
return Double.valueOf(getDoubleFromExpression(path, context)).intValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an integer from config.
|
||||
@@ -256,6 +269,22 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
return getString(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a formatted string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The found value, or an empty string if not found.
|
||||
*/
|
||||
@NotNull
|
||||
default String getFormattedString(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
return Objects.requireNonNullElse(
|
||||
getFormattedStringOrNull(path, context),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
* <p>
|
||||
@@ -288,7 +317,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
* Get a formatted string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @return The found value, or an empty string if not found.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
default String getFormattedStringOrNull(@NotNull String path) {
|
||||
@@ -300,7 +329,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param option The format option.
|
||||
* @return The found value, or an empty string if not found.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
default String getFormattedStringOrNull(@NotNull String path,
|
||||
@@ -308,6 +337,25 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
return getStringOrNull(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a formatted string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
default String getFormattedStringOrNull(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
String nullable = getStringOrNull(path);
|
||||
|
||||
if (nullable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return StringUtils.format(nullable, context.withInjectableContext(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
* <p>
|
||||
@@ -362,6 +410,24 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
return getStrings(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
* <p>
|
||||
* Formatted.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
*/
|
||||
@NotNull
|
||||
default List<String> getFormattedStrings(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
return Objects.requireNonNullElse(
|
||||
getFormattedStringsOrNull(path, context),
|
||||
new ArrayList<>()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
* <p>
|
||||
@@ -418,6 +484,30 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
return getStringsOrNull(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
* <p>
|
||||
* Formatted.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getFormattedStringsOrNull(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
List<String> nullable = getStringsOrNull(path);
|
||||
|
||||
if (nullable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return StringUtils.formatList(
|
||||
nullable,
|
||||
context.withInjectableContext(this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
* <p>
|
||||
@@ -463,7 +553,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path) {
|
||||
return getDoubleFromExpression(path, null);
|
||||
return getDoubleFromExpression(path, PlaceholderContext.of(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,21 +565,38 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@Nullable Player player) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player, this);
|
||||
return getDoubleFromExpression(path, player, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param player The player to evaluate placeholders with respect to.
|
||||
* @param path The key to fetch the value from.
|
||||
* @param player The player to evaluate placeholders with respect to.
|
||||
* @param additionalPlayers The additional players to evaluate placeholders with respect to.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@Nullable Player player,
|
||||
@NotNull Collection<AdditionalPlayer> additionalPlayers) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player, this, additionalPlayers);
|
||||
return getDoubleFromExpression(path, new PlaceholderContext(
|
||||
player,
|
||||
null,
|
||||
this,
|
||||
additionalPlayers
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a decimal value via a mathematical expression.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param context The placeholder context.
|
||||
* @return The computed value, or 0 if not found or invalid.
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@NotNull PlaceholderContext context) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), context.withInjectableContext(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -114,7 +114,7 @@ public class IntegrationRegistry<T extends Integration> extends Registry<T> {
|
||||
Eco.get().getEcoPlugin().getLogger().warning("Integration for " + integration.getPluginName() + " threw an exception!");
|
||||
Eco.get().getEcoPlugin().getLogger().warning("The integration will be disabled.");
|
||||
e.printStackTrace();
|
||||
this.remove(integration.getPluginName());
|
||||
this.remove(integration);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper class for placeholder integrations.
|
||||
* Wrapper class for arguments integrations.
|
||||
*/
|
||||
public interface PlaceholderIntegration extends Integration {
|
||||
/**
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
package com.willfp.eco.core.integrations.placeholder;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.map.DefaultMap;
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||
import com.willfp.eco.core.placeholder.DynamicPlaceholder;
|
||||
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.PlayerDynamicPlaceholder;
|
||||
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 com.willfp.eco.util.StringUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import com.willfp.eco.core.placeholder.RegistrablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -23,58 +17,34 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class to handle placeholder integrations.
|
||||
* Class to handle arguments integrations.
|
||||
*/
|
||||
public final class PlaceholderManager {
|
||||
/**
|
||||
* All registered placeholders.
|
||||
*/
|
||||
private static final Map<EcoPlugin, Map<Pattern, Placeholder>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
private static final DefaultMap<EcoPlugin, Set<Placeholder>> REGISTERED_PLACEHOLDERS = new DefaultMap<>(HashSet::new);
|
||||
|
||||
/**
|
||||
* All registered placeholder integrations.
|
||||
* All registered arguments integrations.
|
||||
*/
|
||||
private static final Set<PlaceholderIntegration> REGISTERED_INTEGRATIONS = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Placeholder Lookup Cache.
|
||||
*/
|
||||
private static final Cache<PlaceholderLookup, Optional<Placeholder>> PLACEHOLDER_LOOKUP_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Placeholder Cache.
|
||||
*/
|
||||
private static final LoadingCache<EntryWithPlayer, String> PLACEHOLDER_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(key -> key.entry.getValue(key.player));
|
||||
|
||||
/**
|
||||
* Dynamic Placeholder Cache.
|
||||
*/
|
||||
private static final LoadingCache<DynamicEntryWithPlayer, String> DYNAMIC_PLACEHOLDER_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(key -> key.entry.getValue(key.args, key.player));
|
||||
|
||||
/**
|
||||
* The default PlaceholderAPI pattern; brought in for compatibility.
|
||||
*/
|
||||
private static final Pattern PATTERN = Pattern.compile("%([^% ]+)%");
|
||||
|
||||
/**
|
||||
* Empty injectable object.
|
||||
* Empty injectableContext object.
|
||||
*/
|
||||
public static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
||||
@Override
|
||||
@@ -105,97 +75,68 @@ public final class PlaceholderManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a placeholder.
|
||||
* Register a arguments.
|
||||
*
|
||||
* @param placeholder The placeholder to register.
|
||||
* @param placeholder The arguments to register.
|
||||
* @deprecated Use {@link #registerPlaceholder(RegistrablePlaceholder)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
public static void registerPlaceholder(@NotNull final Placeholder placeholder) {
|
||||
if (placeholder instanceof StaticPlaceholder || placeholder instanceof PlayerStaticPlaceholder) {
|
||||
throw new IllegalArgumentException("Static placeholders cannot be registered!");
|
||||
if (!(placeholder instanceof RegistrablePlaceholder)) {
|
||||
throw new IllegalArgumentException("Placeholder must be RegistrablePlaceholder!");
|
||||
}
|
||||
|
||||
Map<Pattern, Placeholder> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
.getOrDefault(placeholder.getPlugin(), new HashMap<>());
|
||||
|
||||
pluginPlaceholders.put(placeholder.getPattern(), placeholder);
|
||||
|
||||
REGISTERED_PLACEHOLDERS.put(placeholder.getPlugin(), pluginPlaceholders);
|
||||
registerPlaceholder((RegistrablePlaceholder) placeholder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of a placeholder with respect to a player.
|
||||
* Register a arguments.
|
||||
*
|
||||
* @param player The player to get the result from.
|
||||
* @param identifier The placeholder identifier.
|
||||
* @return The value of the placeholder.
|
||||
* @deprecated Specify a plugin to get the result from.
|
||||
* @param placeholder The arguments to register.
|
||||
*/
|
||||
@Deprecated(since = "6.52.2", forRemoval = true)
|
||||
@SuppressWarnings("unused")
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier) {
|
||||
throw new UnsupportedOperationException("Please specify a plugin to get the result from!");
|
||||
public static void registerPlaceholder(@NotNull final RegistrablePlaceholder placeholder) {
|
||||
// Storing as immutable set leads to slower times to register placeholders, but much
|
||||
// faster times to access registrations.
|
||||
Set<Placeholder> pluginPlaceholders = new HashSet<>(REGISTERED_PLACEHOLDERS.get(placeholder.getPlugin()));
|
||||
pluginPlaceholders.add(placeholder);
|
||||
REGISTERED_PLACEHOLDERS.put(placeholder.getPlugin(), ImmutableSet.copyOf(pluginPlaceholders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of a placeholder with respect to a player.
|
||||
*
|
||||
* @param player The player to get the result from.
|
||||
* @param identifier The placeholder identifier.
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @return The value of the placeholder.
|
||||
* @param identifier The placeholder args.
|
||||
* @param plugin The plugin for the arguments.
|
||||
* @return The value of the arguments.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final EcoPlugin plugin) {
|
||||
Validate.notNull(plugin, "Plugin cannot be null!");
|
||||
@Nullable final EcoPlugin plugin) {
|
||||
return Objects.requireNonNullElse(
|
||||
getResult(
|
||||
plugin,
|
||||
identifier,
|
||||
new PlaceholderContext(player)
|
||||
),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
// This is really janky, and it sucks, but it works so?
|
||||
// Compensating for regex being slow so that's why we get it.
|
||||
Placeholder placeholder = PLACEHOLDER_LOOKUP_CACHE.get(
|
||||
new PlaceholderLookup(identifier, plugin),
|
||||
(it) -> {
|
||||
// I hate the streams API.
|
||||
return REGISTERED_PLACEHOLDERS
|
||||
.getOrDefault(plugin, new HashMap<>())
|
||||
.entrySet()
|
||||
.stream().filter(entry -> entry.getKey().matcher(identifier).matches())
|
||||
.map(Map.Entry::getValue)
|
||||
.findFirst();
|
||||
}
|
||||
).orElse(null);
|
||||
|
||||
if (placeholder == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
This code here is *really* not very good. It's mega externalized logic hacked
|
||||
together and made worse by the addition of dynamic placeholders. But it works,
|
||||
and it means I don't have to rewrite the whole placeholder system. So it's
|
||||
good enough for me.
|
||||
*/
|
||||
|
||||
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 if (placeholder instanceof PlayerDynamicPlaceholder playerDynamicPlaceholder) {
|
||||
if (player == null) {
|
||||
return "";
|
||||
} else {
|
||||
return DYNAMIC_PLACEHOLDER_CACHE.get(new DynamicEntryWithPlayer(playerDynamicPlaceholder, identifier, player));
|
||||
}
|
||||
} else if (placeholder instanceof DynamicPlaceholder dynamicPlaceholder) {
|
||||
return dynamicPlaceholder.getValue(identifier);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
/**
|
||||
* Get the result of a placeholder given a plugin and arguments.
|
||||
*
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @param args The arguments.
|
||||
* @param context The context.
|
||||
* @return The value of the arguments.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getResult(@Nullable final EcoPlugin plugin,
|
||||
@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return Eco.get().getPlaceholderValue(plugin, args, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,7 +145,10 @@ public final class PlaceholderManager {
|
||||
* @param text The text that may contain placeholders to translate.
|
||||
* @param player The player to translate the placeholders with respect to.
|
||||
* @return The text, translated.
|
||||
* @deprecated Use {@link #translatePlaceholders(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player) {
|
||||
return translatePlaceholders(text, player, EMPTY_INJECTABLE);
|
||||
@@ -215,9 +159,12 @@ public final class PlaceholderManager {
|
||||
*
|
||||
* @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.
|
||||
* @param context The injectableContext parseContext.
|
||||
* @return The text, translated.
|
||||
* @deprecated Use {@link #translatePlaceholders(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player,
|
||||
@NotNull final PlaceholderInjectable context) {
|
||||
@@ -229,84 +176,50 @@ public final class PlaceholderManager {
|
||||
*
|
||||
* @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.
|
||||
* @param context The injectableContext parseContext.
|
||||
* @param additionalPlayers Additional players to translate placeholders for.
|
||||
* @return The text, translated.
|
||||
* @deprecated Use {@link #translatePlaceholders(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player,
|
||||
@NotNull final PlaceholderInjectable context,
|
||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||
String processed = text;
|
||||
return translatePlaceholders(
|
||||
text,
|
||||
new PlaceholderContext(
|
||||
player,
|
||||
null,
|
||||
context,
|
||||
additionalPlayers
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Translate all placeholders without a placeholder context.
|
||||
*
|
||||
* @param text The text that may contain placeholders to translate.
|
||||
* @return The text, translated.
|
||||
*/
|
||||
@NotNull
|
||||
public static String translatePlaceholders(@NotNull final String text) {
|
||||
return Eco.get().translatePlaceholders(text, PlaceholderContext.EMPTY);
|
||||
}
|
||||
|
||||
Why am I doing statics at the start, but player statics at the end?
|
||||
|
||||
Additional players let you use something like victim as a player to parse in relation to,
|
||||
for example doing %victim_player_health%, which would parse the health of the victim.
|
||||
|
||||
However, something like libreforge will also inject %victim_max_health%, which is unrelated
|
||||
to additional players, and instead holds a constant value. So, eco saw this, smartly thought
|
||||
"ah, it's an additional player, let's parse it", and then tried to parse %max_health% with
|
||||
relation to the victim, which resolved to zero. So, we have to parse statics and player statics
|
||||
that might include a prefix first, then additional players, then player statics with the support
|
||||
of additional players.
|
||||
|
||||
This was a massive headache and took so many reports before I clocked what was going on.
|
||||
|
||||
Oh well, at least it's fixed now.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
for (InjectablePlaceholder injection : context.getPlaceholderInjections()) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent running 2 scans if there are no additional players.
|
||||
if (!additionalPlayers.isEmpty()) {
|
||||
List<String> found = findPlaceholdersIn(text);
|
||||
|
||||
for (AdditionalPlayer additionalPlayer : additionalPlayers) {
|
||||
for (String placeholder : found) {
|
||||
String prefix = "%" + additionalPlayer.getIdentifier() + "_";
|
||||
|
||||
if (placeholder.startsWith(prefix)) {
|
||||
processed = processed.replace(
|
||||
placeholder,
|
||||
translatePlaceholders(
|
||||
"%" + StringUtils.removePrefix(prefix, placeholder),
|
||||
additionalPlayer.getPlayer()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only run jank code if there are no integrations.
|
||||
if (REGISTERED_INTEGRATIONS.isEmpty()) {
|
||||
processed = setWithoutIntegration(processed, player);
|
||||
}
|
||||
|
||||
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
|
||||
processed = integration.translate(processed, player);
|
||||
}
|
||||
|
||||
// DON'T REMOVE THIS, IT'S NOT DUPLICATE CODE.
|
||||
for (InjectablePlaceholder injection : context.getPlaceholderInjections()) {
|
||||
// Do I know this is a bad way of doing this? Yes.
|
||||
if (injection instanceof PlayerStaticPlaceholder placeholder && player != null) {
|
||||
processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue(player));
|
||||
}
|
||||
}
|
||||
|
||||
return processed;
|
||||
/**
|
||||
* Translate all placeholders in a translation context.
|
||||
*
|
||||
* @param text The text that may contain placeholders to translate.
|
||||
* @param context The translation context.
|
||||
* @return The text, translated.
|
||||
*/
|
||||
@NotNull
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return Eco.get().translatePlaceholders(text, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -331,108 +244,22 @@ public final class PlaceholderManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set placeholders without any integrations.
|
||||
* <p>
|
||||
* This is fallback if for some reason you don't have PAPI installed.
|
||||
* It's a cut-down version of the actual PAPI code, and I don't
|
||||
* really know how it works.
|
||||
* <p>
|
||||
* Original source
|
||||
* <a href="https://github.com/PlaceholderAPI/PlaceholderAPI/blob/master/src/main/java/me/clip/placeholderapi/replacer/CharsReplacer.java">here</a>.
|
||||
* Get all registered placeholder integrations.
|
||||
*
|
||||
* @param text The text.
|
||||
* @param player The player.
|
||||
* @return The text.
|
||||
* @return The integrations.
|
||||
*/
|
||||
private static String setWithoutIntegration(@NotNull final String text,
|
||||
@Nullable final Player player) {
|
||||
char[] chars = text.toCharArray();
|
||||
StringBuilder builder = new StringBuilder(text.length());
|
||||
StringBuilder identifier = new StringBuilder();
|
||||
StringBuilder parameters = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
char currentChar = chars[i];
|
||||
if (currentChar == '%' && i + 1 < chars.length) {
|
||||
boolean identified = false;
|
||||
boolean badPlaceholder = true;
|
||||
boolean hadSpace = false;
|
||||
|
||||
while (true) {
|
||||
i++;
|
||||
if (i >= chars.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
char p = chars[i];
|
||||
if (p == ' ' && !identified) {
|
||||
hadSpace = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == '%') {
|
||||
badPlaceholder = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == '_' && !identified) {
|
||||
identified = true;
|
||||
} else if (identified) {
|
||||
parameters.append(p);
|
||||
} else {
|
||||
identifier.append(p);
|
||||
}
|
||||
}
|
||||
|
||||
String pluginName = identifier.toString().toLowerCase();
|
||||
EcoPlugin plugin = EcoPlugin.getPlugin(pluginName);
|
||||
String placeholderIdentifier = parameters.toString();
|
||||
identifier.setLength(0);
|
||||
parameters.setLength(0);
|
||||
if (badPlaceholder) {
|
||||
builder.append('%').append(pluginName);
|
||||
if (identified) {
|
||||
builder.append('_').append(placeholderIdentifier);
|
||||
}
|
||||
|
||||
if (hadSpace) {
|
||||
builder.append(' ');
|
||||
}
|
||||
} else {
|
||||
if (plugin == null) {
|
||||
builder.append('%').append(pluginName);
|
||||
|
||||
if (identified) {
|
||||
builder.append('_');
|
||||
}
|
||||
|
||||
builder.append(placeholderIdentifier).append('%');
|
||||
} else {
|
||||
builder.append(getResult(player, placeholderIdentifier, plugin));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
builder.append(currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
public static Set<PlaceholderIntegration> getRegisteredIntegrations() {
|
||||
return Set.copyOf(REGISTERED_INTEGRATIONS);
|
||||
}
|
||||
|
||||
private record PlaceholderLookup(@NotNull String identifier,
|
||||
@Nullable EcoPlugin plugin) {
|
||||
|
||||
}
|
||||
|
||||
private record EntryWithPlayer(@NotNull PlayerPlaceholder entry,
|
||||
@NotNull Player player) {
|
||||
|
||||
}
|
||||
|
||||
private record DynamicEntryWithPlayer(@NotNull PlayerDynamicPlaceholder entry,
|
||||
@NotNull String args,
|
||||
@NotNull Player player) {
|
||||
|
||||
/**
|
||||
* Get all registered placeholders for a plugin.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @return The placeholders.
|
||||
*/
|
||||
public static Set<Placeholder> getRegisteredPlaceholders(@NotNull final EcoPlugin plugin) {
|
||||
return REGISTERED_PLACEHOLDERS.get(plugin);
|
||||
}
|
||||
|
||||
private PlaceholderManager() {
|
||||
|
||||
@@ -3,27 +3,25 @@ package com.willfp.eco.core.math;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a context to do math in.
|
||||
* Represents a context to parse math in.
|
||||
*
|
||||
* @param injectableContext The PlaceholderInjectable context.
|
||||
* @param player The player.
|
||||
* @param additionalPlayers The additional players.
|
||||
* @deprecated Use {@link PlaceholderContext} instead.
|
||||
*/
|
||||
public record MathContext(
|
||||
@NotNull PlaceholderInjectable injectableContext,
|
||||
@Nullable Player player,
|
||||
@NotNull Collection<AdditionalPlayer> additionalPlayers
|
||||
) {
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
public class MathContext {
|
||||
/**
|
||||
* Empty math context.
|
||||
* Returns an empty math parseContext.
|
||||
*/
|
||||
public static final MathContext EMPTY = new MathContext(
|
||||
PlaceholderManager.EMPTY_INJECTABLE,
|
||||
@@ -32,9 +30,157 @@ public record MathContext(
|
||||
);
|
||||
|
||||
/**
|
||||
* Create MathContext of a PlaceholderInjectable context.
|
||||
* The PlaceholderInjectable parse context.
|
||||
*/
|
||||
@NotNull
|
||||
private final PlaceholderInjectable injectableContext;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
@Nullable
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The additional players.
|
||||
*/
|
||||
@NotNull
|
||||
private final Collection<AdditionalPlayer> additionalPlayers;
|
||||
|
||||
/**
|
||||
* Constructs a new MathContext with the given parameters.
|
||||
*
|
||||
* @param injectableContext The PlaceholderInjectable context.
|
||||
* @param injectableContext The PlaceholderInjectable parseContext.
|
||||
* @param player The player.
|
||||
* @param additionalPlayers The additional players.
|
||||
*/
|
||||
public MathContext(@NotNull PlaceholderInjectable injectableContext,
|
||||
@Nullable Player player,
|
||||
@NotNull Collection<AdditionalPlayer> additionalPlayers) {
|
||||
this.injectableContext = injectableContext;
|
||||
this.player = player;
|
||||
this.additionalPlayers = additionalPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PlaceholderInjectable parse context.
|
||||
* <p>
|
||||
* Duplicate method because MathContext used to be a record.
|
||||
*
|
||||
* @return The injectable context.
|
||||
* @deprecated Use {@link #getInjectableContext()} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
public PlaceholderInjectable injectableContext() {
|
||||
return injectableContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PlaceholderInjectable parse context.
|
||||
*
|
||||
* @return The injectable context.
|
||||
*/
|
||||
@NotNull
|
||||
public PlaceholderInjectable getInjectableContext() {
|
||||
return injectableContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player.
|
||||
* <p>
|
||||
* Duplicate method because MathContext used to be a record.
|
||||
*
|
||||
* @return The player.
|
||||
* @deprecated Use {@link #getPlayer()} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@Nullable
|
||||
public Player player() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player.
|
||||
*
|
||||
* @return The player.
|
||||
*/
|
||||
@Nullable
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the additional players.
|
||||
* <p>
|
||||
* Duplicate method because MathContext used to be a record.
|
||||
*
|
||||
* @return The additional players.
|
||||
* @deprecated Use {@link #getAdditionalPlayers()} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public Collection<AdditionalPlayer> additionalPlayers() {
|
||||
return additionalPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the additional players.
|
||||
*
|
||||
* @return The additional players.
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<AdditionalPlayer> getAdditionalPlayers() {
|
||||
return additionalPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to PlaceholderContext.
|
||||
*
|
||||
* @return The PlaceholderContext.
|
||||
*/
|
||||
@NotNull
|
||||
public PlaceholderContext toPlaceholderContext() {
|
||||
return new PlaceholderContext(
|
||||
this.player,
|
||||
null,
|
||||
this.injectableContext,
|
||||
this.additionalPlayers
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MathContext{" +
|
||||
"injectableContext=" + injectableContext +
|
||||
", player=" + player +
|
||||
", additionalPlayers=" + additionalPlayers +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof MathContext that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return injectableContext.equals(that.injectableContext) &&
|
||||
Objects.equals(player, that.player) &&
|
||||
additionalPlayers.equals(that.additionalPlayers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(injectableContext, player, additionalPlayers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create MathContext of a PlaceholderInjectable parseContext.
|
||||
*
|
||||
* @param injectableContext The PlaceholderInjectable parseContext.
|
||||
* @return The MathContext.
|
||||
*/
|
||||
public static MathContext of(@NotNull final PlaceholderInjectable injectableContext) {
|
||||
@@ -48,16 +194,16 @@ public record MathContext(
|
||||
/**
|
||||
* Copy a MathContext with a player.
|
||||
*
|
||||
* @param context The context.
|
||||
* @param context The parseContext.
|
||||
* @param player The player.
|
||||
* @return The new MathContext.
|
||||
*/
|
||||
public static MathContext copyWithPlayer(@NotNull final MathContext context,
|
||||
@Nullable final Player player) {
|
||||
return new MathContext(
|
||||
context.injectableContext(),
|
||||
context.injectableContext,
|
||||
player,
|
||||
context.additionalPlayers()
|
||||
context.additionalPlayers
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -12,24 +12,24 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* A placeholder that does not require a player and supports dynamic styles.
|
||||
*/
|
||||
public final class DynamicPlaceholder implements Placeholder {
|
||||
public final class DynamicPlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
* The function to retrieve the output of the arguments.
|
||||
*/
|
||||
private final Function<String, String> function;
|
||||
private final Function<@NotNull String, @Nullable String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
* The plugin for the arguments.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new dynamic placeholder.
|
||||
* Create a new dynamic arguments.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param pattern The pattern.
|
||||
@@ -37,31 +37,33 @@ public final class DynamicPlaceholder implements Placeholder {
|
||||
*/
|
||||
public DynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final Pattern pattern,
|
||||
@NotNull final Function<String, String> function) {
|
||||
@NotNull final Function<@NotNull String, @Nullable String> function) {
|
||||
this.plugin = plugin;
|
||||
this.pattern = pattern;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @param args The args.
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
public String getValue(@NotNull final String args) {
|
||||
@Override
|
||||
@Nullable
|
||||
public String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return function.apply(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @return The placeholder.
|
||||
* @param args The args.
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
public DynamicPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue(@NotNull final String args) {
|
||||
return Objects.requireNonNullElse(
|
||||
function.apply(args),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,18 +71,17 @@ public final class DynamicPlaceholder implements Placeholder {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public @NotNull String getIdentifier() {
|
||||
return "dynamic";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Pattern getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicPlaceholder register() {
|
||||
return (DynamicPlaceholder) RegistrablePlaceholder.super.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
@@ -97,6 +98,6 @@ public final class DynamicPlaceholder implements Placeholder {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
return Objects.hash(this.getPattern(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Placeholders that can be injected into {@link PlaceholderInjectable} objects.
|
||||
*/
|
||||
public sealed interface InjectablePlaceholder extends Placeholder permits PlayerStaticPlaceholder, StaticPlaceholder {
|
||||
public interface InjectablePlaceholder extends Placeholder {
|
||||
/**
|
||||
* Get the plugin that holds the arguments.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
default @NotNull EcoPlugin getPlugin() {
|
||||
return Eco.get().getEcoPlugin();
|
||||
default EcoPlugin getPlugin() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,64 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A placeholder represents a string that can hold a value.
|
||||
*/
|
||||
public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder,
|
||||
DynamicPlaceholder, PlayerDynamicPlaceholder, InjectablePlaceholder {
|
||||
public interface Placeholder {
|
||||
/**
|
||||
* Get the plugin that holds the placeholder.
|
||||
* Get the plugin that holds the arguments.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
@NotNull
|
||||
@Nullable
|
||||
EcoPlugin getPlugin();
|
||||
|
||||
/**
|
||||
* Get the identifier for the placeholder.
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @return The identifier.
|
||||
* @param args The args.
|
||||
* @param context The context.
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
String getIdentifier();
|
||||
@Nullable
|
||||
String getValue(@NotNull String args,
|
||||
@NotNull PlaceholderContext context);
|
||||
|
||||
/**
|
||||
* Get the pattern for the placeholder.
|
||||
* Get the pattern for the arguments.
|
||||
*
|
||||
* @return The pattern.
|
||||
*/
|
||||
@NotNull
|
||||
default Pattern getPattern() {
|
||||
return Pattern.compile(this.getIdentifier());
|
||||
Pattern getPattern();
|
||||
|
||||
/**
|
||||
* Try to translate all instances of this placeholder in text quickly.
|
||||
*
|
||||
* @param text The text to translate.
|
||||
* @param context The context.
|
||||
* @return The translated text.
|
||||
*/
|
||||
default String tryTranslateQuickly(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identifier for the arguments.
|
||||
*
|
||||
* @return The identifier.
|
||||
* @deprecated Some arguments may not have an identifier. Use {@link #getPattern()} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
default String getIdentifier() {
|
||||
return this.getPattern().pattern();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.List;
|
||||
*/
|
||||
public interface PlaceholderInjectable {
|
||||
/**
|
||||
* Inject placeholder.
|
||||
* Inject arguments.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ public interface PlaceholderInjectable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject placeholder.
|
||||
* Inject arguments.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
@@ -29,7 +29,7 @@ public interface PlaceholderInjectable {
|
||||
/**
|
||||
* Inject placeholders.
|
||||
* <p>
|
||||
* When implementing a PlaceholderInjectable object, override this method.
|
||||
* If a placeholder already has the same pattern, it should be replaced.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
@@ -43,7 +43,7 @@ public interface PlaceholderInjectable {
|
||||
/**
|
||||
* Get injected placeholders.
|
||||
* <p>
|
||||
* Override this method in implementations.
|
||||
* This method should always return an immutable list.
|
||||
*
|
||||
* @return Injected placeholders.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -11,26 +11,26 @@ import java.util.function.BiFunction;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A placeholder that does not require a player and supports dynamic styles.
|
||||
* A arguments that does not require a player and supports dynamic styles.
|
||||
*/
|
||||
public final class PlayerDynamicPlaceholder implements Placeholder {
|
||||
public final class PlayerDynamicPlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
* The function to retrieve the output of the arguments.
|
||||
*/
|
||||
private final BiFunction<String, Player, String> function;
|
||||
private final BiFunction<@NotNull String, @NotNull Player, @Nullable String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
* The plugin for the arguments.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new dynamic placeholder.
|
||||
* Create a new dynamic arguments.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param pattern The pattern.
|
||||
@@ -38,33 +38,40 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
||||
*/
|
||||
public PlayerDynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final Pattern pattern,
|
||||
@NotNull final BiFunction<String, Player, String> function) {
|
||||
@NotNull final BiFunction<@NotNull String, @NotNull Player, @Nullable String> function) {
|
||||
this.plugin = plugin;
|
||||
this.pattern = pattern;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @param args The args.
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
public String getValue(@NotNull final String args,
|
||||
@NotNull final Player player) {
|
||||
@Override
|
||||
public @Nullable String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
Player player = context.getPlayer();
|
||||
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return function.apply(args, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @return The placeholder.
|
||||
* @param args The args.
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
public PlayerDynamicPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue(@NotNull final String args,
|
||||
@NotNull final Player player) {
|
||||
return Objects.requireNonNullElse(
|
||||
function.apply(args, player),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,18 +79,17 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public @NotNull String getIdentifier() {
|
||||
return "dynamic";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Pattern getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerDynamicPlaceholder register() {
|
||||
return (PlayerDynamicPlaceholder) RegistrablePlaceholder.super.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
@@ -100,6 +106,6 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
return Objects.hash(this.getPattern(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -11,31 +11,26 @@ import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A placeholder that requires a player.
|
||||
* A arguments that requires a player.
|
||||
*/
|
||||
public final class PlayerPlaceholder implements Placeholder {
|
||||
public final class PlayerPlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder given a player.
|
||||
* The function to retrieve the output of the arguments given a player.
|
||||
*/
|
||||
private final Function<Player, String> function;
|
||||
private final Function<@NotNull Player, @Nullable String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
* The plugin for the arguments.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
* Create a new player arguments.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
@@ -43,32 +38,38 @@ public final class PlayerPlaceholder implements Placeholder {
|
||||
*/
|
||||
public PlayerPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
@NotNull final Function<@NotNull Player, @Nullable String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.pattern = Pattern.compile(identifier);
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder for a given player.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
public String getValue(@NotNull final Player player) {
|
||||
@Override
|
||||
public @Nullable String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
Player player = context.getPlayer();
|
||||
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return function.apply(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
* Get the value of the arguments for a given player.
|
||||
*
|
||||
* @return The placeholder.
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
public PlayerPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue(@NotNull final Player player) {
|
||||
return Objects.requireNonNullElse(
|
||||
function.apply(player),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,17 +77,17 @@ public final class PlayerPlaceholder implements Placeholder {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Pattern getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerPlaceholder register() {
|
||||
return (PlayerPlaceholder) RegistrablePlaceholder.super.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
@@ -95,12 +96,12 @@ public final class PlayerPlaceholder implements Placeholder {
|
||||
if (!(o instanceof PlayerPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
||||
return Objects.equals(this.getPattern(), that.getPattern())
|
||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
return Objects.hash(this.getPattern(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -13,47 +15,72 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public final class PlayerStaticPlaceholder implements InjectablePlaceholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
* The identifier.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
* The function to retrieve the output of the arguments.
|
||||
*/
|
||||
private final Function<Player, String> function;
|
||||
private final Function<@NotNull Player, @Nullable String> function;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
* Create a new player arguments.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public PlayerStaticPlaceholder(@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
this.identifier = identifier;
|
||||
this.pattern = Pattern.compile(identifier);
|
||||
@NotNull final Function<@NotNull Player, @Nullable String> function) {
|
||||
this.identifier = "%" + identifier + "%";
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
Player player = context.getPlayer();
|
||||
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.getValue(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue(@NotNull final Player player) {
|
||||
return function.apply(player);
|
||||
return Objects.requireNonNullElse(
|
||||
function.apply(player),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return this.identifier;
|
||||
public String tryTranslateQuickly(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return StringUtils.replaceQuickly(
|
||||
text,
|
||||
this.identifier,
|
||||
Objects.requireNonNullElse(
|
||||
this.getValue(identifier, context),
|
||||
""
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -70,11 +97,11 @@ public final class PlayerStaticPlaceholder implements InjectablePlaceholder {
|
||||
if (!(o instanceof PlayerStaticPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier());
|
||||
return Objects.equals(this.getPattern(), that.getPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier());
|
||||
return Objects.hash(this.getPattern());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -10,31 +10,26 @@ import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A placeholder that does not require a player.
|
||||
* A arguments that does not require a player.
|
||||
*/
|
||||
public final class PlayerlessPlaceholder implements Placeholder {
|
||||
public final class PlayerlessPlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The placeholder identifier.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
* The function to retrieve the output of the arguments.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
private final Supplier<@Nullable String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
* The plugin for the arguments.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
* Create a new player arguments.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
@@ -42,30 +37,31 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
||||
*/
|
||||
public PlayerlessPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Supplier<String> function) {
|
||||
@NotNull final Supplier<@Nullable String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.pattern = Pattern.compile(identifier);
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue() {
|
||||
@Override
|
||||
public @Nullable String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @return The placeholder.
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
public PlayerlessPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue() {
|
||||
return Objects.requireNonNullElse(
|
||||
this.function.get(),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,17 +69,17 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Pattern getPattern() {
|
||||
return this.pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerlessPlaceholder register() {
|
||||
return (PlayerlessPlaceholder) RegistrablePlaceholder.super.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
@@ -92,12 +88,12 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
||||
if (!(o instanceof PlayerlessPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
||||
return Objects.equals(this.getPattern(), that.getPattern())
|
||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
return Objects.hash(this.getPattern(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents a placeholder that can be registered.
|
||||
*/
|
||||
public interface RegistrablePlaceholder extends Placeholder {
|
||||
/**
|
||||
* Get the plugin that holds the arguments.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
EcoPlugin getPlugin();
|
||||
|
||||
/**
|
||||
* Register the arguments.
|
||||
*
|
||||
* @return The arguments.
|
||||
*/
|
||||
@NotNull
|
||||
default RegistrablePlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -8,50 +10,66 @@ import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A placeholder that cannot be registered, and exists purely in injection.
|
||||
* A arguments that cannot be registered, and exists purely in injection.
|
||||
*/
|
||||
public final class StaticPlaceholder implements InjectablePlaceholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
* The name of the arguments.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
* The arguments pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
* The function to retrieve the output of the arguments.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
private final Supplier<@Nullable String> function;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
* Create a new player arguments.
|
||||
*
|
||||
* @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.pattern = Pattern.compile(identifier);
|
||||
@NotNull final Supplier<@Nullable String> function) {
|
||||
this.identifier = "%" + identifier + "%";
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
public String getValue() {
|
||||
@Override
|
||||
public @Nullable String getValue(@NotNull final String args,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the arguments.
|
||||
*
|
||||
* @return The value.
|
||||
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@NotNull
|
||||
public String getValue() {
|
||||
return Objects.requireNonNullElse(
|
||||
function.get(),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return this.identifier;
|
||||
public String tryTranslateQuickly(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return StringUtils.replaceQuickly(
|
||||
text,
|
||||
this.identifier,
|
||||
Objects.requireNonNullElse(this.getValue(this.identifier, context), "")
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -68,11 +86,11 @@ public final class StaticPlaceholder implements InjectablePlaceholder {
|
||||
if (!(o instanceof StaticPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier());
|
||||
return Objects.equals(this.getPattern(), that.getPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier());
|
||||
return Objects.hash(this.getPattern());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.willfp.eco.core.placeholder.context;
|
||||
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A merged injectable context.
|
||||
*/
|
||||
public class MergedInjectableContext implements PlaceholderInjectable {
|
||||
/**
|
||||
* The base context.
|
||||
*/
|
||||
private final PlaceholderInjectable baseContext;
|
||||
|
||||
/**
|
||||
* The additional context.
|
||||
*/
|
||||
private final PlaceholderInjectable additionalContext;
|
||||
|
||||
/**
|
||||
* Extra injections.
|
||||
*/
|
||||
private final Set<InjectablePlaceholder> extraInjections = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Create a new merged injectable context.
|
||||
*
|
||||
* @param baseContext The base context.
|
||||
* @param additionalContext The additional context.
|
||||
*/
|
||||
public MergedInjectableContext(@NotNull final PlaceholderInjectable baseContext,
|
||||
@NotNull final PlaceholderInjectable additionalContext) {
|
||||
this.baseContext = baseContext;
|
||||
this.additionalContext = additionalContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInjectablePlaceholder(@NotNull final Iterable<InjectablePlaceholder> placeholders) {
|
||||
for (InjectablePlaceholder placeholder : placeholders) {
|
||||
extraInjections.add(placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearInjectedPlaceholders() {
|
||||
baseContext.clearInjectedPlaceholders();
|
||||
additionalContext.clearInjectedPlaceholders();
|
||||
extraInjections.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<InjectablePlaceholder> getPlaceholderInjections() {
|
||||
List<InjectablePlaceholder> base = baseContext.getPlaceholderInjections();
|
||||
List<InjectablePlaceholder> additional = additionalContext.getPlaceholderInjections();
|
||||
|
||||
List<InjectablePlaceholder> injections = new ArrayList<>(base.size() + additional.size() + extraInjections.size());
|
||||
|
||||
injections.addAll(base);
|
||||
injections.addAll(additional);
|
||||
injections.addAll(extraInjections);
|
||||
|
||||
return injections;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
package com.willfp.eco.core.placeholder.context;
|
||||
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents a context to translate placeholders in.
|
||||
*/
|
||||
public class PlaceholderContext {
|
||||
/**
|
||||
* An empty injectable.
|
||||
*/
|
||||
private static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
||||
@Override
|
||||
public void addInjectablePlaceholder(@NotNull final Iterable<InjectablePlaceholder> placeholders) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearInjectedPlaceholders() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<InjectablePlaceholder> getPlaceholderInjections() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An empty context.
|
||||
*/
|
||||
public static final PlaceholderContext EMPTY = new PlaceholderContext(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
@Nullable
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The ItemStack.
|
||||
*/
|
||||
@Nullable
|
||||
private final ItemStack itemStack;
|
||||
|
||||
/**
|
||||
* The PlaceholderInjectable context.
|
||||
*/
|
||||
@NotNull
|
||||
private final PlaceholderInjectable injectableContext;
|
||||
|
||||
/**
|
||||
* The additional players.
|
||||
*/
|
||||
@NotNull
|
||||
private final Collection<AdditionalPlayer> additionalPlayers;
|
||||
|
||||
/**
|
||||
* Create an empty PlaceholderContext.
|
||||
*/
|
||||
public PlaceholderContext() {
|
||||
this(null, null, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PlaceholderContext for a player.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public PlaceholderContext(@Nullable final Player player) {
|
||||
this(player, null, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new PlaceholderContext with the given parameters.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param itemStack The ItemStack.
|
||||
* @param injectableContext The PlaceholderInjectable parseContext.
|
||||
* @param additionalPlayers The additional players.
|
||||
*/
|
||||
public PlaceholderContext(@Nullable final Player player,
|
||||
@Nullable final ItemStack itemStack,
|
||||
@Nullable final PlaceholderInjectable injectableContext,
|
||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||
this.player = player;
|
||||
this.itemStack = itemStack;
|
||||
this.injectableContext = Objects.requireNonNullElse(injectableContext, EMPTY_INJECTABLE);
|
||||
this.additionalPlayers = additionalPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player.
|
||||
*
|
||||
* @return The player.
|
||||
*/
|
||||
@Nullable
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ItemStack.
|
||||
*
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
@Nullable
|
||||
public ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlaceholderInjectable context.
|
||||
*
|
||||
* @return The PlaceholderInjectable context.
|
||||
*/
|
||||
@NotNull
|
||||
public PlaceholderInjectable getInjectableContext() {
|
||||
return injectableContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional players.
|
||||
*
|
||||
* @return The additional players.
|
||||
*/
|
||||
@NotNull
|
||||
public Collection<AdditionalPlayer> getAdditionalPlayers() {
|
||||
return additionalPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to a {@link com.willfp.eco.core.math.MathContext}.
|
||||
*
|
||||
* @return The math context.
|
||||
* @deprecated MathContext is deprecated, use {@link PlaceholderContext} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings({"removal", "DeprecatedIsStillUsed"})
|
||||
public com.willfp.eco.core.math.MathContext toMathContext() {
|
||||
return new com.willfp.eco.core.math.MathContext(this.getInjectableContext(), this.getPlayer(), this.getAdditionalPlayers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy with a player.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The new context.
|
||||
*/
|
||||
public PlaceholderContext copyWithPlayer(@Nullable final Player player) {
|
||||
return new PlaceholderContext(
|
||||
player,
|
||||
this.getItemStack(),
|
||||
this.getInjectableContext(),
|
||||
this.getAdditionalPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy with an item.
|
||||
*
|
||||
* @param itemStack The ItemStack.
|
||||
* @return The new context.
|
||||
*/
|
||||
public PlaceholderContext copyWithItem(@Nullable final ItemStack itemStack) {
|
||||
return new PlaceholderContext(
|
||||
this.getPlayer(),
|
||||
itemStack,
|
||||
this.getInjectableContext(),
|
||||
this.getAdditionalPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy with an extra injectable context.
|
||||
*
|
||||
* @param injectableContext The injectable context to add.
|
||||
* @return The new context.
|
||||
*/
|
||||
public PlaceholderContext withInjectableContext(@NotNull final PlaceholderInjectable injectableContext) {
|
||||
return new PlaceholderContext(
|
||||
this.getPlayer(),
|
||||
this.getItemStack(),
|
||||
new MergedInjectableContext(this.getInjectableContext(), injectableContext),
|
||||
this.getAdditionalPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlaceholderContext{" +
|
||||
"player=" + player +
|
||||
", itemStack=" + itemStack +
|
||||
", injectableContext=" + injectableContext +
|
||||
", additionalPlayers=" + additionalPlayers +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof PlaceholderContext that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(
|
||||
getPlayer(), that.getPlayer())
|
||||
&& Objects.equals(getItemStack(), that.getItemStack())
|
||||
&& getInjectableContext().equals(that.getInjectableContext())
|
||||
&& getAdditionalPlayers().equals(that.getAdditionalPlayers()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getPlayer(), getItemStack(), getInjectableContext(), getAdditionalPlayers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create PlaceholderContext of a PlaceholderInjectable parseContext.
|
||||
*
|
||||
* @param injectableContext The PlaceholderInjectable parseContext.
|
||||
* @return The context.
|
||||
*/
|
||||
public static PlaceholderContext of(@NotNull final PlaceholderInjectable injectableContext) {
|
||||
return new PlaceholderContext(
|
||||
null,
|
||||
null,
|
||||
injectableContext,
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.eco.core.placeholder.context;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A supplier that takes a {@link PlaceholderContext} and returns a value.
|
||||
*
|
||||
* @param <T> The type of value to return.
|
||||
*/
|
||||
public interface PlaceholderContextSupplier<T> {
|
||||
/**
|
||||
* Get the value.
|
||||
*
|
||||
* @param context The context.
|
||||
* @return The value.
|
||||
*/
|
||||
@NotNull
|
||||
T get(@NotNull PlaceholderContext context);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.willfp.eco.core.placeholder.templates;
|
||||
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A template class for dynamic placeholders.
|
||||
*/
|
||||
public abstract class DynamicInjectablePlaceholder implements InjectablePlaceholder {
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* Create a new dynamic injectable placeholder.
|
||||
*
|
||||
* @param pattern The pattern.
|
||||
*/
|
||||
protected DynamicInjectablePlaceholder(@NotNull final Pattern pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DynamicInjectablePlaceholder{" +
|
||||
"pattern='" + pattern + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@NotNull final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof DynamicInjectablePlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(pattern, that.getPattern());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pattern);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.willfp.eco.core.placeholder.templates;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.RegistrablePlaceholder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A template class for dynamic placeholders.
|
||||
*/
|
||||
public abstract class DynamicPlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The plugin.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* Create a new dynamic placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param pattern The pattern.
|
||||
*/
|
||||
protected DynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final Pattern pattern) {
|
||||
this.plugin = plugin;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DynamicPlaceholder{" +
|
||||
"plugin='" + plugin + '\'' +
|
||||
"pattern='" + pattern + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@NotNull final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof DynamicPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(pattern, that.getPattern())
|
||||
&& Objects.equals(plugin, that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pattern, plugin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.willfp.eco.core.placeholder.templates;
|
||||
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A template class for simple placeholders.
|
||||
*/
|
||||
public abstract class SimpleInjectablePlaceholder implements InjectablePlaceholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* Create a new simple injectable placeholder.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
*/
|
||||
protected SimpleInjectablePlaceholder(@NotNull final String identifier) {
|
||||
this.identifier = identifier;
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tryTranslateQuickly(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return text.replace(
|
||||
"%" + this.identifier + "%",
|
||||
Objects.requireNonNullElse(this.getValue(this.identifier, context), "")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleInjectablePlaceholder{" +
|
||||
"identifier='" + identifier + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@NotNull final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof SimpleInjectablePlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(identifier, that.identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(identifier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.willfp.eco.core.placeholder.templates;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.RegistrablePlaceholder;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A template class for simple placeholders.
|
||||
*/
|
||||
public abstract class SimplePlaceholder implements RegistrablePlaceholder {
|
||||
/**
|
||||
* The plugin.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The placeholder pattern.
|
||||
*/
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* Create a new simple placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
*/
|
||||
protected SimplePlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tryTranslateQuickly(@NotNull final String text,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return text.replace(
|
||||
"%" + this.identifier + "%",
|
||||
Objects.requireNonNullElse(this.getValue(this.identifier, context), "")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimplePlaceholder{" +
|
||||
"plugin='" + plugin + '\'' +
|
||||
"identifier='" + identifier + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@NotNull final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(o instanceof SimplePlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(pattern, that.getPattern())
|
||||
&& Objects.equals(plugin, that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(identifier, plugin);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.price;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.price.impl.PriceFree;
|
||||
import com.willfp.eco.core.serialization.ConfigDeserializer;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
@@ -168,7 +168,7 @@ public final class ConfiguredPrice implements Price {
|
||||
Price price = Prices.create(
|
||||
config.getString("value"),
|
||||
config.getString("type"),
|
||||
MathContext.of(config)
|
||||
PlaceholderContext.of(config)
|
||||
);
|
||||
|
||||
return new ConfiguredPrice(price, formatString);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.core.price;
|
||||
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -10,7 +11,8 @@ import java.util.function.Function;
|
||||
/**
|
||||
* Create prices.
|
||||
* <p>
|
||||
* You must override one of the create methods.
|
||||
* Override create(PlaceholderContext, PlaceholderContextSupplier), other methods
|
||||
* are for backwards compatibility.
|
||||
*/
|
||||
public interface PriceFactory {
|
||||
/**
|
||||
@@ -27,20 +29,38 @@ public interface PriceFactory {
|
||||
*
|
||||
* @param value The value.
|
||||
* @return The price.
|
||||
* @deprecated Use {@link #create(PlaceholderContext, PlaceholderContextSupplier)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
default @NotNull Price create(final double value) {
|
||||
return create(MathContext.EMPTY, (ctx) -> value);
|
||||
return create(PlaceholderContext.EMPTY, (ctx) -> value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the price.
|
||||
*
|
||||
* @param baseContext The base MathContext.
|
||||
* @param function The function to use. Should use {@link MathContext#copyWithPlayer(MathContext, Player)} on calls.
|
||||
* @param function The function to use. Should use {@link com.willfp.eco.core.math.MathContext#copyWithPlayer(com.willfp.eco.core.math.MathContext, Player)} on calls.
|
||||
* @return The price.
|
||||
* @deprecated Use {@link #create(PlaceholderContext, PlaceholderContextSupplier)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
default @NotNull Price create(@NotNull final com.willfp.eco.core.math.MathContext baseContext,
|
||||
@NotNull final Function<com.willfp.eco.core.math.MathContext, Double> function) {
|
||||
return create(baseContext.toPlaceholderContext(), (PlaceholderContext ctx) -> function.apply(ctx.toMathContext()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the price.
|
||||
*
|
||||
* @param baseContext The base PlaceholderContext.
|
||||
* @param function The function to use. Should use {@link PlaceholderContext#copyWithPlayer(Player)} on calls.
|
||||
* @return The price.
|
||||
*/
|
||||
default @NotNull Price create(@NotNull final MathContext baseContext,
|
||||
@NotNull final Function<MathContext, Double> function) {
|
||||
return create(function.apply(baseContext));
|
||||
@SuppressWarnings("removal")
|
||||
default @NotNull Price create(@NotNull final PlaceholderContext baseContext,
|
||||
@NotNull final PlaceholderContextSupplier<Double> function) {
|
||||
return create(baseContext.toMathContext(), (com.willfp.eco.core.math.MathContext ctx) -> function.get(ctx.toPlaceholderContext()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ package com.willfp.eco.core.price;
|
||||
|
||||
import com.willfp.eco.core.items.Items;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier;
|
||||
import com.willfp.eco.core.price.impl.PriceEconomy;
|
||||
import com.willfp.eco.core.price.impl.PriceFree;
|
||||
import com.willfp.eco.core.price.impl.PriceItem;
|
||||
@@ -13,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Class to manage prices.
|
||||
@@ -48,7 +48,28 @@ public final class Prices {
|
||||
@NotNull
|
||||
public static Price create(@NotNull final String expression,
|
||||
@Nullable final String priceName) {
|
||||
return create(expression, priceName, MathContext.EMPTY);
|
||||
return create(expression, priceName, PlaceholderContext.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create price from an expression (representing the value),
|
||||
* and a price name. Uses a context to parse the expression.
|
||||
* <p>
|
||||
* Supports items as price names.
|
||||
*
|
||||
* @param expression The expression for the value.
|
||||
* @param priceName The price name.
|
||||
* @param context The math context to parse the expression.
|
||||
* @return The price, or free if invalid.
|
||||
* @deprecated Use {@link #create(String, String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public static Price create(@NotNull final String expression,
|
||||
@Nullable final String priceName,
|
||||
@NotNull final com.willfp.eco.core.math.MathContext context) {
|
||||
return create(expression, priceName, context.toPlaceholderContext());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +86,8 @@ public final class Prices {
|
||||
@NotNull
|
||||
public static Price create(@NotNull final String expression,
|
||||
@Nullable final String priceName,
|
||||
@NotNull final MathContext context) {
|
||||
Function<MathContext, Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
||||
@NotNull final PlaceholderContext context) {
|
||||
PlaceholderContextSupplier<Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
||||
expression,
|
||||
ctx
|
||||
);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.willfp.eco.core.price.impl;
|
||||
|
||||
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier;
|
||||
import com.willfp.eco.core.price.Price;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -18,12 +19,12 @@ public final class PriceEconomy implements Price {
|
||||
/**
|
||||
* The value of the price.
|
||||
*/
|
||||
private final Function<MathContext, Double> function;
|
||||
private final PlaceholderContextSupplier<Double> function;
|
||||
|
||||
/**
|
||||
* The base math context.
|
||||
* The base placeholder context.
|
||||
*/
|
||||
private final MathContext baseContext;
|
||||
private final PlaceholderContext baseContext;
|
||||
|
||||
/**
|
||||
* The multipliers.
|
||||
@@ -36,7 +37,21 @@ public final class PriceEconomy implements Price {
|
||||
* @param value The value.
|
||||
*/
|
||||
public PriceEconomy(final double value) {
|
||||
this(MathContext.EMPTY, ctx -> value);
|
||||
this(PlaceholderContext.EMPTY, (PlaceholderContext ctx) -> value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new economy-based price.
|
||||
*
|
||||
* @param baseContext The base context.
|
||||
* @param function The function.
|
||||
* @deprecated Use {@link #PriceEconomy(PlaceholderContext, PlaceholderContextSupplier)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public PriceEconomy(@NotNull final com.willfp.eco.core.math.MathContext baseContext,
|
||||
@NotNull final Function<com.willfp.eco.core.math.MathContext, Double> function) {
|
||||
this(baseContext.toPlaceholderContext(), (PlaceholderContext ctx) -> function.apply(ctx.toMathContext()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +60,8 @@ public final class PriceEconomy implements Price {
|
||||
* @param baseContext The base context.
|
||||
* @param function The function.
|
||||
*/
|
||||
public PriceEconomy(@NotNull final MathContext baseContext,
|
||||
@NotNull final Function<MathContext, Double> function) {
|
||||
public PriceEconomy(@NotNull final PlaceholderContext baseContext,
|
||||
@NotNull final PlaceholderContextSupplier<Double> function) {
|
||||
this.baseContext = baseContext;
|
||||
this.function = function;
|
||||
}
|
||||
@@ -72,7 +87,7 @@ public final class PriceEconomy implements Price {
|
||||
@Override
|
||||
public double getValue(@NotNull final Player player,
|
||||
final double multiplier) {
|
||||
return this.function.apply(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier;
|
||||
return this.function.get(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,8 @@ package com.willfp.eco.core.price.impl;
|
||||
import com.willfp.eco.core.drops.DropQueue;
|
||||
import com.willfp.eco.core.items.HashedItem;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier;
|
||||
import com.willfp.eco.core.price.Price;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -20,14 +21,14 @@ import java.util.function.Function;
|
||||
*/
|
||||
public final class PriceItem implements Price {
|
||||
/**
|
||||
* The base MathContext.
|
||||
* The base PlaceholderContext.
|
||||
*/
|
||||
private final MathContext baseContext;
|
||||
private final PlaceholderContext baseContext;
|
||||
|
||||
/**
|
||||
* The amount of items.
|
||||
*/
|
||||
private final Function<MathContext, Double> function;
|
||||
private final PlaceholderContextSupplier<Double> function;
|
||||
|
||||
/**
|
||||
* The item.
|
||||
@@ -47,7 +48,23 @@ public final class PriceItem implements Price {
|
||||
*/
|
||||
public PriceItem(final int amount,
|
||||
@NotNull final TestableItem item) {
|
||||
this(MathContext.EMPTY, ctx -> (double) amount, item);
|
||||
this(PlaceholderContext.EMPTY, (PlaceholderContext ctx) -> (double) amount, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new item-based price.
|
||||
*
|
||||
* @param baseContext The base MathContext.
|
||||
* @param function The function to get the amount of items to remove.
|
||||
* @param item The item.
|
||||
* @deprecated Use {@link #PriceItem(PlaceholderContext, PlaceholderContextSupplier, TestableItem)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public PriceItem(@NotNull final com.willfp.eco.core.math.MathContext baseContext,
|
||||
@NotNull final Function<com.willfp.eco.core.math.MathContext, Double> function,
|
||||
@NotNull final TestableItem item) {
|
||||
this(baseContext.toPlaceholderContext(), (PlaceholderContext ctx) -> function.apply(ctx.toMathContext()), item);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,8 +74,8 @@ public final class PriceItem implements Price {
|
||||
* @param function The function to get the amount of items to remove.
|
||||
* @param item The item.
|
||||
*/
|
||||
public PriceItem(@NotNull final MathContext baseContext,
|
||||
@NotNull final Function<MathContext, Double> function,
|
||||
public PriceItem(@NotNull final PlaceholderContext baseContext,
|
||||
@NotNull final PlaceholderContextSupplier<Double> function,
|
||||
@NotNull final TestableItem item) {
|
||||
this.baseContext = baseContext;
|
||||
this.function = function;
|
||||
@@ -137,7 +154,7 @@ public final class PriceItem implements Price {
|
||||
public double getValue(@NotNull final Player player,
|
||||
final double multiplier) {
|
||||
return Math.toIntExact(Math.round(
|
||||
this.function.apply(MathContext.copyWithPlayer(baseContext, player))
|
||||
this.function.get(baseContext.copyWithPlayer(player))
|
||||
* getMultiplier(player) * multiplier
|
||||
));
|
||||
}
|
||||
|
||||
@@ -8,42 +8,15 @@ import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for blocks.
|
||||
*/
|
||||
public final class BlockUtils {
|
||||
/**
|
||||
* Max blocks to mine (yes, this is to prevent a stack overflow).
|
||||
*/
|
||||
private static final int MAX_BLOCKS = 2500;
|
||||
|
||||
private static Set<Block> getNearbyBlocks(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
@NotNull final Set<Block> blocks,
|
||||
final int limit) {
|
||||
for (BlockFace face : BlockFace.values()) {
|
||||
Block block = start.getRelative(face);
|
||||
if (blocks.contains(block)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (allowedMaterials.contains(block.getType())) {
|
||||
blocks.add(block);
|
||||
|
||||
if (blocks.size() > limit || blocks.size() > MAX_BLOCKS) {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit));
|
||||
}
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of all blocks in contact with each other of a specific type.
|
||||
*
|
||||
@@ -56,7 +29,32 @@ public final class BlockUtils {
|
||||
public static Set<Block> getVein(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
final int limit) {
|
||||
return getNearbyBlocks(start, allowedMaterials, new HashSet<>(), limit);
|
||||
Set<Block> blocks = new HashSet<>();
|
||||
Queue<Block> toProcess = new LinkedList<>();
|
||||
|
||||
if (allowedMaterials.contains(start.getType())) {
|
||||
toProcess.add(start);
|
||||
}
|
||||
|
||||
while (!toProcess.isEmpty() && blocks.size() < limit) {
|
||||
Block currentBlock = toProcess.poll();
|
||||
|
||||
if (blocks.contains(currentBlock)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
blocks.add(currentBlock);
|
||||
|
||||
for (BlockFace face : BlockFace.values()) {
|
||||
Block adjacentBlock = currentBlock.getRelative(face);
|
||||
|
||||
if (!blocks.contains(adjacentBlock) && allowedMaterials.contains(adjacentBlock.getType())) {
|
||||
toProcess.add(adjacentBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.math.MathContext;
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -210,7 +209,7 @@ public final class NumberUtils {
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression) {
|
||||
return evaluateExpression(expression, MathContext.EMPTY);
|
||||
return evaluateExpression(expression, PlaceholderContext.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +221,7 @@ public final class NumberUtils {
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@Nullable final Player player) {
|
||||
return evaluateExpression(expression, player, PlaceholderManager.EMPTY_INJECTABLE);
|
||||
return evaluateExpression(expression, player, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,12 +229,12 @@ public final class NumberUtils {
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param context The injectable placeholders.
|
||||
* @param context The injectableContext 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) {
|
||||
@Nullable final PlaceholderInjectable context) {
|
||||
return evaluateExpression(expression, player, context, new ArrayList<>());
|
||||
}
|
||||
|
||||
@@ -244,30 +243,46 @@ public final class NumberUtils {
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param context The injectable placeholders.
|
||||
* @param context The injectableContext placeholders.
|
||||
* @param additionalPlayers Additional players to parse placeholders for.
|
||||
* @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,
|
||||
@Nullable final PlaceholderInjectable context,
|
||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||
return Eco.get().evaluate(expression, new MathContext(
|
||||
context,
|
||||
return Eco.get().evaluate(expression, new PlaceholderContext(
|
||||
player,
|
||||
null,
|
||||
context,
|
||||
additionalPlayers
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression with respect to a player (for placeholders).
|
||||
* Evaluate an expression in a context.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param context The math context.
|
||||
* @param context The context.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
* @deprecated Use {@link #evaluateExpression(String, PlaceholderContext)} instead.
|
||||
*/
|
||||
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@NotNull final com.willfp.eco.core.math.MathContext context) {
|
||||
return evaluateExpression(expression, context.toPlaceholderContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression in a context.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param context The context.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@NotNull final MathContext context) {
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return Eco.get().evaluate(expression, context);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
@@ -200,6 +201,26 @@ public final class StringUtils {
|
||||
return translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
* Coverts color codes and placeholders.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @param context The context.
|
||||
* @return The message, format.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> formatList(@NotNull final List<String> list,
|
||||
@NotNull PlaceholderContext context) {
|
||||
List<String> translated = new ArrayList<>();
|
||||
for (String string : list) {
|
||||
translated.add(format(string, context));
|
||||
}
|
||||
|
||||
return translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string.
|
||||
* <p>
|
||||
@@ -242,7 +263,7 @@ public final class StringUtils {
|
||||
@NotNull
|
||||
public static String format(@NotNull final String message,
|
||||
@NotNull final FormatOption option) {
|
||||
return format(message, null, option);
|
||||
return format(message, (Player) null, option);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +308,7 @@ public final class StringUtils {
|
||||
@NotNull
|
||||
public static Component formatToComponent(@NotNull final String message,
|
||||
@NotNull final FormatOption option) {
|
||||
return formatToComponent(message, null, option);
|
||||
return formatToComponent(message, (Player) null, option);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,10 +342,49 @@ public final class StringUtils {
|
||||
public static String format(@NotNull final String message,
|
||||
@Nullable final Player player,
|
||||
@NotNull final FormatOption option) {
|
||||
String processedMessage = message;
|
||||
if (option == FormatOption.WITH_PLACEHOLDERS) {
|
||||
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
|
||||
return format(
|
||||
message,
|
||||
new PlaceholderContext(player)
|
||||
);
|
||||
}
|
||||
|
||||
return STRING_FORMAT_CACHE.get(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string to a component.
|
||||
* <p>
|
||||
* Converts color codes and placeholders if specified.
|
||||
*
|
||||
* @param message The message to translate.
|
||||
* @param context The placeholder context.
|
||||
* @return The message, formatted, as a component.
|
||||
* @see StringUtils#format(String, Player)
|
||||
*/
|
||||
@NotNull
|
||||
public static Component formatToComponent(@NotNull final String message,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
return toComponent(format(message, context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string.
|
||||
* <p>
|
||||
* Coverts color codes and placeholders if specified.
|
||||
*
|
||||
* @param message The message to format.
|
||||
* @param context The context to translate placeholders with respect to.
|
||||
* @return The message, formatted.
|
||||
*/
|
||||
@NotNull
|
||||
public static String format(@NotNull final String message,
|
||||
@NotNull final PlaceholderContext context) {
|
||||
String processedMessage = message;
|
||||
processedMessage = PlaceholderManager.translatePlaceholders(
|
||||
processedMessage,
|
||||
context
|
||||
);
|
||||
return STRING_FORMAT_CACHE.get(processedMessage);
|
||||
}
|
||||
|
||||
@@ -674,6 +734,56 @@ public final class StringUtils {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast implementation of {@link String#replace(CharSequence, CharSequence)}
|
||||
*
|
||||
* @param input The input string.
|
||||
* @param target The target string.
|
||||
* @param replacement The replacement string.
|
||||
* @return The replaced string.
|
||||
*/
|
||||
@NotNull
|
||||
public static String replaceQuickly(@NotNull final String input,
|
||||
@NotNull final String target,
|
||||
@NotNull final String replacement) {
|
||||
int targetLength = target.length();
|
||||
|
||||
// Count the number of original occurrences
|
||||
int count = 0;
|
||||
for (
|
||||
int index = input.indexOf(target);
|
||||
index != -1;
|
||||
index = input.indexOf(target, index + targetLength)
|
||||
) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return input;
|
||||
}
|
||||
|
||||
int replacementLength = replacement.length();
|
||||
int inputLength = input.length();
|
||||
|
||||
// Pre-calculate the final size of the StringBuilder
|
||||
int newSize = inputLength + (replacementLength - targetLength) * count;
|
||||
StringBuilder result = new StringBuilder(newSize);
|
||||
|
||||
int start = 0;
|
||||
for (
|
||||
int index = input.indexOf(target);
|
||||
index != -1;
|
||||
index = input.indexOf(target, start)
|
||||
) {
|
||||
result.append(input, start, index);
|
||||
result.append(replacement);
|
||||
start = index + targetLength;
|
||||
}
|
||||
|
||||
result.append(input, start, inputLength);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for formatting.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
@file:JvmName("PlaceholderContextExtensions")
|
||||
|
||||
package com.willfp.eco.core.placeholder.context
|
||||
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
/** @see PlaceholderContext */
|
||||
@JvmOverloads
|
||||
fun placeholderContext(
|
||||
player: Player? = null,
|
||||
item: ItemStack? = null,
|
||||
injectable: PlaceholderInjectable? = null,
|
||||
additionalPlayers: Collection<AdditionalPlayer> = emptyList()
|
||||
): PlaceholderContext = PlaceholderContext(player, item, injectable, additionalPlayers)
|
||||
|
||||
/** @see PlaceholderContext */
|
||||
fun PlaceholderContext.copy(
|
||||
player: Player? = this.player,
|
||||
item: ItemStack? = this.itemStack,
|
||||
injectable: PlaceholderInjectable? = this.injectableContext,
|
||||
additionalPlayers: Collection<AdditionalPlayer> = this.additionalPlayers
|
||||
): PlaceholderContext = PlaceholderContext(player, item, injectable, additionalPlayers)
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.willfp.eco.util
|
||||
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import net.kyori.adventure.text.Component
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
@@ -31,6 +32,14 @@ fun String.formatEco(
|
||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
||||
)
|
||||
|
||||
/** @see StringUtils.format */
|
||||
fun String.formatEco(
|
||||
context: PlaceholderContext
|
||||
) = StringUtils.format(
|
||||
this,
|
||||
context
|
||||
)
|
||||
|
||||
/** @see StringUtils.formatList */
|
||||
fun List<String>.formatEco(
|
||||
player: Player? = null,
|
||||
@@ -41,6 +50,14 @@ fun List<String>.formatEco(
|
||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
||||
)
|
||||
|
||||
/** @see StringUtils.formatList */
|
||||
fun List<String>.formatEco(
|
||||
context: PlaceholderContext
|
||||
): List<String> = StringUtils.formatList(
|
||||
this,
|
||||
context
|
||||
)
|
||||
|
||||
/** @see StringUtils.splitAround */
|
||||
fun String.splitAround(separator: String): Array<String> =
|
||||
StringUtils.splitAround(this, separator)
|
||||
@@ -48,3 +65,7 @@ fun String.splitAround(separator: String): Array<String> =
|
||||
/** @see StringUtils.toNiceString */
|
||||
fun Any?.toNiceString(): String =
|
||||
StringUtils.toNiceString(this)
|
||||
|
||||
/** @see StringUtils.replaceQuickly */
|
||||
fun String.replaceQuickly(target: String, replacement: String): String =
|
||||
StringUtils.replaceQuickly(this, target, replacement)
|
||||
|
||||
@@ -3,10 +3,13 @@ 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.InjectablePlaceholder
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.internal.fast.listView
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoConfig(
|
||||
@@ -15,7 +18,7 @@ open class EcoConfig(
|
||||
private val values = ConcurrentHashMap<String, Any?>()
|
||||
|
||||
@Transient
|
||||
var injections = mutableListOf<InjectablePlaceholder>()
|
||||
var injections = ConcurrentHashMap<Pattern, InjectablePlaceholder>()
|
||||
|
||||
fun init(values: Map<String, Any?>) {
|
||||
this.values.clear()
|
||||
@@ -104,12 +107,12 @@ open class EcoConfig(
|
||||
}
|
||||
|
||||
override fun getSubsectionOrNull(path: String): Config? {
|
||||
return (get(path) as? Config)?.apply { this.addInjectablePlaceholder(injections) }
|
||||
return (get(path) as? Config)?.apply { this.addInjectablePlaceholder(injections.values) }
|
||||
}
|
||||
|
||||
override fun getSubsectionsOrNull(path: String): List<Config>? {
|
||||
return getList<Config>(path)
|
||||
?.map { it.apply { this.addInjectablePlaceholder(injections) } }
|
||||
?.map { it.apply { this.addInjectablePlaceholder(injections.values) } }
|
||||
?.toList()
|
||||
}
|
||||
|
||||
@@ -141,9 +144,7 @@ open class EcoConfig(
|
||||
var string = get(path)?.toString() ?: return null
|
||||
if (format && option == StringUtils.FormatOption.WITH_PLACEHOLDERS) {
|
||||
for (injection in placeholderInjections) {
|
||||
if (injection is StaticPlaceholder) {
|
||||
string = string.replace("%${injection.identifier}%", injection.value)
|
||||
}
|
||||
string = injection.tryTranslateQuickly(string, PlaceholderContext.EMPTY)
|
||||
}
|
||||
}
|
||||
return if (format) StringUtils.format(string, option) else string
|
||||
@@ -161,9 +162,7 @@ open class EcoConfig(
|
||||
strings.replaceAll {
|
||||
var string = it
|
||||
for (injection in placeholderInjections) {
|
||||
if (injection is StaticPlaceholder) {
|
||||
string = string.replace("%${injection.identifier}%", injection.value)
|
||||
}
|
||||
string = injection.tryTranslateQuickly(string, PlaceholderContext.EMPTY)
|
||||
}
|
||||
string
|
||||
}
|
||||
@@ -180,12 +179,13 @@ open class EcoConfig(
|
||||
}
|
||||
|
||||
override fun addInjectablePlaceholder(placeholders: Iterable<InjectablePlaceholder>) {
|
||||
injections.removeIf { placeholders.any { placeholder -> it.identifier == placeholder.identifier } }
|
||||
injections.addAll(placeholders)
|
||||
for (placeholder in placeholders) {
|
||||
injections[placeholder.pattern] = placeholder
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPlaceholderInjections(): List<InjectablePlaceholder> {
|
||||
return injections.toList()
|
||||
return injections.values.listView() // Faster than .toList()
|
||||
}
|
||||
|
||||
override fun clearInjectedPlaceholders() {
|
||||
@@ -208,14 +208,6 @@ open class EcoConfig(
|
||||
return bukkit
|
||||
}
|
||||
|
||||
override fun clone(): Config {
|
||||
return EcoConfigSection(type, this.values.toMutableMap(), injections)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return this.toPlaintext()
|
||||
}
|
||||
|
||||
private inline fun <reified T> getList(path: String): List<T>? {
|
||||
val asIterable = get(path) as? Iterable<*> ?: return null
|
||||
val asList = asIterable.toList()
|
||||
@@ -226,4 +218,40 @@ open class EcoConfig(
|
||||
|
||||
return asList as List<T>
|
||||
}
|
||||
|
||||
override fun clone(): Config {
|
||||
return EcoConfigSection(type, this.values.toMutableMap(), injections)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return this.toPlaintext()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (other !is EcoConfig) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (configType != other.configType) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (values != other.values) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (injections != other.injections) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Objects.hash(values, configType, injections)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,16 @@ package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class EcoConfigSection(
|
||||
type: ConfigType,
|
||||
values: Map<String, Any?> = emptyMap(),
|
||||
injections: Collection<InjectablePlaceholder> = emptyList()
|
||||
injections: Map<Pattern, InjectablePlaceholder> = emptyMap()
|
||||
) : EcoConfig(type) {
|
||||
init {
|
||||
this.init(values)
|
||||
this.injections = injections.toMutableList()
|
||||
this.injections = ConcurrentHashMap(injections)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.willfp.eco.internal.fast
|
||||
|
||||
class ListViewOfCollection<T>(private val collection: Collection<T>) : List<T> {
|
||||
/*
|
||||
The backing list is lazy-loaded because it provides a performance hit
|
||||
to copy the contents of the contents of the collection into a list.
|
||||
|
||||
Since the only required operator for most use-cases is .iterator(),
|
||||
we can just use the collection's iterator.
|
||||
*/
|
||||
|
||||
private val backingList: List<T> by lazy { collection.toList() }
|
||||
|
||||
override val size: Int
|
||||
get() = collection.size
|
||||
|
||||
override fun containsAll(elements: Collection<T>) =
|
||||
collection.containsAll(elements)
|
||||
|
||||
override fun get(index: Int): T =
|
||||
backingList[index]
|
||||
|
||||
override fun indexOf(element: T): Int = backingList.indexOf(element)
|
||||
|
||||
override fun contains(element: T): Boolean = collection.contains(element)
|
||||
|
||||
override fun isEmpty() =
|
||||
collection.isEmpty()
|
||||
|
||||
override fun iterator() =
|
||||
collection.iterator()
|
||||
|
||||
override fun listIterator() =
|
||||
backingList.listIterator()
|
||||
|
||||
override fun listIterator(index: Int) =
|
||||
backingList.listIterator(index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int) =
|
||||
backingList.subList(fromIndex, toIndex)
|
||||
|
||||
override fun lastIndexOf(element: T) =
|
||||
backingList.lastIndexOf(element)
|
||||
}
|
||||
|
||||
inline fun <reified T> Collection<T>.listView(): List<T> {
|
||||
return ListViewOfCollection(this)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.willfp.eco.internal.placeholder
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder
|
||||
import com.willfp.eco.core.placeholder.Placeholder
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class PlaceholderLookup(
|
||||
val args: String,
|
||||
val plugin: EcoPlugin?,
|
||||
private val injections: Collection<InjectablePlaceholder>?
|
||||
) {
|
||||
fun findMatchingPlaceholder(): Placeholder? {
|
||||
if (plugin != null) {
|
||||
val pluginPlaceholders = PlaceholderManager.getRegisteredPlaceholders(plugin)
|
||||
for (placeholder in pluginPlaceholders) {
|
||||
if (placeholder.matches(this)) {
|
||||
return placeholder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (injections != null) {
|
||||
for (placeholder in injections) {
|
||||
if (placeholder.matches(this)) {
|
||||
return placeholder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun Placeholder.matches(lookup: PlaceholderLookup): Boolean {
|
||||
val pattern = this.pattern
|
||||
val patternString = pattern.pattern()
|
||||
|
||||
val patternFlags = pattern.flags()
|
||||
val isLiteral = Pattern.LITERAL and patternFlags != 0
|
||||
|
||||
return if (isLiteral) lookup.args == patternString else pattern.matcher(lookup.args).matches()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.willfp.eco.internal.placeholder
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder
|
||||
import com.willfp.eco.core.placeholder.Placeholder
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/*
|
||||
|
||||
A lot of methods here are centered around minimising calls to getPlaceholderInjections,
|
||||
which tends to be slow for things like configs. This was optimised with ListViewOfCollection,
|
||||
but it's still best to minimise the memory overhead.
|
||||
|
||||
*/
|
||||
|
||||
class PlaceholderParser {
|
||||
private val placeholderRegex = Regex("%([^% ]+)%")
|
||||
|
||||
private val placeholderLookupCache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.SECONDS)
|
||||
.build<PlaceholderLookup, Optional<Placeholder>>()
|
||||
|
||||
fun translatePlacholders(text: String, context: PlaceholderContext): String {
|
||||
return translatePlacholders(text, context, context.injectableContext.placeholderInjections)
|
||||
}
|
||||
|
||||
private fun translatePlacholders(
|
||||
text: String,
|
||||
context: PlaceholderContext,
|
||||
injections: Collection<InjectablePlaceholder>,
|
||||
translateEcoPlaceholders: Boolean = true
|
||||
): String {
|
||||
/*
|
||||
|
||||
Why am I doing injections at the start, and again at the end?
|
||||
|
||||
Additional players let you use something like victim as a player to parse in relation to,
|
||||
for example doing %victim_player_health%, which would parse the health of the victim.
|
||||
|
||||
However, something like libreforge will also inject %victim_max_health%, which is unrelated
|
||||
to additional players, and instead holds a constant value. So, eco saw this, smartly thought
|
||||
"ah, it's an additional player, let's parse it", and then tried to parse %max_health% with
|
||||
relation to the victim, which resolved to zero. So, we have to parse statics and player statics
|
||||
that might include a prefix first, then additional players, then player statics with the support
|
||||
of additional players.
|
||||
|
||||
This was a massive headache and took so many reports before I clocked what was going on.
|
||||
|
||||
Oh well, at least it's fixed now.
|
||||
|
||||
*/
|
||||
|
||||
// Apply injections first
|
||||
var processed = injections.fold(text) { acc, injection ->
|
||||
injection.tryTranslateQuickly(acc, context)
|
||||
}
|
||||
|
||||
// Prevent running 2 scans if there are no additional players.
|
||||
if (context.additionalPlayers.isNotEmpty()) {
|
||||
val found = PlaceholderManager.findPlaceholdersIn(text)
|
||||
for (additionalPlayer in context.additionalPlayers) {
|
||||
val prefix = "%${additionalPlayer.identifier}_"
|
||||
processed = found.fold(processed) { acc, placeholder ->
|
||||
if (placeholder.startsWith(prefix)) {
|
||||
val newPlaceholder = "%${StringUtils.removePrefix(prefix, placeholder)}"
|
||||
val translation = translatePlacholders(
|
||||
newPlaceholder,
|
||||
context.copyWithPlayer(additionalPlayer.player),
|
||||
injections
|
||||
)
|
||||
acc.replace(placeholder, translation)
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Translate eco placeholders
|
||||
if (translateEcoPlaceholders) {
|
||||
processed = translateEcoPlaceholdersIn(processed, context, injections)
|
||||
}
|
||||
|
||||
// Apply registered integrations
|
||||
processed = PlaceholderManager.getRegisteredIntegrations().fold(processed) { acc, integration ->
|
||||
integration.translate(acc, context.player)
|
||||
}
|
||||
|
||||
// Apply injections again
|
||||
return injections.fold(processed) { acc, injection ->
|
||||
injection.tryTranslateQuickly(acc, context)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPlaceholderResult(
|
||||
plugin: EcoPlugin?,
|
||||
args: String,
|
||||
context: PlaceholderContext
|
||||
): String? {
|
||||
// Only scan for injections if plugin is null.
|
||||
val injections = if (plugin == null) context.injectableContext.placeholderInjections else null
|
||||
|
||||
return doGetResult(plugin, args, injections, context)
|
||||
}
|
||||
|
||||
// Injections are sent separately here to prevent multiple calls to getPlaceholderInjections
|
||||
private fun doGetResult(
|
||||
plugin: EcoPlugin?,
|
||||
args: String?,
|
||||
injections: Collection<InjectablePlaceholder>?,
|
||||
context: PlaceholderContext
|
||||
): String? {
|
||||
if (args == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val lookup = PlaceholderLookup(args, plugin, injections)
|
||||
|
||||
val placeholder = placeholderLookupCache.get(lookup) {
|
||||
Optional.ofNullable(it.findMatchingPlaceholder())
|
||||
}.orElse(null) ?: return null
|
||||
|
||||
return placeholder.getValue(args, context)
|
||||
}
|
||||
|
||||
private fun translateEcoPlaceholdersIn(
|
||||
text: String,
|
||||
context: PlaceholderContext,
|
||||
injections: Collection<InjectablePlaceholder>
|
||||
): String {
|
||||
val output = StringBuilder()
|
||||
var lastAppendPosition = 0
|
||||
|
||||
for (matchResult in placeholderRegex.findAll(text)) {
|
||||
val placeholder = matchResult.groups[1]?.value ?: ""
|
||||
|
||||
val injectableResult = doGetResult(null, placeholder, injections, context)
|
||||
|
||||
val parts = placeholder.split("_", limit = 2)
|
||||
|
||||
var result: String? = null
|
||||
|
||||
if (injectableResult != null) {
|
||||
result = injectableResult
|
||||
} else if (parts.size == 2) {
|
||||
val plugin = EcoPlugin.getPlugin(parts[0])
|
||||
|
||||
if (plugin != null) {
|
||||
result = doGetResult(plugin, parts[1], null, context)
|
||||
}
|
||||
}
|
||||
|
||||
output.append(text.substring(lastAppendPosition, matchResult.range.first))
|
||||
|
||||
output.append(result ?: matchResult.value)
|
||||
|
||||
lastAppendPosition = matchResult.range.last + 1
|
||||
}
|
||||
|
||||
output.append(text.substring(lastAppendPosition))
|
||||
return output.toString()
|
||||
}
|
||||
|
||||
fun parseIndividualPlaceholders(strings: Collection<String>, context: PlaceholderContext): Collection<String> {
|
||||
val injections = context.injectableContext.placeholderInjections
|
||||
|
||||
return strings.map {
|
||||
parseIndividualEcoPlaceholder(it, context, injections)
|
||||
?: translatePlacholders(
|
||||
it,
|
||||
context,
|
||||
injections,
|
||||
translateEcoPlaceholders = false
|
||||
) // Default to slower translation
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseIndividualEcoPlaceholder(
|
||||
string: String,
|
||||
context: PlaceholderContext,
|
||||
injections: Collection<InjectablePlaceholder>
|
||||
): String? {
|
||||
val placeholder = string.substring(1, string.length - 1)
|
||||
|
||||
val injectableResult = doGetResult(null, placeholder, injections, context)
|
||||
|
||||
if (injectableResult != null) {
|
||||
return injectableResult
|
||||
}
|
||||
|
||||
val parts = placeholder.split("_", limit = 2)
|
||||
|
||||
if (parts.size == 2) {
|
||||
val plugin = EcoPlugin.getPlugin(parts[0])
|
||||
|
||||
if (plugin != null) {
|
||||
return doGetResult(plugin, parts[1], null, context)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.willfp.eco.internal.price
|
||||
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||
import java.util.function.Function
|
||||
|
||||
object PriceFactoryEconomy : PriceFactory {
|
||||
override fun getNames() = listOf(
|
||||
@@ -12,7 +12,7 @@ object PriceFactoryEconomy : PriceFactory {
|
||||
"$"
|
||||
)
|
||||
|
||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PriceEconomy(baseContext, function)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.willfp.eco.internal.price
|
||||
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import java.util.function.Function
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object PriceFactoryXP : PriceFactory {
|
||||
@@ -15,13 +15,13 @@ object PriceFactoryXP : PriceFactory {
|
||||
"experience"
|
||||
)
|
||||
|
||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||
return PriceXP(baseContext) { function.apply(it).roundToInt() }
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PriceXP(baseContext) { function.get(it).roundToInt() }
|
||||
}
|
||||
|
||||
private class PriceXP(
|
||||
private val baseContext: MathContext,
|
||||
private val xp: (MathContext) -> Int
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val xp: (PlaceholderContext) -> Int
|
||||
) : Price {
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
|
||||
@@ -37,7 +37,7 @@ object PriceFactoryXP : PriceFactory {
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return xp(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier
|
||||
return xp(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.willfp.eco.internal.price
|
||||
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import java.util.function.Function
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object PriceFactoryXPLevels : PriceFactory {
|
||||
@@ -16,13 +16,13 @@ object PriceFactoryXPLevels : PriceFactory {
|
||||
"explevels",
|
||||
)
|
||||
|
||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||
return PriceXPLevel(baseContext) { function.apply(it).roundToInt() }
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PriceXPLevel(baseContext) { function.get(it).roundToInt() }
|
||||
}
|
||||
|
||||
private class PriceXPLevel(
|
||||
private val baseContext: MathContext,
|
||||
private val level: (MathContext) -> Int
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val level: (PlaceholderContext) -> Int
|
||||
) : Price {
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
|
||||
@@ -37,7 +37,7 @@ object PriceFactoryXPLevels : PriceFactory {
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return level(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier
|
||||
return level(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
|
||||
@@ -52,12 +52,16 @@ dependencies {
|
||||
compileOnly("com.github.N0RSKA:ScytherAPI:55a")
|
||||
compileOnly("com.ticxo.modelengine:api:R3.0.1")
|
||||
compileOnly("me.TechsCode:UltraEconomyAPI:1.0.0")
|
||||
compileOnly("org.black_ixx:playerpoints:3.2.5")
|
||||
compileOnly("com.github.Ssomar-Developement:SCore:3.4.7")
|
||||
compileOnly("io.lumine:Mythic:5.2.1")
|
||||
compileOnly("io.lumine:LumineUtils:1.19-SNAPSHOT")
|
||||
compileOnly("com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT")
|
||||
compileOnly("com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT")
|
||||
compileOnly("LibsDisguises:LibsDisguises:10.0.26")
|
||||
compileOnly("com.denizenscript:denizen:1.2.7-SNAPSHOT") {
|
||||
exclude(group = "*", module = "*")
|
||||
}
|
||||
|
||||
compileOnly(fileTree("../../lib") {
|
||||
include("*.jar")
|
||||
|
||||
@@ -13,8 +13,8 @@ import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.menu.MenuType
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.packet.Packet
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.internal.EcoPropsParser
|
||||
import com.willfp.eco.internal.command.EcoPluginCommand
|
||||
import com.willfp.eco.internal.command.EcoSubcommand
|
||||
@@ -37,6 +37,7 @@ import com.willfp.eco.internal.gui.menu.renderedInventory
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder
|
||||
import com.willfp.eco.internal.integrations.PAPIExpansion
|
||||
import com.willfp.eco.internal.logging.EcoLogger
|
||||
import com.willfp.eco.internal.placeholder.PlaceholderParser
|
||||
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||
import com.willfp.eco.internal.scheduling.EcoScheduler
|
||||
import com.willfp.eco.internal.spigot.data.DataYml
|
||||
@@ -44,7 +45,9 @@ import com.willfp.eco.internal.spigot.data.KeyRegistry
|
||||
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
||||
import com.willfp.eco.internal.spigot.math.evaluateExpression
|
||||
import com.willfp.eco.internal.spigot.math.DelegatedExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.math.ImmediatePlaceholderTranslationExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.math.LazyPlaceholderTranslationExpressionHandler
|
||||
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||
@@ -88,6 +91,15 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
||||
SafeInternalNamespacedKeyFactory() else FastInternalNamespacedKeyFactory()
|
||||
|
||||
private val placeholderParser = PlaceholderParser()
|
||||
|
||||
private val crunchHandler = DelegatedExpressionHandler(
|
||||
this,
|
||||
if (this.configYml.getBool("use-immediate-placeholder-translation-for-math"))
|
||||
ImmediatePlaceholderTranslationExpressionHandler(placeholderParser)
|
||||
else LazyPlaceholderTranslationExpressionHandler(placeholderParser),
|
||||
)
|
||||
|
||||
override fun createScheduler(plugin: EcoPlugin) =
|
||||
EcoScheduler(plugin)
|
||||
|
||||
@@ -312,8 +324,8 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
override fun getTPS() =
|
||||
getProxy(TPSProxy::class.java).getTPS()
|
||||
|
||||
override fun evaluate(expression: String, context: MathContext) =
|
||||
evaluateExpression(expression, context)
|
||||
override fun evaluate(expression: String, context: PlaceholderContext) =
|
||||
crunchHandler.evaluate(expression, context)
|
||||
|
||||
override fun getOpenMenu(player: Player) =
|
||||
player.renderedInventory?.menu
|
||||
@@ -326,4 +338,10 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||
|
||||
override fun sendPacket(player: Player, packet: Packet) =
|
||||
this.getProxy(PacketHandlerProxy::class.java).sendPacket(player, packet)
|
||||
|
||||
override fun translatePlaceholders(text: String, context: PlaceholderContext) =
|
||||
placeholderParser.translatePlacholders(text, context)
|
||||
|
||||
override fun getPlaceholderValue(plugin: EcoPlugin?, args: String, context: PlaceholderContext) =
|
||||
placeholderParser.getPlaceholderResult(plugin, args, context)
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny
|
||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefWorldGuard
|
||||
import com.willfp.eco.internal.spigot.integrations.customentities.CustomEntitiesMythicMobs
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsCustomCrafting
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsDenizen
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsExecutableItems
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsHeadDatabase
|
||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsItemsAdder
|
||||
@@ -110,6 +111,7 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicD
|
||||
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
|
||||
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
||||
import com.willfp.eco.internal.spigot.integrations.placeholder.PlaceholderIntegrationPAPI
|
||||
import com.willfp.eco.internal.spigot.integrations.price.PriceFactoryPlayerPoints
|
||||
import com.willfp.eco.internal.spigot.integrations.price.PriceFactoryUltraEconomy
|
||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
||||
@@ -323,6 +325,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
},
|
||||
IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) },
|
||||
IntegrationLoader("Scyther") { CustomItemsManager.register(CustomItemsScyther()) },
|
||||
IntegrationLoader("Denizen") { CustomItemsManager.register(CustomItemsDenizen()) },
|
||||
|
||||
// Shop
|
||||
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
|
||||
@@ -355,6 +358,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
Prices.registerPriceFactory(PriceFactoryUltraEconomy(currency))
|
||||
}
|
||||
},
|
||||
IntegrationLoader("PlayerPoints") { Prices.registerPriceFactory(PriceFactoryPlayerPoints()) },
|
||||
|
||||
// Placeholder
|
||||
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
||||
|
||||
@@ -16,9 +16,7 @@ abstract class EcoProfile(
|
||||
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
|
||||
this.data[key] = value
|
||||
|
||||
val changedKeys = CHANGE_MAP[uuid] ?: mutableSetOf()
|
||||
changedKeys.add(key)
|
||||
CHANGE_MAP[uuid] = changedKeys
|
||||
CHANGE_MAP.add(uuid)
|
||||
}
|
||||
|
||||
override fun <T : Any> read(key: PersistentDataKey<T>): T {
|
||||
@@ -44,7 +42,7 @@ abstract class EcoProfile(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CHANGE_MAP: MutableMap<UUID, MutableSet<PersistentDataKey<*>>> = ConcurrentHashMap()
|
||||
val CHANGE_MAP: MutableSet<UUID> = ConcurrentHashMap.newKeySet()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class ProfileHandler(
|
||||
private val type: HandlerType,
|
||||
private val plugin: EcoSpigotPlugin
|
||||
) {
|
||||
private val loaded = mutableMapOf<UUID, Profile>()
|
||||
private val loaded = mutableMapOf<UUID, EcoProfile>()
|
||||
|
||||
val handler: DataHandler = when (type) {
|
||||
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
||||
@@ -41,6 +41,9 @@ class ProfileHandler(
|
||||
}
|
||||
}
|
||||
|
||||
fun accessLoadedProfile(uuid: UUID): EcoProfile? =
|
||||
loaded[uuid]
|
||||
|
||||
fun loadGenericProfile(uuid: UUID): Profile {
|
||||
val found = loaded[uuid]
|
||||
if (found != null) {
|
||||
|
||||
@@ -12,10 +12,16 @@ class ProfileSaver(
|
||||
val interval = plugin.configYml.getInt("save-interval").toLong()
|
||||
|
||||
plugin.scheduler.runTimer(20, interval) {
|
||||
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
||||
handler.saveKeysFor(uuid, set)
|
||||
val iterator = EcoProfile.CHANGE_MAP.iterator()
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
val uuid = iterator.next()
|
||||
iterator.remove()
|
||||
|
||||
val profile = handler.accessLoadedProfile(uuid) ?: continue
|
||||
|
||||
handler.saveKeysFor(uuid, profile.data.keys)
|
||||
}
|
||||
EcoProfile.CHANGE_MAP.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsIntegration
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import com.denizenscript.denizen.objects.ItemTag
|
||||
import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper
|
||||
import com.willfp.eco.core.items.Items
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
class CustomItemsDenizen : CustomItemsIntegration, Listener {
|
||||
|
||||
override fun registerProvider() {
|
||||
Items.registerItemProvider(DenizenProvider())
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "Denizen"
|
||||
}
|
||||
|
||||
private class DenizenProvider : ItemProvider("denizen") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = ItemTag.valueOf(key, false) ?: return null
|
||||
val id = item.scriptName
|
||||
val namespacedKey = NamespacedKeyUtils.create("denizen", id)
|
||||
val stack = item.itemStack
|
||||
return CustomItem(
|
||||
namespacedKey,
|
||||
{ id.equals(ItemScriptHelper.getItemScriptNameText(it), ignoreCase = true) },
|
||||
stack
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.price
|
||||
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import org.black_ixx.playerpoints.PlayerPoints
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class PriceFactoryPlayerPoints : PriceFactory {
|
||||
override fun getNames() = listOf(
|
||||
"player_points",
|
||||
"p_points"
|
||||
)
|
||||
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PricePlayerPoints(baseContext) { function.get(it).roundToInt() }
|
||||
}
|
||||
|
||||
private class PricePlayerPoints(
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val function: (PlaceholderContext) -> Int
|
||||
) : Price {
|
||||
private val api = PlayerPoints.getInstance().api
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
|
||||
override fun canAfford(player: Player, multiplier: Double): Boolean {
|
||||
return api.look(player.uniqueId) >= getValue(player, multiplier)
|
||||
}
|
||||
|
||||
override fun pay(player: Player, multiplier: Double) {
|
||||
api.take(player.uniqueId, getValue(player, multiplier).roundToInt())
|
||||
}
|
||||
|
||||
override fun giveTo(player: Player, multiplier: Double) {
|
||||
api.give(player.uniqueId, getValue(player, multiplier).roundToInt())
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return function(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
return multipliers[player.uniqueId] ?: 1.0
|
||||
}
|
||||
|
||||
override fun setMultiplier(player: Player, multiplier: Double) {
|
||||
multipliers[player.uniqueId] = multiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.eco.internal.spigot.integrations.price
|
||||
|
||||
import com.willfp.eco.core.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContextSupplier
|
||||
import com.willfp.eco.core.price.Price
|
||||
import com.willfp.eco.core.price.PriceFactory
|
||||
import com.willfp.eco.util.toSingletonList
|
||||
@@ -9,21 +10,20 @@ import me.TechsCode.UltraEconomy.objects.Account
|
||||
import me.TechsCode.UltraEconomy.objects.Currency
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import java.util.function.Function
|
||||
|
||||
class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||
override fun getNames(): List<String> {
|
||||
return currency.name.lowercase().toSingletonList()
|
||||
}
|
||||
|
||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||
return PriceUltraEconomy(currency, baseContext) { function.apply(it) }
|
||||
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||
return PriceUltraEconomy(currency, baseContext) { function.get(it) }
|
||||
}
|
||||
|
||||
private class PriceUltraEconomy(
|
||||
private val currency: Currency,
|
||||
private val baseContext: MathContext,
|
||||
private val function: (MathContext) -> Double
|
||||
private val baseContext: PlaceholderContext,
|
||||
private val function: (PlaceholderContext) -> Double
|
||||
) : Price {
|
||||
private val multipliers = mutableMapOf<UUID, Double>()
|
||||
private val api = UltraEconomy.getAPI()
|
||||
@@ -44,7 +44,7 @@ class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||
}
|
||||
|
||||
override fun getValue(player: Player, multiplier: Double): Double {
|
||||
return function(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier
|
||||
return function(baseContext.copyWithPlayer(player)) * getMultiplier(player) * multiplier
|
||||
}
|
||||
|
||||
override fun getMultiplier(player: Player): Double {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
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.math.MathContext
|
||||
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
||||
import org.bukkit.entity.Player
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.data.FastNumberParsing
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
import redempt.crunch.functional.Function
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder().build()
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
private val min = Function("min", 2) {
|
||||
min(it[0], it[1])
|
||||
}
|
||||
|
||||
private val max = Function("max", 2) {
|
||||
max(it[0], it[1])
|
||||
}
|
||||
|
||||
fun evaluateExpression(expression: String, context: MathContext) =
|
||||
evaluateExpression(expression, context.player, context.injectableContext, context.additionalPlayers)
|
||||
.let { if (!it.isFinite()) 0.0 else it } // Fixes NaN bug.
|
||||
|
||||
private fun evaluateExpression(
|
||||
expression: String,
|
||||
player: Player?,
|
||||
context: PlaceholderInjectable,
|
||||
additional: Collection<AdditionalPlayer>
|
||||
): Double {
|
||||
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
.map { PlaceholderManager.translatePlaceholders(it, player, context, additional) }
|
||||
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = cache.get(expression) {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(it)
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
env.addFunctions(min, max)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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.EcoPlugin
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class DelegatedExpressionHandler(
|
||||
plugin: EcoPlugin,
|
||||
private val handler: ExpressionHandler
|
||||
): ExpressionHandler {
|
||||
private val evaluationCache: Cache<Int, Double> = Caffeine.newBuilder()
|
||||
.expireAfterWrite(plugin.configYml.getInt("math-cache-ttl").toLong(), TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
val hash = Objects.hash(
|
||||
expression,
|
||||
context.player?.uniqueId,
|
||||
context.injectableContext
|
||||
)
|
||||
|
||||
return evaluationCache.get(hash) {
|
||||
handler.evaluate(expression, context)
|
||||
.let { if (!it.isFinite()) 0.0 else it } // Fixes NaN bug.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
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.context.PlaceholderContext
|
||||
import com.willfp.eco.internal.placeholder.PlaceholderParser
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
import redempt.crunch.functional.Function
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
private val min = Function("min", 2) {
|
||||
min(it[0], it[1])
|
||||
}
|
||||
|
||||
private val max = Function("max", 2) {
|
||||
max(it[0], it[1])
|
||||
}
|
||||
|
||||
interface ExpressionHandler {
|
||||
fun evaluate(expression: String, context: PlaceholderContext): Double
|
||||
}
|
||||
private fun String.fastToDoubleOrNull(): Double? {
|
||||
if (isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
var idx = 0
|
||||
val isNegative = this[0] == '-'
|
||||
if (isNegative) idx++
|
||||
|
||||
var integerPart = 0.0
|
||||
var decimalPart = 0.0
|
||||
var decimalIdx = -1
|
||||
|
||||
while (idx < length) {
|
||||
|
||||
when (val char = this[idx]) {
|
||||
'.' -> {
|
||||
if (decimalIdx != -1) return null
|
||||
decimalIdx = idx
|
||||
}
|
||||
in '0'..'9' -> {
|
||||
val number = (char.code - '0'.code).toDouble()
|
||||
if (decimalIdx != -1) {
|
||||
decimalPart = decimalPart * 10 + number
|
||||
} else {
|
||||
integerPart = integerPart * 10 + number
|
||||
}
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
idx++
|
||||
}
|
||||
|
||||
decimalPart /= 10.0.pow((length - decimalIdx - 1).toDouble())
|
||||
|
||||
return if (isNegative) -(integerPart + decimalPart) else integerPart + decimalPart
|
||||
}
|
||||
|
||||
|
||||
class ImmediatePlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
.expireAfterAccess(500, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
|
||||
private val env = EvaluationEnvironment().apply {
|
||||
addFunctions(min, max)
|
||||
}
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
val translatedExpression = placeholderParser.translatePlacholders(expression, context)
|
||||
|
||||
val compiled = cache.get(translatedExpression) {
|
||||
runCatching { Crunch.compileExpression(translatedExpression, env) }
|
||||
.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate() }.getOrDefault(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
class LazyPlaceholderTranslationExpressionHandler(
|
||||
private val placeholderParser: PlaceholderParser
|
||||
) : ExpressionHandler {
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder()
|
||||
.build()
|
||||
|
||||
override fun evaluate(expression: String, context: PlaceholderContext): Double {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
|
||||
val placeholderValues = placeholderParser.parseIndividualPlaceholders(placeholders, context)
|
||||
.map { it.fastToDoubleOrNull() ?: 0.0 }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = cache.get(expression) {
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
env.addFunctions(min, max)
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
}
|
||||
@@ -46,11 +46,6 @@ conflicts:
|
||||
# Disable it if it changes drop mechanics too much for you.
|
||||
use-fast-collated-drops: true
|
||||
|
||||
# Some plugins use their own item display systems (eg Triton)
|
||||
# And must be run after eco. Don't enable this unless you run a conflicting plugin
|
||||
# and have been told to enable it.
|
||||
use-lower-protocollib-priority: false
|
||||
|
||||
# Display frames massively optimize PacketWindowItems, however some users have
|
||||
# reported display bugs by using it. If you have any problems with it, then you
|
||||
# should disable this option.
|
||||
@@ -82,4 +77,17 @@ displayed-recipes: true
|
||||
# If eco plugins should not check for updates; only enable this if you know what you're doing
|
||||
# as there can be urgent hotfixes that you are then not notified about. If you're confident
|
||||
# that you can manage updates on your own, turn this on.
|
||||
no-update-checker: false
|
||||
no-update-checker: false
|
||||
|
||||
# Math expressions are parsed using Crunch, which allows for variables to be used in expressions.
|
||||
# If this is false, variables will be used to represent placeholders, which leads to fewer
|
||||
# expression compilations at the expense of slower evaluation times. If this is true, variables
|
||||
# will instead be translated before compilation to reduce evaluation times at the expense of
|
||||
# longer compilation times. If your expressions usually contain many variables, then you
|
||||
# should enable this option as it may improve performance. If you're unsure, leave it disabled.
|
||||
use-immediate-placeholder-translation-for-math: false
|
||||
|
||||
# The time (in milliseconds) for math expressions to be cached for. Higher values will lead to
|
||||
# faster evaluation times (less CPU usage) at the expense of slightly more memory usage and
|
||||
# less reactive values.
|
||||
math-cache-ttl: 200
|
||||
|
||||
@@ -185,4 +185,14 @@ dependencies:
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: UltraEconomy
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: PlayerPoints
|
||||
required: false
|
||||
bootstrap: false
|
||||
|
||||
- name: Denizen
|
||||
required: false
|
||||
bootstrap: false
|
||||
@@ -51,3 +51,6 @@ softdepend:
|
||||
- ModelEngine
|
||||
- PvPManager
|
||||
- DeluxeMenus
|
||||
- UltraEconomy
|
||||
- PlayerPoints
|
||||
- Denizen
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version = 6.55.1
|
||||
version = 6.56.0
|
||||
plugin-name = eco
|
||||
kotlin.code.style = official
|
||||
Reference in New Issue
Block a user