Compare commits
177 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61ace5c8e5 | ||
|
|
94b73ef35c | ||
|
|
5cfc2068e7 | ||
|
|
0ce7d1dd6c | ||
|
|
19eefaf879 | ||
|
|
1ebf7fb875 | ||
|
|
e8afd15d80 | ||
|
|
d024c9238e | ||
|
|
1356bd1f26 | ||
|
|
407ccca5e0 | ||
|
|
82de602d47 | ||
|
|
b0873112af | ||
|
|
3a0b81b7de | ||
|
|
5142b9ce92 | ||
|
|
9403a1cbcb | ||
|
|
e4ebea354d | ||
|
|
d32b31f1e5 | ||
|
|
384657f1dc | ||
|
|
7c9d226bc3 | ||
|
|
031401bb8e | ||
|
|
1a5c429b67 | ||
|
|
d028cf5bf3 | ||
|
|
fdd1581ce3 | ||
|
|
3d07e10543 | ||
|
|
c851e35347 | ||
|
|
4cbb33b1fd | ||
|
|
2ff1458772 | ||
|
|
e71ad9f034 | ||
|
|
196a651ab3 | ||
|
|
253a8c24ad | ||
|
|
ac265d0260 | ||
|
|
ad861b10bb | ||
|
|
db5b7f89f6 | ||
|
|
2c33ce25c0 | ||
|
|
9c3ca429c9 | ||
|
|
70e294501a | ||
|
|
65a0a0ecc7 | ||
|
|
d4431e7569 | ||
|
|
a6191b0870 | ||
|
|
5eecef83ee | ||
|
|
82a02f3738 | ||
|
|
804142799b | ||
|
|
e1de9b9ab3 | ||
|
|
cc56343041 | ||
|
|
69d28e8bc2 | ||
|
|
6878a74724 | ||
|
|
ebc76bba76 | ||
|
|
378218b7da | ||
|
|
e053514b94 | ||
|
|
341a30e6da | ||
|
|
70eb6d4420 | ||
|
|
aa368909ae | ||
|
|
606a54bcf8 | ||
|
|
7f8fb3d87b | ||
|
|
e97d454ff6 | ||
|
|
109b9aa3f3 | ||
|
|
4a90385b27 | ||
|
|
0edd50832c | ||
|
|
46415268b7 | ||
|
|
b652dbad2d | ||
|
|
50550d077a | ||
|
|
60c3b58a33 | ||
|
|
7216d0b09f | ||
|
|
97eeea8d48 | ||
|
|
82061ee6a3 | ||
|
|
f274b9045e | ||
|
|
2241a5c90f | ||
|
|
bbc38ae801 | ||
|
|
e77346ed62 | ||
|
|
6117abca56 | ||
|
|
2e2a061ebe | ||
|
|
cdc89ac397 | ||
|
|
e758cebe77 | ||
|
|
a408e3436a | ||
|
|
3df977c1bc | ||
|
|
136f1841b4 | ||
|
|
1086a59a6a | ||
|
|
d9147f9918 | ||
|
|
d144df4048 | ||
|
|
061f77e911 | ||
|
|
5cebe2fce8 | ||
|
|
1e712dcae6 | ||
|
|
09d444da58 | ||
|
|
09f45c0ab5 | ||
|
|
f64d69f084 | ||
|
|
86a948738f | ||
|
|
8f9c5e7ed8 | ||
|
|
ae897b7493 | ||
|
|
f1a7c9d50e | ||
|
|
83ee8fe4cd | ||
|
|
465f885e22 | ||
|
|
d4141735a9 | ||
|
|
b9b4ce1937 | ||
|
|
56234e6c83 | ||
|
|
2dda34097e | ||
|
|
155a349569 | ||
|
|
ce231934a3 | ||
|
|
5cbb7bfe47 | ||
|
|
06e0ec0295 | ||
|
|
02ed583674 | ||
|
|
8e4cbdd1aa | ||
|
|
8828f8e45d | ||
|
|
d15524ee9e | ||
|
|
d45e66d71e | ||
|
|
6b1dde7540 | ||
|
|
abf2964c48 | ||
|
|
db51c4c761 | ||
|
|
cbb574acec | ||
|
|
93c044ef09 | ||
|
|
1cc39fe40a | ||
|
|
edfd561fcd | ||
|
|
bd7f22cb02 | ||
|
|
3233bad307 | ||
|
|
3cefcbe0bb | ||
|
|
49bce53724 | ||
|
|
2b86159b30 | ||
|
|
d028511a48 | ||
|
|
5ad1ef33b8 | ||
|
|
634d6194d6 | ||
|
|
7f7eb4f45a | ||
|
|
bd90ae996b | ||
|
|
1bc57dec08 | ||
|
|
ce44d40f0f | ||
|
|
68824fb4d0 | ||
|
|
fd96b0d2cf | ||
|
|
2669569e81 | ||
|
|
067f740bcc | ||
|
|
2ce96ab0b1 | ||
|
|
027f9be194 | ||
|
|
a09018d1f0 | ||
|
|
a1da83173d | ||
|
|
8ac30283f8 | ||
|
|
6099b5d64d | ||
|
|
19d2e0788b | ||
|
|
1b223b3736 | ||
|
|
d6d1f01704 | ||
|
|
51231939c0 | ||
|
|
72fb20ecd9 | ||
|
|
58a386922c | ||
|
|
12824c7f6c | ||
|
|
b5236b8db6 | ||
|
|
3ffbb861d1 | ||
|
|
f8fad15f0b | ||
|
|
a0e96fca35 | ||
|
|
6cf9a53a65 | ||
|
|
a4909453d7 | ||
|
|
a10666f792 | ||
|
|
a845cda9ed | ||
|
|
ed5f1ccb5e | ||
|
|
c6e59e1d62 | ||
|
|
ed24b6278e | ||
|
|
3aea7b4077 | ||
|
|
f53c29cd56 | ||
|
|
6845152a09 | ||
|
|
7eaf2dc8ed | ||
|
|
310485402f | ||
|
|
727dc25083 | ||
|
|
364f36d502 | ||
|
|
b6086bc4bd | ||
|
|
dd3beaa548 | ||
|
|
c36c0c247f | ||
|
|
6611a0f82c | ||
|
|
625b981b81 | ||
|
|
d8607917a1 | ||
|
|
30d5f54459 | ||
|
|
a59c05174f | ||
|
|
cf01abcf87 | ||
|
|
70a4a06d4f | ||
|
|
bbee18fd8a | ||
|
|
26ab9a327d | ||
|
|
0676f5fa33 | ||
|
|
051b95ad88 | ||
|
|
d786014cbc | ||
|
|
b62bb48bb6 | ||
|
|
b238a10209 | ||
|
|
251049f1f1 | ||
|
|
16d146dba0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,6 +14,7 @@ bin/
|
||||
# Gradle
|
||||
.gradle
|
||||
**/build/
|
||||
**/out/
|
||||
!eco-api/src/**/build/
|
||||
.gradletasknamecache
|
||||
!gradle-wrapper.jar
|
||||
|
||||
@@ -99,7 +99,7 @@ Here's a list of some (not all) of the features of eco:
|
||||
- ArmorEquipEvent
|
||||
- EntityDeathByEntityEvent
|
||||
- NaturalExpGainEvent
|
||||
- Plugin extensions (Plugins for plugins)
|
||||
- Plugin extensions (com.willfp.eco.internal.Plugins for plugins)
|
||||
- GUI System
|
||||
- Integration system for external plugins
|
||||
- Anticheat support
|
||||
@@ -158,8 +158,12 @@ Here's a list of some (not all) of the features of eco:
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="http://gamersupps.gg/discount/Auxilor?afmc=Auxilor" target="_blank">
|
||||
<img src="https://i.imgur.com/uFDpBAC.png" alt="supps banner">
|
||||
</a>
|
||||
<a href="https://dedimc.promo/Auxilor" target="_blank">
|
||||
<img src="https://i.imgur.com/zdDLhFA.png" alt="dedimc banner">
|
||||
</a>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
|
||||
27
build.gradle
27
build.gradle
@@ -7,7 +7,11 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation project(":eco-api")
|
||||
implementation project(":eco-core").getSubprojects()
|
||||
implementation project(":eco-core:core-plugin")
|
||||
implementation project(":eco-core:core-proxy")
|
||||
implementation project(":eco-core:core-backend")
|
||||
implementation project(":eco-core:core-nms:v1_16_R3")
|
||||
implementation project(path: ":eco-core:core-nms:v1_17_R1", configuration: 'mapped')
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -47,6 +51,9 @@ allprojects {
|
||||
|
||||
// CombatLogX
|
||||
maven { url 'https://nexus.sirblobman.xyz/repository/public/' }
|
||||
|
||||
// Head Database
|
||||
maven { url 'https://mvn.intellectualsites.com/content/groups/public/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -57,6 +64,10 @@ allprojects {
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.20'
|
||||
testCompileOnly 'org.projectlombok:lombok:1.18.20'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
|
||||
|
||||
// Test
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
@@ -75,7 +86,7 @@ allprojects {
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate('org.bstats.bukkit', 'com.willfp.eco.shaded.bstats')
|
||||
relocate('org.bstats', 'com.willfp.eco.shaded.bstats')
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -92,6 +103,18 @@ allprojects {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
|
||||
// Always run tests, even when nothing changed.
|
||||
dependsOn cleanTest
|
||||
|
||||
// Show test results.
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
}
|
||||
}
|
||||
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
compileJava.dependsOn clean
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
-->
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<property name="fileExtensions" value="java, properties, xml, kt"/>
|
||||
|
||||
<!-- Excludes all 'module-info.java' files -->
|
||||
<!-- See https://checkstyle.org/config_filefilters.html -->
|
||||
@@ -66,6 +66,7 @@
|
||||
<module name="FileLength"/>
|
||||
<module name="LineLength">
|
||||
<property name="fileExtensions" value="java"/>
|
||||
<property name="fileExtensions" value="kt"/>
|
||||
<property name="max" value="200"/>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -8,17 +8,16 @@ version rootProject.version
|
||||
dependencies {
|
||||
compileOnly 'org.spigotmc:spigot-api:1.17-R0.1-SNAPSHOT'
|
||||
compileOnly 'org.apache.maven:maven-artifact:3.0.3'
|
||||
compileOnly 'org.bstats:bstats-bukkit:1.7'
|
||||
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
|
||||
compileOnly 'com.google.code.gson:gson:2.8.7'
|
||||
compileOnly 'net.kyori:adventure-text-serializer-gson:4.8.1'
|
||||
compileOnly 'net.kyori:adventure-text-serializer-legacy:4.8.1'
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
compileJava.dependsOn clean
|
||||
|
||||
build.dependsOn publishToMavenLocal
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.willfp.eco.core.web.UpdateChecker;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -52,6 +51,7 @@ import java.util.stream.Collectors;
|
||||
* <b>IMPORTANT: When reloading a plugin, all runnables / tasks will
|
||||
* be cancelled.</b>
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class EcoPlugin extends JavaPlugin {
|
||||
/**
|
||||
* The spigot resource ID of the plugin.
|
||||
@@ -347,7 +347,7 @@ public abstract class EcoPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
if (this.getBStatsId() != 0) {
|
||||
new Metrics(this, this.getBStatsId());
|
||||
Eco.getHandler().registerBStats(this);
|
||||
}
|
||||
|
||||
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
|
||||
@@ -405,7 +405,6 @@ public abstract class EcoPlugin extends JavaPlugin {
|
||||
|
||||
this.getEventManager().unregisterAllListeners();
|
||||
this.getScheduler().cancelAll();
|
||||
this.getConfigHandler().saveAllConfigs();
|
||||
|
||||
this.handleDisable();
|
||||
|
||||
@@ -464,7 +463,7 @@ public abstract class EcoPlugin extends JavaPlugin {
|
||||
}
|
||||
|
||||
/**
|
||||
* Default code to be executed on plugin reload.
|
||||
* Reload the plugin.
|
||||
*/
|
||||
public final void reload() {
|
||||
this.getConfigHandler().updateConfigs();
|
||||
@@ -476,6 +475,19 @@ public abstract class EcoPlugin extends JavaPlugin {
|
||||
this.handleReload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the plugin and return the time taken to reload.
|
||||
*
|
||||
* @return The time.
|
||||
*/
|
||||
public final long reloadWithTime() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
this.reload();
|
||||
|
||||
return System.currentTimeMillis() - startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* The plugin-specific code to be executed on enable.
|
||||
* <p>
|
||||
@@ -601,7 +613,7 @@ public abstract class EcoPlugin extends JavaPlugin {
|
||||
* @param <T> The proxy type.
|
||||
* @return The proxy.
|
||||
*/
|
||||
public <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
|
||||
public final <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
|
||||
Validate.notNull(proxyFactory, "Plugin does not support proxy!");
|
||||
|
||||
return proxyFactory.getProxy(proxyClass);
|
||||
|
||||
@@ -8,11 +8,13 @@ import com.willfp.eco.core.extensions.ExtensionLoader;
|
||||
import com.willfp.eco.core.factory.MetadataValueFactory;
|
||||
import com.willfp.eco.core.factory.NamespacedKeyFactory;
|
||||
import com.willfp.eco.core.factory.RunnableFactory;
|
||||
import com.willfp.eco.core.fast.FastItemStack;
|
||||
import com.willfp.eco.core.gui.GUIFactory;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
|
||||
import com.willfp.eco.core.proxy.Cleaner;
|
||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||
import com.willfp.eco.core.scheduling.Scheduler;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -158,4 +160,19 @@ public interface Handler {
|
||||
* @return A list of plugin names in lowercase.
|
||||
*/
|
||||
List<String> getLoadedPlugins();
|
||||
|
||||
/**
|
||||
* Create a FastItemStack.
|
||||
*
|
||||
* @param itemStack The base ItemStack.
|
||||
* @return The FastItemStack.
|
||||
*/
|
||||
FastItemStack createFastItemStack(@NotNull ItemStack itemStack);
|
||||
|
||||
/**
|
||||
* Register bStats metrics.
|
||||
*
|
||||
* @param plugin The plugin.
|
||||
*/
|
||||
void registerBStats(@NotNull EcoPlugin plugin);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,14 @@ public class Prerequisite {
|
||||
"Requires server to be running paper (or a fork)"
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires the server to be running an implementation of paper.
|
||||
*/
|
||||
public static final Prerequisite HAS_VAULT = new Prerequisite(
|
||||
() -> ClassUtils.exists("net.milkbowl.vault.economy.Economy"),
|
||||
"Requires server to have vault"
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires the server to be running 1.17.
|
||||
*/
|
||||
|
||||
@@ -42,10 +42,24 @@ public interface CommandBase {
|
||||
*/
|
||||
CommandHandler getHandler();
|
||||
|
||||
/**
|
||||
* Set the handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
void setHandler(@NotNull CommandHandler handler);
|
||||
|
||||
/**
|
||||
* Get the tab completer.
|
||||
*
|
||||
* @return The tab completer.
|
||||
*/
|
||||
TabCompleteHandler getTabCompleter();
|
||||
|
||||
/**
|
||||
* Set the tab completer.
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
void setTabCompleter(@NotNull TabCompleteHandler handler);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.willfp.eco.core.command.CommandHandler;
|
||||
import com.willfp.eco.core.command.TabCompleteHandler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.StringUtil;
|
||||
@@ -48,6 +49,20 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
|
||||
@Getter
|
||||
private final boolean playersOnly;
|
||||
|
||||
/**
|
||||
* The actual code to be executed in the command.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private CommandHandler handler = (sender, args) -> { };
|
||||
|
||||
/**
|
||||
* The tab completion code to be executed in the command.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private TabCompleteHandler tabCompleter = (sender, args) -> new ArrayList<>();
|
||||
|
||||
/**
|
||||
* All subcommands for the command.
|
||||
*/
|
||||
@@ -164,14 +179,6 @@ abstract class HandledCommand extends PluginDependent<EcoPlugin> implements Comm
|
||||
return this.getTabCompleter().tabComplete(sender, Arrays.asList(args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract CommandHandler getHandler();
|
||||
|
||||
@Override
|
||||
public TabCompleteHandler getTabCompleter() {
|
||||
return (sender, args) -> new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* If a sender can execute the command.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.willfp.eco.core.config.base;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.config.yaml.YamlBaseConfig;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -42,6 +43,18 @@ public class LangYml extends YamlBaseConfig {
|
||||
* @return The message with a prefix appended.
|
||||
*/
|
||||
public String getMessage(@NotNull final String message) {
|
||||
return getPrefix() + this.getString("messages." + message);
|
||||
return getMessage(message, StringUtils.FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a chat message.
|
||||
*
|
||||
* @param message The key of the message.
|
||||
* @param option The format options.
|
||||
* @return The message with a prefix appended.
|
||||
*/
|
||||
public String getMessage(@NotNull final String message,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return getPrefix() + this.getString("messages." + message, option);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core.config.interfaces;
|
||||
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -165,7 +166,9 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or an empty string if not found.
|
||||
*/
|
||||
@NotNull
|
||||
String getString(@NotNull String path);
|
||||
default String getString(@NotNull String path) {
|
||||
return getString(path, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
@@ -175,8 +178,36 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or an empty string if not found.
|
||||
*/
|
||||
@NotNull
|
||||
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.
|
||||
*/
|
||||
@NotNull
|
||||
default String getString(@NotNull String path,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return this.getString(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the string should be formatted.
|
||||
* @param option The format option.
|
||||
* @return The found value, or an empty string if not found.
|
||||
*/
|
||||
@NotNull
|
||||
String getString(@NotNull String path,
|
||||
boolean format);
|
||||
boolean format,
|
||||
@NotNull StringUtils.FormatOption option);
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
@@ -185,7 +216,9 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
String getStringOrNull(@NotNull String path);
|
||||
default String getStringOrNull(@NotNull String path) {
|
||||
return getStringOrNull(path, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
@@ -195,8 +228,36 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
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.
|
||||
*/
|
||||
@Nullable
|
||||
default String getStringOrNull(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return this.getStringOrNull(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the string should be formatted.
|
||||
* @param option The format option.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
String getStringOrNull(@NotNull String path,
|
||||
boolean format);
|
||||
boolean format,
|
||||
@NotNull StringUtils.FormatOption option);
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
@@ -207,7 +268,9 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
*/
|
||||
@NotNull
|
||||
List<String> getStrings(@NotNull String path);
|
||||
default List<String> getStrings(@NotNull String path) {
|
||||
return getStrings(path, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
@@ -217,8 +280,36 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
*/
|
||||
@NotNull
|
||||
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.
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getStrings(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return getStrings(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the strings should be formatted.
|
||||
* @param option The option.
|
||||
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
|
||||
*/
|
||||
@NotNull
|
||||
List<String> getStrings(@NotNull String path,
|
||||
boolean format);
|
||||
boolean format,
|
||||
@NotNull StringUtils.FormatOption option);
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
@@ -227,7 +318,9 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
List<String> getStringsOrNull(@NotNull String path);
|
||||
default List<String> getStringsOrNull(@NotNull String path) {
|
||||
return getStringsOrNull(path, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
@@ -237,8 +330,36 @@ public interface Config extends Cloneable {
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
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.
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getStringsOrNull(@NotNull String path,
|
||||
@NotNull StringUtils.FormatOption option) {
|
||||
return getStringsOrNull(path, true, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of strings from config.
|
||||
*
|
||||
* @param path The key to fetch the value from.
|
||||
* @param format If the strings should be formatted.
|
||||
* @param option The format option.
|
||||
* @return The found value, or null if not found.
|
||||
*/
|
||||
@Nullable
|
||||
List<String> getStringsOrNull(@NotNull String path,
|
||||
boolean format);
|
||||
boolean format,
|
||||
@NotNull StringUtils.FormatOption option);
|
||||
|
||||
/**
|
||||
* Get a decimal from config.
|
||||
|
||||
@@ -29,6 +29,27 @@ public interface JSONConfig extends Config {
|
||||
@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();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,16 @@ public abstract class JSONConfigWrapper extends ConfigWrapper<JSONConfig> implem
|
||||
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,6 +1,7 @@
|
||||
package com.willfp.eco.core.config.wrapper;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -125,48 +126,33 @@ public abstract class ConfigWrapper<T extends Config> implements Config {
|
||||
return handle.getBoolsOrNull(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getString(@NotNull final String path) {
|
||||
return handle.getString(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getString(@NotNull final String path,
|
||||
final boolean format) {
|
||||
return handle.getString(path, format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getStringOrNull(@NotNull final String path) {
|
||||
return handle.getStringOrNull(path);
|
||||
final boolean format,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return handle.getString(path, format, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getStringOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
return handle.getStringOrNull(path, format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getStrings(@NotNull final String path) {
|
||||
return handle.getStrings(path);
|
||||
final boolean format,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return handle.getStringOrNull(path, format, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getStrings(@NotNull final String path,
|
||||
final boolean format) {
|
||||
return handle.getStrings(path, format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> getStringsOrNull(@NotNull final String path) {
|
||||
return handle.getStringsOrNull(path);
|
||||
final boolean format,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return handle.getStrings(path, format, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> getStringsOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
return handle.getStringsOrNull(path, format);
|
||||
final boolean format,
|
||||
@NotNull final StringUtils.FormatOption option) {
|
||||
return handle.getStringsOrNull(path, format, option);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,12 +3,14 @@ package com.willfp.eco.core.display;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -57,10 +59,18 @@ public class Display {
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack display(@NotNull final ItemStack itemStack) {
|
||||
if (!itemStack.hasItemMeta()) {
|
||||
return itemStack; // return early if there's no customization of the item
|
||||
}
|
||||
return display(itemStack, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display on ItemStacks.
|
||||
*
|
||||
* @param itemStack The item.
|
||||
* @param player The player.
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack display(@NotNull final ItemStack itemStack,
|
||||
@Nullable final Player player) {
|
||||
Map<String, Object[]> pluginVarArgs = new HashMap<>();
|
||||
|
||||
for (DisplayPriority priority : DisplayPriority.values()) {
|
||||
@@ -83,6 +93,9 @@ public class Display {
|
||||
for (DisplayModule module : modules) {
|
||||
Object[] varargs = pluginVarArgs.get(module.getPluginName());
|
||||
module.display(itemStack, varargs);
|
||||
if (player != null) {
|
||||
module.display(itemStack, player, varargs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +109,19 @@ public class Display {
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack displayAndFinalize(@NotNull final ItemStack itemStack) {
|
||||
return finalize(display(itemStack));
|
||||
return finalize(display(itemStack, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display on ItemStacks and then finalize.
|
||||
*
|
||||
* @param itemStack The item.
|
||||
* @param player The player.
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
public ItemStack displayAndFinalize(@NotNull final ItemStack itemStack,
|
||||
@Nullable final Player player) {
|
||||
return finalize(display(itemStack, player));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,10 +135,6 @@ public class Display {
|
||||
unfinalize(itemStack);
|
||||
}
|
||||
|
||||
if (!itemStack.hasItemMeta()) {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
|
||||
if (meta == null) {
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.willfp.eco.core.display;
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Class for all plugin-specific client-side item display modules.
|
||||
@@ -39,6 +41,19 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
|
||||
// Technically optional.
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an item.
|
||||
*
|
||||
* @param itemStack The item.
|
||||
* @param player The player.
|
||||
* @param args Optional args for display.
|
||||
*/
|
||||
protected void display(@NotNull final ItemStack itemStack,
|
||||
@Nullable final Player player,
|
||||
@NotNull final Object... args) {
|
||||
// Technically optional.
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert an item.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.willfp.eco.core.events;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The armor change event <b>does</b> contain information about the event.
|
||||
* <p>
|
||||
* Unlike {@link ArmorEquipEvent}, it is called the next tick and contains previous and current armor contents.
|
||||
*/
|
||||
public class ArmorChangeEvent extends PlayerEvent {
|
||||
/**
|
||||
* Bukkit parity.
|
||||
*/
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
/**
|
||||
* The armor contents before. 0 is helmet, 3 is boots.
|
||||
*/
|
||||
@Getter
|
||||
private final List<ItemStack> before;
|
||||
|
||||
/**
|
||||
* The armor contents after. 0 is helmet, 3 is boots.
|
||||
*/
|
||||
@Getter
|
||||
private final List<ItemStack> after;
|
||||
|
||||
/**
|
||||
* Create a new ArmorChangeEvent.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param before The armor contents before.
|
||||
* @param after The armor contents after.
|
||||
*/
|
||||
public ArmorChangeEvent(@NotNull final Player player,
|
||||
@NotNull final List<ItemStack> before,
|
||||
@NotNull final List<ItemStack> after) {
|
||||
super(player);
|
||||
this.before = before;
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of handlers handling this event.
|
||||
*
|
||||
* @return A list of handlers handling this event.
|
||||
*/
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bukkit parity.
|
||||
*
|
||||
* @return The handler list.
|
||||
*/
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
* <p>
|
||||
* The event is called before the player's inventory actually updates,
|
||||
* so you can check a tick later to see the new contents.
|
||||
*
|
||||
* @see ArmorChangeEvent
|
||||
*/
|
||||
public class ArmorEquipEvent extends PlayerEvent {
|
||||
/**
|
||||
* Bukkit parity.
|
||||
*/
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.willfp.eco.core.fast;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* FastItemStack contains methods to modify and read items faster than in default bukkit.
|
||||
*/
|
||||
public interface FastItemStack {
|
||||
/**
|
||||
* Get all enchantments on an item.
|
||||
*
|
||||
* @param checkStored If stored NBT should also be checked.
|
||||
* @return A map of all enchantments.
|
||||
*/
|
||||
Map<Enchantment, Integer> getEnchantmentsOnItem(boolean checkStored);
|
||||
|
||||
/**
|
||||
* Get the level of an enchantment on an item.
|
||||
*
|
||||
* @param enchantment The enchantment.
|
||||
* @param checkStored If the stored NBT should also be checked.
|
||||
* @return The enchantment level, or 0 if not found.
|
||||
*/
|
||||
int getLevelOnItem(@NotNull Enchantment enchantment,
|
||||
boolean checkStored);
|
||||
|
||||
/**
|
||||
* Set the item lore.
|
||||
*
|
||||
* @param lore The lore.
|
||||
*/
|
||||
void setLore(@Nullable List<String> lore);
|
||||
|
||||
/**
|
||||
* Get the item lore.
|
||||
*
|
||||
* @return The lore.
|
||||
*/
|
||||
List<String> getLore();
|
||||
|
||||
|
||||
/**
|
||||
* Set the rework penalty.
|
||||
*
|
||||
* @param cost The rework penalty to set.
|
||||
*/
|
||||
void setRepairCost(int cost);
|
||||
|
||||
/**
|
||||
* Get the rework penalty.
|
||||
* .
|
||||
*
|
||||
* @return The rework penalty found on the item.
|
||||
*/
|
||||
int getRepairCost();
|
||||
|
||||
/**
|
||||
* Add ItemFlags.
|
||||
*
|
||||
* @param hideFlags The flags.
|
||||
*/
|
||||
void addItemFlags(ItemFlag... hideFlags);
|
||||
|
||||
/**
|
||||
* Remove ItemFlags.
|
||||
*
|
||||
* @param hideFlags The flags.
|
||||
*/
|
||||
void removeItemFlags(ItemFlag... hideFlags);
|
||||
|
||||
/**
|
||||
* Get the ItemFlags.
|
||||
*
|
||||
* @return The flags.
|
||||
*/
|
||||
Set<ItemFlag> getItemFlags();
|
||||
|
||||
/**
|
||||
* Test the item for a flag.
|
||||
*
|
||||
* @param flag The flag.
|
||||
* @return If the flag is present.
|
||||
*/
|
||||
boolean hasItemFlag(ItemFlag flag);
|
||||
|
||||
/**
|
||||
* Get the Bukkit ItemStack again.
|
||||
*
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
ItemStack unwrap();
|
||||
|
||||
/**
|
||||
* Wrap an ItemStack to create a FastItemStack.
|
||||
*
|
||||
* @param itemStack The ItemStack.
|
||||
* @return The FastItemStack.
|
||||
*/
|
||||
static FastItemStack wrap(final ItemStack itemStack) {
|
||||
return Eco.getHandler().createFastItemStack(Objects.requireNonNullElseGet(itemStack, () -> new ItemStack(Material.AIR)));
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,10 @@ package com.willfp.eco.core.gui;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder;
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Internal component used by {@link com.willfp.eco.core.gui.menu.Menu#builder(int)}
|
||||
* and {@link com.willfp.eco.core.gui.slot.Slot#builder(ItemStack)}.
|
||||
@@ -19,7 +17,7 @@ public interface GUIFactory {
|
||||
* @param provider The provider.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder createSlotBuilder(@NotNull Function<Player, ItemStack> provider);
|
||||
SlotBuilder createSlotBuilder(@NotNull SlotProvider provider);
|
||||
|
||||
/**
|
||||
* Create menu builder.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.eco.core.gui.menu;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface to run on menu close.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CloseHandler {
|
||||
/**
|
||||
* Performs this operation on the given arguments.
|
||||
*
|
||||
* @param event The close event.
|
||||
* @param menu The menu.
|
||||
*/
|
||||
void handle(@NotNull InventoryCloseEvent event,
|
||||
@NotNull Menu menu);
|
||||
}
|
||||
@@ -2,9 +2,16 @@ package com.willfp.eco.core.gui.menu;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* GUI version of {@link Inventory}.
|
||||
@@ -44,6 +51,51 @@ public interface Menu {
|
||||
*/
|
||||
Inventory open(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Get captive items.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The items.
|
||||
*/
|
||||
List<ItemStack> getCaptiveItems(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Write data.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param key The key.
|
||||
* @param type The type.
|
||||
* @param value The value.
|
||||
* @param <T> The type.
|
||||
* @param <Z> The type.
|
||||
*/
|
||||
<T, Z> void writeData(@NotNull Player player,
|
||||
@NotNull NamespacedKey key,
|
||||
@NotNull PersistentDataType<T, Z> type,
|
||||
@NotNull Z value);
|
||||
|
||||
/**
|
||||
* Read data.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param key The key.
|
||||
* @param type The type.
|
||||
* @param <T> The type.
|
||||
* @param <Z> The type.
|
||||
* @return The data.
|
||||
*/
|
||||
@Nullable <T, Z> T readData(@NotNull Player player,
|
||||
@NotNull NamespacedKey key,
|
||||
@NotNull PersistentDataType<T, Z> type);
|
||||
|
||||
/**
|
||||
* Get all data keys for a player.
|
||||
*
|
||||
* @param player The player.
|
||||
* @return The keys.
|
||||
*/
|
||||
Set<NamespacedKey> getKeys(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* Create a builder with a given amount of rows.
|
||||
*
|
||||
|
||||
@@ -31,6 +31,14 @@ public interface MenuBuilder {
|
||||
int column,
|
||||
@NotNull Slot slot);
|
||||
|
||||
/**
|
||||
* Run function to modify the builder.
|
||||
*
|
||||
* @param modifier The modifier.
|
||||
* @return The builder.
|
||||
*/
|
||||
MenuBuilder modfiy(@NotNull Consumer<MenuBuilder> modifier);
|
||||
|
||||
/**
|
||||
* Set the menu mask.
|
||||
*
|
||||
@@ -45,7 +53,18 @@ public interface MenuBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
MenuBuilder onClose(@NotNull Consumer<InventoryCloseEvent> action);
|
||||
default MenuBuilder onClose(@NotNull Consumer<InventoryCloseEvent> action) {
|
||||
onClose((event, menu) -> action.accept(event));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu close handler.
|
||||
*
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
MenuBuilder onClose(@NotNull CloseHandler action);
|
||||
|
||||
/**
|
||||
* Build the menu.
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -39,35 +40,46 @@ public class FillerMask {
|
||||
*/
|
||||
public FillerMask(@NotNull final Material material,
|
||||
@NotNull final String... pattern) {
|
||||
if (material == Material.AIR) {
|
||||
throw new IllegalArgumentException("Material cannot be air!");
|
||||
this(new MaskMaterials(material), pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new filler mask.
|
||||
*
|
||||
* @param materials The mask materials.
|
||||
* @param pattern The pattern.
|
||||
*/
|
||||
public FillerMask(@NotNull final MaskMaterials materials,
|
||||
@NotNull final String... pattern) {
|
||||
if (Arrays.stream(materials.materials()).anyMatch(material -> material == Material.AIR)) {
|
||||
throw new IllegalArgumentException("Materials cannot be air!");
|
||||
}
|
||||
|
||||
mask = ListUtils.create2DList(6, 9);
|
||||
|
||||
ItemStack itemStack = new ItemStackBuilder(material)
|
||||
.setDisplayName("&r")
|
||||
.build();
|
||||
for (int i = 0; i < materials.materials().length; i++) {
|
||||
ItemStack itemStack = new ItemStackBuilder(materials.materials()[i])
|
||||
.setDisplayName("&r")
|
||||
.build();
|
||||
|
||||
int row = 0;
|
||||
int row = 0;
|
||||
|
||||
for (String patternRow : pattern) {
|
||||
int column = 0;
|
||||
if (patternRow.length() != 9) {
|
||||
throw new IllegalArgumentException("Invalid amount of columns in pattern!");
|
||||
}
|
||||
for (char c : patternRow.toCharArray()) {
|
||||
if (c == '0') {
|
||||
mask.get(row).set(column, null);
|
||||
} else if (c == '1') {
|
||||
mask.get(row).set(column, new FillerSlot(itemStack));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid character in pattern! (Must only be 0 and 1)");
|
||||
for (String patternRow : pattern) {
|
||||
int column = 0;
|
||||
if (patternRow.length() != 9) {
|
||||
throw new IllegalArgumentException("Invalid amount of columns in pattern!");
|
||||
}
|
||||
for (char c : patternRow.toCharArray()) {
|
||||
if (c == '0') {
|
||||
mask.get(row).set(column, null);
|
||||
} else if (c == Character.forDigit(i + 1, 10)) {
|
||||
mask.get(row).set(column, new FillerSlot(itemStack));
|
||||
}
|
||||
|
||||
column++;
|
||||
column++;
|
||||
}
|
||||
row++;
|
||||
}
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,9 @@ public class FillerSlot implements Slot {
|
||||
public ItemStack getItemStack(@NotNull final Player player) {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaptive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.willfp.eco.core.gui.slot;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Mask materials store a set of materials which can be accessed by
|
||||
* a filler mask.
|
||||
*
|
||||
* @param materials The materials.
|
||||
*/
|
||||
public record MaskMaterials(@NotNull Material... materials) {
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.willfp.eco.core.gui.slot;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -19,6 +21,22 @@ public interface Slot {
|
||||
*/
|
||||
ItemStack getItemStack(@NotNull Player player);
|
||||
|
||||
/**
|
||||
* If the slot is captive. (Can items be placed in it).
|
||||
*
|
||||
* @return If captive.
|
||||
*/
|
||||
boolean isCaptive();
|
||||
|
||||
/**
|
||||
* Create a builder for an ItemStack.
|
||||
*
|
||||
* @return The builder.
|
||||
*/
|
||||
static SlotBuilder builder() {
|
||||
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> new ItemStack(Material.AIR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder for an ItemStack.
|
||||
*
|
||||
@@ -26,7 +44,7 @@ public interface Slot {
|
||||
* @return The builder.
|
||||
*/
|
||||
static SlotBuilder builder(@NotNull final ItemStack itemStack) {
|
||||
return Eco.getHandler().getGUIFactory().createSlotBuilder(player -> itemStack);
|
||||
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> itemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,6 +54,16 @@ public interface Slot {
|
||||
* @return The builder.
|
||||
*/
|
||||
static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) {
|
||||
return Eco.getHandler().getGUIFactory().createSlotBuilder((player, menu) -> provider.apply(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder for a player-specific ItemStack.
|
||||
*
|
||||
* @param provider The provider.
|
||||
* @return The builder.
|
||||
*/
|
||||
static SlotBuilder builder(@NotNull final SlotProvider provider) {
|
||||
return Eco.getHandler().getGUIFactory().createSlotBuilder(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.willfp.eco.core.gui.slot;
|
||||
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotModifier;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -15,7 +17,17 @@ public interface SlotBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action);
|
||||
default SlotBuilder onLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
return onLeftClick((event, slot, menu) -> action.accept(event, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onLeftClick(@NotNull SlotHandler handler);
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
@@ -23,7 +35,17 @@ public interface SlotBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action);
|
||||
default SlotBuilder onRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
return onRightClick((event, slot, menu) -> action.accept(event, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onRightClick(@NotNull SlotHandler handler);
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
@@ -31,7 +53,17 @@ public interface SlotBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onShiftLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action);
|
||||
default SlotBuilder onShiftLeftClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
return onShiftLeftClick((event, slot, menu) -> action.accept(event, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onShiftLeftClick(@NotNull SlotHandler handler);
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
@@ -39,7 +71,17 @@ public interface SlotBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onShiftRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action);
|
||||
default SlotBuilder onShiftRightClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
return onShiftRightClick((event, slot, menu) -> action.accept(event, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onShiftRightClick(@NotNull SlotHandler handler);
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
@@ -47,7 +89,32 @@ public interface SlotBuilder {
|
||||
* @param action The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onMiddleClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action);
|
||||
default SlotBuilder onMiddleClick(@NotNull BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
return onMiddleClick((event, slot, menu) -> action.accept(event, slot));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set click handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder onMiddleClick(@NotNull SlotHandler handler);
|
||||
|
||||
/**
|
||||
* Modify the ItemStack.
|
||||
*
|
||||
* @param modifier The modifier.
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder setModifier(@NotNull SlotModifier modifier);
|
||||
|
||||
/**
|
||||
* Set slot to be a captive slot.
|
||||
*
|
||||
* @return The builder.
|
||||
*/
|
||||
SlotBuilder setCaptive();
|
||||
|
||||
/**
|
||||
* Build the slot.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.willfp.eco.core.gui.slot.functional;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface to run on slot click.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SlotHandler {
|
||||
/**
|
||||
* Performs this operation on the given arguments.
|
||||
*
|
||||
* @param event The click event.
|
||||
* @param slot The slot
|
||||
* @param menu The menu.
|
||||
*/
|
||||
void handle(@NotNull InventoryClickEvent event,
|
||||
@NotNull Slot slot,
|
||||
@NotNull Menu menu);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.willfp.eco.core.gui.slot.functional;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface to run on slot modify.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SlotModifier {
|
||||
/**
|
||||
* Performs this operation on the given arguments.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param menu The menu.
|
||||
* @param previous The previous ItemStack.
|
||||
*/
|
||||
void modify(@NotNull Player player,
|
||||
@NotNull Menu menu,
|
||||
@NotNull ItemStack previous);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.willfp.eco.core.gui.slot.functional;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Interface to run on slot display.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SlotProvider {
|
||||
/**
|
||||
* Performs this operation on the given arguments.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param menu The menu.
|
||||
* @return The ItemStack.
|
||||
*/
|
||||
ItemStack provide(@NotNull Player player,
|
||||
@NotNull Menu menu);
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.willfp.eco.core.integrations.customitems;
|
||||
|
||||
import com.willfp.eco.core.integrations.Integration;
|
||||
|
||||
/**
|
||||
* Wrapper class for custom item integrations.
|
||||
*/
|
||||
public interface CustomItemsWrapper {
|
||||
public interface CustomItemsWrapper extends Integration {
|
||||
/**
|
||||
* Register all the custom items for a specific plugin into eco.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ public class McmmoManager {
|
||||
/**
|
||||
* A set of all registered integrations.
|
||||
*/
|
||||
private final Set<McmmoWrapper> regsistered = new HashSet<>();
|
||||
private final Set<McmmoWrapper> registered = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Register a new integration.
|
||||
@@ -24,7 +24,7 @@ public class McmmoManager {
|
||||
* @param integration The integration to register.
|
||||
*/
|
||||
public void register(@NotNull final McmmoWrapper integration) {
|
||||
regsistered.add(integration);
|
||||
registered.add(integration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,7 @@ public class McmmoManager {
|
||||
* @return The bonus drop count.
|
||||
*/
|
||||
public int getBonusDropCount(@NotNull final Block block) {
|
||||
for (McmmoWrapper mcmmoWrapper : regsistered) {
|
||||
for (McmmoWrapper mcmmoWrapper : registered) {
|
||||
return mcmmoWrapper.getBonusDropCount(block);
|
||||
}
|
||||
return 0;
|
||||
@@ -47,7 +47,7 @@ public class McmmoManager {
|
||||
* @return If the event is fake.
|
||||
*/
|
||||
public boolean isFake(@NotNull final Event event) {
|
||||
for (McmmoWrapper mcmmoWrapper : regsistered) {
|
||||
for (McmmoWrapper mcmmoWrapper : registered) {
|
||||
return mcmmoWrapper.isFake(event);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -77,4 +77,11 @@ public class PlaceholderEntry {
|
||||
public boolean requiresPlayer() {
|
||||
return requiresPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the placeholder.
|
||||
*/
|
||||
public void register() {
|
||||
PlaceholderManager.registerPlaceholder(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class PlaceholderManager {
|
||||
@NotNull final String identifier) {
|
||||
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
|
||||
if (matching.isEmpty()) {
|
||||
return null;
|
||||
return "";
|
||||
}
|
||||
PlaceholderEntry entry = matching.get();
|
||||
if (player == null && entry.requiresPlayer()) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.willfp.eco.core.integrations.shop;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Class to handle shop integrations.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class ShopManager {
|
||||
/**
|
||||
* A set of all registered integrations.
|
||||
*/
|
||||
private final Set<ShopWrapper> registered = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Register a new integration.
|
||||
*
|
||||
* @param integration The integration to register.
|
||||
*/
|
||||
public void register(@NotNull final ShopWrapper integration) {
|
||||
registered.add(integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register eco item provider for shop plugins.
|
||||
*/
|
||||
public void registerEcoProvider() {
|
||||
for (ShopWrapper shopWrapper : registered) {
|
||||
shopWrapper.registerEcoProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.willfp.eco.core.integrations.shop;
|
||||
|
||||
/**
|
||||
* Wrapper class for shop integrations.
|
||||
*/
|
||||
public interface ShopWrapper {
|
||||
/**
|
||||
* Register eco item provider for shop plugins.
|
||||
*/
|
||||
void registerEcoProvider();
|
||||
}
|
||||
@@ -27,7 +27,7 @@ public class CustomItem implements TestableItem {
|
||||
/**
|
||||
* The test for ItemStacks to pass.
|
||||
*/
|
||||
private final Predicate<ItemStack> test;
|
||||
private final Predicate<@NotNull ItemStack> test;
|
||||
|
||||
/**
|
||||
* Example Item: what the user should see.
|
||||
@@ -42,7 +42,7 @@ public class CustomItem implements TestableItem {
|
||||
* @param item The example ItemStacks.
|
||||
*/
|
||||
public CustomItem(@NotNull final NamespacedKey key,
|
||||
@NotNull final Predicate<ItemStack> test,
|
||||
@NotNull final Predicate<@NotNull ItemStack> test,
|
||||
@NotNull final ItemStack item) {
|
||||
this.key = key;
|
||||
this.test = test;
|
||||
@@ -51,6 +51,10 @@ public class CustomItem implements TestableItem {
|
||||
|
||||
@Override
|
||||
public boolean matches(@Nullable final ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return test.test(itemStack);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package com.willfp.eco.core.items;
|
||||
|
||||
import com.willfp.eco.core.items.args.LookupArgParser;
|
||||
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.util.NamespacedKeyUtils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Class to manage all custom and vanilla items.
|
||||
@@ -23,13 +31,18 @@ public final class Items {
|
||||
/**
|
||||
* All recipe parts.
|
||||
*/
|
||||
private static final Map<NamespacedKey, CustomItem> REGISTRY = new HashMap<>();
|
||||
private static final Map<NamespacedKey, CustomItem> REGISTRY = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Register a new recipe part.
|
||||
* All recipe parts.
|
||||
*/
|
||||
private static final List<LookupArgParser> ARG_PARSERS = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Register a new custom item.
|
||||
*
|
||||
* @param key The key of the recipe part.
|
||||
* @param part The recipe part.
|
||||
* @param key The key of the item.
|
||||
* @param part The item.
|
||||
*/
|
||||
public void registerCustomItem(@NotNull final NamespacedKey key,
|
||||
@NotNull final CustomItem part) {
|
||||
@@ -37,44 +50,158 @@ public final class Items {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup item from string.
|
||||
* <p>
|
||||
* Used for recipes.
|
||||
* Register a new arg parser.
|
||||
*
|
||||
* @param key The string to test.
|
||||
* @return The found testable item, or an empty item if not found.
|
||||
* @param parser The parser.
|
||||
*/
|
||||
public void registerArgParser(@NotNull final LookupArgParser parser) {
|
||||
ARG_PARSERS.add(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an item.
|
||||
*
|
||||
* @param key The key of the recipe part.
|
||||
*/
|
||||
public void removeCustomItem(@NotNull final NamespacedKey key) {
|
||||
REGISTRY.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the backbone of the entire eco item system.
|
||||
* <p>
|
||||
* You can lookup a TestableItem for any material, custom item,
|
||||
* or item in general, and it will return it with any modifiers
|
||||
* passed as parameters. This includes stack size (item amount)
|
||||
* and enchantments that should be present on the item.
|
||||
* <p>
|
||||
* If you want to get an ItemStack instance from this, then just call
|
||||
* {@link TestableItem#getItem()}.
|
||||
* <p>
|
||||
* The advantages of the testable item system are that there is the inbuilt
|
||||
* {@link TestableItem#matches(ItemStack)} - this allows to check if any item
|
||||
* is that testable item; which may sound negligible but actually it allows for
|
||||
* much more power an flexibility. For example, you can have an item with an
|
||||
* extra metadata tag, extra lore lines, different display name - and it
|
||||
* will still work as long as the test passes. This is very important
|
||||
* for custom crafting recipes where other plugins may add metadata
|
||||
* values or the play may rename the item.
|
||||
*
|
||||
* @param key The lookup string.
|
||||
* @return The testable item, or an {@link EmptyTestableItem}.
|
||||
*/
|
||||
public TestableItem lookup(@NotNull final String key) {
|
||||
String[] split = key.toLowerCase().split(":");
|
||||
if (key.contains("?")) {
|
||||
String[] options = key.split("\\?");
|
||||
for (String option : options) {
|
||||
TestableItem lookup = lookup(option);
|
||||
if (!(lookup instanceof EmptyTestableItem)) {
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
String[] args = key.split(" ");
|
||||
if (args.length == 0) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
TestableItem item = null;
|
||||
|
||||
int stackAmount = 1;
|
||||
|
||||
String[] split = args[0].toLowerCase().split(":");
|
||||
|
||||
if (split.length == 1) {
|
||||
Material material = Material.getMaterial(key.toUpperCase());
|
||||
Material material = Material.getMaterial(args[0].toUpperCase());
|
||||
if (material == null || material == Material.AIR) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
return new MaterialTestableItem(material);
|
||||
item = new MaterialTestableItem(material);
|
||||
}
|
||||
|
||||
if (split.length == 2) {
|
||||
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
|
||||
|
||||
/*
|
||||
Legacy id:amount format
|
||||
This has been superseded by id amount
|
||||
*/
|
||||
if (part == null) {
|
||||
Material material = Material.getMaterial(split[0].toUpperCase());
|
||||
if (material == null || material == Material.AIR) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
return new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1]));
|
||||
item = new MaterialTestableItem(material);
|
||||
stackAmount = Integer.parseInt(split[1]);
|
||||
} else {
|
||||
return part;
|
||||
item = part;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Legacy namespace:id:amount format
|
||||
This has been superseded by namespace:id amount
|
||||
*/
|
||||
if (split.length == 3) {
|
||||
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
|
||||
return part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2]));
|
||||
if (part == null) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
item = part;
|
||||
stackAmount = Integer.parseInt(split[2]);
|
||||
}
|
||||
|
||||
return new EmptyTestableItem();
|
||||
boolean usingNewStackFormat = false;
|
||||
|
||||
if (args.length >= 2) {
|
||||
try {
|
||||
stackAmount = Integer.parseInt(args[1]);
|
||||
usingNewStackFormat = true;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
if (item == null) {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
ItemStack example = item.getItem();
|
||||
ItemMeta meta = example.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
String[] modifierArgs = Arrays.copyOfRange(args, usingNewStackFormat ? 2 : 1, args.length);
|
||||
|
||||
List<Predicate<ItemStack>> predicates = new ArrayList<>();
|
||||
|
||||
for (LookupArgParser argParser : ARG_PARSERS) {
|
||||
predicates.add(argParser.parseArguments(modifierArgs, meta));
|
||||
}
|
||||
|
||||
example.setItemMeta(meta);
|
||||
if (!predicates.isEmpty()) {
|
||||
item = new ModifiedTestableItem(
|
||||
item,
|
||||
test -> {
|
||||
for (Predicate<ItemStack> predicate : predicates) {
|
||||
if (!predicate.test(test)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
example
|
||||
);
|
||||
}
|
||||
|
||||
if (stackAmount == 1) {
|
||||
return item;
|
||||
} else {
|
||||
return new TestableStack(item, stackAmount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +219,22 @@ public final class Items {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom item from item.
|
||||
*
|
||||
* @param itemStack The item.
|
||||
* @return The custom item, or null if not exists.
|
||||
*/
|
||||
@Nullable
|
||||
public CustomItem getCustomItem(@NotNull final ItemStack itemStack) {
|
||||
for (CustomItem item : REGISTRY.values()) {
|
||||
if (item.matches(itemStack)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all registered custom items.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class EnchantmentArgParser implements LookupArgParser {
|
||||
@Override
|
||||
public Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
Map<Enchantment, Integer> requiredEnchantments = new HashMap<>();
|
||||
|
||||
for (String enchantArg : args) {
|
||||
String[] enchantArgSplit = enchantArg.split(":");
|
||||
|
||||
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase()));
|
||||
if (enchantment == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enchantArgSplit.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int level = Integer.parseInt(enchantArgSplit[1]);
|
||||
|
||||
requiredEnchantments.put(enchantment, level);
|
||||
}
|
||||
|
||||
if (meta instanceof EnchantmentStorageMeta storageMeta) {
|
||||
requiredEnchantments.forEach((enchantment, integer) -> storageMeta.addStoredEnchant(enchantment, integer, true));
|
||||
} else {
|
||||
requiredEnchantments.forEach((enchantment, integer) -> meta.addEnchant(enchantment, integer, true));
|
||||
}
|
||||
|
||||
return test -> {
|
||||
if (!test.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemMeta testMeta = test.getItemMeta();
|
||||
|
||||
assert testMeta != null;
|
||||
|
||||
if (testMeta instanceof EnchantmentStorageMeta storageMeta) {
|
||||
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
|
||||
if (!storageMeta.hasStoredEnchant(entry.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if (storageMeta.getStoredEnchantLevel(entry.getKey()) < entry.getValue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
|
||||
if (!testMeta.hasEnchant(entry.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if (testMeta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface LookupArgParser {
|
||||
/**
|
||||
* Parse the arguments.
|
||||
* <p>
|
||||
* An argument parser should generate the predicate as well
|
||||
* as modify the ItemMeta for {@link TestableItem#getItem()}
|
||||
*
|
||||
* @param args The arguments.
|
||||
* @param meta The ItemMeta to modify.
|
||||
* @return The predicate test to apply to the modified item.
|
||||
*/
|
||||
Predicate<ItemStack> parseArguments(@NotNull String[] args,
|
||||
@NotNull ItemMeta meta);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.willfp.eco.core.items.args;
|
||||
|
||||
import com.willfp.eco.util.SkullUtils;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class TextureArgParser implements LookupArgParser {
|
||||
@Override
|
||||
public Predicate<ItemStack> parseArguments(@NotNull final String[] args,
|
||||
@NotNull final ItemMeta meta) {
|
||||
String skullTexture = null;
|
||||
|
||||
for (String arg : args) {
|
||||
String[] argSplit = arg.split(":");
|
||||
if (!argSplit[0].equalsIgnoreCase("texture")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argSplit.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skullTexture = argSplit[1];
|
||||
}
|
||||
|
||||
if (meta instanceof SkullMeta skullMeta && skullTexture != null) {
|
||||
SkullUtils.setSkullTexture(skullMeta, skullTexture);
|
||||
}
|
||||
|
||||
String finalSkullTexture = skullTexture;
|
||||
return test -> {
|
||||
if (!test.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemMeta testMeta = test.getItemMeta();
|
||||
|
||||
assert testMeta != null;
|
||||
|
||||
if (testMeta instanceof SkullMeta skullMeta && finalSkullTexture != null) {
|
||||
return finalSkullTexture.equalsIgnoreCase(SkullUtils.getSkullTexture(skullMeta));
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.willfp.eco.core.recipe.parts;
|
||||
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Existing testable items with an extra filter.
|
||||
*
|
||||
* @see com.willfp.eco.core.items.CustomItem
|
||||
*/
|
||||
public class ModifiedTestableItem implements TestableItem {
|
||||
/**
|
||||
* The item.
|
||||
*/
|
||||
@Getter
|
||||
private final TestableItem handle;
|
||||
|
||||
/**
|
||||
* The amount.
|
||||
*/
|
||||
@Getter
|
||||
private final Predicate<ItemStack> test;
|
||||
|
||||
/**
|
||||
* The item for the modified test.
|
||||
*/
|
||||
private final ItemStack example;
|
||||
|
||||
/**
|
||||
* Create a new modified testable item.
|
||||
*
|
||||
* @param item The item.
|
||||
* @param test The test.
|
||||
* @param example The example.
|
||||
*/
|
||||
public ModifiedTestableItem(@NotNull final TestableItem item,
|
||||
@NotNull final Predicate<ItemStack> test,
|
||||
@NotNull final ItemStack example) {
|
||||
this.handle = item;
|
||||
this.test = test;
|
||||
this.example = example;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 && handle.matches(itemStack) && test.test(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem() {
|
||||
return example;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
package com.willfp.eco.core.recipe.parts;
|
||||
|
||||
import com.willfp.eco.core.Eco;
|
||||
import com.willfp.eco.core.items.TestableItem;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stacks of items.
|
||||
*/
|
||||
@@ -19,6 +14,7 @@ public class TestableStack implements TestableItem {
|
||||
/**
|
||||
* The item.
|
||||
*/
|
||||
@Getter
|
||||
private final TestableItem handle;
|
||||
|
||||
/**
|
||||
@@ -55,19 +51,7 @@ public class TestableStack implements TestableItem {
|
||||
@Override
|
||||
public ItemStack getItem() {
|
||||
ItemStack temp = handle.getItem().clone();
|
||||
ItemMeta meta = temp.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
|
||||
assert lore != null;
|
||||
lore.add("");
|
||||
String add = Eco.getHandler().getEcoPlugin().getLangYml().getString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(amount));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
temp.setItemMeta(meta);
|
||||
temp.setAmount(amount);
|
||||
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
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.items.TestableItem;
|
||||
import com.willfp.eco.core.recipe.Recipes;
|
||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.RecipeChoice;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -87,7 +90,23 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
|
||||
displayedRecipe.shape("012", "345", "678");
|
||||
for (int i = 0; i < 9; i++) {
|
||||
char character = String.valueOf(i).toCharArray()[0];
|
||||
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(parts.get(i).getItem()));
|
||||
ItemStack item = parts.get(i).getItem();
|
||||
|
||||
if (parts.get(i) instanceof TestableStack) {
|
||||
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().getString("multiple-in-craft");
|
||||
add = add.replace("%amount%", String.valueOf(item.getAmount()));
|
||||
lore.add(add);
|
||||
meta.setLore(lore);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
displayedRecipe.setIngredient(character, new RecipeChoice.ExactChoice(item));
|
||||
}
|
||||
|
||||
Bukkit.getServer().addRecipe(shapedRecipe);
|
||||
|
||||
@@ -29,10 +29,10 @@ public class ArrowUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!(values.get(0) instanceof ItemStack)) {
|
||||
if (!(values.get(0).value() instanceof ItemStack)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (ItemStack) values.get(0);
|
||||
return (ItemStack) values.get(0).value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.tuples.Pair;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -30,12 +31,10 @@ public class BlockUtils {
|
||||
*/
|
||||
private BiConsumer<Player, Block> blockBreakConsumer = null;
|
||||
|
||||
private Pair<Block, Set<Block>> getNearbyBlocksRecursively(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
@NotNull final Set<Block> blocks,
|
||||
final int limit) {
|
||||
Block last = start;
|
||||
|
||||
private Set<Block> getNearbyBlocks(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
@NotNull final Set<Block> blocks,
|
||||
final int limit) {
|
||||
for (BlockFace face : BlockFace.values()) {
|
||||
Block block = start.getRelative(face);
|
||||
if (blocks.contains(block)) {
|
||||
@@ -44,46 +43,15 @@ public class BlockUtils {
|
||||
|
||||
if (allowedMaterials.contains(block.getType())) {
|
||||
blocks.add(block);
|
||||
last = block;
|
||||
|
||||
if (blocks.size() > limit) {
|
||||
return new Pair<>(last, blocks);
|
||||
if (blocks.size() > limit || blocks.size() > 2500) {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
Pair<Block, Set<Block>> pair = getNearbyBlocksRecursively(last, allowedMaterials, blocks, limit);
|
||||
assert pair.getSecond() != null;
|
||||
|
||||
blocks.addAll(pair.getSecond());
|
||||
blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit));
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(last, blocks);
|
||||
}
|
||||
|
||||
private Set<Block> getNearbyBlocks(@NotNull final Block start,
|
||||
@NotNull final List<Material> allowedMaterials,
|
||||
@NotNull final Set<Block> blocks,
|
||||
final int limit) {
|
||||
/*
|
||||
Prevent stack overflow.
|
||||
*/
|
||||
int cycles = (int) Math.ceil(limit / 1024D);
|
||||
|
||||
int cap = limit;
|
||||
Block iterStart = start;
|
||||
|
||||
for (int i = 0; i < cycles; i++) {
|
||||
assert iterStart != null;
|
||||
|
||||
Pair<Block, Set<Block>> pair = getNearbyBlocksRecursively(iterStart, allowedMaterials, blocks, cap);
|
||||
assert pair.getSecond() != null;
|
||||
iterStart = pair.getFirst();
|
||||
|
||||
blocks.addAll(pair.getSecond());
|
||||
|
||||
cap -= 1024;
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@@ -112,6 +80,14 @@ public class BlockUtils {
|
||||
Validate.isTrue(initialized, "Must be initialized!");
|
||||
Validate.notNull(blockBreakConsumer, "Must be initialized!");
|
||||
|
||||
Location location = block.getLocation();
|
||||
World world = location.getWorld();
|
||||
assert world != null;
|
||||
|
||||
if (location.getY() < world.getMinHeight() || location.getY() > world.getMaxHeight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
blockBreakConsumer.accept(player, block);
|
||||
}
|
||||
|
||||
|
||||
22
eco-api/src/main/java/com/willfp/eco/util/MenuUtils.java
Normal file
22
eco-api/src/main/java/com/willfp/eco/util/MenuUtils.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import com.willfp.eco.core.tuples.Pair;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for menus.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class MenuUtils {
|
||||
/**
|
||||
* Convert 0-53 slot to row and column pair.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @return The pair of row and columns.
|
||||
*/
|
||||
public Pair<Integer, Integer> convertSlotToRowColumn(final int slot) {
|
||||
int row = Math.floorDiv(slot, 9);
|
||||
int column = slot - row * 9;
|
||||
return new Pair<>(row + 1, column + 1);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ public class NumberUtils {
|
||||
if (numeral.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
for (Map.Entry<Integer, String> entry : NUMERALS.entrySet()) {
|
||||
for (Map.Entry<Integer, String> entry : NUMERALS.descendingMap().entrySet()) {
|
||||
if (numeral.startsWith(entry.getValue())) {
|
||||
return entry.getKey() + fromNumeral(numeral.substring(entry.getValue().length()));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for player heads.
|
||||
@@ -23,6 +24,11 @@ public class SkullUtils {
|
||||
*/
|
||||
private BiConsumer<SkullMeta, String> metaSetConsumer = null;
|
||||
|
||||
/**
|
||||
* The meta get function.
|
||||
*/
|
||||
private Function<SkullMeta, String> metaGetConsumer = null;
|
||||
|
||||
/**
|
||||
* Set the texture of a skull from base64.
|
||||
*
|
||||
@@ -37,16 +43,32 @@ public class SkullUtils {
|
||||
metaSetConsumer.accept(meta, base64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture of a skull - in base64.
|
||||
*
|
||||
* @param meta The meta to modify.
|
||||
* @return The texture.
|
||||
*/
|
||||
public String getSkullTexture(@NotNull final SkullMeta meta) {
|
||||
Validate.isTrue(initialized, "Must be initialized!");
|
||||
Validate.notNull(metaGetConsumer, "Must be initialized!");
|
||||
|
||||
return metaGetConsumer.apply(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the skull texture function.
|
||||
*
|
||||
* @param function The function.
|
||||
* @param function The function.
|
||||
* @param function2 Get function.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void initialize(@NotNull final BiConsumer<SkullMeta, String> function) {
|
||||
public void initialize(@NotNull final BiConsumer<SkullMeta, String> function,
|
||||
@NotNull final Function<SkullMeta, String> function2) {
|
||||
Validate.isTrue(!initialized, "Already initialized!");
|
||||
|
||||
metaSetConsumer = function;
|
||||
metaGetConsumer = function2;
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,16 @@ package com.willfp.eco.util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -27,9 +31,9 @@ public class StringUtils {
|
||||
* Regexes for gradients.
|
||||
*/
|
||||
private static final List<Pattern> GRADIENT_PATTERNS = new ImmutableList.Builder<Pattern>()
|
||||
.add(Pattern.compile("<GRADIENT:([0-9A-Fa-f]{6})>(.*?)</GRADIENT:([0-9A-Fa-f]{6})>"))
|
||||
.add(Pattern.compile("<gradient:([0-9A-Fa-f]{6})>(.*?)</gradient:([0-9A-Fa-f]{6})>"))
|
||||
.add(Pattern.compile("<G:([0-9A-Fa-f]{6})>(.*?)</G:([0-9A-Fa-f]{6})>"))
|
||||
.add(Pattern.compile("<GRADIENT:([0-9A-Fa-f]{6})>(.*?)</GRADIENT:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
|
||||
.add(Pattern.compile("<GRADIENT:#([0-9A-Fa-f]{6})>(.*?)</GRADIENT:#([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
|
||||
.add(Pattern.compile("<G:([0-9A-Fa-f]{6})>(.*?)</G:([0-9A-Fa-f]{6})>", Pattern.CASE_INSENSITIVE))
|
||||
.add(Pattern.compile("<#:([0-9A-Fa-f]{6})>(.*?)</#:([0-9A-Fa-f]{6})>"))
|
||||
.add(Pattern.compile("\\{#:([0-9A-Fa-f]{6})}(.*?)\\{/#:([0-9A-Fa-f]{6})}"))
|
||||
.build();
|
||||
@@ -44,7 +48,30 @@ public class StringUtils {
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Format a list of strings - converts Placeholders and Color codes.
|
||||
* Legacy serializer.
|
||||
*/
|
||||
private static final LegacyComponentSerializer LEGACY_COMPONENT_SERIALIZER = LegacyComponentSerializer.builder()
|
||||
.character('\u00a7')
|
||||
.useUnusualXRepeatedCharacterHexFormat()
|
||||
.hexColors()
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
* Converts color codes and placeholders.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @return The message, formatted.
|
||||
*/
|
||||
public List<String> formatList(@NotNull final List<String> list) {
|
||||
return formatList(list, (Player) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
* Coverts color codes and placeholders for a player.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @param player The player to translate placeholders with respect to.
|
||||
@@ -52,26 +79,61 @@ public class StringUtils {
|
||||
*/
|
||||
public List<String> formatList(@NotNull final List<String> list,
|
||||
@Nullable final Player player) {
|
||||
return formatList(list, player, FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
* Converts color codes and placeholders if specified.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @param option The format option.
|
||||
* @return The message, formatted.
|
||||
*/
|
||||
public List<String> formatList(@NotNull final List<String> list,
|
||||
@NotNull final FormatOption option) {
|
||||
return formatList(list, null, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list of strings.
|
||||
* <p>
|
||||
* Coverts color codes and placeholders for a player if specified.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @param player The player to translate placeholders with respect to.
|
||||
* @param option The options.
|
||||
* @return The message, format.
|
||||
*/
|
||||
public List<String> formatList(@NotNull final List<String> list,
|
||||
@Nullable final Player player,
|
||||
@NotNull final FormatOption option) {
|
||||
List<String> translated = new ArrayList<>();
|
||||
for (String string : list) {
|
||||
translated.add(format(string, player));
|
||||
translated.add(format(string, player, option));
|
||||
}
|
||||
|
||||
return translated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a list of strings - converts Placeholders and Color codes.
|
||||
* Format a string.
|
||||
* <p>
|
||||
* Converts color codes and placeholders.
|
||||
*
|
||||
* @param list The messages to format.
|
||||
* @param message The message to translate.
|
||||
* @return The message, formatted.
|
||||
* @see StringUtils#format(String, Player)
|
||||
*/
|
||||
public List<String> formatList(@NotNull final List<String> list) {
|
||||
return formatList(list, null);
|
||||
public String format(@NotNull final String message) {
|
||||
return format(message, (Player) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string - converts Placeholders and Color codes.
|
||||
* Format a string.
|
||||
* <p>
|
||||
* Converts color codes and placeholders for a player.
|
||||
*
|
||||
* @param message The message to format.
|
||||
* @param player The player to translate placeholders with respect to.
|
||||
@@ -79,23 +141,45 @@ public class StringUtils {
|
||||
*/
|
||||
public String format(@NotNull final String message,
|
||||
@Nullable final Player player) {
|
||||
String processedMessage = message;
|
||||
processedMessage = translateGradients(processedMessage);
|
||||
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
|
||||
processedMessage = translateHexColorCodes(processedMessage);
|
||||
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
|
||||
return processedMessage;
|
||||
return format(message, player, FormatOption.WITH_PLACEHOLDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string without respect to a player.
|
||||
* Format a string.
|
||||
* <p>
|
||||
* Converts color codes and placeholders if specified.
|
||||
*
|
||||
* @param message The message to translate.
|
||||
* @param option The format option.
|
||||
* @return The message, formatted.
|
||||
* @see StringUtils#format(String, Player)
|
||||
*/
|
||||
public String format(@NotNull final String message) {
|
||||
return format(message, null);
|
||||
public String format(@NotNull final String message,
|
||||
@NotNull final FormatOption option) {
|
||||
return format(message, null, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string.
|
||||
* <p>
|
||||
* Coverts color codes and placeholders for a player if specified.
|
||||
*
|
||||
* @param message The message to format.
|
||||
* @param player The player to translate placeholders with respect to.
|
||||
* @param option The format options.
|
||||
* @return The message, formatted.
|
||||
*/
|
||||
public String format(@NotNull final String message,
|
||||
@Nullable final Player player,
|
||||
@NotNull final FormatOption option) {
|
||||
String processedMessage = message;
|
||||
processedMessage = translateGradients(processedMessage);
|
||||
if (option == FormatOption.WITH_PLACEHOLDERS) {
|
||||
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
|
||||
}
|
||||
processedMessage = translateHexColorCodes(processedMessage);
|
||||
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
|
||||
return processedMessage;
|
||||
}
|
||||
|
||||
private static String translateHexColorCodes(@NotNull final String message) {
|
||||
@@ -122,14 +206,6 @@ public class StringUtils {
|
||||
return matcher.appendTail(builder).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Colors a string with a gradient.
|
||||
*
|
||||
* @param string The string to color.
|
||||
* @param start The start color.
|
||||
* @param end The end color.
|
||||
* @return The string, colored.
|
||||
*/
|
||||
private static String processGradients(@NotNull final String string,
|
||||
@NotNull final Color start,
|
||||
@NotNull final Color end) {
|
||||
@@ -167,14 +243,6 @@ public class StringUtils {
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates chatColors for gradients.
|
||||
*
|
||||
* @param start The start color.
|
||||
* @param end The end color.
|
||||
* @param step How many colors are returned.
|
||||
* @return Array of chat colors.
|
||||
*/
|
||||
private static ChatColor[] getGradientColors(@NotNull final Color start,
|
||||
@NotNull final Color end,
|
||||
final int step) {
|
||||
@@ -195,12 +263,6 @@ public class StringUtils {
|
||||
return colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add gradients to a string.
|
||||
*
|
||||
* @param string The string.
|
||||
* @return The string, colorized.
|
||||
*/
|
||||
private static String translateGradients(@NotNull final String string) {
|
||||
String processedString = string;
|
||||
for (Pattern pattern : GRADIENT_PATTERNS) {
|
||||
@@ -254,4 +316,45 @@ public class StringUtils {
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert legacy string to JSON.
|
||||
*
|
||||
* @param legacy The legacy string.
|
||||
* @return The JSON String.
|
||||
*/
|
||||
public String legacyToJson(@NotNull final String legacy) {
|
||||
return GsonComponentSerializer.gson().serialize(
|
||||
Component.empty().decoration(TextDecoration.ITALIC, false).append(
|
||||
LEGACY_COMPONENT_SERIALIZER.deserialize(legacy)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON string to legacy.
|
||||
*
|
||||
* @param json The JSON string.
|
||||
* @return The legacy string.
|
||||
*/
|
||||
public String jsonToLegacy(@NotNull final String json) {
|
||||
return LEGACY_COMPONENT_SERIALIZER.serialize(
|
||||
GsonComponentSerializer.gson().deserialize(json)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for formatting.
|
||||
*/
|
||||
public enum FormatOption {
|
||||
/**
|
||||
* Completely formatted.
|
||||
*/
|
||||
WITH_PLACEHOLDERS,
|
||||
|
||||
/**
|
||||
* Completely formatted without placeholders.
|
||||
*/
|
||||
WITHOUT_PLACEHOLDERS
|
||||
}
|
||||
}
|
||||
|
||||
24
eco-api/src/test/java/NumberUtilsTest.java
Normal file
24
eco-api/src/test/java/NumberUtilsTest.java
Normal file
@@ -0,0 +1,24 @@
|
||||
import com.willfp.eco.util.NumberUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class NumberUtilsTest {
|
||||
@Test
|
||||
public void testFormatDouble() {
|
||||
Assertions.assertEquals("3", NumberUtils.format(3.0D));
|
||||
Assertions.assertEquals("3.20", NumberUtils.format(3.2D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog2() {
|
||||
Assertions.assertEquals(1, NumberUtils.log2(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumerals() {
|
||||
Assertions.assertEquals(4, NumberUtils.fromNumeral("IV"));
|
||||
Assertions.assertEquals(9, NumberUtils.fromNumeral("IX"));
|
||||
Assertions.assertEquals("XIV", NumberUtils.toNumeral(14));
|
||||
Assertions.assertEquals("XXI", NumberUtils.toNumeral(21));
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,21 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
|
||||
}
|
||||
}
|
||||
|
||||
group 'com.willfp'
|
||||
version rootProject.version
|
||||
|
||||
subprojects {
|
||||
apply plugin: "kotlin"
|
||||
|
||||
dependencies {
|
||||
compileOnly project(":eco-api")
|
||||
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.5.21'
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.willfp.eco.internal;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.proxy.Cleaner;
|
||||
import com.willfp.eco.internal.proxy.EcoProxyFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class EcoCleaner implements Cleaner {
|
||||
@Override
|
||||
public void clean(@NotNull final EcoPlugin plugin) {
|
||||
if (!plugin.getProxyPackage().equalsIgnoreCase("")) {
|
||||
EcoProxyFactory factory = (EcoProxyFactory) plugin.getProxyFactory();
|
||||
factory.clean();
|
||||
}
|
||||
|
||||
Plugins.LOADED_ECO_PLUGINS.remove(plugin.getName().toLowerCase());
|
||||
|
||||
if (plugin.getClass().getClassLoader() instanceof URLClassLoader urlClassLoader) {
|
||||
try {
|
||||
urlClassLoader.close();
|
||||
} catch (IOException e) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.willfp.eco.internal;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@UtilityClass
|
||||
public class Plugins {
|
||||
public static final Map<String, EcoPlugin> LOADED_ECO_PLUGINS = new HashMap<>();
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.willfp.eco.internal.config;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.core.config.wrapper.ConfigFactory;
|
||||
import com.willfp.eco.internal.config.json.EcoJSONConfigSection;
|
||||
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class EcoConfigFactory implements ConfigFactory {
|
||||
@Override
|
||||
public Config createUpdatableYamlConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source,
|
||||
final boolean removeUnused,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
return new EcoUpdatableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
updateBlacklist
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONConfig createLoadableJSONConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source) {
|
||||
return new EcoLoadableJSONConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Config createLoadableYamlConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source) {
|
||||
return new EcoLoadableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Config createYamlConfig(@NotNull final YamlConfiguration config) {
|
||||
return new EcoYamlConfigSection(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONConfig createJSONConfig(@NotNull final Map<String, Object> values) {
|
||||
return new EcoJSONConfigSection(values);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.willfp.eco.internal.config.json;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class EcoJSONConfigSection extends EcoJSONConfigWrapper {
|
||||
public EcoJSONConfigSection(@NotNull final Map<String, Object> values) {
|
||||
this.init(values);
|
||||
}
|
||||
}
|
||||
@@ -1,370 +0,0 @@
|
||||
package com.willfp.eco.internal.config.json;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public class EcoJSONConfigWrapper implements JSONConfig {
|
||||
@Getter
|
||||
private final Gson handle = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
@Getter
|
||||
private final Map<String, Object> values = new HashMap<>();
|
||||
|
||||
@Getter
|
||||
private final Map<String, Object> cache = new HashMap<>();
|
||||
|
||||
public EcoJSONConfigWrapper() {
|
||||
|
||||
}
|
||||
|
||||
public void init(@NotNull final Map<String, Object> values) {
|
||||
this.values.clear();
|
||||
this.values.putAll(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clearCache() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPlaintext() {
|
||||
return this.getHandle().toJson(this.getValues());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(@NotNull final String path) {
|
||||
return getOfKnownType(path, Object.class) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected <T> T getOfKnownType(@NotNull final String path,
|
||||
@NotNull final Class<T> clazz) {
|
||||
return getOfKnownType(path, clazz, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected <T> T getOfKnownType(@NotNull final String path,
|
||||
@NotNull final Class<T> clazz,
|
||||
final boolean isBase) {
|
||||
String closestPath = path;
|
||||
|
||||
if (cache.containsKey(path) && isBase) {
|
||||
return (T) cache.get(path);
|
||||
}
|
||||
|
||||
if (path.contains(".")) {
|
||||
String[] split = path.split("\\.");
|
||||
closestPath = split[0];
|
||||
}
|
||||
|
||||
if (values.get(closestPath) instanceof Map && !path.equals(closestPath)) {
|
||||
EcoJSONConfigSection section = new EcoJSONConfigSection((Map<String, Object>) values.get(closestPath));
|
||||
return section.getOfKnownType(path.substring(closestPath.length() + 1), clazz, false);
|
||||
} else {
|
||||
if (values.containsKey(closestPath)) {
|
||||
return (T) values.get(closestPath);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getKeys(final boolean deep) {
|
||||
if (deep) {
|
||||
return new ArrayList<>(getDeepKeys(new HashSet<>(), ""));
|
||||
} else {
|
||||
return new ArrayList<>(values.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
protected Set<String> getDeepKeys(@NotNull final Set<String> list,
|
||||
@NotNull final String root) {
|
||||
for (String key : values.keySet()) {
|
||||
list.add(root + key);
|
||||
|
||||
if (values.get(key) instanceof Map) {
|
||||
EcoJSONConfigSection section = new EcoJSONConfigSection((Map<String, Object>) values.get(key));
|
||||
list.addAll(section.getDeepKeys(list, root + key + "."));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object get(@NotNull final String path) {
|
||||
return getOfKnownType(path, Object.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NotNull final String path,
|
||||
@Nullable final Object object) {
|
||||
setRecursively(path, object, true);
|
||||
clearCache();
|
||||
}
|
||||
|
||||
protected void setRecursively(@NotNull final String path,
|
||||
@Nullable final Object object,
|
||||
final boolean isBase) {
|
||||
String closestPath = path;
|
||||
|
||||
if (path.contains(".")) {
|
||||
String[] split = path.split("\\.");
|
||||
closestPath = split[0];
|
||||
}
|
||||
|
||||
if (values.get(closestPath) instanceof Map && !path.equals(closestPath)) {
|
||||
EcoJSONConfigSection section = new EcoJSONConfigSection((Map<String, Object>) values.get(closestPath));
|
||||
section.setRecursively(path.substring(closestPath.length() + 1), object, false);
|
||||
values.put(closestPath, section.getValues());
|
||||
} else {
|
||||
Object obj = object;
|
||||
|
||||
if (object instanceof JSONConfig) {
|
||||
obj = ((EcoJSONConfigWrapper) object).getValues();
|
||||
}
|
||||
|
||||
values.put(path, obj);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Config getSubsection(@NotNull final String path) {
|
||||
Config subsection = getSubsectionOrNull(path);
|
||||
Validate.notNull(subsection);
|
||||
return subsection;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Config getSubsectionOrNull(@NotNull final String path) {
|
||||
if (values.containsKey(path)) {
|
||||
Map<String, Object> subsection = (Map<String, Object>) values.get(path);
|
||||
return new EcoJSONConfigSection(subsection);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JSONConfig> getSubsections(@NotNull final String path) {
|
||||
List<JSONConfig> subsections = getSubsectionsOrNull(path);
|
||||
Validate.notNull(subsections);
|
||||
return subsections;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<JSONConfig> getSubsectionsOrNull(@NotNull final String path) {
|
||||
List<Map<String, Object>> maps = (List<Map<String, Object>>) getOfKnownType(path, Object.class);
|
||||
|
||||
if (maps == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<JSONConfig> configs = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> map : maps) {
|
||||
configs.add(new EcoJSONConfigSection(map));
|
||||
}
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NotNull final String path) {
|
||||
// ew
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Double.class), 0D).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Integer getIntOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getInt(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NotNull final String path,
|
||||
final int def) {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Integer.class), def);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Integer> getInts(@NotNull final String path) {
|
||||
return (List<Integer>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Integer> getIntsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getInts(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBool(@NotNull final String path) {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Boolean.class), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Boolean getBoolOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getBool(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Boolean> getBools(@NotNull final String path) {
|
||||
return (List<Boolean>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Boolean> getBoolsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getBools(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getString(@NotNull final String path) {
|
||||
return getString(path, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getString(@NotNull final String path,
|
||||
final boolean format) {
|
||||
String string = Objects.requireNonNullElse(getOfKnownType(path, String.class), "");
|
||||
return format ? StringUtils.format(string) : string;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getStringOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getString(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getStringOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (has(path)) {
|
||||
return getString(path, format);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> getStrings(@NotNull final String path) {
|
||||
return getStrings(path, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> getStrings(@NotNull final String path,
|
||||
final boolean format) {
|
||||
List<String> strings = (List<String>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
|
||||
|
||||
return format ? StringUtils.formatList(strings) : strings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<String> getStringsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getStrings(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> getStringsOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (has(path)) {
|
||||
return getStrings(path, format);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(@NotNull final String path) {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Double.class), 0D);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Double getDoubleOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getDouble(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Double> getDoubles(@NotNull final String path) {
|
||||
return (List<Double>) Objects.requireNonNullElse(getOfKnownType(path, Object.class), new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Double> getDoublesOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getDoubles(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONConfig clone() {
|
||||
return new EcoJSONConfigSection(new HashMap<>(this.getValues()));
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package com.willfp.eco.internal.config.json;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.HashMap;
|
||||
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public class EcoLoadableJSONConfig extends EcoJSONConfigWrapper implements LoadableConfig {
|
||||
@Getter
|
||||
private final File configFile;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final String subDirectoryPath;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final Class<?> source;
|
||||
|
||||
public EcoLoadableJSONConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source) {
|
||||
this.plugin = plugin;
|
||||
this.name = configName + ".json";
|
||||
this.source = source;
|
||||
this.subDirectoryPath = subDirectoryPath;
|
||||
|
||||
File directory = new File(this.getPlugin().getDataFolder(), subDirectoryPath);
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
if (!new File(directory, this.name).exists()) {
|
||||
createFile();
|
||||
}
|
||||
|
||||
this.configFile = new File(directory, this.name);
|
||||
|
||||
try {
|
||||
init(this.configFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
plugin.getConfigHandler().addConfig(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createFile() {
|
||||
String resourcePath = getResourcePath();
|
||||
InputStream in = source.getResourceAsStream(resourcePath);
|
||||
|
||||
File outFile = new File(this.getPlugin().getDataFolder(), resourcePath);
|
||||
int lastIndex = resourcePath.lastIndexOf('/');
|
||||
File outDir = new File(this.getPlugin().getDataFolder(), resourcePath.substring(0, Math.max(lastIndex, 0)));
|
||||
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdirs();
|
||||
}
|
||||
|
||||
try {
|
||||
if (!outFile.exists()) {
|
||||
OutputStream out = new FileOutputStream(outFile);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getResourcePath() {
|
||||
String resourcePath;
|
||||
|
||||
if (subDirectoryPath.isEmpty()) {
|
||||
resourcePath = name;
|
||||
} else {
|
||||
resourcePath = subDirectoryPath + name;
|
||||
}
|
||||
|
||||
return "/" + resourcePath;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
configFile.delete();
|
||||
Files.write(configFile.toPath(), this.toPlaintext().getBytes(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
|
||||
}
|
||||
|
||||
|
||||
public void init(@NotNull final File file) throws FileNotFoundException {
|
||||
super.init(this.getHandle().fromJson(new FileReader(file), HashMap.class));
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.willfp.eco.internal.config.updating;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
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.updating.exceptions.InvalidUpdateMethodException;
|
||||
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.MethodAnnotationsScanner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EcoConfigHandler extends PluginDependent<EcoPlugin> implements ConfigHandler {
|
||||
private final List<LoadableConfig> configs = new ArrayList<>();
|
||||
|
||||
private final Reflections reflections;
|
||||
|
||||
public EcoConfigHandler(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
|
||||
this.reflections = new Reflections(
|
||||
this.getPlugin().getClass().getClassLoader(),
|
||||
new MethodAnnotationsScanner()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callUpdate() {
|
||||
for (Method method : reflections.getMethodsAnnotatedWith(ConfigUpdater.class)) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
throw new InvalidUpdateMethodException("Update method must be static.");
|
||||
}
|
||||
|
||||
try {
|
||||
if (method.getParameterCount() == 0) {
|
||||
method.invoke(null);
|
||||
} else if (method.getParameterCount() == 1) {
|
||||
method.invoke(null, this.getPlugin());
|
||||
} else {
|
||||
throw new InvalidUpdateMethodException("Update method must have 0 parameters or a plugin parameter.");
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
throw new InvalidUpdateMethodException("Update method generated an exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAllConfigs() {
|
||||
try {
|
||||
for (LoadableConfig config : configs) {
|
||||
config.save();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConfig(@NotNull final LoadableConfig config) {
|
||||
configs.add(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateConfigs() {
|
||||
for (LoadableConfig config : configs) {
|
||||
if (config instanceof EcoUpdatableYamlConfig updatableYamlConfig) {
|
||||
updatableYamlConfig.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.willfp.eco.internal.config.updating.exceptions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class InvalidUpdateMethodException extends RuntimeException {
|
||||
public InvalidUpdateMethodException(@NotNull final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class EcoLoadableYamlConfig extends EcoYamlConfigWrapper<YamlConfiguration> implements WrappedYamlConfiguration, LoadableConfig {
|
||||
@Getter
|
||||
private final File configFile;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private final String name;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final String subDirectoryPath;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final Class<?> source;
|
||||
|
||||
public EcoLoadableYamlConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source) {
|
||||
this.plugin = plugin;
|
||||
this.name = configName + ".yml";
|
||||
this.source = source;
|
||||
this.subDirectoryPath = subDirectoryPath;
|
||||
|
||||
File directory = new File(this.getPlugin().getDataFolder(), subDirectoryPath);
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
if (!new File(directory, this.name).exists()) {
|
||||
createFile();
|
||||
}
|
||||
|
||||
this.configFile = new File(directory, this.name);
|
||||
init(YamlConfiguration.loadConfiguration(configFile));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createFile() {
|
||||
String resourcePath = getResourcePath();
|
||||
InputStream in = source.getResourceAsStream(resourcePath);
|
||||
|
||||
File outFile = new File(this.getPlugin().getDataFolder(), resourcePath);
|
||||
int lastIndex = resourcePath.lastIndexOf('/');
|
||||
File outDir = new File(this.getPlugin().getDataFolder(), resourcePath.substring(0, Math.max(lastIndex, 0)));
|
||||
|
||||
if (!outDir.exists()) {
|
||||
outDir.mkdirs();
|
||||
}
|
||||
|
||||
try {
|
||||
if (!outFile.exists()) {
|
||||
OutputStream out = new FileOutputStream(outFile);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
plugin.getConfigHandler().addConfig(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourcePath() {
|
||||
String resourcePath;
|
||||
|
||||
if (subDirectoryPath.isEmpty()) {
|
||||
resourcePath = name;
|
||||
} else {
|
||||
resourcePath = subDirectoryPath + name;
|
||||
}
|
||||
|
||||
return "/" + resourcePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws IOException {
|
||||
this.getHandle().save(this.getConfigFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlConfiguration getBukkitHandle() {
|
||||
return this.getHandle();
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class EcoUpdatableYamlConfig extends EcoLoadableYamlConfig {
|
||||
private final boolean removeUnused;
|
||||
|
||||
private final List<String> updateBlacklist;
|
||||
|
||||
public EcoUpdatableYamlConfig(@NotNull final String configName,
|
||||
@NotNull final EcoPlugin plugin,
|
||||
@NotNull final String subDirectoryPath,
|
||||
@NotNull final Class<?> source,
|
||||
final boolean removeUnused,
|
||||
@NotNull final String... updateBlacklist) {
|
||||
super(configName, plugin, subDirectoryPath, source);
|
||||
this.removeUnused = removeUnused;
|
||||
this.updateBlacklist = new ArrayList<>(Arrays.asList(updateBlacklist));
|
||||
this.updateBlacklist.removeIf(String::isEmpty);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
public void update() {
|
||||
super.clearCache();
|
||||
try {
|
||||
this.getHandle().load(this.getConfigFile());
|
||||
|
||||
YamlConfiguration newConfig = this.getConfigInJar();
|
||||
|
||||
if (newConfig.getKeys(true).equals(this.getHandle().getKeys(true))) {
|
||||
return;
|
||||
}
|
||||
|
||||
newConfig.getKeys(true).forEach((s -> {
|
||||
if (!this.getHandle().getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.getHandle().set(s, newConfig.get(s));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
if (this.removeUnused) {
|
||||
this.getHandle().getKeys(true).forEach((s -> {
|
||||
if (!newConfig.getKeys(true).contains(s)) {
|
||||
if (updateBlacklist.stream().noneMatch(s::contains)) {
|
||||
this.getHandle().set(s, null);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
this.getHandle().save(this.getConfigFile());
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public YamlConfiguration getConfigInJar() {
|
||||
InputStream newIn = this.getSource().getResourceAsStream(getResourcePath());
|
||||
|
||||
if (newIn == null) {
|
||||
throw new NullPointerException(this.getName() + " is null?");
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(newIn, StandardCharsets.UTF_8));
|
||||
YamlConfiguration newConfig = new YamlConfiguration();
|
||||
|
||||
try {
|
||||
newConfig.load(reader);
|
||||
} catch (IOException | InvalidConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoYamlConfigSection extends EcoYamlConfigWrapper<ConfigurationSection> {
|
||||
public EcoYamlConfigSection(@NotNull final ConfigurationSection section) {
|
||||
this.init(section);
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
package com.willfp.eco.internal.config.yaml;
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public class EcoYamlConfigWrapper<T extends ConfigurationSection> implements Config {
|
||||
@Getter
|
||||
private T handle = null;
|
||||
|
||||
private final Map<String, Object> cache = new HashMap<>();
|
||||
|
||||
public EcoYamlConfigWrapper() {
|
||||
|
||||
}
|
||||
|
||||
protected Config init(@NotNull final T config) {
|
||||
this.handle = config;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toPlaintext() {
|
||||
YamlConfiguration temp = new YamlConfiguration();
|
||||
for (String key : handle.getKeys(true)) {
|
||||
temp.set(key, handle.get(key));
|
||||
}
|
||||
return temp.saveToString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clearCache() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(@NotNull final String path) {
|
||||
return handle.contains(path);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getKeys(final boolean deep) {
|
||||
return new ArrayList<>(handle.getKeys(deep));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object get(@NotNull final String path) {
|
||||
return handle.get(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NotNull final String path,
|
||||
@Nullable final Object object) {
|
||||
cache.remove(path);
|
||||
handle.set(path, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Config getSubsection(@NotNull final String path) {
|
||||
Config subsection = getSubsectionOrNull(path);
|
||||
Validate.notNull(subsection);
|
||||
return subsection;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Config getSubsectionOrNull(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (Config) cache.get(path);
|
||||
} else {
|
||||
ConfigurationSection raw = handle.getConfigurationSection(path);
|
||||
if (raw == null) {
|
||||
cache.put(path, null);
|
||||
} else {
|
||||
cache.put(path, new EcoYamlConfigSection(raw));
|
||||
}
|
||||
return getSubsectionOrNull(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (int) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, handle.getInt(path, 0));
|
||||
return getInt(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Integer getIntOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getInt(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(@NotNull final String path,
|
||||
final int def) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (int) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, handle.getInt(path, def));
|
||||
return getInt(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Integer> getInts(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (List<Integer>) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, has(path) ? new ArrayList<>(handle.getIntegerList(path)) : new ArrayList<>());
|
||||
return getInts(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Integer> getIntsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getInts(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBool(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (boolean) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, handle.getBoolean(path));
|
||||
return getBool(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Boolean getBoolOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getBool(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Boolean> getBools(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (List<Boolean>) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, has(path) ? new ArrayList<>(handle.getBooleanList(path)) : new ArrayList<>());
|
||||
return getBools(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Boolean> getBoolsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getBools(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getString(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (String) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, StringUtils.format(Objects.requireNonNull(handle.getString(path, ""))));
|
||||
return getString(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getString(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (String) cache.get(path);
|
||||
} else {
|
||||
String string = Objects.requireNonNull(handle.getString(path, ""));
|
||||
cache.put(path, format ? StringUtils.format(string) : string);
|
||||
return getString(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getStringOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getString(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getStringOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (has(path)) {
|
||||
return getString(path, format);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> getStrings(@NotNull final String path) {
|
||||
return getStrings(path, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<String> getStrings(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (cache.containsKey(path)) {
|
||||
return format ? StringUtils.formatList((List<String>) cache.get(path)) : (List<String>) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, has(path) ? new ArrayList<>(handle.getStringList(path)) : new ArrayList<>());
|
||||
return getStrings(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<String> getStringsOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getStrings(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> getStringsOrNull(@NotNull final String path,
|
||||
final boolean format) {
|
||||
if (has(path)) {
|
||||
return getStrings(path, format);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (double) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, handle.getDouble(path));
|
||||
return getDouble(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Double getDoubleOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getDouble(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<Double> getDoubles(@NotNull final String path) {
|
||||
if (cache.containsKey(path)) {
|
||||
return (List<Double>) cache.get(path);
|
||||
} else {
|
||||
cache.put(path, has(path) ? new ArrayList<>(handle.getDoubleList(path)) : new ArrayList<>());
|
||||
return getDoubles(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<Double> getDoublesOrNull(@NotNull final String path) {
|
||||
if (has(path)) {
|
||||
return getDoubles(path);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Config clone() {
|
||||
return new EcoYamlConfigSection(YamlConfiguration.loadConfiguration(new StringReader(this.toPlaintext())));
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.willfp.eco.internal.drops;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.config.updating.ConfigUpdater;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@UtilityClass
|
||||
public final class DropManager {
|
||||
@Getter
|
||||
private DropQueueType type = DropQueueType.COLLATED;
|
||||
|
||||
@ConfigUpdater
|
||||
public static void update(@NotNull final EcoPlugin plugin) {
|
||||
type = plugin.getConfigYml().getBool("use-fast-collated-drops") ? DropQueueType.COLLATED : DropQueueType.STANDARD;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.willfp.eco.internal.drops;
|
||||
|
||||
public enum DropQueueType {
|
||||
STANDARD,
|
||||
COLLATED
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.willfp.eco.internal.drops;
|
||||
|
||||
import com.willfp.eco.core.drops.DropQueueFactory;
|
||||
import com.willfp.eco.core.drops.InternalDropQueue;
|
||||
import com.willfp.eco.internal.drops.impl.EcoDropQueue;
|
||||
import com.willfp.eco.internal.drops.impl.EcoFastCollatedDropQueue;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoDropQueueFactory implements DropQueueFactory {
|
||||
@Override
|
||||
public InternalDropQueue create(@NotNull final Player player) {
|
||||
return DropManager.getType() == DropQueueType.COLLATED ? new EcoFastCollatedDropQueue(player) : new EcoDropQueue(player);
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.willfp.eco.internal.drops.impl;
|
||||
|
||||
import com.willfp.eco.core.drops.InternalDropQueue;
|
||||
import com.willfp.eco.util.TelekinesisUtils;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerExpChangeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class EcoDropQueue implements InternalDropQueue {
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final List<ItemStack> items;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private int xp;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private final Player player;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private Location loc;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private boolean hasTelekinesis = false;
|
||||
|
||||
public EcoDropQueue(@NotNull final Player player) {
|
||||
this.items = new ArrayList<>();
|
||||
this.xp = 0;
|
||||
this.player = player;
|
||||
this.loc = player.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalDropQueue addItem(@NotNull final ItemStack item) {
|
||||
this.items.add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalDropQueue addItems(@NotNull final Collection<ItemStack> itemStacks) {
|
||||
this.items.addAll(itemStacks);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalDropQueue addXP(final int amount) {
|
||||
this.xp += amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalDropQueue setLocation(@NotNull final Location location) {
|
||||
this.loc = location;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InternalDropQueue forceTelekinesis() {
|
||||
this.hasTelekinesis = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push() {
|
||||
if (!hasTelekinesis) {
|
||||
hasTelekinesis = TelekinesisUtils.testPlayer(player);
|
||||
}
|
||||
|
||||
World world = loc.getWorld();
|
||||
assert world != null;
|
||||
loc = loc.add(0.5, 0.5, 0.5);
|
||||
|
||||
items.removeIf(itemStack -> itemStack.getType() == Material.AIR);
|
||||
if (items.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasTelekinesis) {
|
||||
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(items.toArray(new ItemStack[0]));
|
||||
for (ItemStack drop : leftover.values()) {
|
||||
world.dropItem(loc, drop).setVelocity(new Vector());
|
||||
}
|
||||
if (xp > 0) {
|
||||
PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, xp);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(player.getLocation().add(0, 0.2, 0), EntityType.EXPERIENCE_ORB);
|
||||
orb.setVelocity(new Vector(0, 0, 0));
|
||||
orb.setExperience(event.getAmount());
|
||||
}
|
||||
} else {
|
||||
for (ItemStack drop : items) {
|
||||
world.dropItem(loc, drop).setVelocity(new Vector());
|
||||
}
|
||||
if (xp > 0) {
|
||||
ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(loc, EntityType.EXPERIENCE_ORB);
|
||||
orb.setExperience(xp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.willfp.eco.internal.drops.impl;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class EcoFastCollatedDropQueue extends EcoDropQueue {
|
||||
public static final Map<Player, CollatedDrops> COLLATED_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
public EcoFastCollatedDropQueue(@NotNull final Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push() {
|
||||
CollatedDrops fetched = COLLATED_MAP.get(getPlayer());
|
||||
CollatedDrops collatedDrops = fetched == null ? new CollatedDrops(getItems(), getLoc(), getXp()) : fetched.addDrops(getItems()).setLocation(getLoc()).addXp(getXp());
|
||||
COLLATED_MAP.put(this.getPlayer(), collatedDrops);
|
||||
}
|
||||
|
||||
@ToString
|
||||
public static final class CollatedDrops {
|
||||
@Getter
|
||||
private final List<ItemStack> drops;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
private Location location;
|
||||
|
||||
@Getter
|
||||
private int xp;
|
||||
|
||||
private CollatedDrops(@NotNull final List<ItemStack> drops,
|
||||
@NotNull final Location location,
|
||||
final int xp) {
|
||||
this.drops = drops;
|
||||
this.location = location;
|
||||
this.xp = xp;
|
||||
}
|
||||
|
||||
public CollatedDrops addDrops(@NotNull final List<ItemStack> toAdd) {
|
||||
drops.addAll(toAdd);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CollatedDrops addXp(final int xp) {
|
||||
this.xp += xp;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.willfp.eco.internal.events;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.events.EventManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoEventManager extends PluginDependent<EcoPlugin> implements EventManager {
|
||||
@ApiStatus.Internal
|
||||
public EcoEventManager(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerListener(@NotNull final Listener listener) {
|
||||
Bukkit.getPluginManager().registerEvents(listener, this.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterListener(@NotNull final Listener listener) {
|
||||
HandlerList.unregisterAll(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterAllListeners() {
|
||||
HandlerList.unregisterAll(this.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package com.willfp.eco.internal.extensions;
|
||||
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.extensions.Extension;
|
||||
import com.willfp.eco.core.extensions.ExtensionLoader;
|
||||
import com.willfp.eco.core.extensions.ExtensionMetadata;
|
||||
import com.willfp.eco.core.extensions.MalformedExtensionException;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class EcoExtensionLoader extends PluginDependent<EcoPlugin> implements ExtensionLoader {
|
||||
private final Set<Extension> extensions = new HashSet<>();
|
||||
|
||||
public EcoExtensionLoader(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadExtensions() {
|
||||
File dir = new File(this.getPlugin().getDataFolder(), "/extensions");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
File[] extensionJars = dir.listFiles();
|
||||
|
||||
if (extensionJars == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File extensionJar : extensionJars) {
|
||||
if (!extensionJar.isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
loadExtension(extensionJar);
|
||||
} catch (MalformedExtensionException e) {
|
||||
this.getPlugin().getLogger().severe(extensionJar.getName() + " caused MalformedExtensionException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadExtension(@NotNull final File extensionJar) {
|
||||
URL url = null;
|
||||
try {
|
||||
url = extensionJar.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
ClassLoader cl = new URLClassLoader(new URL[]{url}, this.getPlugin().getClass().getClassLoader());
|
||||
|
||||
InputStream ymlIn = cl.getResourceAsStream("extension.yml");
|
||||
|
||||
if (ymlIn == null) {
|
||||
throw new MalformedExtensionException("No extension.yml found in " + extensionJar.getName());
|
||||
}
|
||||
|
||||
YamlConfiguration extensionYml = YamlConfiguration.loadConfiguration(new InputStreamReader(ymlIn));
|
||||
|
||||
Set<String> keys = extensionYml.getKeys(false);
|
||||
ArrayList<String> required = new ArrayList<>(Arrays.asList("main", "name", "version"));
|
||||
required.removeAll(keys);
|
||||
if (!required.isEmpty()) {
|
||||
throw new MalformedExtensionException("Invalid extension.yml found in " + extensionJar.getName() + " - Missing: " + String.join(", ", required));
|
||||
}
|
||||
|
||||
String mainClass = extensionYml.getString("main");
|
||||
String name = extensionYml.getString("name");
|
||||
String version = extensionYml.getString("version");
|
||||
String author = extensionYml.getString("author");
|
||||
Validate.notNull(name, "Name is missing!");
|
||||
Validate.notNull(version, "Version is missing!");
|
||||
Validate.notNull(author, "Author is missing!");
|
||||
|
||||
ExtensionMetadata metadata = new ExtensionMetadata(version, name, author);
|
||||
|
||||
Class<?> cls;
|
||||
Object object = null;
|
||||
try {
|
||||
cls = cl.loadClass(mainClass);
|
||||
object = cls.getConstructor(EcoPlugin.class).newInstance(this.getPlugin());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!(object instanceof Extension extension)) {
|
||||
throw new MalformedExtensionException(extensionJar.getName() + " is invalid");
|
||||
}
|
||||
|
||||
extension.setMetadata(metadata);
|
||||
extension.enable();
|
||||
extensions.add(extension);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadExtensions() {
|
||||
extensions.forEach(Extension::disable);
|
||||
extensions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Extension> getLoadedExtensions() {
|
||||
return extensions;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.willfp.eco.internal.factory;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.factory.MetadataValueFactory;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoMetadataValueFactory extends PluginDependent<EcoPlugin> implements MetadataValueFactory {
|
||||
public EcoMetadataValueFactory(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedMetadataValue create(@NotNull final Object value) {
|
||||
return new FixedMetadataValue(this.getPlugin(), value);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.willfp.eco.internal.factory;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.factory.NamespacedKeyFactory;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoNamespacedKeyFactory extends PluginDependent<EcoPlugin> implements NamespacedKeyFactory {
|
||||
public EcoNamespacedKeyFactory(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespacedKey create(@NotNull final String key) {
|
||||
return new NamespacedKey(this.getPlugin(), key);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.willfp.eco.internal.factory;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.factory.RunnableFactory;
|
||||
import com.willfp.eco.core.scheduling.RunnableTask;
|
||||
import com.willfp.eco.internal.scheduling.EcoRunnableTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EcoRunnableFactory extends PluginDependent<EcoPlugin> implements RunnableFactory {
|
||||
public EcoRunnableFactory(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunnableTask create(@NotNull final Consumer<RunnableTask> consumer) {
|
||||
return new EcoRunnableTask(this.getPlugin()) {
|
||||
@Override
|
||||
public void run() {
|
||||
consumer.accept(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.willfp.eco.internal.gui;
|
||||
|
||||
import com.willfp.eco.core.gui.GUIFactory;
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder;
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||
import com.willfp.eco.internal.gui.menu.EcoMenuBuilder;
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EcoGUIFactory implements GUIFactory {
|
||||
@Override
|
||||
public SlotBuilder createSlotBuilder(@NotNull final Function<Player, ItemStack> provider) {
|
||||
return new EcoSlotBuilder(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBuilder createMenuBuilder(final int rows) {
|
||||
return new EcoMenuBuilder(rows);
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.menu;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import com.willfp.eco.core.gui.slot.FillerSlot;
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import com.willfp.eco.internal.gui.slot.EcoFillerSlot;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EcoMenu implements Menu {
|
||||
@Getter
|
||||
private final int rows;
|
||||
|
||||
private final List<List<Slot>> slots;
|
||||
|
||||
@Getter
|
||||
private final String title;
|
||||
|
||||
private final Consumer<InventoryCloseEvent> onClose;
|
||||
|
||||
public EcoMenu(final int rows,
|
||||
@NotNull final List<List<Slot>> slots,
|
||||
@NotNull final String title,
|
||||
@NotNull final Consumer<InventoryCloseEvent> onClose) {
|
||||
this.rows = rows;
|
||||
this.slots = slots;
|
||||
this.title = title;
|
||||
this.onClose = onClose;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slot getSlot(final int row,
|
||||
final int column) {
|
||||
if (row < 1 || row > this.rows) {
|
||||
throw new IllegalArgumentException("Invalid row number!");
|
||||
}
|
||||
|
||||
if (column < 1 || column > 9) {
|
||||
throw new IllegalArgumentException("Invalid column number!");
|
||||
}
|
||||
|
||||
Slot slot = slots.get(row - 1).get(column - 1);
|
||||
if (slot instanceof FillerSlot fillerSlot) {
|
||||
slots.get(row - 1).set(
|
||||
column - 1,
|
||||
new EcoFillerSlot(fillerSlot.getItemStack())
|
||||
);
|
||||
|
||||
return getSlot(row, column);
|
||||
}
|
||||
|
||||
return slots.get(row - 1).get(column - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inventory open(@NotNull final Player player) {
|
||||
Inventory inventory = Bukkit.createInventory(null, rows * 9, title);
|
||||
int i = 0;
|
||||
for (List<Slot> row : slots) {
|
||||
for (Slot item : row) {
|
||||
if (i == rows * 9) {
|
||||
break;
|
||||
}
|
||||
ItemStack slotItem = item.getItemStack(player);
|
||||
ItemMeta meta = slotItem.getItemMeta();
|
||||
if (meta != null) {
|
||||
List<String> lore = meta.getLore();
|
||||
if (lore != null) {
|
||||
lore.replaceAll(s -> StringUtils.format(s, player));
|
||||
meta.setLore(lore);
|
||||
}
|
||||
slotItem.setItemMeta(meta);
|
||||
}
|
||||
inventory.setItem(i, slotItem);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
player.openInventory(inventory);
|
||||
MenuHandler.registerMenu(inventory, this);
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public void handleClose(@NotNull final InventoryCloseEvent event) {
|
||||
onClose.accept(event);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.menu;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder;
|
||||
import com.willfp.eco.core.gui.slot.FillerMask;
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import com.willfp.eco.internal.gui.slot.EcoFillerSlot;
|
||||
import com.willfp.eco.util.ListUtils;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EcoMenuBuilder implements MenuBuilder {
|
||||
private final int rows;
|
||||
|
||||
private String title = "Menu";
|
||||
|
||||
private List<List<Slot>> maskSlots;
|
||||
|
||||
private final List<List<Slot>> slots;
|
||||
|
||||
private Consumer<InventoryCloseEvent> onClose = (event) -> {
|
||||
};
|
||||
|
||||
public EcoMenuBuilder(final int rows) {
|
||||
this.rows = rows;
|
||||
this.slots = ListUtils.create2DList(rows, 9);
|
||||
this.maskSlots = ListUtils.create2DList(rows, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBuilder setTitle(@NotNull final String title) {
|
||||
this.title = StringUtils.format(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBuilder setSlot(final int row,
|
||||
final int column,
|
||||
@NotNull final Slot slot) {
|
||||
if (row < 1 || row > this.rows) {
|
||||
throw new IllegalArgumentException("Invalid row number!");
|
||||
}
|
||||
|
||||
if (column < 1 || column > 9) {
|
||||
throw new IllegalArgumentException("Invalid column number!");
|
||||
}
|
||||
|
||||
slots.get(row - 1).set(column - 1, slot);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBuilder setMask(@NotNull final FillerMask mask) {
|
||||
this.maskSlots = mask.getMask();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuBuilder onClose(@NotNull final Consumer<InventoryCloseEvent> action) {
|
||||
this.onClose = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Menu build() {
|
||||
List<List<Slot>> finalSlots = maskSlots;
|
||||
for (int i = 0; i < slots.size(); i++) {
|
||||
for (int j = 0; j < slots.get(i).size(); j++) {
|
||||
Slot slot = slots.get(i).get(j);
|
||||
if (slot != null) {
|
||||
finalSlots.get(i).set(j, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (List<Slot> finalSlot : finalSlots) {
|
||||
for (int j = 0; j < finalSlot.size(); j++) {
|
||||
if (finalSlot.get(j) == null) {
|
||||
finalSlot.set(j, new EcoFillerSlot(new ItemStack(Material.AIR)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new EcoMenu(rows, finalSlots, title, onClose);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.menu;
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@UtilityClass
|
||||
public class MenuHandler {
|
||||
private static final Map<Inventory, Menu> MENUS = new HashMap<>();
|
||||
|
||||
public void registerMenu(@NotNull final Inventory inventory,
|
||||
@NotNull final Menu menu) {
|
||||
MENUS.put(inventory, menu);
|
||||
}
|
||||
|
||||
public void unregisterMenu(@NotNull final Inventory inventory) {
|
||||
MENUS.remove(inventory);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Menu getMenu(@NotNull final Inventory inventory) {
|
||||
return MENUS.get(inventory);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.slot;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoFillerSlot extends EcoSlot {
|
||||
public EcoFillerSlot(@NotNull final ItemStack itemStack) {
|
||||
super((player) -> itemStack, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.slot;
|
||||
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EcoSlot implements Slot {
|
||||
@Getter
|
||||
private final Function<Player, ItemStack> provider;
|
||||
|
||||
private final BiConsumer<InventoryClickEvent, Slot> onLeftClick;
|
||||
|
||||
private final BiConsumer<InventoryClickEvent, Slot> onRightClick;
|
||||
|
||||
private final BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick;
|
||||
|
||||
private final BiConsumer<InventoryClickEvent, Slot> onShiftRightClick;
|
||||
|
||||
private final BiConsumer<InventoryClickEvent, Slot> onMiddleClick;
|
||||
|
||||
public EcoSlot(@NotNull final Function<Player, ItemStack> provider,
|
||||
@Nullable final BiConsumer<InventoryClickEvent, Slot> onLeftClick,
|
||||
@Nullable final BiConsumer<InventoryClickEvent, Slot> onRightClick,
|
||||
@Nullable final BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick,
|
||||
@Nullable final BiConsumer<InventoryClickEvent, Slot> onShiftRightClick,
|
||||
@Nullable final BiConsumer<InventoryClickEvent, Slot> onMiddleClick) {
|
||||
this.provider = provider;
|
||||
this.onLeftClick = onLeftClick == null ? ((event, slot) -> {
|
||||
}) : onLeftClick;
|
||||
this.onRightClick = onRightClick == null ? ((event, slot) -> {
|
||||
}) : onRightClick;
|
||||
this.onShiftLeftClick = onShiftLeftClick == null ? ((event, slot) -> {
|
||||
}) : onShiftLeftClick;
|
||||
this.onShiftRightClick = onShiftRightClick == null ? ((event, slot) -> {
|
||||
}) : onShiftRightClick;
|
||||
this.onMiddleClick = onMiddleClick == null ? ((event, slot) -> {
|
||||
}) : onMiddleClick;
|
||||
}
|
||||
|
||||
public void handleInventoryClick(@NotNull final InventoryClickEvent event) {
|
||||
switch (event.getClick()) {
|
||||
case LEFT -> this.onLeftClick.accept(event, this);
|
||||
case RIGHT -> this.onRightClick.accept(event, this);
|
||||
case SHIFT_LEFT -> this.onShiftLeftClick.accept(event, this);
|
||||
case SHIFT_RIGHT -> this.onShiftRightClick.accept(event, this);
|
||||
case MIDDLE -> this.onMiddleClick.accept(event, this);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemStack(@NotNull final Player player) {
|
||||
return provider.apply(player);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.slot;
|
||||
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class EcoSlotBuilder implements SlotBuilder {
|
||||
private final Function<Player, ItemStack> provider;
|
||||
|
||||
private BiConsumer<InventoryClickEvent, Slot> onLeftClick = null;
|
||||
|
||||
private BiConsumer<InventoryClickEvent, Slot> onRightClick = null;
|
||||
|
||||
private BiConsumer<InventoryClickEvent, Slot> onShiftLeftClick = null;
|
||||
|
||||
private BiConsumer<InventoryClickEvent, Slot> onShiftRightClick = null;
|
||||
|
||||
private BiConsumer<InventoryClickEvent, Slot> onMiddleClick = null;
|
||||
|
||||
public EcoSlotBuilder(@NotNull final Function<Player, ItemStack> provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public SlotBuilder onLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
this.onLeftClick = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SlotBuilder onRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
this.onRightClick = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SlotBuilder onShiftLeftClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
this.onShiftLeftClick = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SlotBuilder onShiftRightClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
this.onShiftRightClick = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SlotBuilder onMiddleClick(@NotNull final BiConsumer<InventoryClickEvent, Slot> action) {
|
||||
this.onMiddleClick = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Slot build() {
|
||||
return new EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.willfp.eco.internal.integrations;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
|
||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PlaceholderIntegrationPAPI extends PlaceholderExpansion implements PlaceholderIntegration {
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
public PlaceholderIntegrationPAPI(@NotNull final EcoPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return String.join(", ", plugin.getDescription().getAuthors());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return plugin.getDescription().getName().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onPlaceholderRequest(@Nullable final Player player,
|
||||
@NotNull final String identifier) {
|
||||
return PlaceholderManager.getResult(player, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIntegration() {
|
||||
this.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginName() {
|
||||
return "PlaceholderAPI";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translate(@NotNull final String text,
|
||||
@Nullable final Player player) {
|
||||
return PlaceholderAPI.setPlaceholders(player, text);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.willfp.eco.internal.logging;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class EcoLogger extends Logger {
|
||||
public EcoLogger(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin.getName(), (String) null);
|
||||
String prefix = plugin.getDescription().getPrefix();
|
||||
this.setParent(plugin.getServer().getLogger());
|
||||
this.setLevel(Level.ALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NotNull final String msg) {
|
||||
super.info(StringUtils.format(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(@NotNull final String msg) {
|
||||
super.warning(StringUtils.format(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void severe(@NotNull final String msg) {
|
||||
super.severe(StringUtils.format(msg));
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
package com.willfp.eco.internal.proxy;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.proxy.AbstractProxy;
|
||||
import com.willfp.eco.core.proxy.ProxyConstants;
|
||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||
import com.willfp.eco.core.proxy.exceptions.ProxyError;
|
||||
import com.willfp.eco.core.proxy.exceptions.UnsupportedVersionException;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EcoProxyFactory extends PluginDependent<EcoPlugin> implements ProxyFactory {
|
||||
private static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
|
||||
"v1_16_R3",
|
||||
"v1_17_R1"
|
||||
);
|
||||
|
||||
private final ClassLoader proxyClassLoader;
|
||||
|
||||
private final Map<Class<? extends AbstractProxy>, AbstractProxy> cache = new IdentityHashMap<>();
|
||||
|
||||
public EcoProxyFactory(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
|
||||
Validate.isTrue(
|
||||
!plugin.getProxyPackage().equalsIgnoreCase(""),
|
||||
"Specified plugin has no proxy support!"
|
||||
);
|
||||
|
||||
this.proxyClassLoader = plugin.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends AbstractProxy> @NotNull T getProxy(@NotNull final Class<T> proxyClass) {
|
||||
try {
|
||||
T cachedProxy = attemptCache(proxyClass);
|
||||
if (cachedProxy != null) {
|
||||
return cachedProxy;
|
||||
}
|
||||
|
||||
String className = this.getPlugin().getProxyPackage() + "." + ProxyConstants.NMS_VERSION + "." + proxyClass.getSimpleName().replace("Proxy", "");
|
||||
Class<?> clazz = this.getPlugin().getClass().getClassLoader().loadClass(className);
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
if (proxyClass.isAssignableFrom(clazz) && proxyClass.isInstance(instance)) {
|
||||
T proxy = proxyClass.cast(instance);
|
||||
cache.put(proxyClass, proxy);
|
||||
return proxy;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throwError(e);
|
||||
}
|
||||
|
||||
throwError(new IllegalArgumentException());
|
||||
|
||||
throw new RuntimeException("Something went wrong.");
|
||||
}
|
||||
|
||||
private void throwError(@Nullable final Exception e) {
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!SUPPORTED_VERSIONS.contains(ProxyConstants.NMS_VERSION)) {
|
||||
throw new UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
|
||||
} else {
|
||||
throw new ProxyError("Error with proxies - here's a stacktrace. Only god can help you now.");
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends AbstractProxy> T attemptCache(@NotNull final Class<T> proxyClass) {
|
||||
Object proxy = cache.get(proxyClass);
|
||||
if (proxy == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (proxyClass.isInstance(proxy)) {
|
||||
return proxyClass.cast(proxy);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
try {
|
||||
if (proxyClassLoader instanceof URLClassLoader urlClassLoader) {
|
||||
urlClassLoader.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.willfp.eco.internal.scheduling;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.scheduling.RunnableTask;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class EcoRunnableTask extends BukkitRunnable implements RunnableTask {
|
||||
private final EcoPlugin plugin;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public EcoRunnableTask(@NotNull final EcoPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
protected final EcoPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTask() {
|
||||
return super.runTask(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTaskAsynchronously() {
|
||||
return super.runTaskAsynchronously(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTaskLater(final long delay) {
|
||||
return super.runTaskLater(plugin, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTaskLaterAsynchronously(final long delay) {
|
||||
return super.runTaskLaterAsynchronously(plugin, delay);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTaskTimer(final long delay, final long period) {
|
||||
return super.runTaskTimer(plugin, delay, period);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final synchronized BukkitTask runTaskTimerAsynchronously(final long delay, final long period) {
|
||||
return super.runTaskTimerAsynchronously(plugin, delay, period);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.willfp.eco.internal.scheduling;
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin;
|
||||
import com.willfp.eco.core.PluginDependent;
|
||||
import com.willfp.eco.core.scheduling.Scheduler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EcoScheduler extends PluginDependent<EcoPlugin> implements Scheduler {
|
||||
@ApiStatus.Internal
|
||||
public EcoScheduler(@NotNull final EcoPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitTask runLater(@NotNull final Runnable runnable,
|
||||
final long ticksLater) {
|
||||
return Bukkit.getScheduler().runTaskLater(this.getPlugin(), runnable, ticksLater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitTask runTimer(@NotNull final Runnable runnable,
|
||||
final long delay,
|
||||
final long repeat) {
|
||||
return Bukkit.getScheduler().runTaskTimer(this.getPlugin(), runnable, delay, repeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitTask runAsyncTimer(@NotNull final Runnable runnable,
|
||||
final long delay,
|
||||
final long repeat) {
|
||||
return Bukkit.getScheduler().runTaskTimerAsynchronously(this.getPlugin(), runnable, delay, repeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitTask run(@NotNull final Runnable runnable) {
|
||||
return Bukkit.getScheduler().runTask(this.getPlugin(), runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitTask runAsync(@NotNull final Runnable runnable) {
|
||||
return Bukkit.getScheduler().runTaskAsynchronously(this.getPlugin(), runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int syncRepeating(@NotNull final Runnable runnable,
|
||||
final long delay,
|
||||
final long repeat) {
|
||||
return Bukkit.getScheduler().scheduleSyncRepeatingTask(this.getPlugin(), runnable, delay, repeat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAll() {
|
||||
Bukkit.getScheduler().cancelTasks(this.getPlugin());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.willfp.eco.internal
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.proxy.Cleaner
|
||||
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||
import java.net.URLClassLoader
|
||||
|
||||
class EcoCleaner: Cleaner {
|
||||
override fun clean(plugin: EcoPlugin) {
|
||||
if (plugin.proxyPackage.isNotEmpty()) {
|
||||
val factory = plugin.proxyFactory as EcoProxyFactory
|
||||
factory.clean()
|
||||
}
|
||||
|
||||
Plugins.LOADED_ECO_PLUGINS.remove(plugin.name.lowercase())
|
||||
|
||||
for (customItem in Items.getCustomItems()) {
|
||||
if (customItem.key.namespace.equals(plugin.name.lowercase(), ignoreCase = true)) {
|
||||
Items.removeCustomItem(customItem.key)
|
||||
}
|
||||
}
|
||||
|
||||
val classLoader = plugin::class.java.classLoader
|
||||
|
||||
if (classLoader is URLClassLoader) {
|
||||
classLoader.close()
|
||||
}
|
||||
|
||||
System.gc()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.willfp.eco.internal
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
|
||||
object Plugins {
|
||||
val LOADED_ECO_PLUGINS = HashMap<String, EcoPlugin>()
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.willfp.eco.internal.config
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig
|
||||
import com.willfp.eco.core.config.wrapper.ConfigFactory
|
||||
import com.willfp.eco.internal.config.json.EcoJSONConfigSection
|
||||
import com.willfp.eco.internal.config.json.EcoLoadableJSONConfig
|
||||
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
|
||||
|
||||
class EcoConfigFactory : ConfigFactory {
|
||||
override fun createUpdatableYamlConfig(
|
||||
configName: String,
|
||||
plugin: EcoPlugin,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>,
|
||||
removeUnused: Boolean,
|
||||
vararg updateBlacklist: String
|
||||
): Config {
|
||||
return EcoUpdatableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source,
|
||||
removeUnused,
|
||||
*updateBlacklist
|
||||
)
|
||||
}
|
||||
|
||||
override fun createLoadableJSONConfig(
|
||||
configName: String,
|
||||
plugin: EcoPlugin,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>
|
||||
): JSONConfig {
|
||||
return EcoLoadableJSONConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
)
|
||||
}
|
||||
|
||||
override fun createLoadableYamlConfig(
|
||||
configName: String,
|
||||
plugin: EcoPlugin,
|
||||
subDirectoryPath: String,
|
||||
source: Class<*>
|
||||
): Config {
|
||||
return EcoLoadableYamlConfig(
|
||||
configName,
|
||||
plugin,
|
||||
subDirectoryPath,
|
||||
source
|
||||
)
|
||||
}
|
||||
|
||||
override fun createYamlConfig(config: YamlConfiguration): Config {
|
||||
return EcoYamlConfigSection(config)
|
||||
}
|
||||
|
||||
override fun createJSONConfig(values: Map<String, Any>): JSONConfig {
|
||||
return EcoJSONConfigSection(values)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
class EcoJSONConfigSection(values: Map<String, Any?>) : EcoJSONConfigWrapper() {
|
||||
init {
|
||||
init(values)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.willfp.eco.core.config.interfaces.JSONConfig
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.apache.commons.lang.Validate
|
||||
import java.util.*
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
open class EcoJSONConfigWrapper : JSONConfig {
|
||||
val handle: Gson = GsonBuilder().setPrettyPrinting().create()
|
||||
|
||||
val values = mutableMapOf<String, Any?>()
|
||||
|
||||
private val cache = mutableMapOf<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 this.handle.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 {
|
||||
val subsection = getSubsectionOrNull(path)
|
||||
Validate.notNull(subsection)
|
||||
return subsection!!
|
||||
}
|
||||
|
||||
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 getSubsections(path: String): List<JSONConfig> {
|
||||
val subsections = getSubsectionsOrNull(path)
|
||||
return subsections ?: mutableListOf()
|
||||
}
|
||||
|
||||
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 getInt(path: String): Int {
|
||||
return (getOfKnownType(path, Double::class.java) ?: 0.0).toInt()
|
||||
}
|
||||
|
||||
override fun getIntOrNull(path: String): Int? {
|
||||
return if (has(path)) {
|
||||
getInt(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInt(
|
||||
path: String,
|
||||
def: Int
|
||||
): Int {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Int::class.java), def)
|
||||
}
|
||||
|
||||
override fun getInts(path: String): MutableList<Int> {
|
||||
return (Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), emptyList<Int>()) as List<Int>).toMutableList()
|
||||
}
|
||||
|
||||
override fun getIntsOrNull(path: String): MutableList<Int>? {
|
||||
return if (has(path)) {
|
||||
getInts(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBool(path: String): Boolean {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Boolean::class.java), false)
|
||||
}
|
||||
|
||||
override fun getBoolOrNull(path: String): Boolean? {
|
||||
return if (has(path)) {
|
||||
getBool(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBools(path: String): MutableList<Boolean> {
|
||||
return (Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), emptyList<Boolean>()) as List<Boolean>).toMutableList()
|
||||
}
|
||||
|
||||
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
|
||||
return if (has(path)) {
|
||||
getBools(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getString(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String {
|
||||
val string = getOfKnownType(path, String::class.java) ?: ""
|
||||
return if (format) StringUtils.format(string, option) else string
|
||||
}
|
||||
|
||||
override fun getStringOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String? {
|
||||
return if (has(path)) {
|
||||
getString(path, format, option)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStrings(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String> {
|
||||
val strings =
|
||||
(Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), emptyList<String>()) as List<String>).toMutableList()
|
||||
return if (format) StringUtils.formatList(strings, option) else strings
|
||||
}
|
||||
|
||||
override fun getStringsOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String>? {
|
||||
return if (has(path)) {
|
||||
getStrings(path, format, option)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDouble(path: String): Double {
|
||||
return Objects.requireNonNullElse(getOfKnownType(path, Double::class.java), 0.0)
|
||||
}
|
||||
|
||||
override fun getDoubleOrNull(path: String): Double? {
|
||||
return if (has(path)) {
|
||||
getDouble(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoubles(path: String): MutableList<Double> {
|
||||
return (Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), emptyList<Double>()) as List<Double>).toMutableList()
|
||||
}
|
||||
|
||||
override fun getDoublesOrNull(path: String): MutableList<Double>? {
|
||||
return if (has(path)) {
|
||||
getDoubles(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun clone(): JSONConfig {
|
||||
return EcoJSONConfigSection(HashMap<String, Any>(this.values))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.willfp.eco.internal.config.json
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import java.io.*
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardOpenOption
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class EcoLoadableJSONConfig(
|
||||
configName: String,
|
||||
private val plugin: EcoPlugin,
|
||||
private val subDirectoryPath: String,
|
||||
private val source: Class<*>
|
||||
) : EcoJSONConfigWrapper(), LoadableConfig {
|
||||
|
||||
private val configFile: File
|
||||
private val name: String = "$configName.json"
|
||||
|
||||
fun reloadFromFile() {
|
||||
try {
|
||||
init(configFile)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
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, 1024)
|
||||
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() {
|
||||
if (configFile.delete()) {
|
||||
Files.write(
|
||||
configFile.toPath(),
|
||||
toPlaintext().toByteArray(),
|
||||
StandardOpenOption.CREATE,
|
||||
StandardOpenOption.WRITE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(FileNotFoundException::class)
|
||||
fun init(file: File) {
|
||||
super.init(handle.fromJson(FileReader(file), Map::class.java) as @NotNull MutableMap<String, Any>)
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return name
|
||||
}
|
||||
|
||||
override fun getConfigFile(): File {
|
||||
return configFile
|
||||
}
|
||||
|
||||
init {
|
||||
val directory: File = File(this.plugin.dataFolder, subDirectoryPath)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
if (!File(directory, name).exists()) {
|
||||
createFile()
|
||||
}
|
||||
configFile = File(directory, name)
|
||||
try {
|
||||
init(configFile)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
plugin.configHandler.addConfig(this)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.willfp.eco.internal.config.updating
|
||||
|
||||
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.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
|
||||
import java.lang.reflect.Modifier
|
||||
|
||||
class EcoConfigHandler(
|
||||
private val plugin: EcoPlugin
|
||||
) : ConfigHandler {
|
||||
private val reflections: Reflections = Reflections(
|
||||
this.plugin::class.java.classLoader,
|
||||
MethodAnnotationsScanner()
|
||||
)
|
||||
|
||||
private val configs = mutableListOf<LoadableConfig>()
|
||||
|
||||
override fun callUpdate() {
|
||||
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
|
||||
if (!Modifier.isStatic(method.modifiers)) {
|
||||
throw InvalidUpdateMethodException("Update method in ${method.declaringClass.name} must be static.")
|
||||
}
|
||||
|
||||
try {
|
||||
when (method.parameterCount) {
|
||||
0 -> method.invoke(null)
|
||||
1 -> method.invoke(null, this.plugin)
|
||||
else -> throw InvalidUpdateMethodException("Update method must have 0 parameters or a plugin parameter.")
|
||||
}
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
e.printStackTrace()
|
||||
throw InvalidUpdateMethodException("Update method generated an exception")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveAllConfigs() {
|
||||
for (config in configs) {
|
||||
config.save()
|
||||
}
|
||||
}
|
||||
|
||||
override fun addConfig(config: LoadableConfig) {
|
||||
configs.add(config)
|
||||
}
|
||||
|
||||
override fun updateConfigs() {
|
||||
for (config in configs) {
|
||||
when (config) {
|
||||
is EcoUpdatableYamlConfig -> config.update()
|
||||
is EcoLoadableYamlConfig -> config.reloadFromFile()
|
||||
is EcoLoadableJSONConfig -> config.reloadFromFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.willfp.eco.internal.config.updating.exceptions
|
||||
|
||||
class InvalidUpdateMethodException(message: String) : RuntimeException(message)
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.LoadableConfig
|
||||
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
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: EcoPlugin,
|
||||
private val subDirectoryPath: String,
|
||||
val source: Class<*>
|
||||
) : EcoYamlConfigWrapper<YamlConfiguration>(), WrappedYamlConfiguration, LoadableConfig {
|
||||
|
||||
private val configFile: File
|
||||
private val name: String = "$configName.yml"
|
||||
|
||||
fun reloadFromFile() {
|
||||
try {
|
||||
handle.load(getConfigFile())
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
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, 1024)
|
||||
out.close()
|
||||
inputStream.close()
|
||||
}
|
||||
plugin.configHandler.addConfig(this)
|
||||
}
|
||||
|
||||
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 getBukkitHandle(): YamlConfiguration {
|
||||
return handle
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
return name
|
||||
}
|
||||
|
||||
override fun getConfigFile(): File {
|
||||
return configFile
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import org.bukkit.configuration.InvalidConfigurationException
|
||||
import org.bukkit.configuration.file.YamlConfiguration
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
class EcoUpdatableYamlConfig(
|
||||
configName: String,
|
||||
plugin: EcoPlugin,
|
||||
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()
|
||||
try {
|
||||
this.handle.load(configFile)
|
||||
val newConfig = configInJar
|
||||
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
|
||||
return
|
||||
}
|
||||
newConfig.getKeys(true).forEach { key: String ->
|
||||
if (!this.handle.getKeys(true).contains(key)) {
|
||||
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) {
|
||||
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)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private val configInJar: YamlConfiguration
|
||||
get() {
|
||||
val newIn = source.getResourceAsStream(resourcePath) ?: throw NullPointerException("$name is null?")
|
||||
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
|
||||
val newConfig = YamlConfiguration()
|
||||
try {
|
||||
newConfig.load(reader)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: InvalidConfigurationException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return newConfig
|
||||
}
|
||||
|
||||
init {
|
||||
this.updateBlacklist.removeIf { obj: String -> obj.isEmpty() }
|
||||
plugin.configHandler.addConfig(this)
|
||||
update()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
|
||||
class EcoYamlConfigSection(section: ConfigurationSection) : EcoYamlConfigWrapper<ConfigurationSection>() {
|
||||
init {
|
||||
init(section)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
package com.willfp.eco.internal.config.yaml
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.apache.commons.lang.Validate
|
||||
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 getSubsection(path: String): Config {
|
||||
val subsection = getSubsectionOrNull(path)
|
||||
Validate.notNull(subsection)
|
||||
return subsection!!
|
||||
}
|
||||
|
||||
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 getInt(path: String): Int {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Int
|
||||
} else {
|
||||
cache[path] = handle.getInt(path, 0)
|
||||
getInt(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIntOrNull(path: String): Int? {
|
||||
return if (has(path)) {
|
||||
getInt(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInt(
|
||||
path: String,
|
||||
def: Int
|
||||
): Int {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Int
|
||||
} else {
|
||||
cache[path] = handle.getInt(path, def)
|
||||
getInt(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInts(path: String): MutableList<Int> {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as MutableList<Int>).toMutableList()
|
||||
} else {
|
||||
cache[path] = if (has(path)) ArrayList(handle.getIntegerList(path)) else mutableListOf<Int>()
|
||||
getInts(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIntsOrNull(path: String): MutableList<Int>? {
|
||||
return if (has(path)) {
|
||||
getInts(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBool(path: String): Boolean {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Boolean
|
||||
} else {
|
||||
cache[path] = handle.getBoolean(path)
|
||||
getBool(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBoolOrNull(path: String): Boolean? {
|
||||
return if (has(path)) {
|
||||
getBool(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBools(path: String): MutableList<Boolean> {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as MutableList<Boolean>).toMutableList()
|
||||
} else {
|
||||
cache[path] =
|
||||
if (has(path)) ArrayList(handle.getBooleanList(path)) else mutableListOf<Boolean>()
|
||||
getBools(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
|
||||
return if (has(path)) {
|
||||
getBools(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getString(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): String? {
|
||||
return if (has(path)) {
|
||||
getString(path, format, option)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStrings(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringsOrNull(
|
||||
path: String,
|
||||
format: Boolean,
|
||||
option: StringUtils.FormatOption
|
||||
): MutableList<String>? {
|
||||
return if (has(path)) {
|
||||
getStrings(path, format, option)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDouble(path: String): Double {
|
||||
return if (cache.containsKey(path)) {
|
||||
cache[path] as Double
|
||||
} else {
|
||||
cache[path] = handle.getDouble(path)
|
||||
getDouble(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoubleOrNull(path: String): Double? {
|
||||
return if (has(path)) {
|
||||
getDouble(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoubles(path: String): MutableList<Double> {
|
||||
return if (cache.containsKey(path)) {
|
||||
(cache[path] as MutableList<Double>).toMutableList()
|
||||
} else {
|
||||
cache[path] = if (has(path)) ArrayList(handle.getDoubleList(path)) else emptyList<Double>()
|
||||
getDoubles(path)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDoublesOrNull(path: String): MutableList<Double>? {
|
||||
return if (has(path)) {
|
||||
getDoubles(path)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun clone(): Config {
|
||||
return EcoYamlConfigSection(
|
||||
YamlConfiguration.loadConfiguration(
|
||||
StringReader(
|
||||
toPlaintext()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user