Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37e271c96c | ||
|
|
3dad48e24d | ||
|
|
ae77e4810b | ||
|
|
3d50e37c37 | ||
|
|
421fd3bd04 | ||
|
|
5ecae0a366 | ||
|
|
5de4914fd7 | ||
|
|
0f9bf094ae | ||
|
|
e67680f397 | ||
|
|
73c0a5d655 | ||
|
|
220ed26f4a | ||
|
|
edf2ea41c7 | ||
|
|
16859b8ce5 | ||
|
|
10fe7d190a | ||
|
|
60a1f2429c | ||
|
|
cc6dc1e67c | ||
|
|
f4f5941691 | ||
|
|
f973281dd9 | ||
|
|
8acd76f363 | ||
|
|
4a165a86dc | ||
|
|
43b7c393b9 | ||
|
|
714952bc45 | ||
|
|
322e179b81 | ||
|
|
469be73ada | ||
|
|
7eac60146f | ||
|
|
ad0223e1bb | ||
|
|
430117f342 | ||
|
|
fa87cae81e | ||
|
|
5695750fc5 | ||
|
|
45e8a57880 | ||
|
|
17fcd2c1b5 | ||
|
|
0c1e17c351 | ||
|
|
9415515849 | ||
|
|
d0e957ea37 | ||
|
|
69514e2f85 | ||
|
|
259e35c978 | ||
|
|
40aec26f15 | ||
|
|
67b2fdd594 | ||
|
|
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 | ||
|
|
4ce2850138 |
@@ -82,6 +82,12 @@ allprojects {
|
|||||||
|
|
||||||
// UltraEconomy
|
// UltraEconomy
|
||||||
maven("https://repo.techscode.com/repository/maven-releases/")
|
maven("https://repo.techscode.com/repository/maven-releases/")
|
||||||
|
|
||||||
|
// PlayerPoints
|
||||||
|
maven("https://repo.rosewooddev.io/repository/public/")
|
||||||
|
|
||||||
|
// Denizen
|
||||||
|
maven("https://maven.citizensnpcs.co/repo")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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.SlotBuilder;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||||
import com.willfp.eco.core.items.TestableItem;
|
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.packet.Packet;
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||||
import com.willfp.eco.core.scheduling.Scheduler;
|
import com.willfp.eco.core.scheduling.Scheduler;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
@@ -531,7 +531,7 @@ public interface Eco {
|
|||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
double evaluate(@NotNull String expression,
|
double evaluate(@NotNull String expression,
|
||||||
@NotNull MathContext context);
|
@NotNull PlaceholderContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the menu a player currently has open.
|
* Get the menu a player currently has open.
|
||||||
@@ -563,6 +563,30 @@ public interface Eco {
|
|||||||
void sendPacket(@NotNull Player player,
|
void sendPacket(@NotNull Player player,
|
||||||
@NotNull Packet packet);
|
@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.
|
* Get the instance of eco; the bridge between the api frontend and the implementation backend.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -366,7 +367,6 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
|||||||
public final void onEnable() {
|
public final void onEnable() {
|
||||||
super.onEnable();
|
super.onEnable();
|
||||||
|
|
||||||
this.getLogger().info("");
|
|
||||||
this.getLogger().info("Loading " + this.getColor() + this.getName());
|
this.getLogger().info("Loading " + this.getColor() + this.getName());
|
||||||
|
|
||||||
if (this.getResourceId() != 0 && !Eco.get().getEcoPlugin().getConfigYml().getBool("no-update-checker")) {
|
if (this.getResourceId() != 0 && !Eco.get().getEcoPlugin().getConfigYml().getBool("no-update-checker")) {
|
||||||
@@ -406,7 +406,9 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
|||||||
|
|
||||||
this.loadedIntegrations.removeIf(pl -> pl.equalsIgnoreCase(this.getName()));
|
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();
|
Prerequisite.update();
|
||||||
|
|
||||||
@@ -428,17 +430,19 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
|||||||
if (this.isSupportingExtensions()) {
|
if (this.isSupportingExtensions()) {
|
||||||
this.getExtensionLoader().loadExtensions();
|
this.getExtensionLoader().loadExtensions();
|
||||||
|
|
||||||
if (this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
|
if (!this.getExtensionLoader().getLoadedExtensions().isEmpty()) {
|
||||||
this.getLogger().info("&cNo extensions found");
|
List<String> loadedExtensions = this.getExtensionLoader().getLoadedExtensions().stream().map(
|
||||||
} else {
|
extension -> extension.getName() + " v" + extension.getVersion()
|
||||||
this.getLogger().info("Extensions Loaded:");
|
).toList();
|
||||||
this.getExtensionLoader().getLoadedExtensions().forEach(extension -> this.getLogger().info("- " + extension.getName() + " v" + extension.getVersion()));
|
|
||||||
|
this.getLogger().info(
|
||||||
|
"Loaded extensions: " +
|
||||||
|
String.join(", ", loadedExtensions)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleLifecycle(this.onEnable, this::handleEnable);
|
this.handleLifecycle(this.onEnable, this::handleEnable);
|
||||||
|
|
||||||
this.getLogger().info("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1082,7 +1086,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
|||||||
*
|
*
|
||||||
* @return The config handler.
|
* @return The config handler.
|
||||||
*/
|
*/
|
||||||
public ConfigHandler getConfigHandler() {
|
public @NotNull ConfigHandler getConfigHandler() {
|
||||||
return this.configHandler;
|
return this.configHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,4 +1155,9 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike, Regist
|
|||||||
public final String getID() {
|
public final String getID() {
|
||||||
return Registry.tryFitPattern(this.getName());
|
return Registry.tryFitPattern(this.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull File getFile() {
|
||||||
|
return super.getFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.willfp.eco.core;
|
package com.willfp.eco.core;
|
||||||
|
|
||||||
import com.willfp.eco.core.config.updating.ConfigHandler;
|
import com.willfp.eco.core.config.updating.ConfigHandler;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -13,12 +15,13 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public interface PluginLike {
|
public interface PluginLike {
|
||||||
/**
|
/**
|
||||||
* Get the data folder of the object.
|
* Get the data folder.
|
||||||
* <p>
|
* <p>
|
||||||
* Returns the plugin data folder for a plugin, or the extension's parent plugin's folder
|
* Returns the plugin data folder for a plugin, or the extension's parent plugin's folder
|
||||||
*
|
*
|
||||||
* @return The data folder.
|
* @return The data folder.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
File getDataFolder();
|
File getDataFolder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,6 +29,7 @@ public interface PluginLike {
|
|||||||
*
|
*
|
||||||
* @return The config handler.
|
* @return The config handler.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
ConfigHandler getConfigHandler();
|
ConfigHandler getConfigHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,5 +37,16 @@ public interface PluginLike {
|
|||||||
*
|
*
|
||||||
* @return The logger.
|
* @return The logger.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Logger getLogger();
|
Logger getLogger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actual file.
|
||||||
|
*
|
||||||
|
* @return The file, i.e. the jar file.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default File getFile() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.willfp.eco.core.config.Configs;
|
|||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
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.NumberUtils;
|
||||||
import com.willfp.eco.util.StringUtils;
|
import com.willfp.eco.util.StringUtils;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
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.
|
* @return The computed value, or 0 if not found or invalid.
|
||||||
*/
|
*/
|
||||||
default int getIntFromExpression(@NotNull String path) {
|
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();
|
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.
|
* Get an integer from config.
|
||||||
@@ -256,6 +269,22 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
return getString(path, true, option);
|
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.
|
* Get a string from config.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -288,7 +317,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
* Get a formatted string from config.
|
* Get a formatted string from config.
|
||||||
*
|
*
|
||||||
* @param path The key to fetch the value from.
|
* @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
|
@Nullable
|
||||||
default String getFormattedStringOrNull(@NotNull String path) {
|
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 path The key to fetch the value from.
|
||||||
* @param option The format option.
|
* @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
|
@Nullable
|
||||||
default String getFormattedStringOrNull(@NotNull String path,
|
default String getFormattedStringOrNull(@NotNull String path,
|
||||||
@@ -308,6 +337,25 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
return getStringOrNull(path, true, option);
|
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.
|
* Get a string from config.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -362,6 +410,24 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
return getStrings(path, true, option);
|
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.
|
* Get a list of strings from config.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -418,6 +484,30 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
return getStringsOrNull(path, true, option);
|
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.
|
* Get a list of strings from config.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -463,7 +553,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
* @return The computed value, or 0 if not found or invalid.
|
* @return The computed value, or 0 if not found or invalid.
|
||||||
*/
|
*/
|
||||||
default double getDoubleFromExpression(@NotNull String path) {
|
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,
|
default double getDoubleFromExpression(@NotNull String path,
|
||||||
@Nullable Player player) {
|
@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.
|
* Get a decimal value via a mathematical expression.
|
||||||
*
|
*
|
||||||
* @param path The key to fetch the value from.
|
* @param path The key to fetch the value from.
|
||||||
* @param player The player to evaluate placeholders with respect to.
|
* @param player The player to evaluate placeholders with respect to.
|
||||||
* @param additionalPlayers The additional players 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.
|
* @return The computed value, or 0 if not found or invalid.
|
||||||
*/
|
*/
|
||||||
default double getDoubleFromExpression(@NotNull String path,
|
default double getDoubleFromExpression(@NotNull String path,
|
||||||
@Nullable Player player,
|
@Nullable Player player,
|
||||||
@NotNull Collection<AdditionalPlayer> additionalPlayers) {
|
@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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -135,20 +135,26 @@ public abstract class Extension implements PluginLike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getDataFolder() {
|
public @NotNull File getDataFolder() {
|
||||||
return this.plugin.getDataFolder();
|
return this.plugin.getDataFolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigHandler getConfigHandler() {
|
public @NotNull ConfigHandler getConfigHandler() {
|
||||||
return this.plugin.getConfigHandler();
|
return this.plugin.getConfigHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Logger getLogger() {
|
public @NotNull Logger getLogger() {
|
||||||
return this.plugin.getLogger();
|
return this.plugin.getLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull File getFile() {
|
||||||
|
Validate.notNull(metadata, "Metadata cannot be null!");
|
||||||
|
return this.metadata.file();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin for the extension.
|
* Get the plugin for the extension.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.willfp.eco.core.extensions;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic exception in extension loading.
|
||||||
|
*/
|
||||||
|
public class ExtensionLoadException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* Create a new ExtensionLoadException.
|
||||||
|
*
|
||||||
|
* @param errorMessage The error message to show.
|
||||||
|
*/
|
||||||
|
public ExtensionLoadException(@NotNull final String errorMessage) {
|
||||||
|
super(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.willfp.eco.core.extensions;
|
package com.willfp.eco.core.extensions;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.version.Version;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The extension's metadata.
|
* The extension's metadata.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -13,6 +16,23 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
*/
|
*/
|
||||||
public record ExtensionMetadata(@NotNull String version,
|
public record ExtensionMetadata(@NotNull String version,
|
||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@NotNull String author) {
|
@NotNull String author,
|
||||||
|
@NotNull File file,
|
||||||
|
@NotNull Version minimumPluginVersion) {
|
||||||
|
/**
|
||||||
|
* Legacy constructor.
|
||||||
|
*
|
||||||
|
* @param version The extension version.
|
||||||
|
* @param name The extension name.
|
||||||
|
* @param author The extension's author.
|
||||||
|
* @deprecated Use {@link ExtensionMetadata#ExtensionMetadata(String, String, String, File, Version)} instead.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@Deprecated(since = "6.57.0", forRemoval = true)
|
||||||
|
public ExtensionMetadata(@NotNull String version,
|
||||||
|
@NotNull String name,
|
||||||
|
@NotNull String author) {
|
||||||
|
this(version, name, author, null, null);
|
||||||
|
throw new UnsupportedOperationException("Legacy constructor is not supported.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Missing or invalid extension.yml.
|
* Missing or invalid extension.yml.
|
||||||
* Invalid filetype.
|
* Invalid filetype.
|
||||||
*/
|
*/
|
||||||
public class MalformedExtensionException extends RuntimeException {
|
public class MalformedExtensionException extends ExtensionLoadException {
|
||||||
/**
|
/**
|
||||||
* Create a new MalformedExtensionException.
|
* Create a new MalformedExtensionException.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for placeholder integrations.
|
* Wrapper class for arguments integrations.
|
||||||
*/
|
*/
|
||||||
public interface PlaceholderIntegration extends Integration {
|
public interface PlaceholderIntegration extends Integration {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
package com.willfp.eco.core.integrations.placeholder;
|
package com.willfp.eco.core.integrations.placeholder;
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.willfp.eco.core.Eco;
|
||||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.DynamicPlaceholder;
|
|
||||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||||
import com.willfp.eco.core.placeholder.Placeholder;
|
import com.willfp.eco.core.placeholder.Placeholder;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
import com.willfp.eco.core.placeholder.PlayerDynamicPlaceholder;
|
import com.willfp.eco.core.placeholder.RegistrablePlaceholder;
|
||||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder;
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||||
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 org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -23,58 +17,34 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to handle placeholder integrations.
|
* Class to handle arguments integrations.
|
||||||
*/
|
*/
|
||||||
public final class PlaceholderManager {
|
public final class PlaceholderManager {
|
||||||
/**
|
/**
|
||||||
* All registered placeholders.
|
* 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<>();
|
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.
|
* The default PlaceholderAPI pattern; brought in for compatibility.
|
||||||
*/
|
*/
|
||||||
private static final Pattern PATTERN = Pattern.compile("%([^% ]+)%");
|
private static final Pattern PATTERN = Pattern.compile("%([^% ]+)%");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty injectable object.
|
* Empty injectableContext object.
|
||||||
*/
|
*/
|
||||||
public static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
public static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
||||||
@Override
|
@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) {
|
public static void registerPlaceholder(@NotNull final Placeholder placeholder) {
|
||||||
if (placeholder instanceof StaticPlaceholder || placeholder instanceof PlayerStaticPlaceholder) {
|
if (!(placeholder instanceof RegistrablePlaceholder)) {
|
||||||
throw new IllegalArgumentException("Static placeholders cannot be registered!");
|
throw new IllegalArgumentException("Placeholder must be RegistrablePlaceholder!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Pattern, Placeholder> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
registerPlaceholder((RegistrablePlaceholder) placeholder);
|
||||||
.getOrDefault(placeholder.getPlugin(), new HashMap<>());
|
|
||||||
|
|
||||||
pluginPlaceholders.put(placeholder.getPattern(), placeholder);
|
|
||||||
|
|
||||||
REGISTERED_PLACEHOLDERS.put(placeholder.getPlugin(), pluginPlaceholders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the result of a placeholder with respect to a player.
|
* Register a arguments.
|
||||||
*
|
*
|
||||||
* @param player The player to get the result from.
|
* @param placeholder The arguments to register.
|
||||||
* @param identifier The placeholder identifier.
|
|
||||||
* @return The value of the placeholder.
|
|
||||||
* @deprecated Specify a plugin to get the result from.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.52.2", forRemoval = true)
|
public static void registerPlaceholder(@NotNull final RegistrablePlaceholder placeholder) {
|
||||||
@SuppressWarnings("unused")
|
// Storing as immutable set leads to slower times to register placeholders, but much
|
||||||
public static String getResult(@Nullable final Player player,
|
// faster times to access registrations.
|
||||||
@NotNull final String identifier) {
|
Set<Placeholder> pluginPlaceholders = new HashSet<>(REGISTERED_PLACEHOLDERS.get(placeholder.getPlugin()));
|
||||||
throw new UnsupportedOperationException("Please specify a plugin to get the result from!");
|
pluginPlaceholders.add(placeholder);
|
||||||
|
REGISTERED_PLACEHOLDERS.put(placeholder.getPlugin(), ImmutableSet.copyOf(pluginPlaceholders));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the result of a placeholder with respect to a player.
|
* Get the result of a placeholder with respect to a player.
|
||||||
*
|
*
|
||||||
* @param player The player to get the result from.
|
* @param player The player to get the result from.
|
||||||
* @param identifier The placeholder identifier.
|
* @param identifier The placeholder args.
|
||||||
* @param plugin The plugin for the placeholder.
|
* @param plugin The plugin for the arguments.
|
||||||
* @return The value of the placeholder.
|
* @return The value of the arguments.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String getResult(@Nullable final Player player,
|
public static String getResult(@Nullable final Player player,
|
||||||
@NotNull final String identifier,
|
@NotNull final String identifier,
|
||||||
@NotNull final EcoPlugin plugin) {
|
@Nullable final EcoPlugin plugin) {
|
||||||
Validate.notNull(plugin, "Plugin cannot be null!");
|
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.
|
* Get the result of a placeholder given a plugin and arguments.
|
||||||
Placeholder placeholder = PLACEHOLDER_LOOKUP_CACHE.get(
|
*
|
||||||
new PlaceholderLookup(identifier, plugin),
|
* @param plugin The plugin for the placeholder.
|
||||||
(it) -> {
|
* @param args The arguments.
|
||||||
// I hate the streams API.
|
* @param context The context.
|
||||||
return REGISTERED_PLACEHOLDERS
|
* @return The value of the arguments.
|
||||||
.getOrDefault(plugin, new HashMap<>())
|
*/
|
||||||
.entrySet()
|
@Nullable
|
||||||
.stream().filter(entry -> entry.getKey().matcher(identifier).matches())
|
public static String getResult(@Nullable final EcoPlugin plugin,
|
||||||
.map(Map.Entry::getValue)
|
@NotNull final String args,
|
||||||
.findFirst();
|
@NotNull final PlaceholderContext context) {
|
||||||
}
|
return Eco.get().getPlaceholderValue(plugin, args, context);
|
||||||
).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 "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,7 +145,10 @@ public final class PlaceholderManager {
|
|||||||
* @param text The text that may contain placeholders to translate.
|
* @param text The text that may contain placeholders to translate.
|
||||||
* @param player The player to translate the placeholders with respect to.
|
* @param player The player to translate the placeholders with respect to.
|
||||||
* @return The text, translated.
|
* @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,
|
public static String translatePlaceholders(@NotNull final String text,
|
||||||
@Nullable final Player player) {
|
@Nullable final Player player) {
|
||||||
return translatePlaceholders(text, player, EMPTY_INJECTABLE);
|
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 text The text that may contain placeholders to translate.
|
||||||
* @param player The player to translate the placeholders with respect to.
|
* @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.
|
* @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,
|
public static String translatePlaceholders(@NotNull final String text,
|
||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final PlaceholderInjectable context) {
|
@NotNull final PlaceholderInjectable context) {
|
||||||
@@ -229,84 +176,50 @@ public final class PlaceholderManager {
|
|||||||
*
|
*
|
||||||
* @param text The text that may contain placeholders to translate.
|
* @param text The text that may contain placeholders to translate.
|
||||||
* @param player The player to translate the placeholders with respect to.
|
* @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.
|
* @param additionalPlayers Additional players to translate placeholders for.
|
||||||
* @return The text, translated.
|
* @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,
|
public static String translatePlaceholders(@NotNull final String text,
|
||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final PlaceholderInjectable context,
|
@NotNull final PlaceholderInjectable context,
|
||||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
@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?
|
/**
|
||||||
|
* Translate all placeholders in a translation context.
|
||||||
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.
|
* @param text The text that may contain placeholders to translate.
|
||||||
|
* @param context The translation context.
|
||||||
However, something like libreforge will also inject %victim_max_health%, which is unrelated
|
* @return The text, translated.
|
||||||
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
|
@NotNull
|
||||||
relation to the victim, which resolved to zero. So, we have to parse statics and player statics
|
public static String translatePlaceholders(@NotNull final String text,
|
||||||
that might include a prefix first, then additional players, then player statics with the support
|
@NotNull final PlaceholderContext context) {
|
||||||
of additional players.
|
return Eco.get().translatePlaceholders(text, context);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -331,108 +244,22 @@ public final class PlaceholderManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set placeholders without any integrations.
|
* Get all registered placeholder 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>.
|
|
||||||
*
|
*
|
||||||
* @param text The text.
|
* @return The integrations.
|
||||||
* @param player The player.
|
|
||||||
* @return The text.
|
|
||||||
*/
|
*/
|
||||||
private static String setWithoutIntegration(@NotNull final String text,
|
public static Set<PlaceholderIntegration> getRegisteredIntegrations() {
|
||||||
@Nullable final Player player) {
|
return Set.copyOf(REGISTERED_INTEGRATIONS);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private record PlaceholderLookup(@NotNull String identifier,
|
/**
|
||||||
@Nullable EcoPlugin plugin) {
|
* Get all registered placeholders for a plugin.
|
||||||
|
*
|
||||||
}
|
* @param plugin The plugin.
|
||||||
|
* @return The placeholders.
|
||||||
private record EntryWithPlayer(@NotNull PlayerPlaceholder entry,
|
*/
|
||||||
@NotNull Player player) {
|
public static Set<Placeholder> getRegisteredPlaceholders(@NotNull final EcoPlugin plugin) {
|
||||||
|
return REGISTERED_PLACEHOLDERS.get(plugin);
|
||||||
}
|
|
||||||
|
|
||||||
private record DynamicEntryWithPlayer(@NotNull PlayerDynamicPlaceholder entry,
|
|
||||||
@NotNull String args,
|
|
||||||
@NotNull Player player) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaceholderManager() {
|
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.integrations.placeholder.PlaceholderManager;
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
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.
|
* @deprecated Use {@link PlaceholderContext} instead.
|
||||||
* @param player The player.
|
|
||||||
* @param additionalPlayers The additional players.
|
|
||||||
*/
|
*/
|
||||||
public record MathContext(
|
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||||
@NotNull PlaceholderInjectable injectableContext,
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
@Nullable Player player,
|
public class MathContext {
|
||||||
@NotNull Collection<AdditionalPlayer> additionalPlayers
|
|
||||||
) {
|
|
||||||
/**
|
/**
|
||||||
* Empty math context.
|
* Returns an empty math parseContext.
|
||||||
*/
|
*/
|
||||||
public static final MathContext EMPTY = new MathContext(
|
public static final MathContext EMPTY = new MathContext(
|
||||||
PlaceholderManager.EMPTY_INJECTABLE,
|
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.
|
* @return The MathContext.
|
||||||
*/
|
*/
|
||||||
public static MathContext of(@NotNull final PlaceholderInjectable injectableContext) {
|
public static MathContext of(@NotNull final PlaceholderInjectable injectableContext) {
|
||||||
@@ -48,16 +194,16 @@ public record MathContext(
|
|||||||
/**
|
/**
|
||||||
* Copy a MathContext with a player.
|
* Copy a MathContext with a player.
|
||||||
*
|
*
|
||||||
* @param context The context.
|
* @param context The parseContext.
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return The new MathContext.
|
* @return The new MathContext.
|
||||||
*/
|
*/
|
||||||
public static MathContext copyWithPlayer(@NotNull final MathContext context,
|
public static MathContext copyWithPlayer(@NotNull final MathContext context,
|
||||||
@Nullable final Player player) {
|
@Nullable final Player player) {
|
||||||
return new MathContext(
|
return new MathContext(
|
||||||
context.injectableContext(),
|
context.injectableContext,
|
||||||
player,
|
player,
|
||||||
context.additionalPlayers()
|
context.additionalPlayers
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.willfp.eco.core.placeholder;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
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.
|
* 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;
|
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;
|
private final EcoPlugin plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new dynamic placeholder.
|
* Create a new dynamic arguments.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
* @param pattern The pattern.
|
* @param pattern The pattern.
|
||||||
@@ -37,31 +37,33 @@ public final class DynamicPlaceholder implements Placeholder {
|
|||||||
*/
|
*/
|
||||||
public DynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
public DynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
||||||
@NotNull final Pattern pattern,
|
@NotNull final Pattern pattern,
|
||||||
@NotNull final Function<String, String> function) {
|
@NotNull final Function<@NotNull String, @Nullable String> function) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the value of the placeholder.
|
@Nullable
|
||||||
*
|
public String getValue(@NotNull final String args,
|
||||||
* @param args The args.
|
@NotNull final PlaceholderContext context) {
|
||||||
* @return The value.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getValue(@NotNull final String args) {
|
|
||||||
return function.apply(args);
|
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() {
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
PlaceholderManager.registerPlaceholder(this);
|
@NotNull
|
||||||
return this;
|
public String getValue(@NotNull final String args) {
|
||||||
|
return Objects.requireNonNullElse(
|
||||||
|
function.apply(args),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,18 +71,17 @@ public final class DynamicPlaceholder implements Placeholder {
|
|||||||
return this.plugin;
|
return this.plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return "dynamic";
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Pattern getPattern() {
|
public Pattern getPattern() {
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull DynamicPlaceholder register() {
|
||||||
|
return (DynamicPlaceholder) RegistrablePlaceholder.super.register();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable final Object o) {
|
public boolean equals(@Nullable final Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@@ -97,6 +98,6 @@ public final class DynamicPlaceholder implements Placeholder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.Eco;
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.
|
* 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
|
@Override
|
||||||
default @NotNull EcoPlugin getPlugin() {
|
default EcoPlugin getPlugin() {
|
||||||
return Eco.get().getEcoPlugin();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,64 @@
|
|||||||
package com.willfp.eco.core.placeholder;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
import com.willfp.eco.core.EcoPlugin;
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A placeholder represents a string that can hold a value.
|
* A placeholder represents a string that can hold a value.
|
||||||
*/
|
*/
|
||||||
public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder,
|
public interface Placeholder {
|
||||||
DynamicPlaceholder, PlayerDynamicPlaceholder, InjectablePlaceholder {
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin that holds the placeholder.
|
* Get the plugin that holds the arguments.
|
||||||
*
|
*
|
||||||
* @return The plugin.
|
* @return The plugin.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@Nullable
|
||||||
EcoPlugin getPlugin();
|
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
|
@Nullable
|
||||||
String getIdentifier();
|
String getValue(@NotNull String args,
|
||||||
|
@NotNull PlaceholderContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the pattern for the placeholder.
|
* Get the pattern for the arguments.
|
||||||
*
|
*
|
||||||
* @return The pattern.
|
* @return The pattern.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
default Pattern getPattern() {
|
Pattern getPattern();
|
||||||
return Pattern.compile(this.getIdentifier());
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
public interface PlaceholderInjectable {
|
||||||
/**
|
/**
|
||||||
* Inject placeholder.
|
* Inject arguments.
|
||||||
*
|
*
|
||||||
* @param placeholders The placeholders.
|
* @param placeholders The placeholders.
|
||||||
*/
|
*/
|
||||||
@@ -18,7 +18,7 @@ public interface PlaceholderInjectable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject placeholder.
|
* Inject arguments.
|
||||||
*
|
*
|
||||||
* @param placeholders The placeholders.
|
* @param placeholders The placeholders.
|
||||||
*/
|
*/
|
||||||
@@ -29,7 +29,7 @@ public interface PlaceholderInjectable {
|
|||||||
/**
|
/**
|
||||||
* Inject placeholders.
|
* Inject placeholders.
|
||||||
* <p>
|
* <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.
|
* @param placeholders The placeholders.
|
||||||
*/
|
*/
|
||||||
@@ -43,7 +43,7 @@ public interface PlaceholderInjectable {
|
|||||||
/**
|
/**
|
||||||
* Get injected placeholders.
|
* Get injected placeholders.
|
||||||
* <p>
|
* <p>
|
||||||
* Override this method in implementations.
|
* This method should always return an immutable list.
|
||||||
*
|
*
|
||||||
* @return Injected placeholders.
|
* @return Injected placeholders.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.willfp.eco.core.placeholder;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -11,26 +11,26 @@ import java.util.function.BiFunction;
|
|||||||
import java.util.regex.Pattern;
|
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;
|
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;
|
private final EcoPlugin plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new dynamic placeholder.
|
* Create a new dynamic arguments.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
* @param pattern The pattern.
|
* @param pattern The pattern.
|
||||||
@@ -38,33 +38,40 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
|||||||
*/
|
*/
|
||||||
public PlayerDynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
public PlayerDynamicPlaceholder(@NotNull final EcoPlugin plugin,
|
||||||
@NotNull final Pattern pattern,
|
@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.plugin = plugin;
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the value of the placeholder.
|
public @Nullable String getValue(@NotNull final String args,
|
||||||
*
|
@NotNull final PlaceholderContext context) {
|
||||||
* @param args The args.
|
Player player = context.getPlayer();
|
||||||
* @param player The player.
|
|
||||||
* @return The value.
|
if (player == null) {
|
||||||
*/
|
return null;
|
||||||
@NotNull
|
}
|
||||||
public String getValue(@NotNull final String args,
|
|
||||||
@NotNull final Player player) {
|
|
||||||
return function.apply(args, player);
|
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() {
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
PlaceholderManager.registerPlaceholder(this);
|
@NotNull
|
||||||
return this;
|
public String getValue(@NotNull final String args,
|
||||||
|
@NotNull final Player player) {
|
||||||
|
return Objects.requireNonNullElse(
|
||||||
|
function.apply(args, player),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,18 +79,17 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
|||||||
return this.plugin;
|
return this.plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Deprecated
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return "dynamic";
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Pattern getPattern() {
|
public Pattern getPattern() {
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull PlayerDynamicPlaceholder register() {
|
||||||
|
return (PlayerDynamicPlaceholder) RegistrablePlaceholder.super.register();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable final Object o) {
|
public boolean equals(@Nullable final Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@@ -100,6 +106,6 @@ public final class PlayerDynamicPlaceholder implements Placeholder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -11,31 +11,26 @@ import java.util.function.Function;
|
|||||||
import java.util.regex.Pattern;
|
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.
|
* The arguments pattern.
|
||||||
*/
|
|
||||||
private final String identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The placeholder pattern.
|
|
||||||
*/
|
*/
|
||||||
private final Pattern 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;
|
private final EcoPlugin plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new player placeholder.
|
* Create a new player arguments.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
* @param identifier The identifier.
|
* @param identifier The identifier.
|
||||||
@@ -43,32 +38,38 @@ public final class PlayerPlaceholder implements Placeholder {
|
|||||||
*/
|
*/
|
||||||
public PlayerPlaceholder(@NotNull final EcoPlugin plugin,
|
public PlayerPlaceholder(@NotNull final EcoPlugin plugin,
|
||||||
@NotNull final String identifier,
|
@NotNull final String identifier,
|
||||||
@NotNull final Function<Player, String> function) {
|
@NotNull final Function<@NotNull Player, @Nullable String> function) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.identifier = identifier;
|
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||||
this.pattern = Pattern.compile(identifier);
|
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the value of the placeholder for a given player.
|
public @Nullable String getValue(@NotNull final String args,
|
||||||
*
|
@NotNull final PlaceholderContext context) {
|
||||||
* @param player The player.
|
Player player = context.getPlayer();
|
||||||
* @return The value.
|
|
||||||
*/
|
if (player == null) {
|
||||||
@NotNull
|
return null;
|
||||||
public String getValue(@NotNull final Player player) {
|
}
|
||||||
|
|
||||||
return function.apply(player);
|
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() {
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
PlaceholderManager.registerPlaceholder(this);
|
@NotNull
|
||||||
return this;
|
public String getValue(@NotNull final Player player) {
|
||||||
|
return Objects.requireNonNullElse(
|
||||||
|
function.apply(player),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,17 +77,17 @@ public final class PlayerPlaceholder implements Placeholder {
|
|||||||
return this.plugin;
|
return this.plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return this.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Pattern getPattern() {
|
public Pattern getPattern() {
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull PlayerPlaceholder register() {
|
||||||
|
return (PlayerPlaceholder) RegistrablePlaceholder.super.register();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable final Object o) {
|
public boolean equals(@Nullable final Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@@ -95,12 +96,12 @@ public final class PlayerPlaceholder implements Placeholder {
|
|||||||
if (!(o instanceof PlayerPlaceholder that)) {
|
if (!(o instanceof PlayerPlaceholder that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
return Objects.equals(this.getPattern(), that.getPattern())
|
||||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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;
|
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.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -13,47 +15,72 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public final class PlayerStaticPlaceholder implements InjectablePlaceholder {
|
public final class PlayerStaticPlaceholder implements InjectablePlaceholder {
|
||||||
/**
|
/**
|
||||||
* The name of the placeholder.
|
* The identifier.
|
||||||
*/
|
*/
|
||||||
private final String identifier;
|
private final String identifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The placeholder pattern.
|
* The arguments pattern.
|
||||||
*/
|
*/
|
||||||
private final Pattern 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 identifier The identifier.
|
||||||
* @param function The function to retrieve the value.
|
* @param function The function to retrieve the value.
|
||||||
*/
|
*/
|
||||||
public PlayerStaticPlaceholder(@NotNull final String identifier,
|
public PlayerStaticPlaceholder(@NotNull final String identifier,
|
||||||
@NotNull final Function<Player, String> function) {
|
@NotNull final Function<@NotNull Player, @Nullable String> function) {
|
||||||
this.identifier = identifier;
|
this.identifier = "%" + identifier + "%";
|
||||||
this.pattern = Pattern.compile(identifier);
|
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||||
this.function = function;
|
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.
|
* @param player The player.
|
||||||
* @return The value.
|
* @return The value.
|
||||||
|
* @deprecated Use {@link #getValue(String, PlaceholderContext)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getValue(@NotNull final Player player) {
|
public String getValue(@NotNull final Player player) {
|
||||||
return function.apply(player);
|
return Objects.requireNonNullElse(
|
||||||
|
function.apply(player),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String getIdentifier() {
|
public String tryTranslateQuickly(@NotNull final String text,
|
||||||
return this.identifier;
|
@NotNull final PlaceholderContext context) {
|
||||||
|
return StringUtils.replaceQuickly(
|
||||||
|
text,
|
||||||
|
this.identifier,
|
||||||
|
Objects.requireNonNullElse(
|
||||||
|
this.getValue(identifier, context),
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -70,11 +97,11 @@ public final class PlayerStaticPlaceholder implements InjectablePlaceholder {
|
|||||||
if (!(o instanceof PlayerStaticPlaceholder that)) {
|
if (!(o instanceof PlayerStaticPlaceholder that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Objects.equals(this.getIdentifier(), that.getIdentifier());
|
return Objects.equals(this.getPattern(), that.getPattern());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.getIdentifier());
|
return Objects.hash(this.getPattern());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.willfp.eco.core.placeholder;
|
package com.willfp.eco.core.placeholder;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -10,31 +10,26 @@ import java.util.function.Supplier;
|
|||||||
import java.util.regex.Pattern;
|
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.
|
* The arguments pattern.
|
||||||
*/
|
|
||||||
private final String identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The placeholder pattern.
|
|
||||||
*/
|
*/
|
||||||
private final Pattern 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;
|
private final EcoPlugin plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new player placeholder.
|
* Create a new player arguments.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
* @param identifier The identifier.
|
* @param identifier The identifier.
|
||||||
@@ -42,30 +37,31 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
|||||||
*/
|
*/
|
||||||
public PlayerlessPlaceholder(@NotNull final EcoPlugin plugin,
|
public PlayerlessPlaceholder(@NotNull final EcoPlugin plugin,
|
||||||
@NotNull final String identifier,
|
@NotNull final String identifier,
|
||||||
@NotNull final Supplier<String> function) {
|
@NotNull final Supplier<@Nullable String> function) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.identifier = identifier;
|
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||||
this.pattern = Pattern.compile(identifier);
|
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the value of the placeholder.
|
public @Nullable String getValue(@NotNull final String args,
|
||||||
*
|
@NotNull final PlaceholderContext context) {
|
||||||
* @return The value.
|
|
||||||
*/
|
|
||||||
public String getValue() {
|
|
||||||
return function.get();
|
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() {
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
PlaceholderManager.registerPlaceholder(this);
|
@NotNull
|
||||||
return this;
|
public String getValue() {
|
||||||
|
return Objects.requireNonNullElse(
|
||||||
|
this.function.get(),
|
||||||
|
""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,17 +69,17 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
|||||||
return this.plugin;
|
return this.plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull String getIdentifier() {
|
|
||||||
return this.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Pattern getPattern() {
|
public Pattern getPattern() {
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull PlayerlessPlaceholder register() {
|
||||||
|
return (PlayerlessPlaceholder) RegistrablePlaceholder.super.register();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable final Object o) {
|
public boolean equals(@Nullable final Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
@@ -92,12 +88,12 @@ public final class PlayerlessPlaceholder implements Placeholder {
|
|||||||
if (!(o instanceof PlayerlessPlaceholder that)) {
|
if (!(o instanceof PlayerlessPlaceholder that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
return Objects.equals(this.getPattern(), that.getPattern())
|
||||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -8,50 +10,66 @@ import java.util.function.Supplier;
|
|||||||
import java.util.regex.Pattern;
|
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 {
|
public final class StaticPlaceholder implements InjectablePlaceholder {
|
||||||
/**
|
/**
|
||||||
* The name of the placeholder.
|
* The name of the arguments.
|
||||||
*/
|
*/
|
||||||
private final String identifier;
|
private final String identifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The placeholder pattern.
|
* The arguments pattern.
|
||||||
*/
|
*/
|
||||||
private final Pattern 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 identifier The identifier.
|
||||||
* @param function The function to retrieve the value.
|
* @param function The function to retrieve the value.
|
||||||
*/
|
*/
|
||||||
public StaticPlaceholder(@NotNull final String identifier,
|
public StaticPlaceholder(@NotNull final String identifier,
|
||||||
@NotNull final Supplier<String> function) {
|
@NotNull final Supplier<@Nullable String> function) {
|
||||||
this.identifier = identifier;
|
this.identifier = "%" + identifier + "%";
|
||||||
this.pattern = Pattern.compile(identifier);
|
this.pattern = Pattern.compile(identifier, Pattern.LITERAL);
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the value of the placeholder.
|
public @Nullable String getValue(@NotNull final String args,
|
||||||
*
|
@NotNull final PlaceholderContext context) {
|
||||||
* @return The value.
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
public String getValue() {
|
|
||||||
return function.get();
|
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
|
@Override
|
||||||
public @NotNull String getIdentifier() {
|
public String tryTranslateQuickly(@NotNull final String text,
|
||||||
return this.identifier;
|
@NotNull final PlaceholderContext context) {
|
||||||
|
return StringUtils.replaceQuickly(
|
||||||
|
text,
|
||||||
|
this.identifier,
|
||||||
|
Objects.requireNonNullElse(this.getValue(this.identifier, context), "")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -68,11 +86,11 @@ public final class StaticPlaceholder implements InjectablePlaceholder {
|
|||||||
if (!(o instanceof StaticPlaceholder that)) {
|
if (!(o instanceof StaticPlaceholder that)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Objects.equals(this.getIdentifier(), that.getIdentifier());
|
return Objects.equals(this.getPattern(), that.getPattern());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(this.getIdentifier());
|
return Objects.hash(this.getPattern());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable final Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(o instanceof MergedInjectableContext that)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Objects.equals(baseContext, that.baseContext)
|
||||||
|
&& Objects.equals(additionalContext, that.additionalContext)
|
||||||
|
&& Objects.equals(extraInjections, that.extraInjections);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(baseContext, additionalContext, extraInjections);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
import com.willfp.eco.core.config.interfaces.Config;
|
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.price.impl.PriceFree;
|
||||||
import com.willfp.eco.core.serialization.ConfigDeserializer;
|
import com.willfp.eco.core.serialization.ConfigDeserializer;
|
||||||
import com.willfp.eco.util.NumberUtils;
|
import com.willfp.eco.util.NumberUtils;
|
||||||
@@ -168,7 +168,7 @@ public final class ConfiguredPrice implements Price {
|
|||||||
Price price = Prices.create(
|
Price price = Prices.create(
|
||||||
config.getString("value"),
|
config.getString("value"),
|
||||||
config.getString("type"),
|
config.getString("type"),
|
||||||
MathContext.of(config)
|
PlaceholderContext.of(config)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new ConfiguredPrice(price, formatString);
|
return new ConfiguredPrice(price, formatString);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.willfp.eco.core.price;
|
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.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -10,7 +11,8 @@ import java.util.function.Function;
|
|||||||
/**
|
/**
|
||||||
* Create prices.
|
* Create prices.
|
||||||
* <p>
|
* <p>
|
||||||
* You must override one of the create methods.
|
* Override create(PlaceholderContext, PlaceholderContextSupplier), other methods
|
||||||
|
* are for backwards compatibility.
|
||||||
*/
|
*/
|
||||||
public interface PriceFactory {
|
public interface PriceFactory {
|
||||||
/**
|
/**
|
||||||
@@ -27,20 +29,38 @@ public interface PriceFactory {
|
|||||||
*
|
*
|
||||||
* @param value The value.
|
* @param value The value.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
|
* @deprecated Use {@link #create(PlaceholderContext, PlaceholderContextSupplier)} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.56.0", forRemoval = true)
|
||||||
default @NotNull Price create(final double value) {
|
default @NotNull Price create(final double value) {
|
||||||
return create(MathContext.EMPTY, (ctx) -> value);
|
return create(PlaceholderContext.EMPTY, (ctx) -> value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the price.
|
* Create the price.
|
||||||
*
|
*
|
||||||
* @param baseContext The base MathContext.
|
* @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.
|
* @return The price.
|
||||||
*/
|
*/
|
||||||
default @NotNull Price create(@NotNull final MathContext baseContext,
|
@SuppressWarnings("removal")
|
||||||
@NotNull final Function<MathContext, Double> function) {
|
default @NotNull Price create(@NotNull final PlaceholderContext baseContext,
|
||||||
return create(function.apply(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.Items;
|
||||||
import com.willfp.eco.core.items.TestableItem;
|
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.PriceEconomy;
|
||||||
import com.willfp.eco.core.price.impl.PriceFree;
|
import com.willfp.eco.core.price.impl.PriceFree;
|
||||||
import com.willfp.eco.core.price.impl.PriceItem;
|
import com.willfp.eco.core.price.impl.PriceItem;
|
||||||
@@ -13,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage prices.
|
* Class to manage prices.
|
||||||
@@ -48,7 +48,28 @@ public final class Prices {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Price create(@NotNull final String expression,
|
public static Price create(@NotNull final String expression,
|
||||||
@Nullable final String priceName) {
|
@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
|
@NotNull
|
||||||
public static Price create(@NotNull final String expression,
|
public static Price create(@NotNull final String expression,
|
||||||
@Nullable final String priceName,
|
@Nullable final String priceName,
|
||||||
@NotNull final MathContext context) {
|
@NotNull final PlaceholderContext context) {
|
||||||
Function<MathContext, Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
PlaceholderContextSupplier<Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
||||||
expression,
|
expression,
|
||||||
ctx
|
ctx
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package com.willfp.eco.core.price.impl;
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
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 com.willfp.eco.core.price.Price;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -18,12 +19,12 @@ public final class PriceEconomy implements Price {
|
|||||||
/**
|
/**
|
||||||
* The value of the 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.
|
* The multipliers.
|
||||||
@@ -36,7 +37,21 @@ public final class PriceEconomy implements Price {
|
|||||||
* @param value The value.
|
* @param value The value.
|
||||||
*/
|
*/
|
||||||
public PriceEconomy(final double 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 baseContext The base context.
|
||||||
* @param function The function.
|
* @param function The function.
|
||||||
*/
|
*/
|
||||||
public PriceEconomy(@NotNull final MathContext baseContext,
|
public PriceEconomy(@NotNull final PlaceholderContext baseContext,
|
||||||
@NotNull final Function<MathContext, Double> function) {
|
@NotNull final PlaceholderContextSupplier<Double> function) {
|
||||||
this.baseContext = baseContext;
|
this.baseContext = baseContext;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
}
|
}
|
||||||
@@ -72,7 +87,7 @@ public final class PriceEconomy implements Price {
|
|||||||
@Override
|
@Override
|
||||||
public double getValue(@NotNull final Player player,
|
public double getValue(@NotNull final Player player,
|
||||||
final double multiplier) {
|
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
|
@Override
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package com.willfp.eco.core.price.impl;
|
|||||||
import com.willfp.eco.core.drops.DropQueue;
|
import com.willfp.eco.core.drops.DropQueue;
|
||||||
import com.willfp.eco.core.items.HashedItem;
|
import com.willfp.eco.core.items.HashedItem;
|
||||||
import com.willfp.eco.core.items.TestableItem;
|
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 com.willfp.eco.core.price.Price;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -20,14 +21,14 @@ import java.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
public final class PriceItem implements Price {
|
public final class PriceItem implements Price {
|
||||||
/**
|
/**
|
||||||
* The base MathContext.
|
* The base PlaceholderContext.
|
||||||
*/
|
*/
|
||||||
private final MathContext baseContext;
|
private final PlaceholderContext baseContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of items.
|
* The amount of items.
|
||||||
*/
|
*/
|
||||||
private final Function<MathContext, Double> function;
|
private final PlaceholderContextSupplier<Double> function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item.
|
* The item.
|
||||||
@@ -47,7 +48,23 @@ public final class PriceItem implements Price {
|
|||||||
*/
|
*/
|
||||||
public PriceItem(final int amount,
|
public PriceItem(final int amount,
|
||||||
@NotNull final TestableItem item) {
|
@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 function The function to get the amount of items to remove.
|
||||||
* @param item The item.
|
* @param item The item.
|
||||||
*/
|
*/
|
||||||
public PriceItem(@NotNull final MathContext baseContext,
|
public PriceItem(@NotNull final PlaceholderContext baseContext,
|
||||||
@NotNull final Function<MathContext, Double> function,
|
@NotNull final PlaceholderContextSupplier<Double> function,
|
||||||
@NotNull final TestableItem item) {
|
@NotNull final TestableItem item) {
|
||||||
this.baseContext = baseContext;
|
this.baseContext = baseContext;
|
||||||
this.function = function;
|
this.function = function;
|
||||||
@@ -137,7 +154,7 @@ public final class PriceItem implements Price {
|
|||||||
public double getValue(@NotNull final Player player,
|
public double getValue(@NotNull final Player player,
|
||||||
final double multiplier) {
|
final double multiplier) {
|
||||||
return Math.toIntExact(Math.round(
|
return Math.toIntExact(Math.round(
|
||||||
this.function.apply(MathContext.copyWithPlayer(baseContext, player))
|
this.function.get(baseContext.copyWithPlayer(player))
|
||||||
* getMultiplier(player) * multiplier
|
* getMultiplier(player) * multiplier
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,8 +127,8 @@ public final class Recipes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (builder.isAir()) {
|
if (builder.isAir()) {
|
||||||
Bukkit.getLogger().warning("RECIPE ERROR! " + plugin.getName() + ":" + key + " consists only");
|
Bukkit.getLogger().warning("Crafting recipe " + plugin.getID() + ":" + key + " consists only");
|
||||||
Bukkit.getLogger().warning("of air or invalid items! Please change that or disable this recipe.");
|
Bukkit.getLogger().warning("of air or invalid items! It will not be registered.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.willfp.eco.util;
|
package com.willfp.eco.util;
|
||||||
|
|
||||||
import com.willfp.eco.core.Eco;
|
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.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -210,7 +209,7 @@ public final class NumberUtils {
|
|||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression) {
|
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,
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
@Nullable final Player player) {
|
@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 expression The expression.
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @param context The injectable placeholders.
|
* @param context The injectableContext placeholders.
|
||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression,
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final PlaceholderInjectable context) {
|
@Nullable final PlaceholderInjectable context) {
|
||||||
return evaluateExpression(expression, player, context, new ArrayList<>());
|
return evaluateExpression(expression, player, context, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,30 +243,46 @@ public final class NumberUtils {
|
|||||||
*
|
*
|
||||||
* @param expression The expression.
|
* @param expression The expression.
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @param context The injectable placeholders.
|
* @param context The injectableContext placeholders.
|
||||||
* @param additionalPlayers Additional players to parse placeholders for.
|
* @param additionalPlayers Additional players to parse placeholders for.
|
||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression,
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final PlaceholderInjectable context,
|
@Nullable final PlaceholderInjectable context,
|
||||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||||
return Eco.get().evaluate(expression, new MathContext(
|
return Eco.get().evaluate(expression, new PlaceholderContext(
|
||||||
context,
|
|
||||||
player,
|
player,
|
||||||
|
null,
|
||||||
|
context,
|
||||||
additionalPlayers
|
additionalPlayers
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate an expression with respect to a player (for placeholders).
|
* Evaluate an expression in a context.
|
||||||
*
|
*
|
||||||
* @param expression The expression.
|
* @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.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression,
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
@NotNull final MathContext context) {
|
@NotNull final PlaceholderContext context) {
|
||||||
return Eco.get().evaluate(expression, context);
|
return Eco.get().evaluate(expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableMap;
|
|||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.willfp.eco.core.Eco;
|
import com.willfp.eco.core.Eco;
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
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.Component;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
@@ -200,6 +201,26 @@ public final class StringUtils {
|
|||||||
return translated;
|
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.
|
* Format a string.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -242,7 +263,7 @@ public final class StringUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static String format(@NotNull final String message,
|
public static String format(@NotNull final String message,
|
||||||
@NotNull final FormatOption option) {
|
@NotNull final FormatOption option) {
|
||||||
return format(message, null, option);
|
return format(message, (Player) null, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -287,7 +308,7 @@ public final class StringUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static Component formatToComponent(@NotNull final String message,
|
public static Component formatToComponent(@NotNull final String message,
|
||||||
@NotNull final FormatOption option) {
|
@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,
|
public static String format(@NotNull final String message,
|
||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final FormatOption option) {
|
@NotNull final FormatOption option) {
|
||||||
String processedMessage = message;
|
|
||||||
if (option == FormatOption.WITH_PLACEHOLDERS) {
|
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);
|
return STRING_FORMAT_CACHE.get(processedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,6 +734,56 @@ public final class StringUtils {
|
|||||||
return builder.toString();
|
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.
|
* 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
|
package com.willfp.eco.util
|
||||||
|
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||||
import net.kyori.adventure.text.Component
|
import net.kyori.adventure.text.Component
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
@@ -31,6 +32,14 @@ fun String.formatEco(
|
|||||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
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 */
|
/** @see StringUtils.formatList */
|
||||||
fun List<String>.formatEco(
|
fun List<String>.formatEco(
|
||||||
player: Player? = null,
|
player: Player? = null,
|
||||||
@@ -41,6 +50,14 @@ fun List<String>.formatEco(
|
|||||||
if (formatPlaceholders) StringUtils.FormatOption.WITH_PLACEHOLDERS else StringUtils.FormatOption.WITHOUT_PLACEHOLDERS
|
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 */
|
/** @see StringUtils.splitAround */
|
||||||
fun String.splitAround(separator: String): Array<String> =
|
fun String.splitAround(separator: String): Array<String> =
|
||||||
StringUtils.splitAround(this, separator)
|
StringUtils.splitAround(this, separator)
|
||||||
@@ -48,3 +65,7 @@ fun String.splitAround(separator: String): Array<String> =
|
|||||||
/** @see StringUtils.toNiceString */
|
/** @see StringUtils.toNiceString */
|
||||||
fun Any?.toNiceString(): String =
|
fun Any?.toNiceString(): String =
|
||||||
StringUtils.toNiceString(this)
|
StringUtils.toNiceString(this)
|
||||||
|
|
||||||
|
/** @see StringUtils.replaceQuickly */
|
||||||
|
fun String.replaceQuickly(target: String, replacement: String): String =
|
||||||
|
StringUtils.replaceQuickly(this, target, replacement)
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package com.willfp.eco.internal.config
|
|||||||
import com.willfp.eco.core.config.ConfigType
|
import com.willfp.eco.core.config.ConfigType
|
||||||
import com.willfp.eco.core.config.interfaces.Config
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder
|
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 com.willfp.eco.util.StringUtils
|
||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@@ -141,9 +142,7 @@ open class EcoConfig(
|
|||||||
var string = get(path)?.toString() ?: return null
|
var string = get(path)?.toString() ?: return null
|
||||||
if (format && option == StringUtils.FormatOption.WITH_PLACEHOLDERS) {
|
if (format && option == StringUtils.FormatOption.WITH_PLACEHOLDERS) {
|
||||||
for (injection in placeholderInjections) {
|
for (injection in placeholderInjections) {
|
||||||
if (injection is StaticPlaceholder) {
|
string = injection.tryTranslateQuickly(string, PlaceholderContext.EMPTY)
|
||||||
string = string.replace("%${injection.identifier}%", injection.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if (format) StringUtils.format(string, option) else string
|
return if (format) StringUtils.format(string, option) else string
|
||||||
@@ -161,9 +160,7 @@ open class EcoConfig(
|
|||||||
strings.replaceAll {
|
strings.replaceAll {
|
||||||
var string = it
|
var string = it
|
||||||
for (injection in placeholderInjections) {
|
for (injection in placeholderInjections) {
|
||||||
if (injection is StaticPlaceholder) {
|
string = injection.tryTranslateQuickly(string, PlaceholderContext.EMPTY)
|
||||||
string = string.replace("%${injection.identifier}%", injection.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
@@ -181,12 +178,12 @@ open class EcoConfig(
|
|||||||
|
|
||||||
override fun addInjectablePlaceholder(placeholders: Iterable<InjectablePlaceholder>) {
|
override fun addInjectablePlaceholder(placeholders: Iterable<InjectablePlaceholder>) {
|
||||||
for (placeholder in placeholders) {
|
for (placeholder in placeholders) {
|
||||||
injections[placeholder.identifier] = placeholder
|
injections[placeholder.pattern.pattern()] = placeholder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPlaceholderInjections(): List<InjectablePlaceholder> {
|
override fun getPlaceholderInjections(): List<InjectablePlaceholder> {
|
||||||
return injections.values.toList()
|
return injections.values.listView() // Faster than .toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearInjectedPlaceholders() {
|
override fun clearInjectedPlaceholders() {
|
||||||
@@ -209,14 +206,6 @@ open class EcoConfig(
|
|||||||
return bukkit
|
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>? {
|
private inline fun <reified T> getList(path: String): List<T>? {
|
||||||
val asIterable = get(path) as? Iterable<*> ?: return null
|
val asIterable = get(path) as? Iterable<*> ?: return null
|
||||||
val asList = asIterable.toList()
|
val asList = asIterable.toList()
|
||||||
@@ -227,4 +216,44 @@ open class EcoConfig(
|
|||||||
|
|
||||||
return asList as List<T>
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hey! Don't care. This works.
|
||||||
|
return this.hashCode() == other.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
/*
|
||||||
|
The keys are completely redundant, as they are only used to prevent
|
||||||
|
duplicate keys in the map. Therefore, we can ignore them and just
|
||||||
|
hash the actual placeholder values.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var injectionHash = 0
|
||||||
|
|
||||||
|
injections.forEachValue(5) {
|
||||||
|
injectionHash = injectionHash xor (it.hashCode() shl 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashCode() has to compute extremely quickly, so we're using bitwise, because why not?
|
||||||
|
// Fucking filthy to use identityHashCode here, but it should be extremely fast
|
||||||
|
val identityHash = System.identityHashCode(this)
|
||||||
|
return (identityHash shl 5) - (identityHash xor configType.hashCode()) + injectionHash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||||||
class EcoConfigSection(
|
class EcoConfigSection(
|
||||||
type: ConfigType,
|
type: ConfigType,
|
||||||
values: Map<String, Any?> = emptyMap(),
|
values: Map<String, Any?> = emptyMap(),
|
||||||
injections: MutableMap<String, InjectablePlaceholder> = mutableMapOf()
|
injections: Map<String, InjectablePlaceholder> = emptyMap()
|
||||||
) : EcoConfig(type) {
|
) : EcoConfig(type) {
|
||||||
init {
|
init {
|
||||||
this.init(values)
|
this.init(values)
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import com.willfp.eco.core.Eco
|
|||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.config.toConfig
|
import com.willfp.eco.core.config.toConfig
|
||||||
import com.willfp.eco.core.extensions.Extension
|
import com.willfp.eco.core.extensions.Extension
|
||||||
|
import com.willfp.eco.core.extensions.ExtensionLoadException
|
||||||
import com.willfp.eco.core.extensions.ExtensionLoader
|
import com.willfp.eco.core.extensions.ExtensionLoader
|
||||||
import com.willfp.eco.core.extensions.ExtensionMetadata
|
import com.willfp.eco.core.extensions.ExtensionMetadata
|
||||||
import com.willfp.eco.core.extensions.MalformedExtensionException
|
import com.willfp.eco.core.extensions.MalformedExtensionException
|
||||||
|
import com.willfp.eco.core.version.Version
|
||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
@@ -32,7 +34,7 @@ class EcoExtensionLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
runCatching { loadExtension(extensionJar) }.onFailure {
|
runCatching { loadExtension(extensionJar) }.onFailure {
|
||||||
this.plugin.logger.warning(extensionJar.name + " caused an error!")
|
this.plugin.logger.warning(extensionJar.name + " caused an error: ${it.message ?: "Unknown error"}")
|
||||||
if (Eco.get().ecoPlugin.configYml.getBool("log-full-extension-errors")) {
|
if (Eco.get().ecoPlugin.configYml.getBool("log-full-extension-errors")) {
|
||||||
it.printStackTrace()
|
it.printStackTrace()
|
||||||
}
|
}
|
||||||
@@ -54,7 +56,12 @@ class EcoExtensionLoader(
|
|||||||
var name = extensionYml.getStringOrNull("name")
|
var name = extensionYml.getStringOrNull("name")
|
||||||
var version = extensionYml.getStringOrNull("version")
|
var version = extensionYml.getStringOrNull("version")
|
||||||
var author = extensionYml.getStringOrNull("author")
|
var author = extensionYml.getStringOrNull("author")
|
||||||
|
val pluginVersion = Version(extensionYml.getStringOrNull("plugin-version") ?: "0.0.0")
|
||||||
|
val pluginName = extensionYml.getStringOrNull("plugin")
|
||||||
|
|
||||||
|
if (pluginName != null && !pluginName.equals(this.plugin.description.name, ignoreCase = true)) {
|
||||||
|
throw ExtensionLoadException("${extensionJar.name} is only compatible with $pluginName!")
|
||||||
|
}
|
||||||
|
|
||||||
if (mainClass == null) {
|
if (mainClass == null) {
|
||||||
throw MalformedExtensionException("Invalid extension.yml found in " + extensionJar.name)
|
throw MalformedExtensionException("Invalid extension.yml found in " + extensionJar.name)
|
||||||
@@ -75,7 +82,11 @@ class EcoExtensionLoader(
|
|||||||
author = "Unnamed Author"
|
author = "Unnamed Author"
|
||||||
}
|
}
|
||||||
|
|
||||||
val metadata = ExtensionMetadata(version, name, author)
|
if (Version(this.plugin.description.version) < pluginVersion) {
|
||||||
|
throw ExtensionLoadException("Plugin version is too low for ${extensionJar.name}!")
|
||||||
|
}
|
||||||
|
|
||||||
|
val metadata = ExtensionMetadata(version, name, author, extensionJar, pluginVersion)
|
||||||
|
|
||||||
val cls: Class<*> = classLoader.loadClass(mainClass)
|
val cls: Class<*> = classLoader.loadClass(mainClass)
|
||||||
val extension: Extension = cls.getConstructor(EcoPlugin::class.java).newInstance(this.plugin) as Extension
|
val extension: Extension = cls.getConstructor(EcoPlugin::class.java).newInstance(this.plugin) as Extension
|
||||||
@@ -85,7 +96,7 @@ class EcoExtensionLoader(
|
|||||||
extensions[extension] = classLoader
|
extensions[extension] = classLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLoadedExtensions(): MutableSet<Extension> {
|
override fun getLoadedExtensions(): Set<Extension> {
|
||||||
return ImmutableSet.copyOf(extensions.keys)
|
return ImmutableSet.copyOf(extensions.keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.willfp.eco.internal.integrations
|
|||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||||
|
import com.willfp.eco.core.placeholder.context.placeholderContext
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
@@ -33,7 +34,19 @@ class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() {
|
|||||||
override fun onPlaceholderRequest(
|
override fun onPlaceholderRequest(
|
||||||
player: Player?,
|
player: Player?,
|
||||||
identifier: String
|
identifier: String
|
||||||
): String {
|
): String? {
|
||||||
return PlaceholderManager.getResult(player, identifier, plugin)
|
return PlaceholderManager.getResult(
|
||||||
|
plugin,
|
||||||
|
identifier,
|
||||||
|
placeholderContext(
|
||||||
|
player = player,
|
||||||
|
item = player?.inventory?.itemInMainHand
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPlaceholders(): List<String> {
|
||||||
|
return PlaceholderManager.getRegisteredPlaceholders(plugin)
|
||||||
|
.map { "%${this.plugin.name.lowercase()}_${it.pattern.pattern()}%" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import com.willfp.eco.core.price.impl.PriceEconomy
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
import java.util.function.Function
|
|
||||||
|
|
||||||
object PriceFactoryEconomy : PriceFactory {
|
object PriceFactoryEconomy : PriceFactory {
|
||||||
override fun getNames() = listOf(
|
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)
|
return PriceEconomy(baseContext, function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.willfp.eco.internal.price
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.function.Function
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object PriceFactoryXP : PriceFactory {
|
object PriceFactoryXP : PriceFactory {
|
||||||
@@ -15,13 +15,13 @@ object PriceFactoryXP : PriceFactory {
|
|||||||
"experience"
|
"experience"
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||||
return PriceXP(baseContext) { function.apply(it).roundToInt() }
|
return PriceXP(baseContext) { function.get(it).roundToInt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PriceXP(
|
private class PriceXP(
|
||||||
private val baseContext: MathContext,
|
private val baseContext: PlaceholderContext,
|
||||||
private val xp: (MathContext) -> Int
|
private val xp: (PlaceholderContext) -> Int
|
||||||
) : Price {
|
) : Price {
|
||||||
private val multipliers = mutableMapOf<UUID, Double>()
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ object PriceFactoryXP : PriceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue(player: Player, multiplier: Double): Double {
|
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 {
|
override fun getMultiplier(player: Player): Double {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package com.willfp.eco.internal.price
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.function.Function
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object PriceFactoryXPLevels : PriceFactory {
|
object PriceFactoryXPLevels : PriceFactory {
|
||||||
@@ -16,13 +16,13 @@ object PriceFactoryXPLevels : PriceFactory {
|
|||||||
"explevels",
|
"explevels",
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||||
return PriceXPLevel(baseContext) { function.apply(it).roundToInt() }
|
return PriceXPLevel(baseContext) { function.get(it).roundToInt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PriceXPLevel(
|
private class PriceXPLevel(
|
||||||
private val baseContext: MathContext,
|
private val baseContext: PlaceholderContext,
|
||||||
private val level: (MathContext) -> Int
|
private val level: (PlaceholderContext) -> Int
|
||||||
) : Price {
|
) : Price {
|
||||||
private val multipliers = mutableMapOf<UUID, Double>()
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ object PriceFactoryXPLevels : PriceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue(player: Player, multiplier: Double): Double {
|
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 {
|
override fun getMultiplier(player: Player): Double {
|
||||||
|
|||||||
@@ -52,12 +52,16 @@ dependencies {
|
|||||||
compileOnly("com.github.N0RSKA:ScytherAPI:55a")
|
compileOnly("com.github.N0RSKA:ScytherAPI:55a")
|
||||||
compileOnly("com.ticxo.modelengine:api:R3.0.1")
|
compileOnly("com.ticxo.modelengine:api:R3.0.1")
|
||||||
compileOnly("me.TechsCode:UltraEconomyAPI:1.0.0")
|
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("com.github.Ssomar-Developement:SCore:3.4.7")
|
||||||
compileOnly("io.lumine:Mythic:5.2.1")
|
compileOnly("io.lumine:Mythic:5.2.1")
|
||||||
compileOnly("io.lumine:LumineUtils:1.19-SNAPSHOT")
|
compileOnly("io.lumine:LumineUtils:1.19-SNAPSHOT")
|
||||||
compileOnly("com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT")
|
compileOnly("com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT")
|
||||||
compileOnly("com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT")
|
compileOnly("com.github.sirblobman.combatlogx:api:11.0.0.0-SNAPSHOT")
|
||||||
compileOnly("LibsDisguises:LibsDisguises:10.0.26")
|
compileOnly("LibsDisguises:LibsDisguises:10.0.26")
|
||||||
|
compileOnly("com.denizenscript:denizen:1.2.7-SNAPSHOT") {
|
||||||
|
exclude(group = "*", module = "*")
|
||||||
|
}
|
||||||
|
|
||||||
compileOnly(fileTree("../../lib") {
|
compileOnly(fileTree("../../lib") {
|
||||||
include("*.jar")
|
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.menu.MenuType
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||||
import com.willfp.eco.core.items.Items
|
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.packet.Packet
|
||||||
|
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||||
import com.willfp.eco.internal.EcoPropsParser
|
import com.willfp.eco.internal.EcoPropsParser
|
||||||
import com.willfp.eco.internal.command.EcoPluginCommand
|
import com.willfp.eco.internal.command.EcoPluginCommand
|
||||||
import com.willfp.eco.internal.command.EcoSubcommand
|
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.gui.slot.EcoSlotBuilder
|
||||||
import com.willfp.eco.internal.integrations.PAPIExpansion
|
import com.willfp.eco.internal.integrations.PAPIExpansion
|
||||||
import com.willfp.eco.internal.logging.EcoLogger
|
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.proxy.EcoProxyFactory
|
||||||
import com.willfp.eco.internal.scheduling.EcoScheduler
|
import com.willfp.eco.internal.scheduling.EcoScheduler
|
||||||
import com.willfp.eco.internal.spigot.data.DataYml
|
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.ProfileHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||||
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
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.BukkitCommandsProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
|
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||||
@@ -88,6 +91,15 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
||||||
SafeInternalNamespacedKeyFactory() else FastInternalNamespacedKeyFactory()
|
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) =
|
override fun createScheduler(plugin: EcoPlugin) =
|
||||||
EcoScheduler(plugin)
|
EcoScheduler(plugin)
|
||||||
|
|
||||||
@@ -312,8 +324,8 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
override fun getTPS() =
|
override fun getTPS() =
|
||||||
getProxy(TPSProxy::class.java).getTPS()
|
getProxy(TPSProxy::class.java).getTPS()
|
||||||
|
|
||||||
override fun evaluate(expression: String, context: MathContext) =
|
override fun evaluate(expression: String, context: PlaceholderContext) =
|
||||||
evaluateExpression(expression, context)
|
crunchHandler.evaluate(expression, context)
|
||||||
|
|
||||||
override fun getOpenMenu(player: Player) =
|
override fun getOpenMenu(player: Player) =
|
||||||
player.renderedInventory?.menu
|
player.renderedInventory?.menu
|
||||||
@@ -326,4 +338,10 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
|
|
||||||
override fun sendPacket(player: Player, packet: Packet) =
|
override fun sendPacket(player: Player, packet: Packet) =
|
||||||
this.getProxy(PacketHandlerProxy::class.java).sendPacket(player, 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.antigrief.AntigriefWorldGuard
|
||||||
import com.willfp.eco.internal.spigot.integrations.customentities.CustomEntitiesMythicMobs
|
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.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.CustomItemsExecutableItems
|
||||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsHeadDatabase
|
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsHeadDatabase
|
||||||
import com.willfp.eco.internal.spigot.integrations.customitems.CustomItemsItemsAdder
|
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.mcmmo.McmmoIntegrationImpl
|
||||||
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
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.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.price.PriceFactoryUltraEconomy
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
||||||
@@ -323,6 +325,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
},
|
},
|
||||||
IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) },
|
IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) },
|
||||||
IntegrationLoader("Scyther") { CustomItemsManager.register(CustomItemsScyther()) },
|
IntegrationLoader("Scyther") { CustomItemsManager.register(CustomItemsScyther()) },
|
||||||
|
IntegrationLoader("Denizen") { CustomItemsManager.register(CustomItemsDenizen()) },
|
||||||
|
|
||||||
// Shop
|
// Shop
|
||||||
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
|
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
|
||||||
@@ -355,6 +358,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
Prices.registerPriceFactory(PriceFactoryUltraEconomy(currency))
|
Prices.registerPriceFactory(PriceFactoryUltraEconomy(currency))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
IntegrationLoader("PlayerPoints") { Prices.registerPriceFactory(PriceFactoryPlayerPoints()) },
|
||||||
|
|
||||||
// Placeholder
|
// Placeholder
|
||||||
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ abstract class EcoProfile(
|
|||||||
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
|
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
|
||||||
this.data[key] = value
|
this.data[key] = value
|
||||||
|
|
||||||
val changedKeys = CHANGE_MAP[uuid] ?: mutableSetOf()
|
CHANGE_MAP.add(uuid)
|
||||||
changedKeys.add(key)
|
|
||||||
CHANGE_MAP[uuid] = changedKeys
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> read(key: PersistentDataKey<T>): T {
|
override fun <T : Any> read(key: PersistentDataKey<T>): T {
|
||||||
@@ -44,7 +42,7 @@ abstract class EcoProfile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val CHANGE_MAP: MutableMap<UUID, MutableSet<PersistentDataKey<*>>> = ConcurrentHashMap()
|
val CHANGE_MAP: MutableSet<UUID> = ConcurrentHashMap.newKeySet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
|||||||
import com.willfp.eco.internal.spigot.ServerLocking
|
import com.willfp.eco.internal.spigot.ServerLocking
|
||||||
import com.willfp.eco.internal.spigot.data.storage.DataHandler
|
import com.willfp.eco.internal.spigot.data.storage.DataHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||||
import com.willfp.eco.internal.spigot.data.storage.LegacyMySQLDataHandler
|
|
||||||
import com.willfp.eco.internal.spigot.data.storage.MongoDataHandler
|
import com.willfp.eco.internal.spigot.data.storage.MongoDataHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.MySQLDataHandler
|
import com.willfp.eco.internal.spigot.data.storage.MySQLDataHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.YamlDataHandler
|
import com.willfp.eco.internal.spigot.data.storage.YamlDataHandler
|
||||||
@@ -22,24 +21,16 @@ class ProfileHandler(
|
|||||||
private val type: HandlerType,
|
private val type: HandlerType,
|
||||||
private val plugin: EcoSpigotPlugin
|
private val plugin: EcoSpigotPlugin
|
||||||
) {
|
) {
|
||||||
private val loaded = mutableMapOf<UUID, Profile>()
|
private val loaded = mutableMapOf<UUID, EcoProfile>()
|
||||||
|
|
||||||
val handler: DataHandler = when (type) {
|
val handler: DataHandler = when (type) {
|
||||||
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
||||||
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
||||||
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
||||||
HandlerType.LEGACY_MYSQL -> LegacyMySQLDataHandler(plugin, this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
fun accessLoadedProfile(uuid: UUID): EcoProfile? =
|
||||||
if (handler.type == HandlerType.LEGACY_MYSQL) {
|
loaded[uuid]
|
||||||
plugin.logger.warning("You're using the legacy MySQL handler!")
|
|
||||||
plugin.logger.warning("Some features will not work and you may get unfixable errors.")
|
|
||||||
plugin.logger.warning("Support cannot be given to data issues related to legacy MySQL.")
|
|
||||||
plugin.logger.warning("Change your data handler to mysql, mongo, or yaml to fix this!")
|
|
||||||
plugin.logger.warning("This can be done in /plugins/eco/config.yml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadGenericProfile(uuid: UUID): Profile {
|
fun loadGenericProfile(uuid: UUID): Profile {
|
||||||
val found = loaded[uuid]
|
val found = loaded[uuid]
|
||||||
@@ -87,11 +78,7 @@ class ProfileHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var previousHandlerType = HandlerType.valueOf(plugin.dataYml.getString("previous-handler"))
|
val previousHandlerType = HandlerType.valueOf(plugin.dataYml.getString("previous-handler"))
|
||||||
|
|
||||||
if (previousHandlerType == HandlerType.MYSQL && !plugin.dataYml.has("new-mysql")) {
|
|
||||||
previousHandlerType = HandlerType.LEGACY_MYSQL
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previousHandlerType == type) {
|
if (previousHandlerType == type) {
|
||||||
return
|
return
|
||||||
@@ -101,7 +88,6 @@ class ProfileHandler(
|
|||||||
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
HandlerType.YAML -> YamlDataHandler(plugin, this)
|
||||||
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
HandlerType.MYSQL -> MySQLDataHandler(plugin, this)
|
||||||
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
HandlerType.MONGO -> MongoDataHandler(plugin, this)
|
||||||
HandlerType.LEGACY_MYSQL -> LegacyMySQLDataHandler(plugin, this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerLocking.lock("Migrating player data! Check console for more information.")
|
ServerLocking.lock("Migrating player data! Check console for more information.")
|
||||||
|
|||||||
@@ -3,6 +3,5 @@ package com.willfp.eco.internal.spigot.data.storage
|
|||||||
enum class HandlerType {
|
enum class HandlerType {
|
||||||
YAML,
|
YAML,
|
||||||
MYSQL,
|
MYSQL,
|
||||||
MONGO,
|
MONGO
|
||||||
LEGACY_MYSQL
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,315 +0,0 @@
|
|||||||
package com.willfp.eco.internal.spigot.data.storage
|
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
|
||||||
import com.willfp.eco.core.Eco
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
|
||||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
|
||||||
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
|
||||||
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
|
||||||
import com.zaxxer.hikari.HikariConfig
|
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
|
||||||
import org.jetbrains.exposed.dao.id.UUIDTable
|
|
||||||
import org.jetbrains.exposed.sql.BooleanColumnType
|
|
||||||
import org.jetbrains.exposed.sql.Column
|
|
||||||
import org.jetbrains.exposed.sql.Database
|
|
||||||
import org.jetbrains.exposed.sql.DoubleColumnType
|
|
||||||
import org.jetbrains.exposed.sql.IntegerColumnType
|
|
||||||
import org.jetbrains.exposed.sql.ResultRow
|
|
||||||
import org.jetbrains.exposed.sql.SchemaUtils
|
|
||||||
import org.jetbrains.exposed.sql.VarCharColumnType
|
|
||||||
import org.jetbrains.exposed.sql.insert
|
|
||||||
import org.jetbrains.exposed.sql.select
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
import org.jetbrains.exposed.sql.update
|
|
||||||
import java.util.UUID
|
|
||||||
import java.util.concurrent.Callable
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
The MySQL data handler is hot garbage for several reasons:
|
|
||||||
- Using MySQL on unstructured data: it's being horrifically misused, but that's just how it has to be.
|
|
||||||
- Can't remove un-needed keys, there's wasted space in the columns everywhere.
|
|
||||||
- No native support for the STRING_LIST type, instead it 'serializes' the lists with semicolons as separators.
|
|
||||||
- General lack of flexibility, it's too rigid.
|
|
||||||
|
|
||||||
That's why I added the MongoDB handler, it's far, far better suited for what eco does - use it over
|
|
||||||
MySQL if you can.
|
|
||||||
|
|
||||||
Oh, also - I don't really know how this class works. I've rewritten it and hacked it together several ways
|
|
||||||
in several sessions, and it's basically complete gibberish to me. Adding the STRING_LIST type is probably
|
|
||||||
the worst bodge I've shipped in production.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class LegacyMySQLDataHandler(
|
|
||||||
plugin: EcoSpigotPlugin,
|
|
||||||
handler: ProfileHandler
|
|
||||||
) : DataHandler(HandlerType.LEGACY_MYSQL) {
|
|
||||||
private val database: Database
|
|
||||||
private val playerHandler: ImplementedMySQLHandler
|
|
||||||
private val serverHandler: ImplementedMySQLHandler
|
|
||||||
|
|
||||||
init {
|
|
||||||
val config = HikariConfig()
|
|
||||||
config.driverClassName = "com.mysql.cj.jdbc.Driver"
|
|
||||||
config.username = plugin.configYml.getString("mysql.user")
|
|
||||||
config.password = plugin.configYml.getString("mysql.password")
|
|
||||||
config.jdbcUrl = "jdbc:mysql://" +
|
|
||||||
"${plugin.configYml.getString("mysql.host")}:" +
|
|
||||||
"${plugin.configYml.getString("mysql.port")}/" +
|
|
||||||
plugin.configYml.getString("mysql.database")
|
|
||||||
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
|
||||||
|
|
||||||
database = Database.connect(HikariDataSource(config))
|
|
||||||
|
|
||||||
playerHandler = ImplementedMySQLHandler(
|
|
||||||
handler,
|
|
||||||
UUIDTable("eco_players"),
|
|
||||||
plugin
|
|
||||||
)
|
|
||||||
|
|
||||||
serverHandler = ImplementedMySQLHandler(
|
|
||||||
handler,
|
|
||||||
UUIDTable("eco_server"),
|
|
||||||
plugin
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
|
||||||
return applyFor(uuid) {
|
|
||||||
it.read(uuid, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: T) {
|
|
||||||
applyFor(uuid) {
|
|
||||||
it.write(uuid, key, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun saveKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
|
||||||
applyFor(uuid) {
|
|
||||||
it.saveKeysForRow(uuid, keys)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <R> applyFor(uuid: UUID, function: (ImplementedMySQLHandler) -> R): R {
|
|
||||||
return if (uuid == serverProfileUUID) {
|
|
||||||
function(serverHandler)
|
|
||||||
} else {
|
|
||||||
function(playerHandler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initialize() {
|
|
||||||
playerHandler.initialize()
|
|
||||||
serverHandler.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
private inner class ImplementedMySQLHandler(
|
|
||||||
private val handler: ProfileHandler,
|
|
||||||
private val table: UUIDTable,
|
|
||||||
private val plugin: EcoPlugin
|
|
||||||
) {
|
|
||||||
private val rows = Caffeine.newBuilder()
|
|
||||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
|
||||||
.build<UUID, ResultRow>()
|
|
||||||
|
|
||||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-legacy-mysql-thread-%d").build()
|
|
||||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
|
||||||
val registeredKeys = mutableSetOf<PersistentDataKey<*>>()
|
|
||||||
|
|
||||||
init {
|
|
||||||
transaction(database) {
|
|
||||||
SchemaUtils.create(table)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initialize() {
|
|
||||||
transaction(database) {
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ensureKeyRegistration(key: PersistentDataKey<*>) {
|
|
||||||
if (table.columns.any { it.name == key.key.toString() }) {
|
|
||||||
registeredKeys.add(key)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registerColumn(key)
|
|
||||||
registeredKeys.add(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
|
|
||||||
getRow(uuid)
|
|
||||||
doWrite(uuid, key, key.type.constrainSQLTypes(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doWrite(uuid: UUID, key: PersistentDataKey<*>, constrainedValue: Any) {
|
|
||||||
val column: Column<Any> = getColumn(key) as Column<Any>
|
|
||||||
|
|
||||||
executor.submit {
|
|
||||||
transaction(database) {
|
|
||||||
table.update({ table.id eq uuid }) {
|
|
||||||
it[column] = constrainedValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
|
||||||
saveRow(uuid, keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
|
||||||
val profile = handler.loadGenericProfile(uuid)
|
|
||||||
|
|
||||||
executor.submit {
|
|
||||||
transaction(database) {
|
|
||||||
getRow(uuid)
|
|
||||||
|
|
||||||
for (key in keys) {
|
|
||||||
doWrite(uuid, key, key.type.constrainSQLTypes(profile.read(key)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
|
||||||
val doRead = Callable<T?> {
|
|
||||||
transaction(database) {
|
|
||||||
val row = getRow(uuid)
|
|
||||||
val column = getColumn(key)
|
|
||||||
val raw = row[column]
|
|
||||||
key.type.fromConstrained(raw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
|
|
||||||
|
|
||||||
doRead.call()
|
|
||||||
|
|
||||||
return if (Eco.get().ecoPlugin.configYml.getBool("mysql.async-reads")) {
|
|
||||||
executor.submit(doRead).get()
|
|
||||||
} else {
|
|
||||||
doRead.call()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> registerColumn(key: PersistentDataKey<T>) {
|
|
||||||
try {
|
|
||||||
transaction(database) {
|
|
||||||
try {
|
|
||||||
table.apply {
|
|
||||||
if (table.columns.any { it.name == key.key.toString() }) {
|
|
||||||
return@apply
|
|
||||||
}
|
|
||||||
|
|
||||||
when (key.type) {
|
|
||||||
PersistentDataKeyType.INT -> registerColumn<Int>(key.key.toString(), IntegerColumnType())
|
|
||||||
.default(key.defaultValue as Int)
|
|
||||||
|
|
||||||
PersistentDataKeyType.DOUBLE -> registerColumn<Double>(
|
|
||||||
key.key.toString(),
|
|
||||||
DoubleColumnType()
|
|
||||||
).default(key.defaultValue as Double)
|
|
||||||
|
|
||||||
PersistentDataKeyType.BOOLEAN -> registerColumn<Boolean>(
|
|
||||||
key.key.toString(),
|
|
||||||
BooleanColumnType()
|
|
||||||
).default(key.defaultValue as Boolean)
|
|
||||||
|
|
||||||
PersistentDataKeyType.STRING -> registerColumn<String>(
|
|
||||||
key.key.toString(),
|
|
||||||
VarCharColumnType(512)
|
|
||||||
).default(key.defaultValue as String)
|
|
||||||
|
|
||||||
PersistentDataKeyType.STRING_LIST -> registerColumn<String>(
|
|
||||||
key.key.toString(),
|
|
||||||
VarCharColumnType(8192)
|
|
||||||
).default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List<String>) as String)
|
|
||||||
|
|
||||||
PersistentDataKeyType.CONFIG -> throw IllegalArgumentException(
|
|
||||||
"Config Persistent Data Keys are not supported by the legacy MySQL handler!"
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw NullPointerException("Null value found!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.logger.info("MySQL Error 1!")
|
|
||||||
e.printStackTrace()
|
|
||||||
// What's that? Two enormous exception catches? That's right! This code sucks.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.logger.info("MySQL Error 2!")
|
|
||||||
e.printStackTrace()
|
|
||||||
// It might fail. Who cares? This is legacy.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getColumn(key: PersistentDataKey<*>): Column<*> {
|
|
||||||
ensureKeyRegistration(key)
|
|
||||||
|
|
||||||
val name = key.key.toString()
|
|
||||||
|
|
||||||
return table.columns.first { it.name == name }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRow(uuid: UUID): ResultRow {
|
|
||||||
fun select(uuid: UUID): ResultRow? {
|
|
||||||
return transaction(database) {
|
|
||||||
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rows.get(uuid) {
|
|
||||||
val row = select(uuid)
|
|
||||||
|
|
||||||
return@get if (row != null) {
|
|
||||||
row
|
|
||||||
} else {
|
|
||||||
transaction(database) {
|
|
||||||
table.insert { it[id] = uuid }
|
|
||||||
}
|
|
||||||
select(uuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> PersistentDataKeyType<T>.constrainSQLTypes(value: Any): Any {
|
|
||||||
return if (this == PersistentDataKeyType.STRING_LIST) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
value as List<String>
|
|
||||||
value.joinToString(separator = ";")
|
|
||||||
} else {
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> PersistentDataKeyType<T>.fromConstrained(constrained: Any?): T? {
|
|
||||||
if (constrained == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return if (this == PersistentDataKeyType.STRING_LIST) {
|
|
||||||
constrained as String
|
|
||||||
constrained.split(";").toList()
|
|
||||||
} else {
|
|
||||||
constrained
|
|
||||||
} as T
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,7 @@ Whatever. At least it works.
|
|||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class MySQLDataHandler(
|
class MySQLDataHandler(
|
||||||
private val plugin: EcoSpigotPlugin,
|
plugin: EcoSpigotPlugin,
|
||||||
private val handler: ProfileHandler
|
private val handler: ProfileHandler
|
||||||
) : DataHandler(HandlerType.MYSQL) {
|
) : DataHandler(HandlerType.MYSQL) {
|
||||||
private val database: Database
|
private val database: Database
|
||||||
@@ -149,9 +149,4 @@ class MySQLDataHandler(
|
|||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun save() {
|
|
||||||
plugin.dataYml.set("new-mysql", true)
|
|
||||||
plugin.dataYml.save()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,16 @@ class ProfileSaver(
|
|||||||
val interval = plugin.configYml.getInt("save-interval").toLong()
|
val interval = plugin.configYml.getInt("save-interval").toLong()
|
||||||
|
|
||||||
plugin.scheduler.runTimer(20, interval) {
|
plugin.scheduler.runTimer(20, interval) {
|
||||||
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
val iterator = EcoProfile.CHANGE_MAP.iterator()
|
||||||
handler.saveKeysFor(uuid, set)
|
|
||||||
|
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
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import com.willfp.eco.util.toSingletonList
|
import com.willfp.eco.util.toSingletonList
|
||||||
@@ -9,21 +10,20 @@ import me.TechsCode.UltraEconomy.objects.Account
|
|||||||
import me.TechsCode.UltraEconomy.objects.Currency
|
import me.TechsCode.UltraEconomy.objects.Currency
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.function.Function
|
|
||||||
|
|
||||||
class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||||
override fun getNames(): List<String> {
|
override fun getNames(): List<String> {
|
||||||
return currency.name.lowercase().toSingletonList()
|
return currency.name.lowercase().toSingletonList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
override fun create(baseContext: PlaceholderContext, function: PlaceholderContextSupplier<Double>): Price {
|
||||||
return PriceUltraEconomy(currency, baseContext) { function.apply(it) }
|
return PriceUltraEconomy(currency, baseContext) { function.get(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PriceUltraEconomy(
|
private class PriceUltraEconomy(
|
||||||
private val currency: Currency,
|
private val currency: Currency,
|
||||||
private val baseContext: MathContext,
|
private val baseContext: PlaceholderContext,
|
||||||
private val function: (MathContext) -> Double
|
private val function: (PlaceholderContext) -> Double
|
||||||
) : Price {
|
) : Price {
|
||||||
private val multipliers = mutableMapOf<UUID, Double>()
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
private val api = UltraEconomy.getAPI()
|
private val api = UltraEconomy.getAPI()
|
||||||
@@ -44,7 +44,7 @@ class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getValue(player: Player, multiplier: Double): Double {
|
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 {
|
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,28 @@
|
|||||||
|
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.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 {
|
||||||
|
// Peak performance (totally not having fun with bitwise operators)
|
||||||
|
val hash = (((expression.hashCode() shl 5) - expression.hashCode()) xor
|
||||||
|
(context.player?.uniqueId?.hashCode() ?: 0)
|
||||||
|
) xor context.injectableContext.hashCode()
|
||||||
|
|
||||||
|
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.
|
# Disable it if it changes drop mechanics too much for you.
|
||||||
use-fast-collated-drops: true
|
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
|
# Display frames massively optimize PacketWindowItems, however some users have
|
||||||
# reported display bugs by using it. If you have any problems with it, then you
|
# reported display bugs by using it. If you have any problems with it, then you
|
||||||
# should disable this option.
|
# should disable this option.
|
||||||
@@ -83,3 +78,16 @@ displayed-recipes: true
|
|||||||
# as there can be urgent hotfixes that you are then not notified about. If you're confident
|
# 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.
|
# 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
|
||||||
|
|||||||
@@ -188,3 +188,11 @@ dependencies:
|
|||||||
- name: UltraEconomy
|
- name: UltraEconomy
|
||||||
required: false
|
required: false
|
||||||
bootstrap: false
|
bootstrap: false
|
||||||
|
|
||||||
|
- name: PlayerPoints
|
||||||
|
required: false
|
||||||
|
bootstrap: false
|
||||||
|
|
||||||
|
- name: Denizen
|
||||||
|
required: false
|
||||||
|
bootstrap: false
|
||||||
@@ -52,3 +52,5 @@ softdepend:
|
|||||||
- PvPManager
|
- PvPManager
|
||||||
- DeluxeMenus
|
- DeluxeMenus
|
||||||
- UltraEconomy
|
- UltraEconomy
|
||||||
|
- PlayerPoints
|
||||||
|
- Denizen
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version = 6.55.4
|
version = 6.57.2
|
||||||
plugin-name = eco
|
plugin-name = eco
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
Reference in New Issue
Block a user