Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdbe5b141a | ||
|
|
08c3fc0cfa | ||
|
|
8f758fb100 | ||
|
|
ec339b0ecd | ||
|
|
9dedfb86a5 | ||
|
|
0146cff8d3 | ||
|
|
2454d99d84 | ||
|
|
7d9b1bc266 | ||
|
|
77c56c46a8 | ||
|
|
85303098a7 | ||
|
|
821dc62d56 | ||
|
|
f9af4a9e66 | ||
|
|
41b9d6b01d | ||
|
|
7a521acccf | ||
|
|
49233aef88 | ||
|
|
c5b47ed073 | ||
|
|
ddcef7cf0c | ||
|
|
0f86e1c1c1 | ||
|
|
f0f7e229ea | ||
|
|
ea674a3757 | ||
|
|
b7c51eba5e | ||
|
|
1127bf1700 | ||
|
|
376e3284fb | ||
|
|
12f355b205 | ||
|
|
f4b02591e8 | ||
|
|
f843725cf5 | ||
|
|
ed0536c188 | ||
|
|
849e005095 | ||
|
|
927d61dd6b | ||
|
|
9285cffc56 | ||
|
|
1b6c90e87d | ||
|
|
c79de6fbc1 | ||
|
|
fc83ebbb34 | ||
|
|
f330cc954c | ||
|
|
df4f98251c | ||
|
|
74861e9c01 | ||
|
|
7dad9d7875 | ||
|
|
338b9b2d4e | ||
|
|
f6d83867f3 | ||
|
|
bb632ac849 | ||
|
|
793f946b44 | ||
|
|
519a59cc88 | ||
|
|
79b1bff547 | ||
|
|
17ee1ac2ff | ||
|
|
a6fa446d95 | ||
|
|
2f98c0ace5 | ||
|
|
60d7abcda8 | ||
|
|
69a5fa81b4 | ||
|
|
0316e627e1 | ||
|
|
5bc5b47bf8 | ||
|
|
a9c906843d | ||
|
|
85861971d3 | ||
|
|
bdb24e5a14 | ||
|
|
cb481d4532 | ||
|
|
97fba3e243 | ||
|
|
e47c6387a2 | ||
|
|
00df39097c | ||
|
|
efcb406e9a | ||
|
|
9e92ea6062 | ||
|
|
9dbc25df6f | ||
|
|
bc85c5232e | ||
|
|
2f4783f13e | ||
|
|
614241a058 | ||
|
|
c541adb557 | ||
|
|
a484eecc8f | ||
|
|
3933e38891 | ||
|
|
1d5345b367 | ||
|
|
f8513ff1e9 | ||
|
|
ca9c940b2b | ||
|
|
af198d30f7 | ||
|
|
637b239c66 | ||
|
|
124c059294 | ||
|
|
f1d0bd901d | ||
|
|
20f4bf4e78 | ||
|
|
595bc76294 | ||
|
|
9a66e78dcd | ||
|
|
0fcf229bfb | ||
|
|
d2ffc43b17 | ||
|
|
c50f69b372 | ||
|
|
f5eafafc4c | ||
|
|
39372c9b1a | ||
|
|
4c64f03aa1 |
@@ -39,7 +39,7 @@ and many more.
|
||||
# For developers
|
||||
|
||||
## Javadoc
|
||||
The 6.13.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.13.0/javadoc/)
|
||||
The 6.27.2 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.27.2/javadoc/)
|
||||
|
||||
## Plugin Information
|
||||
|
||||
@@ -68,7 +68,7 @@ dependencies {
|
||||
}
|
||||
```
|
||||
|
||||
Replace `Tag` with a release tag for eco, eg `6.13.0`.
|
||||
Replace `Tag` with a release tag for eco, eg `6.27.2`.
|
||||
|
||||
Maven:
|
||||
|
||||
@@ -88,7 +88,7 @@ Maven:
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Replace `Tag` with a release tag for eco, eg `6.13.0`.
|
||||
Replace `Tag` with a release tag for eco, eg `6.27.2`.
|
||||
|
||||
## Build locally:
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@ dependencies {
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
build.dependsOn publishToMavenLocal
|
||||
|
||||
publishing {
|
||||
|
||||
@@ -694,7 +694,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
||||
public final FileConfiguration getConfig() {
|
||||
this.getLogger().warning("Call to default config method in eco plugin!");
|
||||
|
||||
return Objects.requireNonNull(this.getConfigYml().getBukkitHandle());
|
||||
return Objects.requireNonNull(this.getConfigYml().toBukkit());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Prerequisite {
|
||||
*
|
||||
* @deprecated Use {@link EconomyManager#hasRegistrations()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
public static final Prerequisite HAS_VAULT = new Prerequisite(
|
||||
() -> ClassUtils.exists("net.milkbowl.vault.economy.Economy"),
|
||||
"Requires server to have vault"
|
||||
@@ -54,7 +54,7 @@ public class Prerequisite {
|
||||
*
|
||||
* @deprecated eco no longer supports versions before 1.17.
|
||||
*/
|
||||
@Deprecated(since = "6.25.2")
|
||||
@Deprecated(since = "6.25.2", forRemoval = true)
|
||||
public static final Prerequisite HAS_1_17 = new Prerequisite(
|
||||
() -> ProxyConstants.NMS_VERSION.contains("17") || HAS_1_18.isMet(),
|
||||
"Requires server to be running 1.17+"
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.List;
|
||||
/**
|
||||
* Interface for all command implementations.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public interface CommandBase {
|
||||
/**
|
||||
* Get command name.
|
||||
@@ -81,7 +82,7 @@ public interface CommandBase {
|
||||
* @see CommandHandler
|
||||
* @deprecated Use {@link CommandBase#onExecute(CommandSender, List)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
CommandHandler getHandler();
|
||||
|
||||
/**
|
||||
@@ -91,7 +92,7 @@ public interface CommandBase {
|
||||
* @see CommandHandler
|
||||
* @deprecated Handlers have been deprecated.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
void setHandler(@NotNull CommandHandler handler);
|
||||
|
||||
/**
|
||||
@@ -101,7 +102,7 @@ public interface CommandBase {
|
||||
* @see TabCompleteHandler
|
||||
* @deprecated Use {@link CommandBase#tabComplete(CommandSender, List)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
TabCompleteHandler getTabCompleter();
|
||||
|
||||
/**
|
||||
@@ -111,6 +112,6 @@ public interface CommandBase {
|
||||
* @see TabCompleteHandler
|
||||
* @deprecated Handlers have been deprecated.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
void setTabCompleter(@NotNull TabCompleteHandler handler);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
* update to use the new system: {@link CommandBase#onExecute(CommandSender, List)}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@Deprecated(since = "6.17.0")
|
||||
@Deprecated(since = "6.17.0", forRemoval = true)
|
||||
public interface CommandHandler {
|
||||
/**
|
||||
* The code to be called on execution.
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.List;
|
||||
* update to use the new system: {@link CommandBase#tabComplete(CommandSender, List)}
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@Deprecated(since = "6.17.0")
|
||||
@Deprecated(since = "6.17.0", forRemoval = true)
|
||||
public interface TabCompleteHandler {
|
||||
/**
|
||||
* Handle Tab Completion.
|
||||
|
||||
@@ -2,8 +2,6 @@ package com.willfp.eco.core.command.impl;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.command.CommandBase;
|
||||
import com.willfp.eco.core.command.CommandHandler;
|
||||
import com.willfp.eco.core.command.TabCompleteHandler;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.StringUtil;
|
||||
@@ -23,7 +21,7 @@ import java.util.stream.Collectors;
|
||||
* in order to execute the command-specific code. It's essentially an internal
|
||||
* layer, hence why it's a package-private class.
|
||||
*/
|
||||
@SuppressWarnings({"DeprecatedIsStillUsed"})
|
||||
@SuppressWarnings({"DeprecatedIsStillUsed", "removal"})
|
||||
abstract class HandledCommand implements CommandBase {
|
||||
/**
|
||||
* The plugin.
|
||||
@@ -54,14 +52,14 @@ abstract class HandledCommand implements CommandBase {
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
private CommandHandler handler = null;
|
||||
private com.willfp.eco.core.command.CommandHandler handler = null;
|
||||
|
||||
/**
|
||||
* The tab completion code to be executed in the command.
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
private TabCompleteHandler tabCompleter = null;
|
||||
private com.willfp.eco.core.command.TabCompleteHandler tabCompleter = null;
|
||||
|
||||
/**
|
||||
* All subcommands for the command.
|
||||
@@ -256,27 +254,27 @@ abstract class HandledCommand implements CommandBase {
|
||||
return this.subcommands;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
@Override
|
||||
public @Nullable CommandHandler getHandler() {
|
||||
public @Nullable com.willfp.eco.core.command.CommandHandler getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
@Override
|
||||
public @Nullable TabCompleteHandler getTabCompleter() {
|
||||
public @Nullable com.willfp.eco.core.command.TabCompleteHandler getTabCompleter() {
|
||||
return this.tabCompleter;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
@Override
|
||||
public void setHandler(@Nullable final CommandHandler handler) {
|
||||
public void setHandler(@Nullable final com.willfp.eco.core.command.CommandHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
@Override
|
||||
public void setTabCompleter(@Nullable final TabCompleteHandler tabCompleter) {
|
||||
public void setTabCompleter(@Nullable final com.willfp.eco.core.command.TabCompleteHandler tabCompleter) {
|
||||
this.tabCompleter = tabCompleter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.willfp.eco.core.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Builder for configs to create them programmatically.
|
||||
*/
|
||||
public class BuildableConfig extends TransientConfig {
|
||||
/**
|
||||
* Create a new empty config builder.
|
||||
*/
|
||||
public BuildableConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to the config builder.
|
||||
*
|
||||
* @param path The path.
|
||||
* @param object The object.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BuildableConfig add(@NotNull final String path,
|
||||
@Nullable final Object object) {
|
||||
set(path, object);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.core.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Config types, classified by file extension.
|
||||
*/
|
||||
@@ -7,10 +9,28 @@ public enum ConfigType {
|
||||
/**
|
||||
* .json config.
|
||||
*/
|
||||
JSON,
|
||||
JSON("json"),
|
||||
|
||||
/**
|
||||
* .yml config.
|
||||
*/
|
||||
YAML
|
||||
YAML("yml");
|
||||
|
||||
/**
|
||||
* The file extension.
|
||||
*/
|
||||
private final String extension;
|
||||
|
||||
ConfigType(@NotNull final String extension) {
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension.
|
||||
*
|
||||
* @return The extension.
|
||||
*/
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,17 @@ package com.willfp.eco.core.config;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -18,10 +23,19 @@ import java.util.Map;
|
||||
*/
|
||||
public class TransientConfig extends ConfigWrapper<Config> {
|
||||
/**
|
||||
* @param config The ConfigurationSection handle.
|
||||
*/
|
||||
public TransientConfig(@NotNull final ConfigurationSection config) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exists for backwards compatibility, YamlConfigurations are ConfigurationSections.
|
||||
*
|
||||
* @param config The YamlConfiguration handle.
|
||||
*/
|
||||
public TransientConfig(@NotNull final YamlConfiguration config) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(config));
|
||||
this((ConfigurationSection) config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,20 +47,50 @@ public class TransientConfig extends ConfigWrapper<Config> {
|
||||
)) : new TransientConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file The File.
|
||||
* @deprecated Specify the config type to prevent bugs.
|
||||
*/
|
||||
@Deprecated(since = "6.30.0", forRemoval = true)
|
||||
public TransientConfig(@Nullable final File file) {
|
||||
this(file, ConfigType.YAML);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file The file.
|
||||
* @param type The config type to try read from.
|
||||
*/
|
||||
public TransientConfig(@Nullable final File file,
|
||||
@NotNull final ConfigType type) {
|
||||
super(file != null ? Eco.getHandler().getConfigFactory().createConfig(readFile(file), type)
|
||||
: new TransientConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty transient config.
|
||||
*
|
||||
* @param values The values.
|
||||
*/
|
||||
public TransientConfig(@NotNull final Map<String, Object> values) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(values));
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(values, ConfigType.YAML));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty transient config.
|
||||
*
|
||||
* @param values The values.
|
||||
* @param type The type.
|
||||
*/
|
||||
public TransientConfig(@NotNull final Map<String, Object> values,
|
||||
@NotNull final ConfigType type) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(values, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty transient config.
|
||||
*/
|
||||
public TransientConfig() {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig("", ConfigType.YAML));
|
||||
this(new HashMap<>(), ConfigType.JSON);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,4 +101,22 @@ public class TransientConfig extends ConfigWrapper<Config> {
|
||||
@NotNull final ConfigType type) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(contents, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a file to a string.
|
||||
*
|
||||
* @param file The file.
|
||||
* @return The string.
|
||||
*/
|
||||
private static String readFile(@Nullable final File file) {
|
||||
if (file == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
return Files.readString(file.toPath());
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import com.willfp.eco.core.config.BuildableConfig;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.TransientConfig;
|
||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* All configs implement this interface.
|
||||
@@ -18,7 +27,7 @@ import java.util.Objects;
|
||||
* Contains all methods that must exist in yaml and json configurations.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Config extends Cloneable {
|
||||
public interface Config extends Cloneable, PlaceholderInjectable {
|
||||
/**
|
||||
* Clears cache.
|
||||
*/
|
||||
@@ -48,6 +57,19 @@ public interface Config extends Cloneable {
|
||||
@NotNull
|
||||
List<String> getKeys(boolean deep);
|
||||
|
||||
/**
|
||||
* Recurse config keys.
|
||||
*
|
||||
* @param found The found keys.
|
||||
* @param root The root.
|
||||
* @return The keys.
|
||||
*/
|
||||
@NotNull
|
||||
default List<String> recurseKeys(@NotNull Set<String> found,
|
||||
@NotNull String root) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object from config.
|
||||
* Default implementations call {@link org.bukkit.configuration.file.YamlConfiguration#get(String)}.
|
||||
@@ -238,35 +260,6 @@ public interface Config extends Cloneable {
|
||||
return getString(path, false, StringUtils.FormatOption.WITHOUT_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the string should be formatted.
|
||||
* @return The found value, or an empty string if not found.
|
||||
* @deprecated Since 6.18.0, {@link Config#getString(String)} is not formatted by default.
|
||||
*/
|
||||
@Deprecated(since = "6.18.0")
|
||||
default String getString(@NotNull String path,
|
||||
boolean format) {
|
||||
return this.getString(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param option The format option.
|
||||
* @return The found value, or an empty string if not found.
|
||||
* @deprecated Use {@link Config#getFormattedString(String, StringUtils.FormatOption)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
default String getString(@NotNull String path,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return this.getString(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
@@ -319,36 +312,6 @@ public interface Config extends Cloneable {
|
||||
return getStringOrNull(path, false, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the string should be formatted.
|
||||
* @return The found value, or null if not found.
|
||||
* @deprecated Since 6.18.0, {@link Config#getString(String)} is not formatted by default.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "6.18.0")
|
||||
default String getStringOrNull(@NotNull String path,
|
||||
boolean format) {
|
||||
return this.getStringOrNull(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param option The format option.
|
||||
* @return The found value, or null if not found.
|
||||
* @deprecated Use {@link Config#getFormattedString(String, StringUtils.FormatOption)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
default String getStringOrNull(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return this.getStringOrNull(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
@@ -403,36 +366,6 @@ public interface Config extends Cloneable {
|
||||
return getStrings(path, false, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the strings should be formatted.
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
* @deprecated Since 6.18.0, {@link Config#getString(String)} is not formatted by default.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "6.18.0")
|
||||
default List<String> getStrings(@NotNull String path,
|
||||
boolean format) {
|
||||
return this.getStrings(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param option The format option.
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
* @deprecated Use {@link Config#getFormattedStrings(String, StringUtils.FormatOption)} instead.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
default List<String> getStrings(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return getStrings(path, false, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
@@ -491,36 +424,6 @@ public interface Config extends Cloneable {
|
||||
return getStringsOrNull(path, false, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the strings should be formatted.
|
||||
* @return The found value, or null if not found.
|
||||
* @deprecated Since 6.18.0, {@link Config#getString(String)} is not formatted by default.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "6.18.0")
|
||||
default List<String> getStringsOrNull(@NotNull String path,
|
||||
boolean format) {
|
||||
return getStringsOrNull(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param option The format option.
|
||||
* @return The found value, or null if not found.
|
||||
* @deprecated Use {@link Config#getFormattedStringsOrNull(String, StringUtils.FormatOption)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
default List<String> getStringsOrNull(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return getStringsOrNull(path, false, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
@@ -563,7 +466,7 @@ public interface Config extends Cloneable {
|
||||
*/
|
||||
default double getDoubleFromExpression(@NotNull String path,
|
||||
@Nullable Player player) {
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player);
|
||||
return NumberUtils.evaluateExpression(this.getString(path), player, this.getInjectedPlaceholders());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,4 +532,48 @@ public interface Config extends Cloneable {
|
||||
* @return The clone.
|
||||
*/
|
||||
Config clone();
|
||||
|
||||
@Override
|
||||
default void injectPlaceholders(@NotNull Iterable<StaticPlaceholder> placeholders) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
default List<StaticPlaceholder> getInjectedPlaceholders() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clearInjectedPlaceholders() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the config to a map of values.
|
||||
*
|
||||
* @return The values.
|
||||
*/
|
||||
default Map<String, Object> toMap() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the config to a map of values.
|
||||
*
|
||||
* @return The values.
|
||||
*/
|
||||
default ConfigurationSection toBukkit() {
|
||||
YamlConfiguration empty = new YamlConfiguration();
|
||||
empty.createSection("temp", this.toMap());
|
||||
return empty.getConfigurationSection("temp");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new config builder.
|
||||
*
|
||||
* @return The builder.
|
||||
*/
|
||||
static BuildableConfig builder() {
|
||||
return new BuildableConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* JSON config.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
public interface JSONConfig extends Config {
|
||||
/**
|
||||
* Get a list of subsections from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
*/
|
||||
@NotNull
|
||||
default List<JSONConfig> getSubsections(@NotNull String path) {
|
||||
return Objects.requireNonNullElse(getSubsectionsOrNull(path), new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of subsections from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
List<JSONConfig> getSubsectionsOrNull(@NotNull String path);
|
||||
|
||||
|
||||
/**
|
||||
* Get subsection from config.
|
||||
*
|
||||
* @param path The key to check.
|
||||
* @return The subsection. Throws NPE if not found.
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
JSONConfig getSubsection(@NotNull String path);
|
||||
|
||||
/**
|
||||
* Get subsection from config.
|
||||
*
|
||||
* @param path The key to check.
|
||||
* @return The subsection, or null if not found.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
JSONConfig getSubsectionOrNull(@NotNull String path);
|
||||
|
||||
@Override
|
||||
JSONConfig clone();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
@@ -47,14 +47,21 @@ public interface LoadableConfig extends Config {
|
||||
/**
|
||||
* Get bukkit {@link YamlConfiguration}.
|
||||
* <p>
|
||||
* This method is not recommended unless absolutely required as it
|
||||
* only returns true if the type of config is {@link com.willfp.eco.core.config.ConfigType#YAML},
|
||||
* and if the handle is an {@link YamlConfiguration} specifically. This depends on the internals
|
||||
* and the implementation, and so may cause problems - it exists mostly for parity with
|
||||
* {@link JavaPlugin#getConfig()}.
|
||||
* This used to represent the underlying config, but since 6.30.0 configs use
|
||||
* their own implementations internally, without relying on bukkit.
|
||||
*
|
||||
* @return The config, or null if config is not yaml-based.
|
||||
* @deprecated Use toBukkit() instead.
|
||||
*/
|
||||
@Nullable
|
||||
YamlConfiguration getBukkitHandle();
|
||||
@Deprecated(since = "6.30.0", forRemoval = true)
|
||||
default YamlConfiguration getBukkitHandle() {
|
||||
return this.toBukkit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the config to a bukkit {@link YamlConfiguration}.
|
||||
*/
|
||||
@NotNull
|
||||
YamlConfiguration toBukkit();
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
/**
|
||||
* Interface for configs that wrap an {@link YamlConfiguration}.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
@SuppressWarnings("DeprecatedIsStillUsed")
|
||||
public interface WrappedYamlConfiguration {
|
||||
/**
|
||||
* Get the ConfigurationSection handle.
|
||||
*
|
||||
* @return The handle.
|
||||
*/
|
||||
YamlConfiguration getBukkitHandle();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package com.willfp.eco.core.config.json;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.json).
|
||||
* <p>
|
||||
* Automatically updates.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class JSONBaseConfig extends LoadableJSONConfigWrapper {
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
*/
|
||||
protected JSONBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
super(
|
||||
(JSONConfig)
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
"",
|
||||
plugin.getClass(),
|
||||
removeUnused,
|
||||
ConfigType.JSON,
|
||||
updateBlacklist
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected JSONBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin) {
|
||||
super(
|
||||
(JSONConfig)
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
"",
|
||||
plugin.getClass(),
|
||||
removeUnused,
|
||||
ConfigType.JSON
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
*/
|
||||
protected JSONBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
this(configName, removeUnused, (PluginLike) plugin, updateBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected JSONBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin) {
|
||||
this(configName, removeUnused, (PluginLike) plugin);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.willfp.eco.core.config.json;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in one of two places:
|
||||
* <ul>
|
||||
* <li>Plugin base directory (eg config.yml, lang.yml)</li>
|
||||
* <li>Other extension's configs</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Automatically updates.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class JSONExtendableConfig extends LoadableJSONConfigWrapper {
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
* @param subDirectoryPath The subdirectory path.
|
||||
* @param source The class that owns the resource.
|
||||
*/
|
||||
protected JSONExtendableConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin,
|
||||
@NotNull final Class<?> source,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
super(
|
||||
(JSONConfig)
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
ConfigType.JSON,
|
||||
updateBlacklist
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
* @param subDirectoryPath The subdirectory path.
|
||||
* @param source The class that owns the resource.
|
||||
*/
|
||||
protected JSONExtendableConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final Class<?> source,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
this(configName, removeUnused, (PluginLike) plugin, source, subDirectoryPath, updateBlacklist);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.willfp.eco.core.config.json;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Non-updatable JSON config that exists within a plugin jar.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class JSONStaticBaseConfig extends LoadableJSONConfigWrapper {
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.json, lang.json).
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @param configName The name of the config
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected JSONStaticBaseConfig(@NotNull final String configName,
|
||||
@NotNull final PluginLike plugin) {
|
||||
super((JSONConfig) Eco.getHandler().getConfigFactory().createLoadableConfig(configName, plugin, "", plugin.getClass(), ConfigType.JSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.json, lang.json).
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @param configName The name of the config
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected JSONStaticBaseConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin) {
|
||||
this(configName, (PluginLike) plugin);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.willfp.eco.core.config.json;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.json.wrapper.JSONConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Raw JSON config with a map of values at its core.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public class JSONTransientConfig extends JSONConfigWrapper {
|
||||
/**
|
||||
* Config implementation for passing maps.
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @param values The map of values.
|
||||
*/
|
||||
public JSONTransientConfig(@NotNull final Map<String, Object> values) {
|
||||
super((JSONConfig) Eco.getHandler().getConfigFactory().createConfig(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty JSON config.
|
||||
*/
|
||||
public JSONTransientConfig() {
|
||||
super((JSONConfig) Eco.getHandler().getConfigFactory().createConfig(new HashMap<>()));
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.willfp.eco.core.config.json.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper to handle the backend JSON config implementations.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class JSONConfigWrapper extends ConfigWrapper<JSONConfig> implements JSONConfig {
|
||||
/**
|
||||
* Create a config wrapper.
|
||||
*
|
||||
* @param handle The handle.
|
||||
*/
|
||||
protected JSONConfigWrapper(@NotNull final JSONConfig handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull List<JSONConfig> getSubsections(@NotNull final String path) {
|
||||
return this.getHandle().getSubsections(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<JSONConfig> getSubsectionsOrNull(@NotNull final String path) {
|
||||
return this.getHandle().getSubsectionsOrNull(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JSONConfig getSubsection(@NotNull final String path) {
|
||||
return this.getHandle().getSubsection(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable JSONConfig getSubsectionOrNull(@NotNull final String path) {
|
||||
return this.getHandle().getSubsectionOrNull(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONConfig clone() {
|
||||
return this.getHandle().clone();
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.willfp.eco.core.config.json.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Wrapper to handle the backend loadable JSON config implementations.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class LoadableJSONConfigWrapper extends JSONConfigWrapper implements LoadableConfig {
|
||||
/**
|
||||
* Create a config wrapper.
|
||||
*
|
||||
* @param handle The handle.
|
||||
*/
|
||||
protected LoadableJSONConfigWrapper(@NotNull final JSONConfig handle) {
|
||||
super(handle);
|
||||
|
||||
Validate.isTrue(handle instanceof LoadableConfig, "Wrapped config must be loadable!");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createFile() {
|
||||
((LoadableConfig) this.getHandle()).createFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourcePath() {
|
||||
return ((LoadableConfig) this.getHandle()).getResourcePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
((LoadableConfig) this.getHandle()).save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getConfigFile() {
|
||||
return ((LoadableConfig) this.getHandle()).getConfigFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ((LoadableConfig) this.getHandle()).getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable YamlConfiguration getBukkitHandle() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.config.updating;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -29,7 +30,8 @@ import java.lang.annotation.Target;
|
||||
* }</pre>
|
||||
* <p>
|
||||
* If using kotlin, you have to annotate the method with {@code @JvmStatic}
|
||||
* in order to prevent null pointer exceptions.
|
||||
* in order to prevent null pointer exceptions - this also means that you cannot
|
||||
* have config updater methods in companion objects.
|
||||
* <p>
|
||||
* Config update methods in all classes in a plugin jar will be called
|
||||
* on reload.
|
||||
@@ -39,5 +41,6 @@ import java.lang.annotation.Target;
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Documented
|
||||
public @interface ConfigUpdater {
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -59,15 +59,17 @@ public interface ConfigFactory {
|
||||
* @param config The handle.
|
||||
* @return The config implementation.
|
||||
*/
|
||||
Config createConfig(@NotNull YamlConfiguration config);
|
||||
Config createConfig(@NotNull ConfigurationSection config);
|
||||
|
||||
/**
|
||||
* Create config.
|
||||
*
|
||||
* @param values The values.
|
||||
* @param type The config type.
|
||||
* @return The config implementation.
|
||||
*/
|
||||
Config createConfig(@NotNull Map<String, Object> values);
|
||||
Config createConfig(@NotNull Map<String, Object> values,
|
||||
@NotNull ConfigType type);
|
||||
|
||||
/**
|
||||
* Create config.
|
||||
|
||||
@@ -2,11 +2,14 @@ package com.willfp.eco.core.config.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Configs from eco have an internal implementation,
|
||||
@@ -59,6 +62,12 @@ public abstract class ConfigWrapper<T extends Config> implements Config {
|
||||
return handle.getKeys(deep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> recurseKeys(@NotNull final Set<String> found,
|
||||
@NotNull final String root) {
|
||||
return handle.recurseKeys(found, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object get(@NotNull final String path) {
|
||||
return handle.get(path);
|
||||
@@ -134,6 +143,31 @@ public abstract class ConfigWrapper<T extends Config> implements Config {
|
||||
return handle.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlaceholders(@NotNull final StaticPlaceholder... placeholders) {
|
||||
handle.injectPlaceholders(placeholders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectPlaceholders(@NotNull final Iterable<StaticPlaceholder> placeholders) {
|
||||
handle.injectPlaceholders(placeholders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StaticPlaceholder> getInjectedPlaceholders() {
|
||||
return handle.getInjectedPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearInjectedPlaceholders() {
|
||||
handle.clearInjectedPlaceholders();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> toMap() {
|
||||
return this.handle.toMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handle.
|
||||
*
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.willfp.eco.core.config.wrapper;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -47,7 +46,7 @@ public abstract class LoadableConfigWrapper extends ConfigWrapper<LoadableConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable YamlConfiguration getBukkitHandle() {
|
||||
return this.getHandle().getBukkitHandle();
|
||||
public @NotNull YamlConfiguration toBukkit() {
|
||||
return this.getHandle().toBukkit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
|
||||
* <p>
|
||||
* Automatically updates.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class YamlBaseConfig extends LoadableYamlConfigWrapper {
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
*/
|
||||
protected YamlBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
super(
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
"",
|
||||
plugin.getClass(),
|
||||
removeUnused,
|
||||
ConfigType.YAML,
|
||||
updateBlacklist
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected YamlBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin) {
|
||||
super(
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
"",
|
||||
plugin.getClass(),
|
||||
removeUnused,
|
||||
ConfigType.YAML
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
*/
|
||||
protected YamlBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
this(configName, removeUnused, (PluginLike) plugin, updateBlacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected YamlBaseConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin) {
|
||||
this(configName, removeUnused, (PluginLike) plugin);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in one of two places:
|
||||
* <ul>
|
||||
* <li>Plugin base directory (eg config.yml, lang.yml)</li>
|
||||
* <li>Other extension's configs</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Automatically updates.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class YamlExtendableConfig extends LoadableYamlConfigWrapper {
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
* @param subDirectoryPath The subdirectory path.
|
||||
* @param source The class that owns the resource.
|
||||
*/
|
||||
protected YamlExtendableConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final PluginLike plugin,
|
||||
@NotNull final Class<?> source,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
super(
|
||||
Eco.getHandler().getConfigFactory().createUpdatableConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
ConfigType.YAML,
|
||||
updateBlacklist
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configName The name of the config
|
||||
* @param removeUnused Whether keys not present in the default config should be removed on update.
|
||||
* @param plugin The plugin.
|
||||
* @param updateBlacklist Substring of keys to not add/remove keys for.
|
||||
* @param subDirectoryPath The subdirectory path.
|
||||
* @param source The class that owns the resource.
|
||||
*/
|
||||
protected YamlExtendableConfig(@NotNull final String configName,
|
||||
final boolean removeUnused,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final Class<?> source,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
this(configName, removeUnused, (PluginLike) plugin, source, subDirectoryPath, updateBlacklist);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginLike;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Non-updatable yaml config that exists within a plugin jar.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class YamlStaticBaseConfig extends LoadableYamlConfigWrapper {
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @param configName The name of the config
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected YamlStaticBaseConfig(@NotNull final String configName,
|
||||
@NotNull final PluginLike plugin) {
|
||||
super(Eco.getHandler().getConfigFactory().createLoadableConfig(configName, plugin, "", plugin.getClass(), ConfigType.YAML));
|
||||
}
|
||||
|
||||
/**
|
||||
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @param configName The name of the config
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
protected YamlStaticBaseConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin) {
|
||||
this(configName, (PluginLike) plugin);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.config.ConfigType;
|
||||
import com.willfp.eco.core.config.yaml.wrapper.YamlConfigWrapper;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
/**
|
||||
* Config implementation for passing YamlConfigurations.
|
||||
* <p>
|
||||
* Does not automatically update.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public class YamlTransientConfig extends YamlConfigWrapper {
|
||||
/**
|
||||
* @param config The YamlConfiguration handle.
|
||||
*/
|
||||
public YamlTransientConfig(@NotNull final YamlConfiguration config) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contents The contents of the config.
|
||||
*/
|
||||
public YamlTransientConfig(@NotNull final String contents) {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(contents, ConfigType.YAML));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty transient config.
|
||||
*/
|
||||
public YamlTransientConfig() {
|
||||
super(Eco.getHandler().getConfigFactory().createConfig(YamlConfiguration.loadConfiguration(new StringReader(""))));
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Wrapper to handle the backend loadable yaml config implementations.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class LoadableYamlConfigWrapper extends YamlConfigWrapper implements LoadableConfig {
|
||||
/**
|
||||
* Create a config wrapper.
|
||||
*
|
||||
* @param handle The handle.
|
||||
*/
|
||||
protected LoadableYamlConfigWrapper(@NotNull final Config handle) {
|
||||
super(handle);
|
||||
|
||||
Validate.isTrue(handle instanceof LoadableConfig, "Wrapped config must be loadable!");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void createFile() {
|
||||
((LoadableConfig) this.getHandle()).createFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourcePath() {
|
||||
return ((LoadableConfig) this.getHandle()).getResourcePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
((LoadableConfig) this.getHandle()).save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getConfigFile() {
|
||||
return ((LoadableConfig) this.getHandle()).getConfigFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return ((LoadableConfig) this.getHandle()).getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable YamlConfiguration getBukkitHandle() {
|
||||
return ((LoadableConfig) this.getHandle()).getBukkitHandle();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.willfp.eco.core.config.yaml.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration;
|
||||
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Wrapper to handle the backend yaml config implementations.
|
||||
*
|
||||
* @deprecated JSON and yml have full parity, use configs without a prefix instead,
|
||||
* eg {@link com.willfp.eco.core.config.TransientConfig}, {@link com.willfp.eco.core.config.BaseConfig}.
|
||||
* These configs will be removed eventually.
|
||||
*/
|
||||
@Deprecated(since = "6.17.0")
|
||||
public abstract class YamlConfigWrapper extends ConfigWrapper<Config> implements WrappedYamlConfiguration {
|
||||
/**
|
||||
* Create a config wrapper.
|
||||
*
|
||||
* @param handle The handle.
|
||||
*/
|
||||
protected YamlConfigWrapper(@NotNull final Config handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlConfiguration getBukkitHandle() {
|
||||
return ((WrappedYamlConfiguration) this.getHandle()).getBukkitHandle();
|
||||
}
|
||||
}
|
||||
@@ -40,9 +40,9 @@ public abstract class CustomGoal<T extends Mob> implements EntityGoal<T>, Target
|
||||
/**
|
||||
* Tick the goal.
|
||||
* <p>
|
||||
* Runs ever tick as long as {@link this#canUse()} returns true.
|
||||
* Runs ever tick as long as canUse returns true.
|
||||
* <p>
|
||||
* Runs after {@link this#start()}.
|
||||
* Runs after start().
|
||||
*/
|
||||
public void tick() {
|
||||
// Override when needed.
|
||||
@@ -51,7 +51,7 @@ public abstract class CustomGoal<T extends Mob> implements EntityGoal<T>, Target
|
||||
/**
|
||||
* Start the goal.
|
||||
* <p>
|
||||
* Runs once {@link this#canUse()} returns true.
|
||||
* Runs once canUse() returns true.
|
||||
*/
|
||||
public void start() {
|
||||
// Override when needed.
|
||||
@@ -60,7 +60,7 @@ public abstract class CustomGoal<T extends Mob> implements EntityGoal<T>, Target
|
||||
/**
|
||||
* Stop the goal.
|
||||
* <p>
|
||||
* Runs once {@link this#canUse()} returns false.
|
||||
* Runs once canUse() returns false.
|
||||
*/
|
||||
public void stop() {
|
||||
// Override when needed.
|
||||
|
||||
@@ -24,7 +24,7 @@ public interface FastItemStack {
|
||||
* @return A map of all enchantments.
|
||||
* @deprecated Poorly named method. Use getEnchants instead.
|
||||
*/
|
||||
@Deprecated(since = "6.24.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
default Map<Enchantment, Integer> getEnchantmentsOnItem(boolean checkStored) {
|
||||
return getEnchants(checkStored);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,13 @@ public interface Menu {
|
||||
*/
|
||||
Set<NamespacedKey> getKeys(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Re-render the menu for a player.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
void refresh(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Create a builder with a given amount of rows.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.willfp.eco.core.integrations.placeholder;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.Placeholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -10,10 +14,13 @@ import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A {@link PlaceholderEntry} is a placeholder in and of itself.
|
||||
* A placeholder entry is a placeholder in and of itself.
|
||||
* <p>
|
||||
* It should be fairly straightforward.
|
||||
*
|
||||
* @deprecated Confusing functionality with inconsistent nullability and poor naming.
|
||||
*/
|
||||
@Deprecated(since = "6.28.0", forRemoval = true)
|
||||
public class PlaceholderEntry {
|
||||
/**
|
||||
* The name of the placeholder, used in lookups.
|
||||
@@ -140,7 +147,28 @@ public class PlaceholderEntry {
|
||||
* Register the placeholder.
|
||||
*/
|
||||
public void register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
PlaceholderManager.registerPlaceholder(this.toModernPlaceholder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the placeholder to a modern placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
Placeholder toModernPlaceholder() {
|
||||
if (this.requiresPlayer) {
|
||||
return new PlayerPlaceholder(
|
||||
Objects.requireNonNullElse(plugin, Eco.getHandler().getEcoPlugin()),
|
||||
identifier,
|
||||
function
|
||||
);
|
||||
} else {
|
||||
return new PlayerlessPlaceholder(
|
||||
Objects.requireNonNullElse(plugin, Eco.getHandler().getEcoPlugin()),
|
||||
identifier,
|
||||
() -> function.apply(null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,11 +4,16 @@ import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.placeholder.Placeholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder;
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -19,11 +24,12 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Class to handle placeholder integrations.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public final class PlaceholderManager {
|
||||
/**
|
||||
* All registered placeholders.
|
||||
*/
|
||||
private static final Map<EcoPlugin, Map<String, PlaceholderEntry>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
private static final Map<EcoPlugin, Map<String, Placeholder>> REGISTERED_PLACEHOLDERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* All registered placeholder integrations.
|
||||
@@ -35,7 +41,7 @@ public final class PlaceholderManager {
|
||||
*/
|
||||
private static final LoadingCache<EntryWithPlayer, String> PLACEHOLDER_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||
.build(key -> key.entry.getResult(key.player));
|
||||
.build(key -> key.entry.getValue(key.player));
|
||||
|
||||
/**
|
||||
* Register a new placeholder integration.
|
||||
@@ -50,16 +56,31 @@ public final class PlaceholderManager {
|
||||
/**
|
||||
* Register a placeholder.
|
||||
*
|
||||
* @param expansion The {@link com.willfp.eco.core.integrations.placeholder.PlaceholderEntry} to register.
|
||||
* @param placeholder The placeholder to register.
|
||||
*/
|
||||
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
|
||||
EcoPlugin plugin = expansion.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : expansion.getPlugin();
|
||||
Map<String, PlaceholderEntry> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
public static void registerPlaceholder(@NotNull final Placeholder placeholder) {
|
||||
if (placeholder instanceof StaticPlaceholder) {
|
||||
throw new IllegalArgumentException("Static placeholders cannot be registered!");
|
||||
}
|
||||
|
||||
EcoPlugin plugin = placeholder.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : placeholder.getPlugin();
|
||||
Map<String, Placeholder> pluginPlaceholders = REGISTERED_PLACEHOLDERS
|
||||
.getOrDefault(plugin, new HashMap<>());
|
||||
pluginPlaceholders.put(expansion.getIdentifier(), expansion);
|
||||
pluginPlaceholders.put(placeholder.getIdentifier(), placeholder);
|
||||
REGISTERED_PLACEHOLDERS.put(plugin, pluginPlaceholders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a placeholder.
|
||||
*
|
||||
* @param placeholder The placeholder to register.
|
||||
* @deprecated Uses old placeholder system.
|
||||
*/
|
||||
@Deprecated(since = "6.28.0", forRemoval = true)
|
||||
public static void registerPlaceholder(@NotNull final PlaceholderEntry placeholder) {
|
||||
registerPlaceholder(placeholder.toModernPlaceholder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of a placeholder with respect to a player.
|
||||
*
|
||||
@@ -82,29 +103,36 @@ public final class PlaceholderManager {
|
||||
* @param plugin The plugin for the placeholder.
|
||||
* @return The value of the placeholder.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getResult(@Nullable final Player player,
|
||||
@NotNull final String identifier,
|
||||
@Nullable final EcoPlugin plugin) {
|
||||
EcoPlugin owner = plugin == null ? Eco.getHandler().getEcoPlugin() : plugin;
|
||||
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
|
||||
Placeholder placeholder = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
|
||||
|
||||
if (entry == null && plugin != null) {
|
||||
PlaceholderEntry alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
|
||||
if (placeholder == null && plugin != null) {
|
||||
Placeholder alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
|
||||
.get(identifier.toLowerCase());
|
||||
if (alternate != null) {
|
||||
entry = alternate;
|
||||
placeholder = alternate;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) {
|
||||
if (placeholder == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (player == null && entry.requiresPlayer()) {
|
||||
if (placeholder instanceof PlayerPlaceholder playerPlaceholder) {
|
||||
if (player == null) {
|
||||
return "";
|
||||
} else {
|
||||
return PLACEHOLDER_CACHE.get(new EntryWithPlayer(playerPlaceholder, player));
|
||||
}
|
||||
} else if (placeholder instanceof PlayerlessPlaceholder playerlessPlaceholder) {
|
||||
return playerlessPlaceholder.getValue();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
return PLACEHOLDER_CACHE.get(new EntryWithPlayer(entry, player));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,10 +144,28 @@ public final class PlaceholderManager {
|
||||
*/
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player) {
|
||||
return translatePlaceholders(text, player, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate all placeholders with respect to a player.
|
||||
*
|
||||
* @param text The text that may contain placeholders to translate.
|
||||
* @param player The player to translate the placeholders with respect to.
|
||||
* @param statics Extra static placeholders.
|
||||
* @return The text, translated.
|
||||
*/
|
||||
public static String translatePlaceholders(@NotNull final String text,
|
||||
@Nullable final Player player,
|
||||
@NotNull final List<StaticPlaceholder> statics) {
|
||||
String processed = text;
|
||||
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
|
||||
processed = integration.translate(processed, player);
|
||||
}
|
||||
for (StaticPlaceholder placeholder : statics) {
|
||||
// Do I know this is a bad way of doing this? Yes.
|
||||
processed = processed.replace("%" + placeholder.getIdentifier() + "%", placeholder.getValue());
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
@@ -138,8 +184,8 @@ public final class PlaceholderManager {
|
||||
return found;
|
||||
}
|
||||
|
||||
private static record EntryWithPlayer(@NotNull PlaceholderEntry entry,
|
||||
@Nullable Player player) {
|
||||
private record EntryWithPlayer(@NotNull PlayerPlaceholder entry,
|
||||
@NotNull Player player) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import com.willfp.eco.core.recipe.parts.UnrestrictedMaterialTestableItem;
|
||||
import com.willfp.eco.util.NamespacedKeyUtils;
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import org.bukkit.Material;
|
||||
@@ -155,11 +156,16 @@ public final class Items {
|
||||
String[] split = args[0].toLowerCase().split(":");
|
||||
|
||||
if (split.length == 1) {
|
||||
Material material = Material.getMaterial(args[0].toUpperCase());
|
||||
String itemType = args[0];
|
||||
boolean isWildcard = itemType.startsWith("*");
|
||||
if (isWildcard) {
|
||||
itemType = itemType.substring(1);
|
||||
}
|
||||
Material material = Material.getMaterial(itemType.toUpperCase());
|
||||
if (material == null || material == Material.AIR) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
item = new MaterialTestableItem(material);
|
||||
item = isWildcard ? new UnrestrictedMaterialTestableItem(material) : new MaterialTestableItem(material);
|
||||
}
|
||||
|
||||
if (split.length == 2) {
|
||||
@@ -183,11 +189,16 @@ public final class Items {
|
||||
This has been superseded by id amount
|
||||
*/
|
||||
if (part == null) {
|
||||
Material material = Material.getMaterial(split[0].toUpperCase());
|
||||
String itemType = split[0];
|
||||
boolean isWildcard = itemType.startsWith("*");
|
||||
if (isWildcard) {
|
||||
itemType = itemType.substring(1);
|
||||
}
|
||||
Material material = Material.getMaterial(itemType.toUpperCase());
|
||||
if (material == null || material == Material.AIR) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
item = new MaterialTestableItem(material);
|
||||
item = isWildcard ? new UnrestrictedMaterialTestableItem(material) : new MaterialTestableItem(material);
|
||||
stackAmount = Integer.parseInt(split[1]);
|
||||
} else {
|
||||
item = part;
|
||||
@@ -298,7 +309,7 @@ public final class Items {
|
||||
* @param itemStack The itemStack to check.
|
||||
* @return If is recipe.
|
||||
*/
|
||||
public static boolean isCustomItem(@NotNull final ItemStack itemStack) {
|
||||
public static boolean isCustomItem(@Nullable final ItemStack itemStack) {
|
||||
return getCustomItem(itemStack) != null;
|
||||
}
|
||||
|
||||
@@ -309,7 +320,11 @@ public final class Items {
|
||||
* @return The custom item, or null if not exists.
|
||||
*/
|
||||
@Nullable
|
||||
public static CustomItem getCustomItem(@NotNull final ItemStack itemStack) {
|
||||
public static CustomItem getCustomItem(@Nullable final ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CACHE.get(HashedItem.of(itemStack)).map(Items::getOrWrap).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public interface LookupHandler<T extends Testable<?>> {
|
||||
* <p>
|
||||
* You shouldn't override this method unless you're doing something
|
||||
* technically interesting or weird. This is the entry point for all
|
||||
* lookup parsers, {@link this#parse(String[])} is to specify implementation-specific
|
||||
* lookup parsers, parse() is to specify implementation-specific
|
||||
* parsing.
|
||||
*
|
||||
* @param key The key.
|
||||
@@ -56,7 +56,7 @@ public interface LookupHandler<T extends Testable<?>> {
|
||||
/**
|
||||
* Get the failsafe object.
|
||||
* <p>
|
||||
* A failsafe object should never pass {@link this#validate(Testable)}, as this will
|
||||
* A failsafe object should never pass validate(), as this will
|
||||
* cause issues with segment parsers. See {@link com.willfp.eco.core.items.ItemsLookupHandler} and
|
||||
* {@link com.willfp.eco.core.recipe.parts.EmptyTestableItem} for examples.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
|
||||
/**
|
||||
* A placeholder represents a string that can hold a value.
|
||||
*/
|
||||
public sealed interface Placeholder permits PlayerPlaceholder, PlayerlessPlaceholder, StaticPlaceholder {
|
||||
/**
|
||||
* Get the plugin that holds the placeholder.
|
||||
*
|
||||
* @return The plugin.
|
||||
*/
|
||||
EcoPlugin getPlugin();
|
||||
|
||||
/**
|
||||
* Get the identifier for the placeholder.
|
||||
*
|
||||
* @return The identifier.
|
||||
*/
|
||||
String getIdentifier();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a class that can have placeholders injected into it.
|
||||
*/
|
||||
public interface PlaceholderInjectable {
|
||||
/**
|
||||
* Inject placeholder.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
default void injectPlaceholders(@NotNull StaticPlaceholder... placeholders) {
|
||||
this.injectPlaceholders(List.of(placeholders));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject placeholder.
|
||||
*
|
||||
* @param placeholders The placeholders.
|
||||
*/
|
||||
void injectPlaceholders(@NotNull Iterable<StaticPlaceholder> placeholders);
|
||||
|
||||
/**
|
||||
* Clear injected placeholders.
|
||||
*/
|
||||
void clearInjectedPlaceholders();
|
||||
|
||||
/**
|
||||
* Get injected placeholders.
|
||||
*
|
||||
* @return Injected placeholders.
|
||||
*/
|
||||
List<StaticPlaceholder> getInjectedPlaceholders();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A placeholder that requires a player.
|
||||
*/
|
||||
public final class PlayerPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder given a player.
|
||||
*/
|
||||
private final Function<Player, String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public PlayerPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Function<Player, String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder for a given player.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue(@NotNull final Player player) {
|
||||
return function.apply(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
public PlayerPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof StaticPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A placeholder that does not require a player.
|
||||
*/
|
||||
public final class PlayerlessPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
|
||||
/**
|
||||
* The plugin for the placeholder.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public PlayerlessPlaceholder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String identifier,
|
||||
@NotNull final Supplier<String> function) {
|
||||
this.plugin = plugin;
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*
|
||||
* @return The placeholder.
|
||||
*/
|
||||
public PlayerlessPlaceholder register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof StaticPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier())
|
||||
&& Objects.equals(this.getPlugin(), that.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier(), this.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.willfp.eco.core.placeholder;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A placeholder that cannot be registered, and exists purely in injection.
|
||||
*/
|
||||
public final class StaticPlaceholder implements Placeholder {
|
||||
/**
|
||||
* The name of the placeholder.
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
/**
|
||||
* The function to retrieve the output of the placeholder.
|
||||
*/
|
||||
private final Supplier<String> function;
|
||||
|
||||
/**
|
||||
* Create a new player placeholder.
|
||||
*
|
||||
* @param identifier The identifier.
|
||||
* @param function The function to retrieve the value.
|
||||
*/
|
||||
public StaticPlaceholder(@NotNull final String identifier,
|
||||
@NotNull final Supplier<String> function) {
|
||||
this.identifier = identifier;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the placeholder.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return function.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EcoPlugin getPlugin() {
|
||||
return Eco.getHandler().getEcoPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof StaticPlaceholder that)) {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(this.getIdentifier(), that.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.getIdentifier());
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class ProxyError extends Error {
|
||||
* @param message The message to send.
|
||||
* @deprecated Proxy Errors should include a cause.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(forRemoval = true)
|
||||
public ProxyError(@NotNull final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
*
|
||||
* @deprecated Poorly named, exception when it's actually an error, contains doubly nested errors.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
public class UnsupportedVersionException extends ProxyError {
|
||||
/**
|
||||
@@ -16,7 +17,7 @@ public class UnsupportedVersionException extends ProxyError {
|
||||
* @param message The message to send.
|
||||
* @deprecated Use the default constructor.
|
||||
*/
|
||||
@Deprecated(since = "6.24.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
public UnsupportedVersionException(@NotNull final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.willfp.eco.core.recipe.parts;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Same as material testable items, but doesn't filter out custom items.
|
||||
*/
|
||||
public class UnrestrictedMaterialTestableItem extends MaterialTestableItem {
|
||||
/**
|
||||
* Create a new simple recipe part.
|
||||
*
|
||||
* @param material The material.
|
||||
*/
|
||||
public UnrestrictedMaterialTestableItem(@NotNull final Material material) {
|
||||
super(material);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the item matches the material.
|
||||
*
|
||||
* @param itemStack The item to test.
|
||||
* @return If the item is of the specified material.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(@Nullable final ItemStack itemStack) {
|
||||
return itemStack != null && itemStack.getType() == this.getMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.willfp.eco.core.recipe.recipes;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.Prerequisite;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.Recipes;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
@@ -139,12 +138,6 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(displayedItems));
|
||||
}
|
||||
|
||||
if (Prerequisite.HAS_1_18.isMet() && !Prerequisite.HAS_PAPER.isMet()) {
|
||||
if (Bukkit.getServer().getRecipe(this.getKey()) != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Bukkit.getServer().addRecipe(shapedRecipe);
|
||||
Bukkit.getServer().addRecipe(displayedRecipe);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
package com.willfp.eco.core.recipe.recipes;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.Recipes;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.GroupedTestableItems;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.RecipeChoice;
|
||||
import org.bukkit.inventory.ShapelessRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Shapeless crafting recipe.
|
||||
*/
|
||||
@Beta
|
||||
public final class ShapelessCraftingRecipe extends PluginDependent<EcoPlugin> implements CraftingRecipe {
|
||||
/**
|
||||
* Recipe parts.
|
||||
*/
|
||||
private final List<TestableItem> parts;
|
||||
|
||||
/**
|
||||
* The key of the recipe.
|
||||
*/
|
||||
private final NamespacedKey key;
|
||||
|
||||
/**
|
||||
* The key of the displayed recipe.
|
||||
*/
|
||||
private final NamespacedKey displayedKey;
|
||||
|
||||
/**
|
||||
* The recipe's output.
|
||||
*/
|
||||
private final ItemStack output;
|
||||
|
||||
/**
|
||||
* The permission.
|
||||
*/
|
||||
private final String permission;
|
||||
|
||||
private ShapelessCraftingRecipe(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String key,
|
||||
@NotNull final List<TestableItem> parts,
|
||||
@NotNull final ItemStack output,
|
||||
@Nullable final String permission) {
|
||||
super(plugin);
|
||||
|
||||
this.parts = parts;
|
||||
this.key = plugin.getNamespacedKeyFactory().create(key);
|
||||
this.displayedKey = plugin.getNamespacedKeyFactory().create(key + "_displayed");
|
||||
this.output = output;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new test.
|
||||
*
|
||||
* @return The test.
|
||||
*/
|
||||
@NotNull
|
||||
public RecipeTest newTest() {
|
||||
return new RecipeTest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(@NotNull final ItemStack[] matrix) {
|
||||
RecipeTest test = newTest();
|
||||
|
||||
for (ItemStack stack : matrix) {
|
||||
if (test.matchAndRemove(stack) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register() {
|
||||
Recipes.register(this);
|
||||
|
||||
Bukkit.getServer().removeRecipe(this.getKey());
|
||||
Bukkit.getServer().removeRecipe(this.getDisplayedKey());
|
||||
|
||||
ShapelessRecipe shapelessRecipe = new ShapelessRecipe(this.getKey(), this.getOutput());
|
||||
for (TestableItem part : parts) {
|
||||
shapelessRecipe.addIngredient(part.getItem().getType());
|
||||
}
|
||||
|
||||
ShapelessRecipe displayedRecipe = new ShapelessRecipe(this.getDisplayedKey(), this.getOutput());
|
||||
for (TestableItem part : parts) {
|
||||
List<TestableItem> items = new ArrayList<>();
|
||||
if (part instanceof GroupedTestableItems group) {
|
||||
items.addAll(group.getChildren());
|
||||
} else {
|
||||
items.add(part);
|
||||
}
|
||||
|
||||
List<ItemStack> displayedItems = new ArrayList<>();
|
||||
|
||||
for (TestableItem testableItem : items) {
|
||||
if (testableItem instanceof TestableStack) {
|
||||
ItemStack item = testableItem.getItem().clone();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
|
||||
assert lore != null;
|
||||
lore.add("");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getFormattedString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(item.getAmount()));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
displayedItems.add(item);
|
||||
} else {
|
||||
displayedItems.add(testableItem.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
displayedRecipe.addIngredient(new RecipeChoice.ExactChoice(displayedItems));
|
||||
}
|
||||
|
||||
Bukkit.getServer().addRecipe(shapelessRecipe);
|
||||
Bukkit.getServer().addRecipe(displayedRecipe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new recipe builder.
|
||||
*
|
||||
* @param plugin The plugin that owns the recipe.
|
||||
* @param key The recipe key.
|
||||
* @return A new builder.
|
||||
*/
|
||||
public static Builder builder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String key) {
|
||||
return new Builder(plugin, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parts.
|
||||
*
|
||||
* @return The parts.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TestableItem> getParts() {
|
||||
return this.parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key.
|
||||
*
|
||||
* @return The key.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayed key.
|
||||
*
|
||||
* @return The displayed key.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public NamespacedKey getDisplayedKey() {
|
||||
return this.displayedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output.
|
||||
*
|
||||
* @return The output.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getOutput() {
|
||||
return this.output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the permission.
|
||||
*
|
||||
* @return The permission.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for recipes.
|
||||
*/
|
||||
public static final class Builder {
|
||||
/**
|
||||
* The recipe parts.
|
||||
*/
|
||||
private final List<TestableItem> recipeParts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The output of the recipe.
|
||||
*/
|
||||
private ItemStack output = null;
|
||||
|
||||
/**
|
||||
* The permission for the recipe.
|
||||
*/
|
||||
private String permission = null;
|
||||
|
||||
/**
|
||||
* The key of the recipe.
|
||||
*/
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* The plugin that created the recipe.
|
||||
*/
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
/**
|
||||
* Create a new recipe builder.
|
||||
*
|
||||
* @param plugin The plugin that owns the recipe.
|
||||
* @param key The recipe key.
|
||||
*/
|
||||
private Builder(@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String key) {
|
||||
this.key = key;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a recipe part.
|
||||
*
|
||||
* @param part The part of the recipe.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder addRecipePart(@NotNull final TestableItem part) {
|
||||
recipeParts.add(part);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output of the recipe.
|
||||
*
|
||||
* @param output The output.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder setOutput(@NotNull final ItemStack output) {
|
||||
this.output = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the permission required to craft the recipe.
|
||||
*
|
||||
* @param permission The permission.
|
||||
* @return The builder.
|
||||
*/
|
||||
public Builder setPermission(@Nullable final String permission) {
|
||||
this.permission = permission;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if recipe parts are all air.
|
||||
*
|
||||
* @return If recipe parts are all air.
|
||||
*/
|
||||
public boolean isAir() {
|
||||
for (TestableItem recipePart : this.recipeParts) {
|
||||
if (recipePart != null && !(recipePart instanceof EmptyTestableItem)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the recipe.
|
||||
*
|
||||
* @return The built recipe.
|
||||
*/
|
||||
public ShapelessCraftingRecipe build() {
|
||||
return new ShapelessCraftingRecipe(plugin, key.toLowerCase(), recipeParts, output, permission);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for shapeless recipes.
|
||||
*/
|
||||
public static final class RecipeTest {
|
||||
/**
|
||||
* The remaining items left to be found.
|
||||
*/
|
||||
private final List<TestableItem> remaining;
|
||||
|
||||
private RecipeTest(@NotNull final ShapelessCraftingRecipe recipe) {
|
||||
this.remaining = new ArrayList<>(recipe.getParts());
|
||||
}
|
||||
|
||||
/**
|
||||
* If the item is in the recipe, remove it from the remaining items to test and
|
||||
* return the matching item.
|
||||
*
|
||||
* @param itemStack The item.
|
||||
* @return The matching item, or null if no match was found.
|
||||
*/
|
||||
@Nullable
|
||||
public TestableItem matchAndRemove(@NotNull final ItemStack itemStack) {
|
||||
if (remaining.isEmpty() && !(new EmptyTestableItem().matches(itemStack))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Optional<TestableItem> match = remaining.stream()
|
||||
.filter(item -> item.matches(itemStack))
|
||||
.findFirst();
|
||||
|
||||
match.ifPresent(remaining::remove);
|
||||
|
||||
return match.orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public final class DurabilityUtils {
|
||||
* @param slot The slot in the inventory of the item.
|
||||
* @deprecated The slot is not required.
|
||||
*/
|
||||
@Deprecated(since = "6.24.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
public static void damageItem(@NotNull final Player player,
|
||||
@NotNull final ItemStack item,
|
||||
final int damage,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -7,10 +8,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for numbers.
|
||||
@@ -24,7 +25,7 @@ public final class NumberUtils {
|
||||
/**
|
||||
* Crunch handler.
|
||||
*/
|
||||
private static BiFunction<String, Player, Double> crunch = null;
|
||||
private static CrunchHandler crunch = null;
|
||||
|
||||
/**
|
||||
* Set of roman numerals to look up.
|
||||
@@ -109,7 +110,7 @@ public final class NumberUtils {
|
||||
* @return The new value.
|
||||
* @deprecated Pointless method.
|
||||
*/
|
||||
@Deprecated(since = "6.19.0")
|
||||
@Deprecated(since = "6.19.0", forRemoval = true)
|
||||
public static double equalIfOver(final double toChange,
|
||||
final double limit) {
|
||||
return Math.min(toChange, limit);
|
||||
@@ -251,7 +252,21 @@ public final class NumberUtils {
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@Nullable final Player player) {
|
||||
return crunch.apply(expression, player);
|
||||
return evaluateExpression(expression, player, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate an expression with respect to a player (for placeholders).
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param statics The static placeholders.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
public static double evaluateExpression(@NotNull final String expression,
|
||||
@Nullable final Player player,
|
||||
@NotNull final Iterable<StaticPlaceholder> statics) {
|
||||
return crunch.evaluate(expression, player, statics);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,11 +275,29 @@ public final class NumberUtils {
|
||||
* @param handler The handler.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void initCrunch(@NotNull final BiFunction<String, Player, Double> handler) {
|
||||
public static void initCrunch(@NotNull final CrunchHandler handler) {
|
||||
Validate.isTrue(crunch == null, "Already initialized!");
|
||||
crunch = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bridge component for crunch.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface CrunchHandler {
|
||||
/**
|
||||
* Evaluate an expression.
|
||||
*
|
||||
* @param expression The expression.
|
||||
* @param player The player.
|
||||
* @param statics The statics.
|
||||
* @return The value of the expression, or zero if invalid.
|
||||
*/
|
||||
double evaluate(@NotNull String expression,
|
||||
@Nullable Player player,
|
||||
@NotNull Iterable<StaticPlaceholder> statics);
|
||||
}
|
||||
|
||||
private NumberUtils() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class TeamUtils {
|
||||
* @deprecated Stupid method.
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated(since = "6.24.0")
|
||||
@Deprecated(since = "6.24.0", forRemoval = true)
|
||||
public static Team getMaterialColorTeam(@NotNull final Material material) {
|
||||
return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import org.bukkit.configuration.file.YamlConstructor
|
||||
import org.yaml.snakeyaml.DumperOptions
|
||||
import org.yaml.snakeyaml.LoaderOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.io.BufferedReader
|
||||
import java.io.Reader
|
||||
|
||||
fun ConfigType.toMap(input: String?): Map<String, Any?> =
|
||||
this.handler.toMap(input)
|
||||
|
||||
fun ConfigType.toString(map: Map<String, Any?>): String =
|
||||
this.handler.toString(map)
|
||||
|
||||
fun Any?.constrainConfigTypes(type: ConfigType): Any? = when (this) {
|
||||
is Map<*, *> -> EcoConfigSection(type, this.normalizeToConfig(type))
|
||||
is Iterable<*> -> {
|
||||
if (this.firstOrNull() == null) {
|
||||
mutableListOf<Any>()
|
||||
} else if (this.firstOrNull() is Map<*, *>) {
|
||||
this as Iterable<Map<*, *>>
|
||||
this.map { map -> EcoConfigSection(type, map.normalizeToConfig(type)) }
|
||||
} else {
|
||||
this.toMutableList()
|
||||
}
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
|
||||
fun Map<*, *>.normalizeToConfig(type: ConfigType): Map<String, Any?> {
|
||||
val building = mutableMapOf<String, Any?>()
|
||||
|
||||
for ((unprocessedKey, value) in this.entries) {
|
||||
if (unprocessedKey == null || value == null) {
|
||||
continue
|
||||
}
|
||||
|
||||
val key = unprocessedKey.toString()
|
||||
|
||||
val constrained = value.constrainConfigTypes(type)
|
||||
|
||||
building[key] = constrained
|
||||
}
|
||||
|
||||
return building
|
||||
}
|
||||
|
||||
fun Reader.readToString(): String {
|
||||
val input = this as? BufferedReader ?: BufferedReader(this)
|
||||
val builder = StringBuilder()
|
||||
|
||||
var line: String?
|
||||
input.use {
|
||||
while (it.readLine().also { read -> line = read } != null) {
|
||||
builder.append(line)
|
||||
builder.append('\n')
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
private val ConfigType.handler: ConfigTypeHandler
|
||||
get() = if (this == ConfigType.JSON) JSONConfigTypeHandler else YamlConfigTypeHandler
|
||||
|
||||
private abstract class ConfigTypeHandler(
|
||||
val type: ConfigType
|
||||
) {
|
||||
fun toMap(input: String?): Map<String, Any?> {
|
||||
if (input == null || input.isBlank()) {
|
||||
return emptyMap()
|
||||
}
|
||||
|
||||
return parseToMap(input).normalizeToConfig(type)
|
||||
}
|
||||
|
||||
protected abstract fun parseToMap(input: String): Map<*, *>
|
||||
|
||||
abstract fun toString(map: Map<String, Any?>): String
|
||||
}
|
||||
|
||||
private object YamlConfigTypeHandler : ConfigTypeHandler(ConfigType.YAML) {
|
||||
private fun newYaml(): Yaml {
|
||||
val yamlOptions = DumperOptions()
|
||||
val loaderOptions = LoaderOptions()
|
||||
val representer = EcoRepresenter()
|
||||
|
||||
loaderOptions.maxAliasesForCollections = Int.MAX_VALUE
|
||||
loaderOptions.isAllowDuplicateKeys = false
|
||||
|
||||
yamlOptions.indent = 2
|
||||
yamlOptions.defaultFlowStyle = DumperOptions.FlowStyle.BLOCK
|
||||
|
||||
representer.defaultFlowStyle = DumperOptions.FlowStyle.BLOCK
|
||||
|
||||
return Yaml(
|
||||
YamlConstructor(),
|
||||
representer,
|
||||
yamlOptions,
|
||||
loaderOptions,
|
||||
)
|
||||
}
|
||||
|
||||
override fun parseToMap(input: String): Map<*, *> {
|
||||
return newYaml().load(input) ?: emptyMap<Any, Any>()
|
||||
}
|
||||
|
||||
override fun toString(map: Map<String, Any?>): String {
|
||||
return newYaml().dump(map)
|
||||
}
|
||||
}
|
||||
|
||||
private object JSONConfigTypeHandler : ConfigTypeHandler(ConfigType.JSON) {
|
||||
override fun parseToMap(input: String): Map<*, *> {
|
||||
return EcoGsonSerializer.gson.fromJson(input, Map::class.java)
|
||||
}
|
||||
|
||||
override fun toString(map: Map<String, Any?>): String {
|
||||
return EcoGsonSerializer.gson.toJson(map)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoConfig(
|
||||
private val configType: ConfigType
|
||||
) : Config {
|
||||
private val values = ConcurrentHashMap<String, Any?>()
|
||||
|
||||
@Transient
|
||||
var injections = mutableListOf<StaticPlaceholder>()
|
||||
|
||||
fun init(values: Map<String, Any?>) {
|
||||
this.values.clear()
|
||||
this.values.putAll(values.normalizeToConfig(this.type))
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
// No cache
|
||||
}
|
||||
|
||||
override fun toPlaintext(): String {
|
||||
return configType.toString(this.values)
|
||||
}
|
||||
|
||||
override fun has(path: String): Boolean {
|
||||
return get(path) != null
|
||||
}
|
||||
|
||||
override fun getKeys(deep: Boolean): List<String> {
|
||||
return if (deep) {
|
||||
recurseKeys(mutableSetOf(), "")
|
||||
} else {
|
||||
values.keys.toList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun recurseKeys(current: MutableSet<String>, root: String): List<String> {
|
||||
val list = mutableSetOf<String>()
|
||||
for (key in getKeys(false)) {
|
||||
list.add("$root$key")
|
||||
val found = get(key)
|
||||
if (found is Config) {
|
||||
list.addAll(found.recurseKeys(current, "$root$key."))
|
||||
}
|
||||
}
|
||||
|
||||
return list.toList()
|
||||
}
|
||||
|
||||
override fun get(path: String): Any? {
|
||||
val nearestPath = path.split(".")[0]
|
||||
|
||||
if (path.contains(".")) {
|
||||
val remainingPath = path.removePrefix("${nearestPath}.")
|
||||
|
||||
if (remainingPath.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val first = get(nearestPath)
|
||||
|
||||
return if (first is Config) {
|
||||
first.get(remainingPath)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
return values[nearestPath]
|
||||
}
|
||||
|
||||
override fun set(
|
||||
path: String,
|
||||
obj: Any?
|
||||
) {
|
||||
this.clearCache()
|
||||
val nearestPath = path.split(".")[0]
|
||||
|
||||
if (path.contains(".")) {
|
||||
val remainingPath = path.removePrefix("${nearestPath}.")
|
||||
|
||||
if (remainingPath.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val section = get(nearestPath)
|
||||
if (section == null) {
|
||||
values[nearestPath] = EcoConfigSection(this.type)
|
||||
return set(path, obj)
|
||||
} else if (section is Config) {
|
||||
section.set(remainingPath, obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (obj == null) {
|
||||
values.remove(nearestPath)
|
||||
} else {
|
||||
values[nearestPath] = obj.constrainConfigTypes(type)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSubsection(path: String): Config {
|
||||
return getSubsectionOrNull(path) ?: EcoConfigSection(type, mutableMapOf(), injections)
|
||||
}
|
||||
|
||||
override fun getSubsectionOrNull(path: String): Config? {
|
||||
return get(path) as? Config
|
||||
}
|
||||
|
||||
override fun getSubsectionsOrNull(path: String): List<Config>? {
|
||||
return (get(path) as? Iterable<Config>)?.toList()
|
||||
}
|
||||
|
||||
override fun getType(): ConfigType {
|
||||
return configType
|
||||
}
|
||||
|
||||
override fun getIntOrNull(path: String): Int? {
|
||||
return (get(path) as? Number)?.toInt()
|
||||
}
|
||||
|
||||
override fun getIntsOrNull(path: String): List<Int>? {
|
||||
return (get(path) as? Iterable<Number>)?.map { it.toInt() }
|
||||
}
|
||||
|
||||
override fun getBoolOrNull(path: String): Boolean? {
|
||||
return get(path) as? Boolean
|
||||
}
|
||||
|
||||
override fun getBoolsOrNull(path: String): List<Boolean>? {
|
||||
return (get(path) as? Iterable<Boolean>)?.toList()
|
||||
}
|
||||
|
||||
override fun getStringOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String? {
|
||||
val string = get(path)?.toString() ?: return null
|
||||
return if (format) StringUtils.format(string, option) else string
|
||||
}
|
||||
|
||||
override fun getStringsOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): List<String>? {
|
||||
val strings = (get(path) as? Iterable<*>)?.map { it.toString() } ?: return null
|
||||
return if (format) StringUtils.formatList(strings, option) else strings
|
||||
}
|
||||
|
||||
override fun getDoubleOrNull(path: String): Double? {
|
||||
return (get(path) as? Number)?.toDouble()
|
||||
}
|
||||
|
||||
override fun getDoublesOrNull(path: String): List<Double>? {
|
||||
return (get(path) as? Iterable<Number>)?.map { it.toDouble() }
|
||||
}
|
||||
|
||||
override fun injectPlaceholders(placeholders: Iterable<StaticPlaceholder>) {
|
||||
injections.removeIf { placeholders.any { placeholder -> it.identifier == placeholder.identifier } }
|
||||
injections.addAll(placeholders)
|
||||
this.clearCache()
|
||||
}
|
||||
|
||||
override fun getInjectedPlaceholders(): List<StaticPlaceholder> {
|
||||
return injections.toList()
|
||||
}
|
||||
|
||||
override fun clearInjectedPlaceholders() {
|
||||
injections.clear()
|
||||
this.clearCache()
|
||||
}
|
||||
|
||||
override fun toMap(): MutableMap<String, Any?> {
|
||||
return values.toMutableMap()
|
||||
}
|
||||
|
||||
override fun toBukkit(): YamlConfiguration {
|
||||
val temp = YamlConfiguration()
|
||||
temp.createSection("temp", this.values.toMap())
|
||||
val section = temp.getConfigurationSection("temp")!!
|
||||
|
||||
val bukkit = YamlConfiguration()
|
||||
for (key in section.getKeys(true)) {
|
||||
bukkit.set(key, section.get(key))
|
||||
}
|
||||
return bukkit
|
||||
}
|
||||
|
||||
override fun clone(): Config {
|
||||
return EcoConfigSection(type, this.values.toMutableMap(), injections)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return this.toPlaintext()
|
||||
}
|
||||
}
|
||||
@@ -5,61 +5,37 @@ import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import com.willfp.eco.core.config.wrapper.ConfigFactory
|
||||
import com.willfp.eco.internal.config.json.EcoJSONConfigSection
|
||||
import com.willfp.eco.internal.config.json.EcoJSONConfigWrapper
|
||||
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig
|
||||
import com.willfp.eco.internal.config.json.EcoUpdatableJSONConfig
|
||||
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
|
||||
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
|
||||
import com.willfp.eco.internal.config.yaml.EcoYamlConfigSection
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.StringReader
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
|
||||
object EcoConfigFactory : ConfigFactory {
|
||||
override fun createConfig(config: YamlConfiguration): Config {
|
||||
return EcoYamlConfigSection(config)
|
||||
}
|
||||
|
||||
override fun createConfig(values: MutableMap<String, Any>): Config {
|
||||
return EcoJSONConfigSection(values)
|
||||
}
|
||||
|
||||
override fun createConfig(contents: String, type: ConfigType): Config {
|
||||
return if (type == ConfigType.JSON) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
EcoJSONConfigSection(
|
||||
EcoJSONConfigWrapper.gson.fromJson(
|
||||
StringReader(contents), Map::class.java
|
||||
) as MutableMap<String, Any>
|
||||
)
|
||||
} else {
|
||||
EcoYamlConfigSection(YamlConfiguration.loadConfiguration(StringReader(contents)))
|
||||
override fun createConfig(bukkit: ConfigurationSection): Config {
|
||||
val config = createConfig(emptyMap(), ConfigType.YAML)
|
||||
for (key in bukkit.getKeys(true)) {
|
||||
config.set(key, bukkit.get(key))
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
override fun createConfig(values: Map<String, Any>, type: ConfigType): Config =
|
||||
EcoConfigSection(type, values)
|
||||
|
||||
override fun createConfig(contents: String, type: ConfigType): Config =
|
||||
EcoConfigSection(type, type.toMap(contents))
|
||||
|
||||
override fun createLoadableConfig(
|
||||
configName: String,
|
||||
plugin: PluginLike,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>,
|
||||
type: ConfigType
|
||||
): LoadableConfig {
|
||||
return if (type == ConfigType.JSON) {
|
||||
EcoLoadableJSONConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
)
|
||||
} else {
|
||||
EcoLoadableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
)
|
||||
}
|
||||
}
|
||||
): LoadableConfig = EcoLoadableConfig(
|
||||
type,
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
)
|
||||
|
||||
override fun createUpdatableConfig(
|
||||
configName: String,
|
||||
@@ -69,25 +45,13 @@ object EcoConfigFactory : ConfigFactory {
|
||||
removeUnused: Boolean,
|
||||
type: ConfigType,
|
||||
vararg updateBlacklist: String
|
||||
): LoadableConfig {
|
||||
return if (type == ConfigType.JSON) {
|
||||
EcoUpdatableJSONConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
*updateBlacklist
|
||||
)
|
||||
} else {
|
||||
EcoUpdatableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
*updateBlacklist
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
): LoadableConfig = EcoUpdatableConfig(
|
||||
type,
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
*updateBlacklist
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
package com.willfp.eco.internal.config.updating
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import com.willfp.eco.core.config.updating.ConfigHandler
|
||||
import com.willfp.eco.core.config.updating.ConfigUpdater
|
||||
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig
|
||||
import com.willfp.eco.internal.config.json.EcoUpdatableJSONConfig
|
||||
import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException
|
||||
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
|
||||
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
|
||||
import org.reflections.Reflections
|
||||
import org.reflections.scanners.MethodAnnotationsScanner
|
||||
|
||||
@@ -24,7 +19,7 @@ class EcoConfigHandler(
|
||||
|
||||
override fun callUpdate() {
|
||||
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
|
||||
kotlin.runCatching {
|
||||
runCatching {
|
||||
when (method.parameterCount) {
|
||||
0 -> method.invoke(null)
|
||||
1 -> method.invoke(null, this.plugin)
|
||||
@@ -50,11 +45,11 @@ class EcoConfigHandler(
|
||||
override fun updateConfigs() {
|
||||
for (config in configs) {
|
||||
when (config) {
|
||||
is EcoUpdatableYamlConfig -> config.update()
|
||||
is EcoUpdatableJSONConfig -> config.update()
|
||||
is EcoLoadableYamlConfig -> config.reloadFromFile()
|
||||
is EcoLoadableJSONConfig -> config.reloadFromFile()
|
||||
is EcoUpdatableConfig -> config.update()
|
||||
is EcoLoadableConfig -> config.reloadFromFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidUpdateMethodException(message: String) : RuntimeException(message)
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class EcoConfigSection(
|
||||
type: ConfigType,
|
||||
values: Map<String, Any?> = emptyMap(),
|
||||
injections: Collection<StaticPlaceholder> = emptyList()
|
||||
) : EcoConfig(type) {
|
||||
init {
|
||||
this.init(values)
|
||||
this.injections = injections.toMutableList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object EcoGsonSerializer : JsonSerializer<Config> {
|
||||
val gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(Config::class.java, this)
|
||||
.create()
|
||||
|
||||
override fun serialize(src: Config, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
|
||||
return gson.toJsonTree(src.toMap())
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,30 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.FileReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.io.OutputStream
|
||||
import java.io.Reader
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardOpenOption
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoLoadableJSONConfig(
|
||||
open class EcoLoadableConfig(
|
||||
type: ConfigType,
|
||||
configName: String,
|
||||
private val plugin: PluginLike,
|
||||
private val subDirectoryPath: String,
|
||||
val source: Class<*>
|
||||
) : EcoJSONConfigWrapper(), LoadableConfig {
|
||||
|
||||
) : EcoConfig(type), LoadableConfig {
|
||||
private val configFile: File
|
||||
private val name: String = "$configName.json"
|
||||
private val name: String = "$configName.${type.extension}"
|
||||
private var hasChanged = false
|
||||
private val header = mutableListOf<String>()
|
||||
|
||||
fun reloadFromFile() {
|
||||
runCatching { init(configFile) }.onFailure { it.printStackTrace() }
|
||||
@@ -54,19 +57,64 @@ open class EcoLoadableJSONConfig(
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun save() {
|
||||
if (!hasChanged) { // In order to preserve comments
|
||||
return
|
||||
}
|
||||
|
||||
if (configFile.delete()) {
|
||||
Files.write(
|
||||
configFile.toPath(),
|
||||
toPlaintext().toByteArray(),
|
||||
this.toPlaintext().toByteArray(),
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.WRITE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(FileNotFoundException::class)
|
||||
private fun makeHeader(contents: String) {
|
||||
if (this.type == ConfigType.YAML) {
|
||||
for (line in contents.lines()) {
|
||||
if (!line.startsWith("#")) {
|
||||
break
|
||||
}
|
||||
|
||||
header.add(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun init(reader: Reader) {
|
||||
val string = reader.readToString()
|
||||
makeHeader(string)
|
||||
super.init(type.toMap(string))
|
||||
}
|
||||
|
||||
fun init(file: File) {
|
||||
super.init(gson.fromJson(FileReader(file), Map::class.java) as MutableMap<String, Any>)
|
||||
init(InputStreamReader(FileInputStream(file), Charsets.UTF_8))
|
||||
}
|
||||
|
||||
override fun toPlaintext(): String {
|
||||
val contents = StringBuilder()
|
||||
|
||||
if (this.type == ConfigType.YAML) {
|
||||
for (s in header) {
|
||||
contents.append(s + "\n")
|
||||
}
|
||||
|
||||
if (header.isNotEmpty()) {
|
||||
contents.append("\n")
|
||||
}
|
||||
}
|
||||
|
||||
for (line in super.toPlaintext().lines()) {
|
||||
if (line.startsWith("#")) {
|
||||
continue
|
||||
}
|
||||
|
||||
contents.append(line + "\n")
|
||||
}
|
||||
|
||||
return contents.toString()
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
@@ -77,8 +125,9 @@ open class EcoLoadableJSONConfig(
|
||||
return configFile
|
||||
}
|
||||
|
||||
override fun getBukkitHandle(): YamlConfiguration? {
|
||||
return null
|
||||
override fun set(path: String, obj: Any?) {
|
||||
hasChanged = true
|
||||
super.set(path, obj)
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -93,4 +142,4 @@ open class EcoLoadableJSONConfig(
|
||||
init(configFile)
|
||||
plugin.configHandler.addConfig(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import org.yaml.snakeyaml.nodes.Node
|
||||
import org.yaml.snakeyaml.representer.Represent
|
||||
import org.yaml.snakeyaml.representer.Representer
|
||||
|
||||
class EcoRepresenter : Representer() {
|
||||
init {
|
||||
multiRepresenters[Config::class.java] = RepresentConfig(multiRepresenters[Map::class.java]!!)
|
||||
}
|
||||
|
||||
private class RepresentConfig(
|
||||
val handle: Represent
|
||||
) : Represent {
|
||||
override fun representData(data: Any): Node {
|
||||
data as Config
|
||||
return handle.representData(data.toMap())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,22 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
open class EcoUpdatableJSONConfig(
|
||||
open class EcoUpdatableConfig(
|
||||
type: ConfigType,
|
||||
configName: String,
|
||||
plugin: PluginLike,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>,
|
||||
private val removeUnused: Boolean,
|
||||
vararg updateBlacklist: String
|
||||
) : EcoLoadableJSONConfig(configName, plugin, subDirectoryPath, source) {
|
||||
|
||||
private val updateBlacklist: MutableList<String> = mutableListOf(*updateBlacklist)
|
||||
) : EcoLoadableConfig(type, configName, plugin, subDirectoryPath, source) {
|
||||
private val updateBlacklist = mutableListOf(*updateBlacklist)
|
||||
|
||||
fun update() {
|
||||
super.clearCache()
|
||||
@@ -43,13 +44,14 @@ open class EcoUpdatableJSONConfig(
|
||||
this.save()
|
||||
}
|
||||
|
||||
private val configInJar: YamlConfiguration?
|
||||
private val configInJar: Config?
|
||||
get() {
|
||||
val newIn = this.source.getResourceAsStream(resourcePath) ?: return null
|
||||
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
|
||||
val newConfig = YamlConfiguration()
|
||||
newConfig.load(reader)
|
||||
return newConfig
|
||||
|
||||
val config = EcoConfigSection(type, emptyMap())
|
||||
config.init(type.toMap(reader.readToString()))
|
||||
return config
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -57,4 +59,4 @@ open class EcoUpdatableJSONConfig(
|
||||
plugin.configHandler.addConfig(this)
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class EcoJSONConfigSection(values: Map<String, Any?>) : EcoJSONConfigWrapper() {
|
||||
init {
|
||||
init(values)
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoJSONConfigWrapper : JSONConfig {
|
||||
companion object {
|
||||
val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.create()
|
||||
}
|
||||
|
||||
val values = ConcurrentHashMap<String, Any?>()
|
||||
|
||||
private val cache = ConcurrentHashMap<String, Any>()
|
||||
|
||||
fun init(values: Map<String, Any?>) {
|
||||
this.values.clear()
|
||||
this.values.putAll(values)
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
override fun toPlaintext(): String {
|
||||
return gson.toJson(this.values)
|
||||
}
|
||||
|
||||
override fun has(path: String): Boolean {
|
||||
return getOfKnownType(path, Any::class.java) != null
|
||||
}
|
||||
|
||||
private fun <T : Any?> getOfKnownType(
|
||||
path: String,
|
||||
clazz: Class<T>
|
||||
): T? {
|
||||
return getOfKnownType(path, clazz, true)
|
||||
}
|
||||
|
||||
protected fun <T> getOfKnownType(
|
||||
path: String,
|
||||
clazz: Class<T>,
|
||||
isBase: Boolean
|
||||
): T? {
|
||||
var closestPath = path
|
||||
if (cache.containsKey(path) && isBase) {
|
||||
return cache[path] as T?
|
||||
}
|
||||
if (path.contains(".")) {
|
||||
val split = path.split("\\.".toRegex()).toTypedArray()
|
||||
closestPath = split[0]
|
||||
}
|
||||
return if (values[closestPath] is Map<*, *> && path != closestPath) {
|
||||
val section =
|
||||
EcoJSONConfigSection((values[closestPath] as Map<String, Any?>?)!!)
|
||||
section.getOfKnownType(path.substring(closestPath.length + 1), clazz, false)
|
||||
} else {
|
||||
if (values.containsKey(closestPath)) {
|
||||
values[closestPath] as T?
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getKeys(deep: Boolean): List<String> {
|
||||
return if (deep) {
|
||||
ArrayList(getDeepKeys(HashSet(), ""))
|
||||
} else {
|
||||
ArrayList(values.keys)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun getDeepKeys(
|
||||
list: MutableSet<String>,
|
||||
root: String
|
||||
): Set<String> {
|
||||
for (key in values.keys) {
|
||||
list.add(root + key)
|
||||
if (values[key] is Map<*, *>) {
|
||||
val section = EcoJSONConfigSection((values[key] as Map<String, Any?>?)!!)
|
||||
list.addAll(section.getDeepKeys(list, "$root$key."))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
override fun get(path: String): Any? {
|
||||
return getOfKnownType(path, Any::class.java)
|
||||
}
|
||||
|
||||
override fun set(
|
||||
path: String,
|
||||
`object`: Any?
|
||||
) {
|
||||
setRecursively(path, `object`)
|
||||
clearCache()
|
||||
}
|
||||
|
||||
protected fun setRecursively(
|
||||
path: String,
|
||||
obj: Any?
|
||||
) {
|
||||
var closestPath = path
|
||||
if (path.contains(".")) {
|
||||
val split = path.split("\\.".toRegex()).toTypedArray()
|
||||
closestPath = split[0]
|
||||
}
|
||||
if (values[closestPath] is Map<*, *> && path != closestPath) {
|
||||
val section = EcoJSONConfigSection((values[closestPath] as Map<String, Any?>?)!!)
|
||||
section.setRecursively(path.substring(closestPath.length + 1), obj)
|
||||
values[closestPath] = section.values
|
||||
} else {
|
||||
var ob = obj
|
||||
if (ob is JSONConfig) {
|
||||
ob = (obj as EcoJSONConfigWrapper).values
|
||||
}
|
||||
values[path] = ob
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSubsection(path: String): JSONConfig {
|
||||
return getSubsectionOrNull(path) ?: EcoJSONConfigSection(mutableMapOf())
|
||||
}
|
||||
|
||||
override fun getSubsectionOrNull(path: String): JSONConfig? {
|
||||
return if (values.containsKey(path)) {
|
||||
val subsection = values[path] as Map<String, Any>
|
||||
EcoJSONConfigSection(subsection)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSubsectionsOrNull(path: String): List<JSONConfig>? {
|
||||
val maps = getOfKnownType(path, Any::class.java) as List<Map<String, Any>>?
|
||||
?: return null
|
||||
val configs = mutableListOf<JSONConfig>()
|
||||
for (map in maps) {
|
||||
configs.add(EcoJSONConfigSection(map))
|
||||
}
|
||||
return configs.toMutableList()
|
||||
}
|
||||
|
||||
override fun getIntOrNull(path: String): Int? {
|
||||
return getOfKnownType(path, Double::class.java)?.toInt()
|
||||
}
|
||||
|
||||
override fun getIntsOrNull(path: String): MutableList<Int>? {
|
||||
return (getOfKnownType(path, Any::class.java) as Collection<Int>?)?.toMutableList()
|
||||
}
|
||||
|
||||
override fun getBoolOrNull(path: String): Boolean? {
|
||||
return getOfKnownType(path, Boolean::class.java)
|
||||
}
|
||||
|
||||
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
|
||||
return (getOfKnownType(path, Any::class.java) as Collection<Boolean>?)?.toMutableList()
|
||||
}
|
||||
|
||||
override fun getStringOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String? {
|
||||
return if (has(path)) {
|
||||
val string = getOfKnownType(path, String::class.java) ?: ""
|
||||
return if (format) StringUtils.format(string, option) else string
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringsOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String>? {
|
||||
return if (has(path)) {
|
||||
val strings =
|
||||
(Objects.requireNonNullElse(
|
||||
getOfKnownType(path, Any::class.java),
|
||||
emptyList<String>()
|
||||
) as List<String>).toMutableList()
|
||||
return if (format) StringUtils.formatList(strings, option) else strings
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoubleOrNull(path: String): Double? {
|
||||
return getOfKnownType(path, Double::class.java)
|
||||
}
|
||||
|
||||
override fun getDoublesOrNull(path: String): MutableList<Double>? {
|
||||
return (getOfKnownType(path, Any::class.java) as Collection<Double>?)?.toMutableList()
|
||||
}
|
||||
|
||||
override fun getType(): ConfigType {
|
||||
return ConfigType.JSON
|
||||
}
|
||||
|
||||
override fun clone(): JSONConfig {
|
||||
return EcoJSONConfigSection(this.values.toMutableMap())
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.willfp.eco.internal.config.updating.exceptions
|
||||
|
||||
class InvalidUpdateMethodException(message: String) : RuntimeException(message)
|
||||
@@ -1,82 +0,0 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
open class EcoLoadableYamlConfig(
|
||||
configName: String,
|
||||
private val plugin: PluginLike,
|
||||
private val subDirectoryPath: String,
|
||||
val source: Class<*>
|
||||
) : EcoYamlConfigWrapper<YamlConfiguration>(), WrappedYamlConfiguration, LoadableConfig {
|
||||
|
||||
private val configFile: File
|
||||
private val name: String = "$configName.yml"
|
||||
|
||||
fun reloadFromFile() {
|
||||
handle.load(getConfigFile())
|
||||
}
|
||||
|
||||
final override fun createFile() {
|
||||
val inputStream = source.getResourceAsStream(resourcePath)!!
|
||||
val outFile = File(this.plugin.dataFolder, resourcePath)
|
||||
val lastIndex = resourcePath.lastIndexOf('/')
|
||||
val outDir = File(this.plugin.dataFolder, resourcePath.substring(0, lastIndex.coerceAtLeast(0)))
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdirs()
|
||||
}
|
||||
if (!outFile.exists()) {
|
||||
val out: OutputStream = FileOutputStream(outFile)
|
||||
inputStream.copyTo(out)
|
||||
out.close()
|
||||
inputStream.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getResourcePath(): String {
|
||||
val resourcePath: String = if (subDirectoryPath.isEmpty()) {
|
||||
name
|
||||
} else {
|
||||
subDirectoryPath + name
|
||||
}
|
||||
return "/$resourcePath"
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun save() {
|
||||
handle.save(getConfigFile())
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return name
|
||||
}
|
||||
|
||||
override fun getConfigFile(): File {
|
||||
return configFile
|
||||
}
|
||||
|
||||
override fun getBukkitHandle(): YamlConfiguration? {
|
||||
return handle
|
||||
}
|
||||
|
||||
init {
|
||||
val directory = File(this.plugin.dataFolder, subDirectoryPath)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
if (!File(directory, name).exists()) {
|
||||
createFile()
|
||||
}
|
||||
configFile = File(directory, name)
|
||||
this.plugin.configHandler.addConfig(this)
|
||||
init(YamlConfiguration.loadConfiguration(configFile))
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.PluginLike
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
class EcoUpdatableYamlConfig(
|
||||
configName: String,
|
||||
plugin: PluginLike,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>,
|
||||
private val removeUnused: Boolean,
|
||||
vararg updateBlacklist: String
|
||||
) : EcoLoadableYamlConfig(configName, plugin, subDirectoryPath, source) {
|
||||
|
||||
private val updateBlacklist: MutableList<String> = mutableListOf(*updateBlacklist)
|
||||
|
||||
fun update() {
|
||||
super.clearCache()
|
||||
this.handle.load(configFile)
|
||||
val newConfig = configInJar ?: return
|
||||
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key ->
|
||||
if (!this.handle.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
|
||||
this.handle.set(key, newConfig[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeUnused) {
|
||||
this.handle.getKeys(true).forEach { s ->
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.handle.set(s, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.handle.save(configFile)
|
||||
}
|
||||
|
||||
private val configInJar: YamlConfiguration?
|
||||
get() {
|
||||
val newIn = source.getResourceAsStream(resourcePath) ?: return null
|
||||
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
|
||||
val newConfig = YamlConfiguration()
|
||||
newConfig.load(reader)
|
||||
return newConfig
|
||||
}
|
||||
|
||||
init {
|
||||
this.updateBlacklist.removeIf { it.isEmpty() }
|
||||
plugin.configHandler.addConfig(this)
|
||||
update()
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
|
||||
class EcoYamlConfigSection(section: ConfigurationSection) : EcoYamlConfigWrapper<ConfigurationSection>() {
|
||||
init {
|
||||
init(section)
|
||||
}
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.config.ConfigType
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.StringReader
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
|
||||
lateinit var handle: T
|
||||
private val cache = mutableMapOf<String, Any?>()
|
||||
|
||||
protected fun init(config: T): Config {
|
||||
handle = config
|
||||
return this
|
||||
}
|
||||
|
||||
override fun toPlaintext(): String {
|
||||
val temp = YamlConfiguration()
|
||||
for (key in handle.getKeys(true)) {
|
||||
temp[key] = handle[key]
|
||||
}
|
||||
return temp.saveToString()
|
||||
}
|
||||
|
||||
override fun clearCache() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
override fun has(path: String): Boolean {
|
||||
return handle.contains(path)
|
||||
}
|
||||
|
||||
override fun getKeys(deep: Boolean): List<String> {
|
||||
return ArrayList(handle.getKeys(deep))
|
||||
}
|
||||
|
||||
override fun get(path: String): Any? {
|
||||
return handle[path]
|
||||
}
|
||||
|
||||
override fun set(
|
||||
path: String,
|
||||
obj: Any?
|
||||
) {
|
||||
cache.remove(path)
|
||||
handle[path] = obj
|
||||
}
|
||||
|
||||
override fun getSubsectionOrNull(path: String): Config? {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Config?
|
||||
} else {
|
||||
val raw = handle.getConfigurationSection(path)
|
||||
if (raw == null) {
|
||||
cache[path] = null
|
||||
} else {
|
||||
cache[path] = EcoYamlConfigSection(raw)
|
||||
}
|
||||
getSubsectionOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIntOrNull(path: String): Int? {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Number).toInt()
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getDouble(path).toInt()
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getIntOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIntsOrNull(path: String): MutableList<Int>? {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Collection<Int>).toMutableList()
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getIntegerList(path).toMutableList()
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getIntsOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBoolOrNull(path: String): Boolean? {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Boolean
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getBoolean(path)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getBoolOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Collection<Boolean>).toMutableList()
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getBooleanList(path).toMutableList()
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getBoolsOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String? {
|
||||
return if (has(path)) {
|
||||
if (format && option == StringUtils.FormatOption.WITHOUT_PLACEHOLDERS) {
|
||||
return if (cache.containsKey("$path\$FMT")) {
|
||||
cache["$path\$FMT"] as String
|
||||
} else {
|
||||
val string: String = handle.getString(path, "")!!
|
||||
cache["$path\$FMT"] = StringUtils.format(string, option)
|
||||
getString(path, format, option)
|
||||
}
|
||||
} else {
|
||||
val string = if (cache.containsKey(path)) {
|
||||
cache[path] as String
|
||||
} else {
|
||||
cache[path] = handle.getString(path, "")!!
|
||||
getString(path, format, option)
|
||||
}
|
||||
|
||||
return if (format) StringUtils.format(string) else string
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringsOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String>? {
|
||||
return if (has(path)) {
|
||||
if (format && option == StringUtils.FormatOption.WITHOUT_PLACEHOLDERS) {
|
||||
return if (cache.containsKey("$path\$FMT")) {
|
||||
(cache["$path\$FMT"] as MutableList<String>).toMutableList()
|
||||
} else {
|
||||
val list = if (has(path)) handle.getStringList(path) else mutableListOf<String>()
|
||||
cache["$path\$FMT"] = StringUtils.formatList(list, option)
|
||||
getStrings(path, true, option)
|
||||
}
|
||||
} else {
|
||||
val strings = if (cache.containsKey(path)) {
|
||||
(cache[path] as MutableList<String>).toMutableList()
|
||||
} else {
|
||||
cache[path] =
|
||||
if (has(path)) ArrayList(handle.getStringList(path)) else mutableListOf<String>()
|
||||
getStrings(path, false, option)
|
||||
}
|
||||
|
||||
return if (format) {
|
||||
StringUtils.formatList(strings, StringUtils.FormatOption.WITH_PLACEHOLDERS)
|
||||
} else {
|
||||
strings
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoubleOrNull(path: String): Double? {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Number).toDouble()
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getDouble(path)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getDoubleOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoublesOrNull(path: String): MutableList<Double>? {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Collection<Double>).toMutableList()
|
||||
} else {
|
||||
if (has(path)) {
|
||||
cache[path] = handle.getDoubleList(path).toMutableList()
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
getDoublesOrNull(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSubsectionsOrNull(path: String): MutableList<out Config>? {
|
||||
return if (has(path)) {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as Collection<Config>).toMutableList()
|
||||
} else {
|
||||
val mapList = ArrayList(handle.getMapList(path)) as List<Map<String, Any?>>
|
||||
val configList = mutableListOf<Config>()
|
||||
for (map in mapList) {
|
||||
val temp = YamlConfiguration.loadConfiguration(StringReader(""))
|
||||
temp.createSection("a", map)
|
||||
configList.add(EcoYamlConfigSection(temp.getConfigurationSection("a")!!))
|
||||
}
|
||||
|
||||
cache[path] = if (has(path)) configList else emptyList()
|
||||
getSubsections(path)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getType(): ConfigType {
|
||||
return ConfigType.JSON
|
||||
}
|
||||
|
||||
override fun clone(): Config {
|
||||
return EcoYamlConfigSection(
|
||||
YamlConfiguration.loadConfiguration(
|
||||
StringReader(
|
||||
toPlaintext()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.willfp.eco.core.gui.menu.CloseHandler
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlot
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
@@ -19,7 +18,7 @@ class EcoMenu(
|
||||
val slots: List<MutableList<EcoSlot>>,
|
||||
private val title: String,
|
||||
private val onClose: CloseHandler
|
||||
): Menu {
|
||||
) : Menu {
|
||||
override fun getSlot(row: Int, column: Int): Slot {
|
||||
if (row < 1 || row > this.rows) {
|
||||
return slots[0][0]
|
||||
@@ -37,33 +36,23 @@ class EcoMenu(
|
||||
|
||||
var i = 0
|
||||
for (row in slots) {
|
||||
for (item in row) {
|
||||
for (slot in row) {
|
||||
if (i == rows * 9) {
|
||||
break
|
||||
}
|
||||
val slotItem = item.getItemStack(player, this)
|
||||
val meta = slotItem.itemMeta
|
||||
if (meta != null) {
|
||||
val lore = meta.lore
|
||||
if (lore != null) {
|
||||
lore.replaceAll{ s -> StringUtils.format(s, player) }
|
||||
meta.lore = lore
|
||||
}
|
||||
slotItem.itemMeta = meta
|
||||
}
|
||||
inventory.setItem(i, slotItem)
|
||||
inventory.setItem(i, slot.getItemStack(player, this))
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
player.openInventory(inventory)
|
||||
MenuHandler.registerMenu(inventory, this)
|
||||
MenuHandler.registerInventory(inventory, this, player)
|
||||
return inventory
|
||||
}
|
||||
|
||||
fun handleClose(event: InventoryCloseEvent) {
|
||||
onClose.handle(event, this)
|
||||
MenuHandler.unregisterMenu(event.inventory)
|
||||
MenuHandler.unregisterInventory(event.inventory)
|
||||
}
|
||||
|
||||
override fun getRows(): Int {
|
||||
@@ -74,9 +63,8 @@ class EcoMenu(
|
||||
return title
|
||||
}
|
||||
|
||||
override fun getCaptiveItems(player: Player): MutableList<ItemStack> {
|
||||
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
|
||||
inventory ?: return mutableListOf()
|
||||
override fun getCaptiveItems(player: Player): List<ItemStack> {
|
||||
val inventory = player.openInventory.topInventory.asRenderedInventory() ?: return emptyList()
|
||||
return inventory.captiveItems
|
||||
}
|
||||
|
||||
@@ -86,21 +74,22 @@ class EcoMenu(
|
||||
type: PersistentDataType<T, Z>,
|
||||
value: Z
|
||||
) {
|
||||
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
|
||||
inventory ?: return
|
||||
val inventory = player.openInventory.topInventory.asRenderedInventory() ?: return
|
||||
inventory.data[key] = value
|
||||
inventory.refresh(player)
|
||||
inventory.render()
|
||||
}
|
||||
|
||||
override fun <T : Any, Z : Any> readData(player: Player, key: NamespacedKey, type: PersistentDataType<T, Z>): T? {
|
||||
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
|
||||
inventory ?: return null
|
||||
return inventory.data[key] as T?
|
||||
val inventory = player.openInventory.topInventory.asRenderedInventory() ?: return null
|
||||
return inventory.data[key] as? T?
|
||||
}
|
||||
|
||||
override fun getKeys(player: Player): MutableSet<NamespacedKey> {
|
||||
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
|
||||
inventory ?: return HashSet()
|
||||
override fun getKeys(player: Player): Set<NamespacedKey> {
|
||||
val inventory = player.openInventory.topInventory.asRenderedInventory() ?: return emptySet()
|
||||
return inventory.data.keys
|
||||
}
|
||||
}
|
||||
|
||||
override fun refresh(player: Player) {
|
||||
player.openInventory.topInventory.asRenderedInventory()?.render()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
package com.willfp.eco.internal.gui.menu
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.Inventory
|
||||
import java.util.WeakHashMap
|
||||
|
||||
object MenuHandler {
|
||||
private val menus = WeakHashMap<ExtendedInventory, EcoMenu>()
|
||||
private val inventories = WeakHashMap<Inventory, ExtendedInventory>()
|
||||
private val inventories = WeakHashMap<Inventory, MenuRenderedInventory>()
|
||||
|
||||
fun registerMenu(
|
||||
object MenuHandler {
|
||||
fun registerInventory(
|
||||
inventory: Inventory,
|
||||
menu: EcoMenu
|
||||
menu: EcoMenu,
|
||||
player: Player
|
||||
) {
|
||||
val extendedInventory = ExtendedInventory(inventory, menu)
|
||||
inventories[inventory] = extendedInventory
|
||||
menus[extendedInventory] = menu
|
||||
val rendered = MenuRenderedInventory(menu, inventory, player)
|
||||
inventories[inventory] = rendered
|
||||
}
|
||||
|
||||
fun unregisterMenu(inventory: Inventory) {
|
||||
menus.remove(inventories[inventory])
|
||||
fun unregisterInventory(inventory: Inventory) {
|
||||
inventories.remove(inventory)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMenu(inventory: Inventory): Menu? {
|
||||
return menus[inventories[inventory]]
|
||||
}
|
||||
fun Inventory.asRenderedInventory(): MenuRenderedInventory? =
|
||||
inventories[this]
|
||||
|
||||
fun getExtendedInventory(inventory: Inventory): ExtendedInventory? {
|
||||
return inventories[inventory]
|
||||
}
|
||||
}
|
||||
fun Inventory.getMenu(): Menu? =
|
||||
this.asRenderedInventory()?.menu
|
||||
|
||||
@@ -1,35 +1,21 @@
|
||||
package com.willfp.eco.internal.gui.menu
|
||||
|
||||
import com.willfp.eco.util.MenuUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.Inventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class ExtendedInventory(
|
||||
class MenuRenderedInventory(
|
||||
val menu: EcoMenu,
|
||||
val inventory: Inventory,
|
||||
private val menu: EcoMenu
|
||||
val player: Player
|
||||
) {
|
||||
val captiveItems = mutableListOf<ItemStack>()
|
||||
val data = mutableMapOf<NamespacedKey, Any>()
|
||||
|
||||
fun refresh(player: Player) {
|
||||
captiveItems.clear()
|
||||
for (i in 0 until inventory.size) {
|
||||
val (row, column) = MenuUtils.convertSlotToRowColumn(i)
|
||||
val slot = menu.getSlot(row, column)
|
||||
if (slot.isCaptive) {
|
||||
val defaultItem = slot.getItemStack(player)
|
||||
val item = inventory.getItem(i) ?: continue
|
||||
if (item == defaultItem && item.type == Material.AIR) {
|
||||
continue
|
||||
}
|
||||
|
||||
captiveItems.add(item)
|
||||
}
|
||||
}
|
||||
fun render() {
|
||||
generateCaptive()
|
||||
|
||||
var i = 0
|
||||
for (row in menu.slots) {
|
||||
@@ -37,21 +23,31 @@ class ExtendedInventory(
|
||||
if (i == menu.rows * 9) {
|
||||
break
|
||||
}
|
||||
val slotItem = slot.getItemStack(player, menu)
|
||||
val meta = slotItem.itemMeta
|
||||
if (meta != null) {
|
||||
val lore = meta.lore
|
||||
if (lore != null) {
|
||||
lore.replaceAll{ s -> StringUtils.format(s, player) }
|
||||
meta.lore = lore
|
||||
}
|
||||
slotItem.itemMeta = meta
|
||||
}
|
||||
|
||||
if (!slot.isCaptive) {
|
||||
inventory.setItem(i, slotItem)
|
||||
inventory.setItem(i, slot.getItemStack(player, menu))
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateCaptive() {
|
||||
captiveItems.clear()
|
||||
for (i in 0 until inventory.size) {
|
||||
val (row, column) = MenuUtils.convertSlotToRowColumn(i)
|
||||
val slot = menu.getSlot(row, column)
|
||||
if (slot.isCaptive) {
|
||||
val renderedItem = slot.getItemStack(player)
|
||||
val itemStack = inventory.getItem(i) ?: continue
|
||||
|
||||
if (itemStack == renderedItem || itemStack.type.isAir || itemStack.amount == 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
captiveItems.add(itemStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
|
||||
import com.willfp.eco.internal.gui.menu.MenuHandler
|
||||
import com.willfp.eco.internal.gui.menu.getMenu
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
@@ -20,11 +21,12 @@ open class EcoSlot(
|
||||
private val onMiddleClick: SlotHandler,
|
||||
private val updater: SlotUpdater
|
||||
) : Slot {
|
||||
|
||||
fun handleInventoryClick(
|
||||
event: InventoryClickEvent,
|
||||
menu: Menu
|
||||
) {
|
||||
event.isCancelled = true
|
||||
|
||||
when (event.click) {
|
||||
ClickType.LEFT -> this.onLeftClick.handle(event, this, menu)
|
||||
ClickType.RIGHT -> this.onRightClick.handle(event, this, menu)
|
||||
@@ -36,9 +38,9 @@ open class EcoSlot(
|
||||
}
|
||||
|
||||
override fun getItemStack(player: Player): ItemStack {
|
||||
val menu = MenuHandler.getMenu(player.openInventory.topInventory)!!
|
||||
val menu = player.openInventory.topInventory.getMenu()!!
|
||||
val prev = provider.provide(player, menu)
|
||||
return updater.update(player, menu, prev)
|
||||
return updater.update(player, menu, prev) ?: ItemStack(Material.AIR)
|
||||
}
|
||||
|
||||
fun getItemStack(
|
||||
@@ -46,7 +48,8 @@ open class EcoSlot(
|
||||
menu: Menu
|
||||
): ItemStack {
|
||||
val prev = provider.provide(player, menu)
|
||||
return updater.update(player, menu, prev)
|
||||
val updated = updater.update(player, menu, prev)
|
||||
return updated ?: ItemStack(Material.AIR)
|
||||
}
|
||||
|
||||
override fun isCaptive(): Boolean {
|
||||
|
||||
@@ -11,7 +11,7 @@ class ArgParserFlag : LookupArgParser {
|
||||
val flags = mutableSetOf<ItemFlag>()
|
||||
|
||||
for (arg in args) {
|
||||
val flag = kotlin.runCatching { ItemFlag.valueOf(arg.uppercase()) }.getOrNull() ?: continue
|
||||
val flag = runCatching { ItemFlag.valueOf(arg.uppercase()) }.getOrNull() ?: continue
|
||||
flags.add(flag)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ class ChatComponent : ChatComponentProxy {
|
||||
}
|
||||
|
||||
val newShowItem = showItem.nbt(
|
||||
BinaryTagHolder.binaryTagHolder(
|
||||
@Suppress("UnstableApiUsage", "DEPRECATION")
|
||||
BinaryTagHolder.of(
|
||||
CraftItemStack.asNMSCopy(
|
||||
Display.display(
|
||||
CraftItemStack.asBukkitCopy(
|
||||
|
||||
@@ -62,7 +62,8 @@ class ChatComponent : ChatComponentProxy {
|
||||
}
|
||||
|
||||
val newShowItem = showItem.nbt(
|
||||
BinaryTagHolder.binaryTagHolder(
|
||||
@Suppress("UnstableApiUsage", "DEPRECATION")
|
||||
BinaryTagHolder.of(
|
||||
CraftItemStack.asNMSCopy(
|
||||
Display.display(
|
||||
CraftItemStack.asBukkitCopy(
|
||||
|
||||
@@ -22,8 +22,10 @@ class MiniMessageTranslator : MiniMessageTranslatorProxy {
|
||||
).toLegacy()
|
||||
}.getOrNull() ?: mut
|
||||
|
||||
if (startsWithPrefix) {
|
||||
mut = Display.PREFIX + miniMessage
|
||||
mut = if (startsWithPrefix) {
|
||||
Display.PREFIX + miniMessage
|
||||
} else {
|
||||
miniMessage
|
||||
}
|
||||
|
||||
return mut
|
||||
|
||||
@@ -2,7 +2,7 @@ group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
dependencies {
|
||||
implementation 'com.github.Redempt:Crunch:1.0'
|
||||
implementation 'com.github.Redempt:Crunch:1.1.2'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.1.0'
|
||||
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
|
||||
compileOnly 'com.google.code.gson:gson:2.8.8'
|
||||
@@ -40,7 +40,8 @@ dependencies {
|
||||
compileOnly 'com.github.WhipDevelopment:CrashClaim:f9cd7d92eb'
|
||||
compileOnly 'com.wolfyscript.wolfyutilities:wolfyutilities:3.16.0.0'
|
||||
compileOnly 'com.github.decentsoftware-eu:decentholograms:2.1.2'
|
||||
compileOnly 'io.lumine.xikage:MythicMobs:4.9.1'
|
||||
compileOnly 'io.lumine:Mythic:5.0.1'
|
||||
compileOnly 'io.lumine:LumineUtils:1.16.1-SNAPSHOT'
|
||||
|
||||
// CombatLogX V10 + NewbieHelper Expansion
|
||||
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.willfp.eco.internal.EcoCleaner
|
||||
import com.willfp.eco.internal.EcoPropsParser
|
||||
import com.willfp.eco.internal.Plugins
|
||||
import com.willfp.eco.internal.config.EcoConfigFactory
|
||||
import com.willfp.eco.internal.config.updating.EcoConfigHandler
|
||||
import com.willfp.eco.internal.config.EcoConfigHandler
|
||||
import com.willfp.eco.internal.drops.EcoDropQueueFactory
|
||||
import com.willfp.eco.internal.events.EcoEventManager
|
||||
import com.willfp.eco.internal.extensions.EcoExtensionLoader
|
||||
|
||||
@@ -110,10 +110,12 @@ import com.willfp.eco.internal.spigot.math.evaluateExpression
|
||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
||||
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.CraftingRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.StackedRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
|
||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
|
||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler
|
||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler
|
||||
import com.willfp.eco.util.NumberUtils
|
||||
import com.willfp.eco.util.ServerUtils
|
||||
import com.willfp.eco.util.SkullUtils
|
||||
@@ -156,8 +158,11 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
Entities.registerArgParser(EntityArgParserSilent())
|
||||
Entities.registerArgParser(EntityArgParserEquipment())
|
||||
|
||||
ShapedRecipeListener.registerListener(ComplexInComplex())
|
||||
ShapedRecipeListener.registerListener(ComplexInVanilla())
|
||||
CraftingRecipeListener.registerListener(ComplexInComplex())
|
||||
CraftingRecipeListener.registerListener(ComplexInVanilla())
|
||||
|
||||
StackedRecipeListener.registerHandler(ShapedCraftingRecipeStackHandler())
|
||||
StackedRecipeListener.registerHandler(ShapelessCraftingRecipeStackHandler())
|
||||
|
||||
SegmentParserGroup().register()
|
||||
SegmentParserUseIfPresent().register()
|
||||
@@ -171,7 +176,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
val tpsProxy = getProxy(TPSProxy::class.java)
|
||||
ServerUtils.initialize { tpsProxy.getTPS() }
|
||||
|
||||
NumberUtils.initCrunch { exp, player -> evaluateExpression(exp, player) }
|
||||
NumberUtils.initCrunch { expression, player, statics -> evaluateExpression(expression, player, statics) }
|
||||
|
||||
postInit()
|
||||
}
|
||||
@@ -263,9 +268,8 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
IntegrationLoader("HeadDatabase") { CustomItemsManager.register(CustomItemsHeadDatabase(this)) },
|
||||
IntegrationLoader("ExecutableItems") { CustomItemsManager.register(CustomItemsExecutableItems()) },
|
||||
IntegrationLoader("CustomCrafting") {
|
||||
CustomItemsManager.register(CustomItemsCustomCrafting()); ShapedRecipeListener.registerValidator(
|
||||
CustomRecipeCustomCrafting()
|
||||
)
|
||||
CustomItemsManager.register(CustomItemsCustomCrafting())
|
||||
CraftingRecipeListener.registerValidator(CustomRecipeCustomCrafting())
|
||||
},
|
||||
IntegrationLoader("MythicMobs") { CustomItemsManager.register(CustomItemsMythicMobs(this)) },
|
||||
|
||||
@@ -317,7 +321,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||
NaturalExpGainListeners(),
|
||||
ArmorListener(),
|
||||
EntityDeathByEntityListeners(this),
|
||||
ShapedRecipeListener(),
|
||||
CraftingRecipeListener(),
|
||||
StackedRecipeListener(this),
|
||||
GUIListener(this),
|
||||
ArrowDataListener(this),
|
||||
|
||||
@@ -1,67 +1,42 @@
|
||||
package com.willfp.eco.internal.spigot.gui
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.drops.DropQueue
|
||||
import com.willfp.eco.internal.gui.menu.EcoMenu
|
||||
import com.willfp.eco.internal.gui.menu.MenuHandler
|
||||
import com.willfp.eco.internal.gui.menu.asRenderedInventory
|
||||
import com.willfp.eco.internal.gui.menu.getMenu
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlot
|
||||
import com.willfp.eco.util.MenuUtils
|
||||
import org.apache.commons.lang.Validate
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||
|
||||
class GUIListener(private val plugin: EcoPlugin) : Listener {
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
fun handleSlotClick(event: InventoryClickEvent) {
|
||||
val player = event.whoClicked
|
||||
if (player !is Player) {
|
||||
return
|
||||
}
|
||||
val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return
|
||||
val rendered = event.clickedInventory?.asRenderedInventory() ?: return
|
||||
|
||||
val menu = rendered.menu
|
||||
|
||||
val (row, column) = MenuUtils.convertSlotToRowColumn(event.slot)
|
||||
val slot = menu.getSlot(row, column)
|
||||
Validate.isTrue(slot is EcoSlot, "Slot not instance of EcoSlot!")
|
||||
val ecoSlot = menu.getSlot(row, column) as EcoSlot
|
||||
event.isCancelled = true
|
||||
ecoSlot.handleInventoryClick(event, menu)
|
||||
|
||||
if (event.clickedInventory == null) {
|
||||
return
|
||||
}
|
||||
val slot = menu.getSlot(row, column) as? EcoSlot ?: return
|
||||
|
||||
val extendedInventory = MenuHandler.getExtendedInventory(event.clickedInventory!!) ?: return
|
||||
slot.handleInventoryClick(event, menu)
|
||||
|
||||
plugin.scheduler.run { extendedInventory.refresh(player) }
|
||||
plugin.scheduler.run { rendered.render() }
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun handleCaptivatorSlots(event: InventoryClickEvent) {
|
||||
val player = event.whoClicked
|
||||
if (player !is Player) {
|
||||
return
|
||||
}
|
||||
|
||||
MenuHandler.getMenu(player.openInventory.topInventory) ?: return
|
||||
MenuHandler.getExtendedInventory(player.openInventory.topInventory) ?: return
|
||||
|
||||
plugin.scheduler.run { MenuHandler.getExtendedInventory(player.openInventory.topInventory)?.refresh(player) }
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
fun handleShiftClick(event: InventoryClickEvent) {
|
||||
if (!(event.click == ClickType.SHIFT_RIGHT || event.click == ClickType.SHIFT_LEFT)) {
|
||||
if (!event.isShiftClick) {
|
||||
return
|
||||
}
|
||||
|
||||
val player = event.whoClicked
|
||||
if (player !is Player) {
|
||||
return
|
||||
}
|
||||
val player = event.whoClicked as? Player ?: return
|
||||
|
||||
val inv = player.openInventory.topInventory
|
||||
|
||||
@@ -69,33 +44,26 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
||||
return
|
||||
}
|
||||
|
||||
val menu = MenuHandler.getMenu(inv) ?: return
|
||||
val menu = inv.getMenu() ?: return
|
||||
val rendered = inv.asRenderedInventory() ?: return
|
||||
|
||||
val (row, column) = MenuUtils.convertSlotToRowColumn(inv.firstEmpty())
|
||||
|
||||
val slot = menu.getSlot(row, column)
|
||||
|
||||
if (!slot.isCaptive) {
|
||||
event.isCancelled = true
|
||||
}
|
||||
|
||||
plugin.scheduler.run { rendered.render() }
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
fun handleClose(event: InventoryCloseEvent) {
|
||||
val player = event.player
|
||||
if (player !is Player) {
|
||||
return
|
||||
}
|
||||
val menu = MenuHandler.getMenu(event.inventory) ?: return
|
||||
Validate.isTrue(menu is EcoMenu, "Menu not instance of EcoMenu!")
|
||||
val ecoMenu = menu as EcoMenu
|
||||
ecoMenu.handleClose(event)
|
||||
val menu = event.inventory.getMenu() as? EcoMenu ?: return
|
||||
|
||||
DropQueue(player)
|
||||
.addItems(ecoMenu.getCaptiveItems(player))
|
||||
.setLocation(player.location)
|
||||
.forceTelekinesis()
|
||||
.push()
|
||||
menu.handleClose(event)
|
||||
|
||||
plugin.scheduler.run { MenuHandler.unregisterMenu(event.inventory) }
|
||||
plugin.scheduler.run { MenuHandler.unregisterInventory(event.inventory) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ package com.willfp.eco.internal.spigot.integrations.customentities
|
||||
|
||||
import com.willfp.eco.core.entities.CustomEntity
|
||||
import com.willfp.eco.core.integrations.customentities.CustomEntitiesWrapper
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs
|
||||
import io.lumine.mythic.bukkit.MythicBukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
|
||||
class CustomEntitiesMythicMobs : CustomEntitiesWrapper {
|
||||
override fun registerAllEntities() {
|
||||
val mobManager = MythicMobs.inst().mobManager
|
||||
val api = MythicMobs.inst().apiHelper
|
||||
val mobManager = MythicBukkit.inst().mobManager
|
||||
val api = MythicBukkit.inst().apiHelper
|
||||
|
||||
for (id in mobManager.mobNames) {
|
||||
val key = NamespacedKey.fromString("mythicmobs:${id.lowercase()}")
|
||||
|
||||
@@ -35,7 +35,7 @@ class CustomItemsHeadDatabase(
|
||||
private lateinit var api: HeadDatabaseAPI
|
||||
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
if (this::api.isInitialized) {
|
||||
if (!this::api.isInitialized) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@ import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitItemStack
|
||||
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicDropLoadEvent
|
||||
import io.lumine.xikage.mythicmobs.drops.Drop
|
||||
import io.lumine.xikage.mythicmobs.drops.DropMetadata
|
||||
import io.lumine.xikage.mythicmobs.drops.IMultiDrop
|
||||
import io.lumine.xikage.mythicmobs.drops.LootBag
|
||||
import io.lumine.xikage.mythicmobs.drops.droppables.ItemDrop
|
||||
import io.lumine.xikage.mythicmobs.io.MythicLineConfig
|
||||
import io.lumine.mythic.api.config.MythicLineConfig
|
||||
import io.lumine.mythic.api.drops.DropMetadata
|
||||
import io.lumine.mythic.api.drops.IMultiDrop
|
||||
import io.lumine.mythic.bukkit.adapters.BukkitItemStack
|
||||
import io.lumine.mythic.bukkit.events.MythicDropLoadEvent
|
||||
import io.lumine.mythic.core.drops.Drop
|
||||
import io.lumine.mythic.core.drops.LootBag
|
||||
import io.lumine.mythic.core.drops.droppables.ItemDrop
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
@@ -42,9 +42,9 @@ class CustomItemsMythicMobs(
|
||||
|
||||
private class MythicMobsDrop(
|
||||
private val plugin: EcoPlugin,
|
||||
private val config: MythicLineConfig
|
||||
) : Drop(config.line, config), IMultiDrop {
|
||||
private val id = config.getString(arrayOf("type", "t", "item", "i"), this.dropVar)
|
||||
itemConfig: MythicLineConfig
|
||||
) : Drop(itemConfig.line, itemConfig), IMultiDrop {
|
||||
private val id = itemConfig.getString(arrayOf("type", "t", "item", "i"), this.dropVar)
|
||||
|
||||
override fun get(data: DropMetadata): LootBag {
|
||||
val bag = LootBag(data)
|
||||
|
||||
@@ -2,33 +2,31 @@ package com.willfp.eco.internal.spigot.integrations.customitems
|
||||
|
||||
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
|
||||
import com.willfp.eco.core.items.CustomItem
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.items.provider.ItemProvider
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import io.th0rgal.oraxen.items.OraxenItems
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.Objects
|
||||
import java.util.function.Predicate
|
||||
|
||||
class CustomItemsOraxen : CustomItemsWrapper {
|
||||
override fun registerAllItems() {
|
||||
for (item in OraxenItems.getItems()) {
|
||||
val stack = item.build()
|
||||
val id: String = Objects.requireNonNullElse(OraxenItems.getIdByItem(item), "")
|
||||
if (id.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
val key: NamespacedKey = NamespacedKeyUtils.create("oraxen", id.lowercase())
|
||||
CustomItem(
|
||||
key, Predicate { test: ItemStack ->
|
||||
val oraxenId: String = OraxenItems.getIdByItem(test) ?: return@Predicate false
|
||||
oraxenId.equals(id, ignoreCase = true)
|
||||
},
|
||||
stack
|
||||
).register()
|
||||
}
|
||||
Items.registerItemProvider(OraxenProvider())
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "Oraxen"
|
||||
}
|
||||
}
|
||||
|
||||
private class OraxenProvider : ItemProvider("oraxen") {
|
||||
override fun provideForKey(key: String): TestableItem? {
|
||||
val item = OraxenItems.getItemById(key) ?: return null
|
||||
val id = OraxenItems.getIdByItem(item)
|
||||
val namespacedKey = NamespacedKeyUtils.create("oraxen", id)
|
||||
return CustomItem(
|
||||
namespacedKey,
|
||||
{ id.equals(OraxenItems.getIdByItem(it), ignoreCase = true) },
|
||||
item.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,30 @@
|
||||
package com.willfp.eco.internal.spigot.math
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||
import com.willfp.eco.core.placeholder.StaticPlaceholder
|
||||
import org.bukkit.entity.Player
|
||||
import redempt.crunch.CompiledExpression
|
||||
import redempt.crunch.Crunch
|
||||
import redempt.crunch.data.FastNumberParsing
|
||||
import redempt.crunch.functional.EvaluationEnvironment
|
||||
|
||||
private val cache = mutableMapOf<String, CompiledExpression>()
|
||||
private val cache: Cache<String, CompiledExpression> = Caffeine.newBuilder().build()
|
||||
private val goToZero = Crunch.compileExpression("0")
|
||||
|
||||
fun evaluateExpression(expression: String, player: Player?): Double {
|
||||
fun evaluateExpression(expression: String, player: Player?, statics: Iterable<StaticPlaceholder>): Double {
|
||||
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
.map { PlaceholderManager.translatePlaceholders(expression, player) }
|
||||
.map { PlaceholderManager.translatePlaceholders(it, player, statics.toList()) }
|
||||
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
||||
.toDoubleArray()
|
||||
|
||||
val compiled = generateExpression(expression)
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
|
||||
private fun generateExpression(expression: String): CompiledExpression {
|
||||
val cached = cache[expression]
|
||||
|
||||
if (cached != null) {
|
||||
return cached
|
||||
val compiled = cache.get(expression) {
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(it)
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
}
|
||||
|
||||
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
|
||||
|
||||
val env = EvaluationEnvironment()
|
||||
env.setVariableNames(*placeholders.toTypedArray())
|
||||
|
||||
val compiled = runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
|
||||
cache[expression] = compiled
|
||||
return compiled
|
||||
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.bukkit.event.inventory.CraftItemEvent
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent
|
||||
import org.bukkit.event.player.PlayerRecipeDiscoverEvent
|
||||
|
||||
class ShapedRecipeListener : Listener {
|
||||
class CraftingRecipeListener : Listener {
|
||||
@EventHandler
|
||||
fun preventLearningDisplayedRecipes(event: PlayerRecipeDiscoverEvent) {
|
||||
if (!EcoPlugin.getPluginNames().contains(event.recipe.namespace)) {
|
||||
@@ -1,16 +1,19 @@
|
||||
package com.willfp.eco.internal.spigot.recipes
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||
import com.willfp.eco.core.recipe.parts.GroupedTestableItems
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.EventPriority
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.inventory.CraftingInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -38,13 +41,18 @@ class StackedRecipeListener(
|
||||
|
||||
val recipe = Recipes.getMatch(matrix) ?: return
|
||||
|
||||
// Get the handler for the type of recipe
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val handler = handlers.firstOrNull { recipe::class.java.isAssignableFrom(it.recipeType) } ?: return
|
||||
|
||||
var isStackedRecipe = false
|
||||
var maxCraftable = Int.MAX_VALUE
|
||||
|
||||
// Start by calculating the maximum number of items to craft
|
||||
val maxToCraftData = handler.makeData(recipe)
|
||||
for (i in 0..8) {
|
||||
val item = inventory.matrix.getOrNull(i) ?: continue
|
||||
val part = recipe.parts[i].let {
|
||||
val part = handler.getPart(recipe, i, item, maxToCraftData).let {
|
||||
if (it is GroupedTestableItems) {
|
||||
it.getMatchingChild(item)
|
||||
} else it
|
||||
@@ -68,9 +76,11 @@ class StackedRecipeListener(
|
||||
val existingResult = inventory.result
|
||||
|
||||
// Deduct the correct number of items from the inventory
|
||||
|
||||
val deductionData = handler.makeData(recipe)
|
||||
for (i in 0..8) {
|
||||
val item = inventory.matrix.getOrNull(i) ?: continue
|
||||
val part = recipe.parts[i].let {
|
||||
val part = handler.getPart(recipe, i, item, deductionData).let {
|
||||
if (it is GroupedTestableItems) {
|
||||
it.getMatchingChild(item)
|
||||
} else it
|
||||
@@ -128,4 +138,18 @@ class StackedRecipeListener(
|
||||
block()
|
||||
plugin.scheduler.run(block)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val handlers = mutableListOf<StackedRecipeHandler>()
|
||||
|
||||
fun registerHandler(handler: StackedRecipeHandler) {
|
||||
handlers.add(handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface StackedRecipeHandler {
|
||||
fun makeData(recipe: CraftingRecipe): Any?
|
||||
fun getPart(recipe: CraftingRecipe, position: Int, item: ItemStack, data: Any?): TestableItem?
|
||||
val recipeType: Class<out CraftingRecipe>
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.recipe.Recipes
|
||||
import com.willfp.eco.internal.spigot.recipes.CraftingRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class ComplexInComplex : RecipeListener {
|
||||
@@ -19,7 +19,7 @@ class ComplexInComplex : RecipeListener {
|
||||
|
||||
val matrix = event.inventory.matrix
|
||||
|
||||
if (ShapedRecipeListener.validators.any { it.validate(event) }) {
|
||||
if (CraftingRecipeListener.validators.any { it.validate(event) }) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,4 +44,4 @@ class ComplexInComplex : RecipeListener {
|
||||
event.deny()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package com.willfp.eco.internal.spigot.recipes.listeners
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.internal.spigot.recipes.CraftingRecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.GenericCraftEvent
|
||||
import com.willfp.eco.internal.spigot.recipes.RecipeListener
|
||||
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
|
||||
|
||||
class ComplexInVanilla : RecipeListener {
|
||||
override fun handle(event: GenericCraftEvent) {
|
||||
@@ -12,7 +12,7 @@ class ComplexInVanilla : RecipeListener {
|
||||
return
|
||||
}
|
||||
|
||||
if (ShapedRecipeListener.validators.any { it.validate(event) }) {
|
||||
if (CraftingRecipeListener.validators.any { it.validate(event) }) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -22,4 +22,4 @@ class ComplexInVanilla : RecipeListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.stackhandlers
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe
|
||||
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe
|
||||
import com.willfp.eco.internal.spigot.recipes.StackedRecipeHandler
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class ShapedCraftingRecipeStackHandler : StackedRecipeHandler {
|
||||
override val recipeType = ShapedCraftingRecipe::class.java
|
||||
override fun makeData(recipe: CraftingRecipe): Any? = null
|
||||
|
||||
override fun getPart(recipe: CraftingRecipe, position: Int, item: ItemStack, data: Any?): TestableItem? =
|
||||
recipe.parts[position]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.willfp.eco.internal.spigot.recipes.stackhandlers
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem
|
||||
import com.willfp.eco.core.recipe.recipes.CraftingRecipe
|
||||
import com.willfp.eco.core.recipe.recipes.ShapelessCraftingRecipe
|
||||
import com.willfp.eco.internal.spigot.recipes.StackedRecipeHandler
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class ShapelessCraftingRecipeStackHandler :
|
||||
StackedRecipeHandler {
|
||||
override val recipeType = ShapelessCraftingRecipe::class.java
|
||||
override fun makeData(recipe: CraftingRecipe): Any {
|
||||
recipe as ShapelessCraftingRecipe
|
||||
return recipe.newTest()
|
||||
}
|
||||
|
||||
override fun getPart(
|
||||
recipe: CraftingRecipe,
|
||||
position: Int,
|
||||
item: ItemStack,
|
||||
data: Any?
|
||||
): TestableItem? {
|
||||
recipe as ShapelessCraftingRecipe
|
||||
data as ShapelessCraftingRecipe.RecipeTest
|
||||
|
||||
return data.matchAndRemove(item)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
version = 6.27.1
|
||||
version = 6.30.0
|
||||
plugin-name = eco
|
||||
kotlin.code.style = official
|
||||
Reference in New Issue
Block a user