Compare commits

..

80 Commits
6.4.1 ... 6.8.0

Author SHA1 Message Date
Auxilor
3341093735 Fixed non-final params 2021-09-17 19:56:54 +01:00
Auxilor
714d04e48f Added missing javadoc 2021-09-17 19:55:29 +01:00
Auxilor
73b7ccea3a Merge branch 'dev'
# Conflicts:
#	gradle.properties
2021-09-17 19:53:40 +01:00
Auxilor
606bf8fcd2 Updated to 6.8.0 2021-09-17 19:53:24 +01:00
Auxilor
fbbf893d64 Added requirements into eco 2021-09-17 19:52:49 +01:00
Auxilor
36001373eb Removed redundant default methods from DisplayHandler 2021-09-16 15:07:37 +01:00
Auxilor
9ac34288eb EcoDisplayHandler.kt changes 2021-09-16 15:04:24 +01:00
Auxilor
6345d1fe92 Moved display impl code off to internals 2021-09-16 14:56:56 +01:00
Auxilor
a7fa0ecf26 Updated to 6.7.5 2021-09-14 08:35:02 +01:00
Auxilor
a65f16cfac Improved PR 2021-09-14 08:34:51 +01:00
Will FP
49965c091b Merge pull request #13
Added silent lightning option
2021-09-14 08:33:38 +01:00
Auxilor
f9bc2aba99 Merge remote-tracking branch 'origin/master' into dev 2021-09-13 12:12:33 +01:00
Auxilor
5627582bd5 Updated to 6.7.4 2021-09-13 10:10:14 +01:00
Auxilor
ab8065d06e Fixed ShopGUIPlus softdepend 2021-09-13 10:09:54 +01:00
Auxilor
444764e481 Fixed ShopGUIPlus integration not working 2021-09-13 10:09:34 +01:00
_OfTeN_
c240e94a6b Removed NPE warning in the console if Oraxen returns null on OraxenItems#getIdByItem 2021-09-12 23:03:04 +03:00
_OfTeN_
9da28a1dff Added boolean silent param to LightningUtils#strike method to make a lightning with sound only played locally for nearest players 2021-09-12 22:45:41 +03:00
Auxilor
cf3c1f8394 Added destructuring support to pairs 2021-09-10 13:48:50 +01:00
Auxilor
f98befbdce Used FastItemStack on display reverting 2021-09-09 13:03:24 +01:00
Auxilor
d0d8ea07e4 Added JSON updatable configs 2021-09-08 10:59:11 +01:00
Auxilor
109347a601 Updated to 6.7.3 2021-09-06 15:07:15 +01:00
Auxilor
43bef762bf Removed buggy headdb integration 2021-09-06 15:07:06 +01:00
Auxilor
69a2e0e247 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	eco-api/src/main/java/com/willfp/eco/core/items/args/EnchantmentArgParser.java
#	eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java
#	eco-api/src/main/java/com/willfp/eco/core/items/args/TextureArgParser.java
2021-09-06 15:05:32 +01:00
Auxilor
874a9b4f32 Updated to 6.7.2 2021-09-05 12:53:33 +01:00
Auxilor
5690221c27 Fixed crafting 2021-09-05 12:53:22 +01:00
Auxilor
f19b143804 Added validation to testable items 2021-09-05 12:02:35 +01:00
Auxilor
10a313bef5 Added missing javadoc 2021-09-05 11:08:05 +01:00
Auxilor
9ae40ae09e Removed redundant nullability 2021-09-05 11:07:15 +01:00
Auxilor
7b4e1d8d24 Updated to 6.7.1 2021-09-05 11:05:33 +01:00
Auxilor
7035280731 Item checks and improvements related to EmptyTestableItem 2021-09-05 11:05:23 +01:00
Auxilor
a1e3d53cd2 Janky HeadDB fix 2021-09-04 16:44:15 +01:00
Auxilor
d7885f05c3 Optimised placeholders 2021-09-04 13:59:46 +01:00
Auxilor
415c425097 Fixed bugs 2021-09-04 11:03:04 +01:00
Auxilor
cb4d992e7d Added option to create custom lang.yml and config.yml implementations 2021-09-04 10:59:49 +01:00
Auxilor
cb64d088d1 Added nullability annotations to all utility methods 2021-09-04 10:53:06 +01:00
Auxilor
bbbf19c041 Added missing javadoc 2021-09-03 13:03:28 +01:00
Auxilor
61ace5c8e5 Updated to 6.7.0 2021-09-03 12:50:23 +01:00
Auxilor
94b73ef35c Improved Arg Parser javadoc 2021-09-03 12:49:59 +01:00
Auxilor
5cfc2068e7 Added arg parser lookup system 2021-09-03 12:47:23 +01:00
Auxilor
0ce7d1dd6c Added texture:<base64> to Items.lookup 2021-09-03 12:28:03 +01:00
Auxilor
19eefaf879 Improved Items.lookup javadoc 2021-09-03 11:54:48 +01:00
Auxilor
1ebf7fb875 Added Head Database integration 2021-09-03 11:45:34 +01:00
Auxilor
e8afd15d80 Updated to 6.6.4 2021-09-02 18:55:49 +01:00
Auxilor
d024c9238e Switched TestableStack display to only show recipe lore in recipes 2021-09-02 18:55:37 +01:00
Auxilor
1356bd1f26 ItemsAdder fix 2021-09-02 18:50:01 +01:00
Auxilor
407ccca5e0 TestableStack changes don't stop ever 2021-09-02 11:49:48 +01:00
Auxilor
82de602d47 Hopefully fixed crafting exploit 2021-09-02 10:53:14 +01:00
Auxilor
b0873112af Added ItemsAdder and Oraxen to plugin.yml 2021-09-02 10:50:40 +01:00
Auxilor
3a0b81b7de Updated to 6.6.3 2021-09-02 10:50:12 +01:00
Auxilor
5142b9ce92 More Items#lookup improvements 2021-09-02 10:46:25 +01:00
Auxilor
9403a1cbcb Marked item:amount system as legacy and replaced it with item amount 2021-09-02 10:42:29 +01:00
Auxilor
e4ebea354d Added ItemsAdder support 2021-09-02 10:35:03 +01:00
Auxilor
d32b31f1e5 Updated to 6.6.2 2021-09-01 15:35:57 +01:00
Auxilor
384657f1dc Fixed menu inventory registration memory leak 2021-09-01 15:35:33 +01:00
Auxilor
7c9d226bc3 Updated to 6.6.1 2021-08-31 14:52:52 +01:00
Auxilor
031401bb8e Added option to lang.yml 2021-08-31 14:52:37 +01:00
Auxilor
1a5c429b67 Fixed villager trade display with players 2021-08-31 14:51:45 +01:00
Auxilor
d028cf5bf3 Added ShopGuiPlus to softdepend 2021-08-29 16:35:16 +01:00
Auxilor
fdd1581ce3 Removed redundant code 2021-08-29 16:34:26 +01:00
Auxilor
3d07e10543 Fixed ItemFlag application 2021-08-29 16:33:31 +01:00
Auxilor
c851e35347 Added ItemFlags to FastItemStack 2021-08-29 16:32:42 +01:00
Auxilor
4cbb33b1fd More code cleanup 2021-08-29 16:03:14 +01:00
Auxilor
2ff1458772 Fixed config wrappers missing methods 2021-08-29 15:56:39 +01:00
Auxilor
e71ad9f034 Updated to 6.6.0 2021-08-29 15:51:49 +01:00
Auxilor
196a651ab3 Added ShopGuiPlus integration 2021-08-29 15:51:38 +01:00
Auxilor
253a8c24ad Improved kotlin codestyle conventions 2021-08-29 15:38:27 +01:00
Auxilor
ac265d0260 Added more formatting options 2021-08-29 15:30:25 +01:00
Auxilor
ad861b10bb Updated to 6.5.2 2021-08-23 17:14:41 +01:00
Auxilor
db5b7f89f6 Fixed null placeholder bug and improved config loading 2021-08-23 17:14:23 +01:00
Auxilor
2c33ce25c0 Merge remote-tracking branch 'origin/master' 2021-08-22 23:14:30 +01:00
Auxilor
9c3ca429c9 Fixed recipe stack bug 2021-08-22 23:14:24 +01:00
Auxilor
70e294501a Fixed enchanted books in Items.lookup modifier 2021-08-21 13:50:33 +01:00
Will FP
65a0a0ecc7 Update README.md 2021-08-21 01:22:16 +01:00
Auxilor
d4431e7569 Changes 2021-08-20 23:02:45 +01:00
Auxilor
a6191b0870 Added data read/write to menu, updated to 6.5.0, removed event deprecation 2021-08-20 22:29:25 +01:00
Auxilor
5eecef83ee Merge remote-tracking branch 'origin/master' 2021-08-20 17:35:34 +01:00
Auxilor
82a02f3738 Updated to 6.4.2 2021-08-20 17:35:30 +01:00
Auxilor
804142799b Fixed NPE 2021-08-20 17:35:20 +01:00
Will FP
e1de9b9ab3 Update README.md 2021-08-18 15:15:50 +01:00
Will FP
cc56343041 Update README.md 2021-08-18 15:15:36 +01:00
98 changed files with 2132 additions and 601 deletions

View File

@@ -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>

View File

@@ -51,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 {

View File

@@ -305,10 +305,27 @@ public abstract class EcoPlugin extends JavaPlugin {
this.logger = Eco.getHandler().createLogger(this);
this.proxyFactory = this.proxyPackage.equalsIgnoreCase("") ? null : Eco.getHandler().createProxyFactory(this);
this.langYml = new LangYml(this);
this.configYml = new ConfigYml(this);
this.langYml = this.createLangYml();
this.configYml = this.createConfigYml();
Eco.getHandler().addNewPlugin(this);
/*
The minimum eco version check was moved here because it's very common
to add a lot of code in the constructor of plugins; meaning that the plugin
can throw errors without it being obvious to the user that the reason is
because they have an outdated version of eco installed.
*/
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.getHandler().getEcoPlugin().getDescription().getVersion());
DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(this.getMinimumEcoVersion());
if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) {
this.getLogger().severe("You are running an outdated version of eco!");
this.getLogger().severe("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this);
}
}
/**
@@ -336,29 +353,22 @@ public abstract class EcoPlugin extends JavaPlugin {
});
}
DefaultArtifactVersion runningVersion = new DefaultArtifactVersion(Eco.getHandler().getEcoPlugin().getDescription().getVersion());
DefaultArtifactVersion requiredVersion = new DefaultArtifactVersion(this.getMinimumEcoVersion());
if (!(runningVersion.compareTo(requiredVersion) > 0 || runningVersion.equals(requiredVersion))) {
this.getLogger().severe("You are running an outdated version of eco!");
this.getLogger().severe("You must be on at least" + this.getMinimumEcoVersion());
this.getLogger().severe("Download the newest version here:");
this.getLogger().severe("https://polymart.org/download/773/recent/JSpprMspkuyecf5y1wQ2Jn8OoLQSQ_IW");
Bukkit.getPluginManager().disablePlugin(this);
}
if (this.getBStatsId() != 0) {
Eco.getHandler().registerBStats(this);
}
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins())
.map(Plugin::getName)
.map(String::toLowerCase)
.collect(Collectors.toSet());
if (enabledPlugins.contains("PlaceholderAPI")) {
if (enabledPlugins.contains("PlaceholderAPI".toLowerCase())) {
this.loadedIntegrations.add("PlaceholderAPI");
PlaceholderManager.addIntegration(Eco.getHandler().createPAPIIntegration(this));
}
this.loadIntegrationLoaders().forEach((integrationLoader -> {
if (enabledPlugins.contains(integrationLoader.getPluginName())) {
if (enabledPlugins.contains(integrationLoader.getPluginName().toLowerCase())) {
this.loadedIntegrations.add(integrationLoader.getPluginName());
integrationLoader.load();
}
@@ -571,6 +581,28 @@ public abstract class EcoPlugin extends JavaPlugin {
*/
protected abstract List<Listener> loadListeners();
/**
* Useful for custom LangYml implementations.
* <p>
* Override if needed.
*
* @return lang.yml.
*/
protected LangYml createLangYml() {
return new LangYml(this);
}
/**
* Useful for custom ConfigYml implementations.
* <p>
* Override if needed.
*
* @return config.yml.
*/
protected ConfigYml createConfigYml() {
return new ConfigYml(this);
}
/**
* Create the display module for the plugin.
*

View File

@@ -13,9 +13,11 @@ 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.requirement.RequirementFactory;
import com.willfp.eco.core.scheduling.Scheduler;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.logging.Logger;
@@ -30,6 +32,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The scheduler.
*/
@NotNull
Scheduler createScheduler(@NotNull EcoPlugin plugin);
/**
@@ -38,6 +41,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The event manager.
*/
@NotNull
EventManager createEventManager(@NotNull EcoPlugin plugin);
/**
@@ -46,6 +50,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The factory.
*/
@NotNull
NamespacedKeyFactory createNamespacedKeyFactory(@NotNull EcoPlugin plugin);
/**
@@ -54,6 +59,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The factory.
*/
@NotNull
MetadataValueFactory createMetadataValueFactory(@NotNull EcoPlugin plugin);
/**
@@ -62,6 +68,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The factory.
*/
@NotNull
RunnableFactory createRunnableFactory(@NotNull EcoPlugin plugin);
/**
@@ -70,6 +77,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The factory.
*/
@NotNull
ExtensionLoader createExtensionLoader(@NotNull EcoPlugin plugin);
/**
@@ -78,6 +86,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The handler.
*/
@NotNull
ConfigHandler createConfigHandler(@NotNull EcoPlugin plugin);
/**
@@ -86,6 +95,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The logger.
*/
@NotNull
Logger createLogger(@NotNull EcoPlugin plugin);
/**
@@ -94,6 +104,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The integration.
*/
@NotNull
PlaceholderIntegration createPAPIIntegration(@NotNull EcoPlugin plugin);
/**
@@ -102,6 +113,7 @@ public interface Handler {
* @param plugin The plugin.
* @return The factory.
*/
@NotNull
ProxyFactory createProxyFactory(@NotNull EcoPlugin plugin);
/**
@@ -109,6 +121,7 @@ public interface Handler {
*
* @return The plugin.
*/
@NotNull
EcoPlugin getEcoPlugin();
/**
@@ -116,6 +129,7 @@ public interface Handler {
*
* @return The factory.
*/
@NotNull
ConfigFactory getConfigFactory();
/**
@@ -123,6 +137,7 @@ public interface Handler {
*
* @return The factory.
*/
@NotNull
DropQueueFactory getDropQueueFactory();
/**
@@ -130,6 +145,7 @@ public interface Handler {
*
* @return The factory.
*/
@NotNull
GUIFactory getGUIFactory();
/**
@@ -137,6 +153,7 @@ public interface Handler {
*
* @return The cleaner.
*/
@NotNull
Cleaner getCleaner();
/**
@@ -152,6 +169,7 @@ public interface Handler {
* @param name The name.
* @return The plugin.
*/
@Nullable
EcoPlugin getPluginByName(@NotNull String name);
/**
@@ -159,6 +177,7 @@ public interface Handler {
*
* @return A list of plugin names in lowercase.
*/
@NotNull
List<String> getLoadedPlugins();
/**
@@ -167,6 +186,7 @@ public interface Handler {
* @param itemStack The base ItemStack.
* @return The FastItemStack.
*/
@NotNull
FastItemStack createFastItemStack(@NotNull ItemStack itemStack);
/**
@@ -175,4 +195,11 @@ public interface Handler {
* @param plugin The plugin.
*/
void registerBStats(@NotNull EcoPlugin plugin);
/**
* Get the requirement factory.
*
* @return The factory.
*/
RequirementFactory getRequirementFactory();
}

View File

@@ -9,11 +9,12 @@ import org.jetbrains.annotations.NotNull;
*
* @param <T> The eco plugin type.
*/
public abstract class PluginDependent<T extends EcoPlugin> {
public abstract class PluginDependent<@NotNull T extends EcoPlugin> {
/**
* The {@link EcoPlugin} that is stored.
*/
@Getter(AccessLevel.PROTECTED)
@NotNull
private final T plugin;
/**

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -0,0 +1,54 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in the plugin's base directory (eg config.json).
* <p>
* Automatically updates.
*/
public abstract class JSONBaseConfig extends LoadableJSONConfigWrapper {
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
*/
protected JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused, updateBlacklist
)
);
}
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
*/
protected JSONBaseConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
"",
plugin.getClass(),
removeUnused
)
);
}
}

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.core.config.json;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.eco.core.config.json.wrapper.LoadableJSONConfigWrapper;
import com.willfp.eco.core.config.yaml.wrapper.LoadableYamlConfigWrapper;
import org.jetbrains.annotations.NotNull;
/**
* Config implementation for configs present in one of two places:
* <ul>
* <li>Plugin base directory (eg config.yml, lang.yml)</li>
* <li>Other extension's configs</li>
* </ul>
* <p>
* Automatically updates.
*/
public abstract class JSONExtendableConfig extends LoadableJSONConfigWrapper {
/**
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param plugin The plugin.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
*/
protected JSONExtendableConfig(@NotNull final String configName,
final boolean removeUnused,
@NotNull final EcoPlugin plugin,
@NotNull final Class<?> source,
@NotNull final String subDirectoryPath,
@NotNull final String... updateBlacklist) {
super(
Eco.getHandler().getConfigFactory().createUpdatableJSONConfig(
configName,
plugin,
subDirectoryPath,
source,
removeUnused,
updateBlacklist
)
);
}
}

View File

@@ -30,6 +30,24 @@ public interface ConfigFactory {
boolean removeUnused,
@NotNull String... updateBlacklist);
/**
* Updatable config.
*
* @param configName The name of the config
* @param plugin The plugin.
* @param subDirectoryPath The subdirectory path.
* @param source The class that owns the resource.
* @param removeUnused Whether keys not present in the default config should be removed on update.
* @param updateBlacklist Substring of keys to not add/remove keys for.
* @return The config implementation.
*/
JSONConfig createUpdatableJSONConfig(@NotNull String configName,
@NotNull EcoPlugin plugin,
@NotNull String subDirectoryPath,
@NotNull Class<?> source,
boolean removeUnused,
@NotNull String... updateBlacklist);
/**
* JSON loadable config.
*

View File

@@ -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

View File

@@ -1,22 +1,12 @@
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;
import java.util.List;
import java.util.Map;
/**
* Utility class to manage client-side item display.
*/
@@ -28,29 +18,9 @@ public class Display {
public static final String PREFIX = "§z";
/**
* All registered display modules.
* The display handler.
*/
private static final Map<DisplayPriority, List<DisplayModule>> MODULES = new HashMap<>();
/**
* NamespacedKey for finalizing.
*/
private static NamespacedKey finalizeKey = null;
/**
* Register display module.
*
* @param module The module.
*/
public void registerDisplayModule(@NotNull final DisplayModule module) {
List<DisplayModule> modules = MODULES.get(module.getPriority());
modules.removeIf(module1 -> module1.getPluginName().equalsIgnoreCase(module.getPluginName()));
modules.add(module);
MODULES.put(module.getPriority(), modules);
}
public static DisplayHandler handler = null;
/**
* Display on ItemStacks.
@@ -71,35 +41,7 @@ public class Display {
*/
public ItemStack display(@NotNull final ItemStack itemStack,
@Nullable final Player player) {
Map<String, Object[]> pluginVarArgs = new HashMap<>();
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
pluginVarArgs.put(module.getPluginName(), module.generateVarArgs(itemStack));
}
}
revert(itemStack);
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
Object[] varargs = pluginVarArgs.get(module.getPluginName());
module.display(itemStack, varargs);
if (player != null) {
module.display(itemStack, player, varargs);
}
}
}
return itemStack;
return handler.display(itemStack, player);
}
/**
@@ -131,31 +73,7 @@ public class Display {
* @return The ItemStack.
*/
public ItemStack revert(@NotNull final ItemStack itemStack) {
if (Display.isFinalized(itemStack)) {
unfinalize(itemStack);
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
List<String> lore = meta.getLore();
if (lore != null && lore.removeIf(line -> line.startsWith(Display.PREFIX))) { // only apply lore modification if needed
meta.setLore(lore);
itemStack.setItemMeta(meta);
}
for (DisplayPriority priority : DisplayPriority.values()) {
List<DisplayModule> modules = MODULES.get(priority);
for (DisplayModule module : modules) {
module.revert(itemStack);
}
}
return itemStack;
return handler.revert(itemStack);
}
/**
@@ -165,21 +83,7 @@ public class Display {
* @return The ItemStack.
*/
public ItemStack finalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!");
if (itemStack.getType().getMaxStackSize() > 1) {
return itemStack;
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
container.set(finalizeKey, PersistentDataType.INTEGER, 1);
itemStack.setItemMeta(meta);
return itemStack;
return handler.finalize(itemStack);
}
/**
@@ -189,18 +93,7 @@ public class Display {
* @return The ItemStack.
*/
public ItemStack unfinalize(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!");
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return itemStack;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
container.remove(finalizeKey);
itemStack.setItemMeta(meta);
return itemStack;
return handler.unfinalize(itemStack);
}
/**
@@ -210,31 +103,62 @@ public class Display {
* @return If finalized.
*/
public boolean isFinalized(@NotNull final ItemStack itemStack) {
Validate.notNull(finalizeKey, "Key cannot be null!");
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return false;
}
PersistentDataContainer container = meta.getPersistentDataContainer();
return container.has(finalizeKey, PersistentDataType.INTEGER);
return handler.isFinalized(itemStack);
}
/**
* Set key to be used for finalization.
* Register a new display module.
*
* @param finalizeKey The key.
* @param module The module.
*/
@ApiStatus.Internal
public static void setFinalizeKey(@NotNull final NamespacedKey finalizeKey) {
Display.finalizeKey = finalizeKey;
public void registerDisplayModule(@NotNull final DisplayModule module) {
handler.registerDisplayModule(module);
}
static {
for (DisplayPriority priority : DisplayPriority.values()) {
MODULES.put(priority, new ArrayList<>());
/**
* Initialize the display system.
*
* @param handler The handler.
*/
@ApiStatus.Internal
public static void init(@NotNull final DisplayHandler handler) {
if (Display.handler != null) {
throw new IllegalArgumentException("Already Initialized!");
}
Display.handler = handler;
}
/**
* Extremely janky method - also internal, so don't use it. <b>This method is
* NOT part of the API and may be removed at any time!</b>
* <p>
* This calls a display module with the specified parameters, now
* you might ask why I need a static java method when the DisplayHandler
* implementation could just call it itself? Well, kotlin doesn't really
* like dealing with vararg ambiguity, and so while kotlin can't figure out
* what is and isn't a vararg when I call display with a player, java can.
* <p>
* Because of this, I need to have this part of the code in java.
*
* <b>Don't call this method as part of your plugins!</b>
* <p>
* No, seriously - don't. This skips a bunch of checks and you'll almost
* definitely break something.
*
* @param module The display module.
* @param itemStack The ItemStack.
* @param player The player.
* @param args The args.
*/
@SuppressWarnings("checkstyle:FinalParameters")
@ApiStatus.Internal
public static void callDisplayModule(@NotNull final DisplayModule module,
@NotNull final ItemStack itemStack,
@Nullable final Player player,
@NotNull final Object... args) {
module.display(itemStack, args);
if (player != null) {
module.display(itemStack, player, args);
}
}
}

View File

@@ -0,0 +1,60 @@
package com.willfp.eco.core.display;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Interface for display implementations.
*/
public interface DisplayHandler {
/**
* Register display module.
*
* @param module The module.
*/
void registerDisplayModule(@NotNull DisplayModule module);
/**
* Display on ItemStacks.
*
* @param itemStack The item.
* @param player The player.
* @return The ItemStack.
*/
ItemStack display(@NotNull final ItemStack itemStack,
@Nullable final Player player);
/**
* Revert on ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack revert(@NotNull final ItemStack itemStack);
/**
* Finalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack finalize(@NotNull final ItemStack itemStack);
/**
* Unfinalize an ItemStacks.
*
* @param itemStack The item.
* @return The ItemStack.
*/
ItemStack unfinalize(@NotNull final ItemStack itemStack);
/**
* If an item is finalized.
*
* @param itemStack The item.
* @return If finalized.
*/
boolean isFinalized(@NotNull final ItemStack itemStack);
}

View File

@@ -36,8 +36,8 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @param itemStack The item.
* @param args Optional args for display.
*/
protected void display(@NotNull final ItemStack itemStack,
@NotNull final Object... args) {
public void display(@NotNull final ItemStack itemStack,
@NotNull final Object... args) {
// Technically optional.
}
@@ -48,9 +48,9 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @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) {
public void display(@NotNull final ItemStack itemStack,
@Nullable final Player player,
@NotNull final Object... args) {
// Technically optional.
}
@@ -59,7 +59,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
*
* @param itemStack The item.
*/
protected void revert(@NotNull final ItemStack itemStack) {
public void revert(@NotNull final ItemStack itemStack) {
// Technically optional.
}
@@ -69,7 +69,7 @@ public abstract class DisplayModule extends PluginDependent<EcoPlugin> {
* @param itemStack The itemStack.
* @return The plugin-specific varargs.
*/
protected Object[] generateVarArgs(@NotNull final ItemStack itemStack) {
public Object[] generateVarArgs(@NotNull final ItemStack itemStack) {
return new Object[0];
}

View File

@@ -16,7 +16,6 @@ import org.jetbrains.annotations.NotNull;
*
* @see ArmorChangeEvent
*/
@Deprecated
public class ArmorEquipEvent extends PlayerEvent {
/**
* Bukkit parity.

View File

@@ -3,6 +3,7 @@ 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;
@@ -10,6 +11,7 @@ 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.
@@ -51,17 +53,47 @@ public interface FastItemStack {
/**
* Set the rework penalty.
*
* @param cost The rework penalty to set.
* @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.
*

View File

@@ -2,12 +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}.
@@ -55,6 +59,43 @@ public interface Menu {
*/
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.
*

View File

@@ -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.
*

View File

@@ -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;

View File

@@ -5,7 +5,9 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@@ -18,7 +20,7 @@ public class PlaceholderManager {
/**
* All registered placeholders.
*/
private static final Set<PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashSet<>();
private static final Map<String, PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashMap<>();
/**
* All registered placeholder integrations.
@@ -41,8 +43,8 @@ public class PlaceholderManager {
* @param expansion The {@link PlaceholderEntry} to register.
*/
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
REGISTERED_PLACEHOLDERS.removeIf(placeholderEntry -> placeholderEntry.getIdentifier().equalsIgnoreCase(expansion.getIdentifier()));
REGISTERED_PLACEHOLDERS.add(expansion);
REGISTERED_PLACEHOLDERS.remove(expansion.getIdentifier());
REGISTERED_PLACEHOLDERS.put(expansion.getIdentifier(), expansion);
}
/**
@@ -54,14 +56,15 @@ public class PlaceholderManager {
*/
public static String getResult(@Nullable final Player player,
@NotNull final String identifier) {
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
if (matching.isEmpty()) {
return null;
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.get(identifier.toLowerCase());
if (entry == null) {
return "";
}
PlaceholderEntry entry = matching.get();
if (player == null && entry.requiresPlayer()) {
return "";
}
return entry.getResult(player);
}
@@ -74,8 +77,10 @@ public class PlaceholderManager {
*/
public static String translatePlaceholders(@NotNull final String text,
@Nullable final Player player) {
AtomicReference<String> translatedReference = new AtomicReference<>(text);
REGISTERED_INTEGRATIONS.forEach(placeholderIntegration -> translatedReference.set(placeholderIntegration.translate(translatedReference.get(), player)));
return translatedReference.get();
String processed = text;
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
processed = integration.translate(processed, player);
}
return processed;
}
}

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.core.integrations.shop;
import com.willfp.eco.core.integrations.Integration;
/**
* Wrapper class for shop integrations.
*/
public interface ShopWrapper extends Integration {
/**
* Register eco item provider for shop plugins.
*/
void registerEcoProvider();
}

View File

@@ -1,6 +1,9 @@
package com.willfp.eco.core.items;
import com.willfp.eco.core.Eco;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -47,6 +50,12 @@ public class CustomItem implements TestableItem {
this.key = key;
this.test = test;
this.item = item;
Eco.getHandler().getEcoPlugin().getScheduler().runLater(() -> {
if (!matches(getItem())) {
Bukkit.getLogger().severe("Item with key " + key + " is invalid!");
}
}, 1);
}
@Override

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.core.items;
import com.willfp.eco.core.items.builder.ItemBuilder;
import com.willfp.eco.core.items.builder.ItemStackBuilder;
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;
@@ -10,16 +9,19 @@ import com.willfp.eco.util.NamespacedKeyUtils;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
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.Arrays;
import java.util.HashMap;
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.
@@ -29,19 +31,33 @@ 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) {
REGISTRY.put(key, part);
}
/**
* Register a new arg parser.
*
* @param parser The parser.
*/
public void registerArgParser(@NotNull final LookupArgParser parser) {
ARG_PARSERS.add(parser);
}
/**
* Remove an item.
*
@@ -52,12 +68,27 @@ public final class Items {
}
/**
* Lookup item from string.
* This is the backbone of the entire eco item system.
* <p>
* Used for recipes.
* 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 string to test.
* @return The found testable item, or an empty item if not found.
* @param key The lookup string.
* @return The testable item, or an {@link EmptyTestableItem}.
*/
public TestableItem lookup(@NotNull final String key) {
if (key.contains("?")) {
@@ -79,6 +110,8 @@ public final class Items {
TestableItem item = null;
int stackAmount = 1;
String[] split = args[0].toLowerCase().split(":");
if (split.length == 1) {
@@ -92,71 +125,87 @@ public final class Items {
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();
}
item = new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1]));
item = new MaterialTestableItem(material);
stackAmount = Integer.parseInt(split[1]);
} else {
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]));
item = part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2]));
if (part == null) {
return new EmptyTestableItem();
}
item = part;
stackAmount = Integer.parseInt(split[2]);
}
boolean usingNewStackFormat = false;
if (args.length >= 2) {
try {
stackAmount = Integer.parseInt(args[1]);
usingNewStackFormat = true;
} catch (NumberFormatException ignored) {
}
}
// Marked as redundant but i am covering all bases here
if (item == null || item instanceof EmptyTestableItem) {
return new EmptyTestableItem();
}
String[] enchantArgs = Arrays.copyOfRange(args, 1, args.length);
ItemStack example = item.getItem();
ItemMeta meta = example.getItemMeta();
assert meta != null;
Map<Enchantment, Integer> requiredEnchantments = new HashMap<>();
String[] modifierArgs = Arrays.copyOfRange(args, usingNewStackFormat ? 2 : 1, args.length);
for (String enchantArg : enchantArgs) {
String[] enchantArgSplit = enchantArg.split(":");
List<Predicate<ItemStack>> predicates = new ArrayList<>();
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase()));
int level = Integer.parseInt(enchantArgSplit[1]);
requiredEnchantments.put(enchantment, level);
for (LookupArgParser argParser : ARG_PARSERS) {
Predicate<ItemStack> predicate = argParser.parseArguments(modifierArgs, meta);
if (predicate != null) {
predicates.add(argParser.parseArguments(modifierArgs, meta));
}
}
if (requiredEnchantments.isEmpty()) {
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);
}
ItemBuilder builder = new ItemStackBuilder(item.getItem());
requiredEnchantments.forEach(builder::addEnchantment);
ItemStack example = builder.build();
return new ModifiedTestableItem(
item,
itemStack -> {
if (!itemStack.hasItemMeta()) {
return false;
}
ItemMeta meta = itemStack.getItemMeta();
assert meta != null;
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
if (!meta.hasEnchant(entry.getKey())) {
return false;
}
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
return false;
}
}
return true;
},
example
);
}
/**
@@ -174,6 +223,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.
*

View File

@@ -0,0 +1,83 @@
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 org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
/**
* Parses enchantment arguments.
*/
public class EnchantmentArgParser implements LookupArgParser {
@Override
public @Nullable 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 (requiredEnchantments.isEmpty()) {
return null;
}
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;
};
}
}

View File

@@ -0,0 +1,25 @@
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 org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* An argument parser should generate the predicate as well
* as modify the ItemMeta for {@link TestableItem#getItem()}.
*/
public interface LookupArgParser {
/**
* Parse the arguments.
*
* @param args The arguments.
* @param meta The ItemMeta to modify.
* @return The predicate test to apply to the modified item.
*/
@Nullable Predicate<ItemStack> parseArguments(@NotNull String[] args,
@NotNull ItemMeta meta);
}

View File

@@ -0,0 +1,59 @@
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 org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parse skull textures.
*/
public class TextureArgParser implements LookupArgParser {
@Override
public @Nullable 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);
}
if (skullTexture == null) {
return null;
}
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;
};
}
}

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.recipe.parts;
import com.willfp.eco.core.items.TestableItem;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@@ -23,6 +24,8 @@ public class MaterialTestableItem implements TestableItem {
* @param material The material.
*/
public MaterialTestableItem(@NotNull final Material material) {
Validate.isTrue(material != Material.AIR, "You can't have air as the type!");
this.material = material;
}

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.core.recipe.parts;
import com.willfp.eco.core.items.TestableItem;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -17,6 +18,7 @@ public class ModifiedTestableItem implements TestableItem {
/**
* The item.
*/
@Getter
private final TestableItem handle;
/**

View File

@@ -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;
/**
@@ -35,7 +31,8 @@ public class TestableStack implements TestableItem {
*/
public TestableStack(@NotNull final TestableItem item,
final int amount) {
Validate.isTrue(!(item instanceof TestableStack));
Validate.isTrue(!(item instanceof TestableStack), "You can't stack a stack!");
Validate.isTrue(!(item instanceof EmptyTestableItem), "You can't stack air!");
this.handle = item;
this.amount = amount;
@@ -55,19 +52,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;
}
}

View File

@@ -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;
@@ -79,6 +82,10 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
ShapedRecipe shapedRecipe = new ShapedRecipe(this.getKey(), this.getOutput());
shapedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) {
if (parts.get(i) instanceof EmptyTestableItem) {
continue;
}
char character = String.valueOf(i).toCharArray()[0];
shapedRecipe.setIngredient(character, parts.get(i).getItem().getType());
}
@@ -86,8 +93,28 @@ public final class ShapedCraftingRecipe extends PluginDependent<EcoPlugin> imple
ShapedRecipe displayedRecipe = new ShapedRecipe(this.getDisplayedKey(), this.getOutput());
displayedRecipe.shape("012", "345", "678");
for (int i = 0; i < 9; i++) {
if (parts.get(i) instanceof EmptyTestableItem) {
continue;
}
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);

View File

@@ -0,0 +1,28 @@
package com.willfp.eco.core.requirement;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* A requirement is a defined goal that a player must meet.
*/
public abstract class Requirement {
/**
* Create a new requirement.
*/
protected Requirement() {
}
/**
* Test if the player meets the requirement.
*
* @param player The player.
* @param args The arguments.
* @return The requirement.
*/
public abstract boolean doesPlayerMeet(@NotNull Player player,
@NotNull List<String> args);
}

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.core.requirement;
import org.jetbrains.annotations.NotNull;
/**
* Interface for internal requirement factory implementations.
*/
public interface RequirementFactory {
/**
* Create a requirement.
*
* @param name The name.
* @return The requirement returned for the name.
* Will return a requirement that is always true if not found.
*/
Requirement create(@NotNull String name);
}

View File

@@ -0,0 +1,41 @@
package com.willfp.eco.core.requirement;
import com.willfp.eco.core.Eco;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
/**
* Contains methods and fields pertaining to requirements.
*/
@UtilityClass
public class Requirements {
/**
* Requires a player to have a permission.
*/
public static final Requirement HAS_PERMISSION = Eco.getHandler().getRequirementFactory().create("has-permission");
/**
* Placeholder equals value.
*/
public static final Requirement PLACEHOLDER_EQUALS = Eco.getHandler().getRequirementFactory().create("placeholder-equals");
/**
* Numeric placeholder greater than value.
*/
public static final Requirement PLACEHOLDER_GREATER_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-greater-than");
/**
* Numeric placeholder less than value.
*/
public static final Requirement PLACEHOLDER_LESS_THAN = Eco.getHandler().getRequirementFactory().create("placeholder-less-than");
/**
* Get Requirements matching ID.
*
* @param name The ID to search for.
* @return The matching Requirements.
*/
public static Requirement getByID(@NotNull final String name) {
return Eco.getHandler().getRequirementFactory().create(name);
}
}

View File

@@ -38,4 +38,26 @@ public class Pair<A, B> {
this.first = first;
this.second = second;
}
/**
* component1 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public A component1() {
return first;
}
/**
* component2 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public B component2() {
return second;
}
}

View File

@@ -34,4 +34,15 @@ public class Triplet<A, B, C> extends Pair<A, B> {
this.third = third;
}
/**
* component3 exists to allow a pair to be destructured by kotlin.
* The default kotlin pair already has this, however there is no default
* pair in java so this exists for parity.
*
* @return First.
*/
public C component3() {
return third;
}
}

View File

@@ -19,7 +19,7 @@ public class ArrowUtils {
* Get the bow from an arrow.
*
* @param arrow The arrow.
* @return The bow.
* @return The bow, or null if no bow.
*/
@Nullable
public ItemStack getBow(@NotNull final Arrow arrow) {

View File

@@ -63,6 +63,7 @@ public class BlockUtils {
* @param limit The maximum size of vein to return.
* @return A set of all {@link Block}s.
*/
@NotNull
public Set<Block> getVein(@NotNull final Block start,
@NotNull final List<Material> allowedMaterials,
final int limit) {

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
@@ -10,18 +11,37 @@ import org.jetbrains.annotations.NotNull;
*/
@UtilityClass
public class LightningUtils {
/**
* Strike lightning on player without fire.
*
* @param victim The entity to smite.
* @param damage The damage to deal.
* @param silent If the lightning sound should be played locally
*/
public void strike(@NotNull final LivingEntity victim,
final double damage,
final boolean silent) {
Location loc = victim.getLocation();
if (silent) {
victim.getWorld().spigot().strikeLightningEffect(loc, true);
victim.getWorld().playSound(loc, Sound.ENTITY_LIGHTNING_BOLT_IMPACT, 1, 1);
} else {
victim.getWorld().strikeLightningEffect(loc);
}
victim.damage(damage);
}
/**
* Strike lightning on a victim without fire.
*
* @param victim The entity to smite.
* @param damage The damage to deal.
*/
public void strike(@NotNull final LivingEntity victim,
final double damage) {
Location loc = victim.getLocation();
victim.getWorld().strikeLightningEffect(loc);
victim.damage(damage);
strike(victim, damage, false);
}
}

View File

@@ -1,6 +1,8 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -18,8 +20,9 @@ public class ListUtils {
* @param <T> The type of the object stored in the list.
* @return The list, filled will null objects.
*/
public <T> List<List<T>> create2DList(final int rows,
final int columns) {
@NotNull
public <@Nullable T> List<List<T>> create2DList(final int rows,
final int columns) {
List<List<T>> list = new ArrayList<>(rows);
while (list.size() < rows) {
List<T> row = new ArrayList<>(columns);

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import com.willfp.eco.core.tuples.Pair;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
/**
* Utilities / API methods for menus.
@@ -14,6 +15,7 @@ public class MenuUtils {
* @param slot The slot.
* @return The pair of row and columns.
*/
@NotNull
public Pair<Integer, Integer> convertSlotToRowColumn(final int slot) {
int row = Math.floorDiv(slot, 9);
int column = slot - row * 9;

View File

@@ -17,6 +17,7 @@ public class NamespacedKeyUtils {
* @param string The string.
* @return The key.
*/
@NotNull
public NamespacedKey createEcoKey(@NotNull final String string) {
return Objects.requireNonNull(NamespacedKey.fromString("eco:" + string));
}
@@ -28,6 +29,7 @@ public class NamespacedKeyUtils {
* @param key The key.
* @return The key.
*/
@NotNull
public NamespacedKey create(@NotNull final String namespace,
@NotNull final String key) {
return Objects.requireNonNull(NamespacedKey.fromString(namespace + ":" + key));

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.util;
import lombok.experimental.NonFinal;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@@ -109,6 +110,7 @@ public class NumberUtils {
* @param number The number to convert.
* @return The number, converted to a roman numeral.
*/
@NotNull
public String toNumeral(final int number) {
if (number >= 1 && number <= 4096) {
int l = NUMERALS.floorKey(number);
@@ -199,6 +201,7 @@ public class NumberUtils {
* @param toFormat The number to format.
* @return Formatted.
*/
@NotNull
public String format(final double toFormat) {
DecimalFormat df = new DecimalFormat("0.00");
String formatted = df.format(toFormat);

View File

@@ -5,8 +5,10 @@ import org.apache.commons.lang.Validate;
import org.bukkit.inventory.meta.SkullMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* Utilities / API methods for player heads.
@@ -23,6 +25,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 +44,33 @@ public class SkullUtils {
metaSetConsumer.accept(meta, base64);
}
/**
* Get the texture of a skull - in base64.
*
* @param meta The meta to modify.
* @return The texture, potentially null.
*/
@Nullable
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;
}
}

View File

@@ -12,7 +12,7 @@ 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;
@@ -57,58 +57,137 @@ public class StringUtils {
.build();
/**
* Format a list of strings - converts Placeholders and Color codes.
* Format a list of strings.
* <p>
* Converts color codes and placeholders.
*
* @param list The messages to format.
* @return The message, formatted.
*/
@NotNull
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.
* @return The message, format.
*/
@NotNull
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.
*/
@NotNull
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.
*/
@NotNull
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.
*
* @param list The messages to format.
* @return The message, formatted.
*/
public List<String> formatList(@NotNull final List<String> list) {
return formatList(list, null);
}
/**
* Format a string - converts Placeholders and Color codes.
*
* @param message The message to format.
* @param player The player to translate placeholders with respect to.
* @return The message, formatted.
*/
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;
}
/**
* Format a string without respect to a player.
* Format a string.
* <p>
* Converts color codes and placeholders.
*
* @param message The message to translate.
* @return The message, formatted.
* @see StringUtils#format(String, Player)
*/
@NotNull
public String format(@NotNull final String message) {
return format(message, null);
return format(message, (Player) null);
}
/**
* 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.
* @return The message, formatted.
*/
@NotNull
public String format(@NotNull final String message,
@Nullable final Player player) {
return format(message, player, FormatOption.WITH_PLACEHOLDERS);
}
/**
* 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)
*/
@NotNull
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.
*/
@NotNull
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) {
@@ -213,6 +292,7 @@ public class StringUtils {
* @param object The object to convert to string.
* @return The object stringified.
*/
@NotNull
public String internalToString(@Nullable final Object object) {
if (object == null) {
return "null";
@@ -238,6 +318,7 @@ public class StringUtils {
* @param prefix The substring to remove.
* @return The string with the prefix removed.
*/
@NotNull
public String removePrefix(@NotNull final String string,
@NotNull final String prefix) {
if (string.startsWith(prefix)) {
@@ -252,6 +333,7 @@ public class StringUtils {
* @param legacy The legacy string.
* @return The JSON String.
*/
@NotNull
public String legacyToJson(@NotNull final String legacy) {
return GsonComponentSerializer.gson().serialize(
Component.empty().decoration(TextDecoration.ITALIC, false).append(
@@ -266,9 +348,25 @@ public class StringUtils {
* @param json The JSON string.
* @return The legacy string.
*/
@NotNull
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
}
}

View File

@@ -43,6 +43,7 @@ public class TeamUtils {
* @param color The color to find the team for.
* @return The team.
*/
@NotNull
public Team fromChatColor(@NotNull final ChatColor color) {
if (CHAT_COLOR_TEAMS.containsKey(color)) {
return CHAT_COLOR_TEAMS.get(color);
@@ -70,6 +71,7 @@ public class TeamUtils {
* @param material The material to find the team from.
* @return The team.
*/
@NotNull
public Team getMaterialColorTeam(@NotNull final Material material) {
return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE));
}

View File

@@ -44,6 +44,7 @@ public class VectorUtils {
* @param vec The vector to simplify.
* @return The vector, simplified.
*/
@NotNull
public Vector simplifyVector(@NotNull final Vector vec) {
double x = Math.abs(vec.getX());
double y = Math.abs(vec.getY());
@@ -76,6 +77,7 @@ public class VectorUtils {
* @param radius The radius.
* @return An array of {@link Vector}s.
*/
@NotNull
public Vector[] getCircle(final int radius) {
Vector[] cached = CIRCLE_CACHE.get(radius);
if (cached != null) {
@@ -112,6 +114,7 @@ public class VectorUtils {
* @param radius The radius of the square.
* @return An array of {@link Vector}s.
*/
@NotNull
public Vector[] getSquare(final int radius) {
List<Vector> vectors = new ArrayList<>();
@@ -136,6 +139,7 @@ public class VectorUtils {
* @param radius The radius of the cube.
* @return An array of {@link Vector}s.
*/
@NotNull
public Vector[] getCube(final int radius) {
List<Vector> vectors = new ArrayList<>();

View File

@@ -6,6 +6,7 @@ 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.json.EcoUpdatableJSONConfig
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoYamlConfigSection
@@ -30,6 +31,24 @@ class EcoConfigFactory : ConfigFactory {
)
}
override fun createUpdatableJSONConfig(
configName: String,
plugin: EcoPlugin,
subDirectoryPath: String,
source: Class<*>,
removeUnused: Boolean,
vararg updateBlacklist: String
): JSONConfig {
return EcoUpdatableJSONConfig(
configName,
plugin,
subDirectoryPath,
source,
removeUnused,
*updateBlacklist
)
}
override fun createLoadableJSONConfig(
configName: String,
plugin: EcoPlugin,

View File

@@ -11,9 +11,9 @@ import java.util.*
open class EcoJSONConfigWrapper : JSONConfig {
val handle: Gson = GsonBuilder().setPrettyPrinting().create()
val values: MutableMap<String, Any?> = HashMap()
val values = mutableMapOf<String, Any?>()
private val cache: MutableMap<String, Any> = HashMap()
private val cache = mutableMapOf<String, Any>()
fun init(values: Map<String, Any?>) {
this.values.clear()
@@ -138,17 +138,17 @@ open class EcoJSONConfigWrapper : JSONConfig {
override fun getSubsections(path: String): List<JSONConfig> {
val subsections = getSubsectionsOrNull(path)
return subsections ?: ArrayList()
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: MutableList<JSONConfig> = ArrayList()
val configs = mutableListOf<JSONConfig>()
for (map in maps) {
configs.add(EcoJSONConfigSection(map))
}
return configs
return configs.toMutableList()
}
override fun getInt(path: String): Int {
@@ -170,11 +170,11 @@ open class EcoJSONConfigWrapper : JSONConfig {
return Objects.requireNonNullElse(getOfKnownType(path, Int::class.java), def)
}
override fun getInts(path: String): List<Int> {
return Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), ArrayList<Any>()) as List<Int>
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): List<Int>? {
override fun getIntsOrNull(path: String): MutableList<Int>? {
return if (has(path)) {
getInts(path)
} else {
@@ -194,11 +194,11 @@ open class EcoJSONConfigWrapper : JSONConfig {
}
}
override fun getBools(path: String): List<Boolean> {
return Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), ArrayList<Any>()) as List<Boolean>
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): List<Boolean>? {
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
return if (has(path)) {
getBools(path)
} else {
@@ -206,64 +206,44 @@ open class EcoJSONConfigWrapper : JSONConfig {
}
}
override fun getString(path: String): String {
return getString(path, true)
}
override fun getString(
path: String,
format: Boolean
format: Boolean,
option: StringUtils.FormatOption
): String {
val string = getOfKnownType(path, String::class.java) ?: ""
return if (format) StringUtils.format(string) else string
}
override fun getStringOrNull(path: String): String? {
return if (has(path)) {
getString(path)
} else {
null
}
return if (format) StringUtils.format(string, option) else string
}
override fun getStringOrNull(
path: String,
format: Boolean
format: Boolean,
option: StringUtils.FormatOption
): String? {
return if (has(path)) {
getString(path, format)
getString(path, format, option)
} else {
null
}
}
override fun getStrings(path: String): List<String> {
return getStrings(path, true)
}
override fun getStrings(
path: String,
format: Boolean
): List<String> {
format: Boolean,
option: StringUtils.FormatOption
): MutableList<String> {
val strings =
Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), ArrayList<Any>()) as List<String>
return if (format) StringUtils.formatList(strings) else strings
}
override fun getStringsOrNull(path: String): List<String>? {
return if (has(path)) {
getStrings(path)
} else {
null
}
(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
): List<String>? {
format: Boolean,
option: StringUtils.FormatOption
): MutableList<String>? {
return if (has(path)) {
getStrings(path, format)
getStrings(path, format, option)
} else {
null
}
@@ -281,11 +261,11 @@ open class EcoJSONConfigWrapper : JSONConfig {
}
}
override fun getDoubles(path: String): List<Double> {
return Objects.requireNonNullElse(getOfKnownType(path, Any::class.java), ArrayList<Any>()) as List<Double>
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): List<Double>? {
override fun getDoublesOrNull(path: String): MutableList<Double>? {
return if (has(path)) {
getDoubles(path)
} else {

View File

@@ -8,11 +8,11 @@ import java.nio.file.Files
import java.nio.file.StandardOpenOption
@Suppress("UNCHECKED_CAST")
class EcoLoadableJSONConfig(
open class EcoLoadableJSONConfig(
configName: String,
private val plugin: EcoPlugin,
private val subDirectoryPath: String,
private val source: Class<*>
val source: Class<*>
) : EcoJSONConfigWrapper(), LoadableConfig {
private val configFile: File
@@ -27,7 +27,6 @@ class EcoLoadableJSONConfig(
}
override fun createFile() {
val resourcePath = resourcePath
val inputStream = source.getResourceAsStream(resourcePath)!!
val outFile = File(this.plugin.dataFolder, resourcePath)
val lastIndex = resourcePath.lastIndexOf('/')
@@ -37,11 +36,7 @@ class EcoLoadableJSONConfig(
}
if (!outFile.exists()) {
val out: OutputStream = FileOutputStream(outFile)
val buf = ByteArray(1024)
var len: Int
while (inputStream.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
inputStream.copyTo(out, 1024)
out.close()
inputStream.close()
}
@@ -70,7 +65,7 @@ class EcoLoadableJSONConfig(
@Throws(FileNotFoundException::class)
fun init(file: File) {
super.init(handle.fromJson(FileReader(file), Map::class.java) as @NotNull MutableMap<String, Any>)
super.init(handle.fromJson(FileReader(file), Map::class.java) as MutableMap<String, Any>)
}
override fun getName(): String {

View File

@@ -0,0 +1,74 @@
package com.willfp.eco.internal.config.json
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
open class EcoUpdatableJSONConfig(
configName: String,
plugin: EcoPlugin,
subDirectoryPath: String,
source: Class<*>,
private val removeUnused: Boolean,
vararg updateBlacklist: String
) : EcoLoadableJSONConfig(configName, plugin, subDirectoryPath, source) {
private val updateBlacklist: MutableList<String> = mutableListOf(*updateBlacklist)
fun update() {
super.clearCache()
try {
this.init(configFile)
val newConfig = configInJar
if (newConfig.getKeys(true) == this.getKeys(true)) {
return
}
newConfig.getKeys(true).forEach { key: String ->
if (!this.getKeys(true).contains(key)) {
if (updateBlacklist.stream().noneMatch { s: String -> key.contains(s) }) {
this.set(key, newConfig[key])
}
}
}
if (removeUnused) {
this.getKeys(true).forEach { s ->
if (!newConfig.getKeys(true).contains(s)) {
if (updateBlacklist.stream().noneMatch(s::contains)) {
this.set(s, null)
}
}
}
}
this.save()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
}
}
private val configInJar: YamlConfiguration
get() {
val newIn = this.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()
}
}

View File

@@ -1,11 +1,11 @@
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.json.EcoLoadableJSONConfig
import com.willfp.eco.internal.config.json.EcoUpdatableJSONConfig
import com.willfp.eco.internal.config.updating.exceptions.InvalidUpdateMethodException
import com.willfp.eco.internal.config.yaml.EcoLoadableYamlConfig
import com.willfp.eco.internal.config.yaml.EcoUpdatableYamlConfig
@@ -14,14 +14,14 @@ import org.reflections.scanners.MethodAnnotationsScanner
import java.lang.reflect.Modifier
class EcoConfigHandler(
plugin: EcoPlugin
) : PluginDependent<EcoPlugin>(plugin), ConfigHandler {
private val plugin: EcoPlugin
) : ConfigHandler {
private val reflections: Reflections = Reflections(
this.plugin::class.java.classLoader,
MethodAnnotationsScanner()
)
private val configs: MutableList<LoadableConfig> = ArrayList()
private val configs = mutableListOf<LoadableConfig>()
override fun callUpdate() {
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
@@ -56,6 +56,7 @@ class EcoConfigHandler(
for (config in configs) {
when (config) {
is EcoUpdatableYamlConfig -> config.update()
is EcoUpdatableJSONConfig -> config.update()
is EcoLoadableYamlConfig -> config.reloadFromFile()
is EcoLoadableJSONConfig -> config.reloadFromFile()
}

View File

@@ -31,7 +31,6 @@ open class EcoLoadableYamlConfig(
}
final override fun createFile() {
val resourcePath = resourcePath
val inputStream = source.getResourceAsStream(resourcePath)!!
val outFile = File(this.plugin.dataFolder, resourcePath)
val lastIndex = resourcePath.lastIndexOf('/')
@@ -41,11 +40,7 @@ open class EcoLoadableYamlConfig(
}
if (!outFile.exists()) {
val out: OutputStream = FileOutputStream(outFile)
val buf = ByteArray(1024)
var len: Int
while (inputStream.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
inputStream.copyTo(out, 1024)
out.close()
inputStream.close()
}

View File

@@ -10,7 +10,7 @@ import java.io.StringReader
@Suppress("UNCHECKED_CAST")
open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
lateinit var handle: T
private val cache: MutableMap<String, Any?> = HashMap()
private val cache = mutableMapOf<String, Any?>()
protected fun init(config: T): Config {
handle = config
@@ -98,16 +98,16 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
}
}
override fun getInts(path: String): List<Int> {
override fun getInts(path: String): MutableList<Int> {
return if (cache.containsKey(path)) {
cache[path] as List<Int>
(cache[path] as MutableList<Int>).toMutableList()
} else {
cache[path] = if (has(path)) ArrayList(handle.getIntegerList(path)) else ArrayList<Any>()
cache[path] = if (has(path)) ArrayList(handle.getIntegerList(path)) else mutableListOf<Int>()
getInts(path)
}
}
override fun getIntsOrNull(path: String): List<Int>? {
override fun getIntsOrNull(path: String): MutableList<Int>? {
return if (has(path)) {
getInts(path)
} else {
@@ -132,17 +132,17 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
}
}
override fun getBools(path: String): List<Boolean> {
override fun getBools(path: String): MutableList<Boolean> {
return if (cache.containsKey(path)) {
cache[path] as List<Boolean>
(cache[path] as MutableList<Boolean>).toMutableList()
} else {
cache[path] =
if (has(path)) ArrayList(handle.getBooleanList(path)) else ArrayList<Any>()
if (has(path)) ArrayList(handle.getBooleanList(path)) else mutableListOf<Boolean>()
getBools(path)
}
}
override fun getBoolsOrNull(path: String): List<Boolean>? {
override fun getBoolsOrNull(path: String): MutableList<Boolean>? {
return if (has(path)) {
getBools(path)
} else {
@@ -150,92 +150,80 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
}
}
override fun getString(path: String): String {
return getString(path, true)
}
override fun getString(
path: String,
format: Boolean
format: Boolean,
option: StringUtils.FormatOption
): String {
if (format) {
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)
getString(path, format)
cache["$path\$FMT"] = StringUtils.format(string, option)
getString(path, format, option)
}
} else {
return if (cache.containsKey(path)) {
val string = if (cache.containsKey(path)) {
cache[path] as String
} else {
cache[path] = handle.getString(path, "")!!
getString(path)
getString(path, format, option)
}
}
}
override fun getStringOrNull(path: String): String? {
return if (has(path)) {
getString(path)
} else {
null
return if (format) StringUtils.format(string) else string
}
}
override fun getStringOrNull(
path: String,
format: Boolean
format: Boolean,
option: StringUtils.FormatOption
): String? {
return if (has(path)) {
getString(path, format)
getString(path, format, option)
} else {
null
}
}
override fun getStrings(path: String): List<String> {
return getStrings(path, true)
}
override fun getStrings(
path: String,
format: Boolean
): List<String> {
if (format) {
format: Boolean,
option: StringUtils.FormatOption
): MutableList<String> {
if (format && option == StringUtils.FormatOption.WITHOUT_PLACEHOLDERS) {
return if (cache.containsKey("$path\$FMT")) {
cache["$path\$FMT"] as List<String>
(cache["$path\$FMT"] as MutableList<String>).toMutableList()
} else {
val list = if (has(path)) handle.getStringList(path) else ArrayList()
cache["$path\$FMT"] = StringUtils.formatList(list);
getStrings(path, true)
val list = if (has(path)) handle.getStringList(path) else mutableListOf<String>()
cache["$path\$FMT"] = StringUtils.formatList(list, option)
getStrings(path, true, option)
}
} else {
return if (cache.containsKey(path)) {
cache[path] as List<String>
val strings = if (cache.containsKey(path)) {
(cache[path] as MutableList<String>).toMutableList()
} else {
cache[path] =
if (has(path)) ArrayList(handle.getStringList(path)) else ArrayList<Any>()
getStrings(path, false)
if (has(path)) ArrayList(handle.getStringList(path)) else mutableListOf<String>()
getStrings(path, false, option)
}
}
}
override fun getStringsOrNull(path: String): List<String>? {
return if (has(path)) {
getStrings(path)
} else {
null
return if (format) {
StringUtils.formatList(strings, StringUtils.FormatOption.WITH_PLACEHOLDERS)
} else {
strings
}
}
}
override fun getStringsOrNull(
path: String,
format: Boolean
): List<String>? {
format: Boolean,
option: StringUtils.FormatOption
): MutableList<String>? {
return if (has(path)) {
getStrings(path, format)
getStrings(path, format, option)
} else {
null
}
@@ -258,16 +246,16 @@ open class EcoYamlConfigWrapper<T : ConfigurationSection> : Config {
}
}
override fun getDoubles(path: String): List<Double> {
override fun getDoubles(path: String): MutableList<Double> {
return if (cache.containsKey(path)) {
cache[path] as List<Double>
(cache[path] as MutableList<Double>).toMutableList()
} else {
cache[path] = if (has(path)) ArrayList(handle.getDoubleList(path)) else ArrayList<Any>()
cache[path] = if (has(path)) ArrayList(handle.getDoubleList(path)) else emptyList<Double>()
getDoubles(path)
}
}
override fun getDoublesOrNull(path: String): List<Double>? {
override fun getDoublesOrNull(path: String): MutableList<Double>? {
return if (has(path)) {
getDoubles(path)
} else {

View File

@@ -0,0 +1,119 @@
package com.willfp.eco.internal.display
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.display.Display
import com.willfp.eco.core.display.DisplayHandler
import com.willfp.eco.core.display.DisplayModule
import com.willfp.eco.core.display.DisplayPriority
import com.willfp.eco.core.fast.FastItemStack
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataType
class EcoDisplayHandler(plugin: EcoPlugin) : DisplayHandler {
/**
* All registered display modules.
*/
private val registeredModules = mutableMapOf<DisplayPriority, MutableList<DisplayModule>>()
/**
* NamespacedKey for finalizing.
*/
private val finalizeKey: NamespacedKey = plugin.namespacedKeyFactory.create("finalized")
init {
for (priority in DisplayPriority.values()) {
registeredModules[priority] = mutableListOf()
}
}
override fun registerDisplayModule(module: DisplayModule) {
val modules = registeredModules[module.priority] ?: return
modules.removeIf { module1: DisplayModule ->
module1.pluginName.equals(module.pluginName, ignoreCase = true)
}
modules.add(module)
registeredModules[module.priority] = modules
}
override fun display(itemStack: ItemStack, player: Player?): ItemStack {
val pluginVarArgs = mutableMapOf<String, Array<Any>>()
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
pluginVarArgs[module.pluginName] = module.generateVarArgs(itemStack)
}
}
Display.revert(itemStack)
itemStack.itemMeta ?: return itemStack
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
val varargs = pluginVarArgs[module.pluginName] ?: continue
Display.callDisplayModule(module, itemStack, player, *varargs)
}
}
return itemStack
}
override fun revert(itemStack: ItemStack): ItemStack {
if (Display.isFinalized(itemStack)) {
Display.unfinalize(itemStack)
}
val fast = FastItemStack.wrap(itemStack)
val lore = fast.lore
if (lore.isNotEmpty() && lore.removeIf { line: String ->
line.startsWith(
Display.PREFIX
)
}) { // Only modify lore if needed.
fast.lore = lore
}
for (priority in DisplayPriority.values()) {
val modules = registeredModules[priority] ?: continue
for (module in modules) {
module.revert(itemStack)
}
}
return itemStack
}
override fun finalize(itemStack: ItemStack): ItemStack {
if (itemStack.type.maxStackSize > 1) {
return itemStack
}
val meta = itemStack.itemMeta ?: return itemStack
val container = meta.persistentDataContainer
container.set(finalizeKey, PersistentDataType.INTEGER, 1)
itemStack.itemMeta = meta
return itemStack
}
override fun unfinalize(itemStack: ItemStack): ItemStack {
val meta = itemStack.itemMeta ?: return itemStack
val container = meta.persistentDataContainer
container.remove(finalizeKey)
itemStack.itemMeta = meta
return itemStack
}
override fun isFinalized(itemStack: ItemStack): Boolean {
val meta = itemStack.itemMeta ?: return false
val container = meta.persistentDataContainer
return container.has(finalizeKey, PersistentDataType.INTEGER)
}
}

View File

@@ -13,8 +13,8 @@ import org.bukkit.inventory.ItemStack
import org.bukkit.util.Vector
open class EcoDropQueue(player: Player) : InternalDropQueue {
val items: MutableList<ItemStack>
var xp: Int
val items = mutableListOf<ItemStack>()
var xp: Int = 0
val player: Player
var loc: Location
var hasTelekinesis = false
@@ -79,8 +79,6 @@ open class EcoDropQueue(player: Player) : InternalDropQueue {
}
init {
items = ArrayList()
xp = 0
this.player = player
loc = player.location
}

View File

@@ -1,13 +1,12 @@
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
class EcoEventManager constructor(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), EventManager {
class EcoEventManager (private val plugin: EcoPlugin) : EventManager {
override fun registerListener(listener: Listener) {
Bukkit.getPluginManager().registerEvents(listener, plugin)
}

View File

@@ -2,7 +2,6 @@ package com.willfp.eco.internal.extensions
import com.google.common.collect.ImmutableSet
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent
import com.willfp.eco.core.config.yaml.YamlTransientConfig
import com.willfp.eco.core.extensions.Extension
import com.willfp.eco.core.extensions.ExtensionLoader
@@ -16,9 +15,9 @@ import java.net.URL
import java.net.URLClassLoader
class EcoExtensionLoader(
plugin: EcoPlugin
) : PluginDependent<EcoPlugin>(plugin), ExtensionLoader {
private val extensions: MutableMap<Extension, URLClassLoader> = HashMap()
private val plugin: EcoPlugin
) : ExtensionLoader {
private val extensions = mutableMapOf<Extension, URLClassLoader>()
override fun loadExtensions() {
val dir = File(this.plugin.dataFolder, "/extensions")
@@ -43,7 +42,7 @@ class EcoExtensionLoader(
@Throws(MalformedExtensionException::class)
private fun loadExtension(extensionJar: File) {
lateinit var url : URL
lateinit var url: URL
try {
url = extensionJar.toURI().toURL()
@@ -53,7 +52,7 @@ class EcoExtensionLoader(
val classLoader = URLClassLoader(arrayOf(url), this.plugin::class.java.classLoader)
val ymlIn = classLoader.getResourceAsStream("extension.yml")
?: throw MalformedExtensionException ("No extension.yml found in " + extensionJar.name)
?: throw MalformedExtensionException("No extension.yml found in " + extensionJar.name)
val extensionYml = YamlTransientConfig(YamlConfiguration.loadConfiguration(InputStreamReader(ymlIn)))
@@ -64,7 +63,7 @@ class EcoExtensionLoader(
if (mainClass == null) {
throw MalformedExtensionException ("Invalid extension.yml found in " + extensionJar.name)
throw MalformedExtensionException("Invalid extension.yml found in " + extensionJar.name)
}
if (name == null) {

View File

@@ -1,11 +1,10 @@
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
class EcoMetadataValueFactory(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), MetadataValueFactory {
class EcoMetadataValueFactory(private val plugin: EcoPlugin) : MetadataValueFactory {
override fun create(value: Any): FixedMetadataValue {
return FixedMetadataValue(plugin, value)
}

View File

@@ -1,11 +1,10 @@
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
class EcoNamespacedKeyFactory(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), NamespacedKeyFactory {
class EcoNamespacedKeyFactory(private val plugin: EcoPlugin) : NamespacedKeyFactory {
override fun create(key: String): NamespacedKey {
return NamespacedKey(plugin, key)
}

View File

@@ -1,13 +1,12 @@
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 java.util.function.Consumer
class EcoRunnableFactory(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), RunnableFactory {
class EcoRunnableFactory(private val plugin: EcoPlugin) : RunnableFactory {
override fun create(consumer: Consumer<RunnableTask>): RunnableTask {
return object : EcoRunnableTask(plugin) {
override fun run() {

View File

@@ -1,6 +1,7 @@
package com.willfp.eco.internal.fast
import com.willfp.eco.core.fast.FastItemStack
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
abstract class EcoFastItemStack<T: Any>(
@@ -10,4 +11,8 @@ abstract class EcoFastItemStack<T: Any>(
override fun unwrap(): ItemStack {
return bukkit
}
fun getBitModifier(hideFlag: ItemFlag): Int {
return 1 shl hideFlag.ordinal
}
}

View File

@@ -6,11 +6,14 @@ import com.willfp.eco.core.gui.slot.Slot
import com.willfp.eco.internal.gui.slot.EcoSlot
import com.willfp.eco.util.StringUtils
import org.bukkit.Bukkit
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
import org.bukkit.persistence.PersistentDataType
@Suppress("UNCHECKED_CAST")
class EcoMenu(
private val rows: Int,
val slots: List<MutableList<EcoSlot>>,
@@ -60,6 +63,7 @@ class EcoMenu(
fun handleClose(event: InventoryCloseEvent) {
onClose.handle(event, this)
MenuHandler.unregisterMenu(event.inventory)
}
override fun getRows(): Int {
@@ -72,7 +76,31 @@ class EcoMenu(
override fun getCaptiveItems(player: Player): MutableList<ItemStack> {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return ArrayList()
inventory ?: return mutableListOf()
return inventory.captiveItems
}
override fun <T : Any, Z : Any> writeData(
player: Player,
key: NamespacedKey,
type: PersistentDataType<T, Z>,
value: Z
) {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return
inventory.data[key] = value
inventory.refresh(player)
}
override fun <T : Any, Z : Any> readData(player: Player, key: NamespacedKey, type: PersistentDataType<T, Z>): T? {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return null
return inventory.data[key] as T?
}
override fun getKeys(player: Player): MutableSet<NamespacedKey> {
val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory)
inventory ?: return HashSet()
return inventory.data.keys
}
}

View File

@@ -61,10 +61,10 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
}
}
val finalSlots: MutableList<MutableList<EcoSlot>> = ArrayList()
val finalSlots = mutableListOf<MutableList<EcoSlot>>()
for (row in tempSlots) {
val tempRow = ArrayList<EcoSlot>()
val tempRow = mutableListOf<EcoSlot>()
for (slot in row) {
var tempSlot = slot
if (tempSlot is FillerSlot) {

View File

@@ -3,6 +3,7 @@ package com.willfp.eco.internal.gui.menu
import com.willfp.eco.internal.gui.slot.EcoCaptivatorSlot
import com.willfp.eco.util.MenuUtils
import com.willfp.eco.util.StringUtils
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
@@ -11,7 +12,8 @@ class ExtendedInventory(
val inventory: Inventory,
private val menu: EcoMenu
) {
val captiveItems: MutableList<ItemStack> = ArrayList()
val captiveItems = mutableListOf<ItemStack>()
val data = mutableMapOf<NamespacedKey, Any>()
fun refresh(player: Player) {
captiveItems.clear()

View File

@@ -4,28 +4,28 @@ import com.willfp.eco.core.gui.menu.Menu
import org.bukkit.inventory.Inventory
object MenuHandler {
private val MENUS: MutableMap<ExtendedInventory, EcoMenu> = HashMap()
private val INVS: MutableMap<Inventory, ExtendedInventory> = HashMap()
private val menus = mutableMapOf<ExtendedInventory, EcoMenu>()
private val inventories = mutableMapOf<Inventory, ExtendedInventory>()
fun registerMenu(
inventory: Inventory,
menu: EcoMenu
) {
val extendedInventory = ExtendedInventory(inventory, menu)
INVS[inventory] = extendedInventory
MENUS[extendedInventory] = menu
inventories[inventory] = extendedInventory
menus[extendedInventory] = menu
}
fun unregisterMenu(inventory: Inventory) {
MENUS.remove(INVS[inventory])
INVS.remove(inventory)
menus.remove(inventories[inventory])
inventories.remove(inventory)
}
fun getMenu(inventory: Inventory): Menu? {
return MENUS[INVS[inventory]]
return menus[inventories[inventory]]
}
fun getExtendedInventory(inventory: Inventory): ExtendedInventory? {
return INVS[inventory]
return inventories[inventory]
}
}

View File

@@ -15,7 +15,7 @@ class EcoCaptivatorSlot : EcoSlot(
{ _, _, _ -> }
) {
companion object {
val plugin = Eco.getHandler().ecoPlugin!!
val plugin = Eco.getHandler().ecoPlugin
val allowMovingItem = SlotHandler { event, _, _ ->
event.isCancelled = false

View File

@@ -8,7 +8,7 @@ import com.willfp.eco.core.gui.slot.functional.SlotProvider
class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
private var captive = false
var modifier: SlotModifier = SlotModifier{ player, menu, _ -> provider.provide(player, menu)}
private var modifier: SlotModifier = SlotModifier{ player, menu, _ -> provider.provide(player, menu)}
private var onLeftClick =
SlotHandler { _, _, _ -> run { } }

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.internal.proxy;
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
@@ -11,8 +10,8 @@ import java.net.URLClassLoader
import java.util.*
class EcoProxyFactory(
plugin: EcoPlugin
) : PluginDependent<EcoPlugin>(plugin), ProxyFactory {
private val plugin: EcoPlugin
) : ProxyFactory {
private val proxyClassLoader: ClassLoader = plugin::class.java.classLoader
private val cache: MutableMap<Class<out AbstractProxy>, AbstractProxy> = IdentityHashMap()

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.internal.requirement
import com.willfp.eco.core.requirement.Requirement
import com.willfp.eco.core.requirement.RequirementFactory
import com.willfp.eco.internal.requirement.requirements.*
class EcoRequirementFactory: RequirementFactory {
override fun create(name: String): Requirement {
return when (name.lowercase()) {
"has-permission" -> RequirementHasPermission()
"placeholder-equals" -> RequirementPlaceholderEquals()
"placeholder-greater-than" -> RequirementPlaceholderGreaterThan()
"placeholder-less-than" -> RequirementPlaceholderLessThan()
else -> RequirementTrue()
}
}
}

View File

@@ -0,0 +1,18 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementHasPermission : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.isEmpty()) {
return false
}
val permission = args[0]
return player.hasPermission(permission)
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderEquals : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1]
return PlaceholderManager.translatePlaceholders(placeholder, player).equals(equals, ignoreCase = true)
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderGreaterThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0 >= equals
}
}

View File

@@ -0,0 +1,20 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementPlaceholderLessThan : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
if (args.size < 2) {
return false
}
val placeholder = args[0]
val equals = args[1].toDoubleOrNull() ?: return false
return PlaceholderManager.translatePlaceholders(placeholder, player).toDoubleOrNull() ?: 0.0 < equals
}
}

View File

@@ -0,0 +1,13 @@
package com.willfp.eco.internal.requirement.requirements
import com.willfp.eco.core.requirement.Requirement
import org.bukkit.entity.Player
class RequirementTrue : Requirement() {
override fun doesPlayerMeet(
player: Player,
args: List<String>
): Boolean {
return true
}
}

View File

@@ -1,12 +1,11 @@
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
class EcoScheduler(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Scheduler {
class EcoScheduler(private val plugin: EcoPlugin) : Scheduler {
override fun runLater(
runnable: Runnable,
ticksLater: Long

View File

@@ -1,32 +1,43 @@
package com.willfp.eco.proxy.v1_16_R3
import com.mojang.authlib.GameProfile
import com.mojang.authlib.properties.Property
import org.bukkit.inventory.meta.SkullMeta
import com.willfp.eco.proxy.SkullProxy
import org.bukkit.inventory.meta.SkullMeta
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.util.*
class Skull : SkullProxy {
private lateinit var setProfile: Method
private lateinit var profile: Field
override fun setSkullTexture(
meta: SkullMeta,
base64: String
) {
try {
if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true
}
val uuid = UUID(
base64.substring(base64.length - 20).hashCode().toLong(),
base64.substring(base64.length - 10).hashCode().toLong()
)
val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile)
} catch (e: ReflectiveOperationException) {
e.printStackTrace()
if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true
}
val uuid = UUID(
base64.substring(base64.length - 20).hashCode().toLong(),
base64.substring(base64.length - 10).hashCode().toLong()
)
val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile)
}
override fun getSkullTexture(
meta: SkullMeta
): String? {
if (!this::profile.isInitialized) {
profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true
}
val profile = profile[meta] as GameProfile?
val property = profile?.properties?.get("textures") as Property?
return property?.value
}
}

View File

@@ -1,9 +1,9 @@
package com.willfp.eco.proxy.v1_16_R3
import com.willfp.eco.core.display.Display
import com.willfp.eco.proxy.VillagerTradeProxy
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe
import org.bukkit.entity.Player
import org.bukkit.inventory.MerchantRecipe
import com.willfp.eco.proxy.VillagerTradeProxy
import java.lang.reflect.Field
class VillagerTrade : VillagerTradeProxy {
@@ -15,7 +15,7 @@ class VillagerTrade : VillagerTradeProxy {
): MerchantRecipe {
val oldRecipe = recipe as CraftMerchantRecipe
val newRecipe = CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
Display.display(recipe.getResult().clone(), player),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),

View File

@@ -8,7 +8,7 @@ import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack
import org.bukkit.craftbukkit.v1_16_R3.util.CraftMagicNumbers
import org.bukkit.craftbukkit.v1_16_R3.util.CraftNamespacedKey
import org.bukkit.enchantments.Enchantment
import java.lang.reflect.Field
import org.bukkit.inventory.ItemFlag
import kotlin.experimental.and
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
@@ -96,12 +96,59 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
}
}
override fun addItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits or getBitModifier(flag)
}
apply()
}
override fun removeItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits and getBitModifier(flag)
}
apply()
}
override fun getItemFlags(): MutableSet<ItemFlag> {
val flags = mutableSetOf<ItemFlag>()
var flagArr: Array<ItemFlag>
val size = ItemFlag.values().also { flagArr = it }.size
for (i in 0 until size) {
val flag = flagArr[i]
if (this.hasItemFlag(flag)) {
flags.add(flag)
}
}
return flags
}
override fun hasItemFlag(flag: ItemFlag): Boolean {
val bitModifier = getBitModifier(flag)
return this.flagBits and bitModifier == bitModifier
}
private var flagBits: Int
get() =
if (handle.hasTag() && handle.tag!!.hasKeyOfType(
"HideFlags",
99
)
) handle.tag!!.getInt("HideFlags") else 0
set(value) =
handle.orCreateTag.setInt("HideFlags", value)
override fun getRepairCost(): Int {
return handle.repairCost;
return handle.repairCost
}
override fun setRepairCost(cost: Int) {
handle.repairCost = cost;
handle.repairCost = cost
}
private fun apply() {
@@ -109,28 +156,4 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta
}
}
companion object {
private var field: Field
init {
lateinit var temp: Field
try {
val handleField = CraftItemStack::class.java.getDeclaredField("handle")
handleField.isAccessible = true
temp = handleField
} catch (e: ReflectiveOperationException) {
e.printStackTrace()
}
field = temp
}
fun getNMSStack(itemStack: org.bukkit.inventory.ItemStack): ItemStack? {
return if (itemStack !is CraftItemStack) {
CraftItemStack.asNMSCopy(itemStack)
} else {
field.get(itemStack) as ItemStack
}
}
}
}

View File

@@ -4,30 +4,40 @@ import com.mojang.authlib.GameProfile
import com.mojang.authlib.properties.Property
import com.willfp.eco.proxy.SkullProxy
import org.bukkit.inventory.meta.SkullMeta
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.util.*
class Skull : SkullProxy {
private lateinit var setProfile: Method
private lateinit var profile: Field
override fun setSkullTexture(
meta: SkullMeta,
base64: String
) {
try {
if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true
}
val uuid = UUID(
base64.substring(base64.length - 20).hashCode().toLong(),
base64.substring(base64.length - 10).hashCode().toLong()
)
val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile)
} catch (e: ReflectiveOperationException) {
e.printStackTrace()
if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true
}
val uuid = UUID(
base64.substring(base64.length - 20).hashCode().toLong(),
base64.substring(base64.length - 10).hashCode().toLong()
)
val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile)
}
override fun getSkullTexture(
meta: SkullMeta
): String? {
if (!this::profile.isInitialized) {
profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true
}
val profile = profile[meta] as GameProfile?
val property = profile?.properties?.get("textures") as Property?
return property?.value
}
}

View File

@@ -1,15 +1,15 @@
package com.willfp.eco.proxy.v1_17_R1
import com.willfp.eco.core.display.Display
import com.willfp.eco.proxy.VillagerTradeProxy
import net.minecraft.world.item.trading.MerchantOffer
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftMerchantRecipe
import org.bukkit.entity.Player
import org.bukkit.inventory.MerchantRecipe
import com.willfp.eco.proxy.VillagerTradeProxy
import java.lang.reflect.Field
class VillagerTrade : VillagerTradeProxy {
private var handle: Field
private val handle: Field = CraftMerchantRecipe::class.java.getDeclaredField("handle")
override fun displayTrade(
recipe: MerchantRecipe,
@@ -17,7 +17,7 @@ class VillagerTrade : VillagerTradeProxy {
): MerchantRecipe {
val oldRecipe = recipe as CraftMerchantRecipe
val newRecipe = CraftMerchantRecipe(
Display.display(recipe.getResult().clone()),
Display.display(recipe.getResult().clone(), player),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
@@ -32,21 +32,10 @@ class VillagerTrade : VillagerTradeProxy {
}
private fun getHandle(recipe: CraftMerchantRecipe): MerchantOffer {
try {
return handle[recipe] as MerchantOffer
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
throw IllegalArgumentException("Not CMR")
return handle[recipe] as MerchantOffer
}
init {
try {
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
handle.isAccessible = true
} catch (e: NoSuchFieldException) {
e.printStackTrace()
throw RuntimeException("Error!")
}
handle.isAccessible = true
}
}

View File

@@ -13,6 +13,7 @@ import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers
import org.bukkit.craftbukkit.v1_17_R1.util.CraftNamespacedKey
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.ItemFlag
import kotlin.experimental.and
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
@@ -115,12 +116,59 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
}
}
override fun addItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits or getBitModifier(flag)
}
apply()
}
override fun removeItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits and getBitModifier(flag)
}
apply()
}
override fun getItemFlags(): MutableSet<ItemFlag> {
val flags = mutableSetOf<ItemFlag>()
var flagArr: Array<ItemFlag>
val size = ItemFlag.values().also { flagArr = it }.size
for (i in 0 until size) {
val flag = flagArr[i]
if (this.hasItemFlag(flag)) {
flags.add(flag)
}
}
return flags
}
override fun hasItemFlag(flag: ItemFlag): Boolean {
val bitModifier = getBitModifier(flag)
return this.flagBits and bitModifier == bitModifier
}
private var flagBits: Int
get() =
if (handle.hasTag() && handle.tag!!.contains(
"HideFlags",
99
)
) handle.tag!!.getInt("HideFlags") else 0
set(value) =
handle.orCreateTag.putInt("HideFlags", value)
override fun getRepairCost(): Int {
return handle.baseRepairCost;
return handle.baseRepairCost
}
override fun setRepairCost(cost: Int) {
handle.setRepairCost(cost);
handle.setRepairCost(cost)
}
private fun apply() {

View File

@@ -20,8 +20,9 @@ dependencies {
compileOnly 'com.gmail.nossr50.mcMMO:mcMMO:2.1.157'
compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'com.willfp:Oraxen:e1f4003d8d'
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.3.8'
compileOnly 'com.github.brcdev-minecraft:shopgui-api:2.2.0'
compileOnly 'com.github.LoneDev6:API-ItemsAdder:2.4.7'
compileOnly 'me.arcaniax:HeadDatabase-API:1.2.0'
// CombatLogX V10 + NewbieHelper Expansion
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'

View File

@@ -6,6 +6,7 @@ import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.recipe.Recipes;
import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
@@ -97,16 +98,65 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
return;
}
this.getPlugin().getScheduler().runLater(() -> {
for (int i = 0; i < 9; i++) {
ItemStack inMatrix = event.getInventory().getMatrix()[i];
TestableItem inRecipe = matched.getParts().get(i);
boolean isStackedRecipe = false;
if (inRecipe instanceof TestableStack testableStack) {
int upperBound = 64;
for (int i = 0; i < 9; i++) {
ItemStack inMatrix = event.getInventory().getMatrix()[i];
TestableItem inRecipe = matched.getParts().get(i);
if (inRecipe instanceof TestableStack testableStack) {
int max = Math.floorDiv(inMatrix.getAmount(), testableStack.getAmount());
if (max < upperBound) {
upperBound = max;
}
isStackedRecipe = true;
} else if (inMatrix != null) {
int max = inMatrix.getAmount();
if (max < upperBound) {
upperBound = max;
}
}
}
if (!isStackedRecipe) {
return;
}
int toGivePerRecipe = event.getRecipe().getResult().getAmount();
int maxStackSize = event.getRecipe().getResult().getMaxStackSize();
while (toGivePerRecipe * upperBound > maxStackSize) {
upperBound--;
}
for (int i = 0; i < 9; i++) {
ItemStack inMatrix = event.getInventory().getMatrix()[i];
TestableItem inRecipe = matched.getParts().get(i);
if (inRecipe instanceof TestableStack testableStack) {
if (event.isShiftClick()) {
int amount = inMatrix.getAmount() + 1;
for (int j = 0; j < upperBound; j++) {
amount -= testableStack.getAmount();
}
inMatrix.setAmount(amount);
} else {
inMatrix.setAmount(inMatrix.getAmount() - (testableStack.getAmount() - 1));
}
}
}, 1);
}
int finalUpperBound = upperBound;
if (event.isShiftClick()) {
ItemStack result = event.getInventory().getResult();
if (result == null) {
return;
}
result.setAmount(result.getAmount() * finalUpperBound);
event.getInventory().setResult(result);
}
}
@EventHandler
@@ -130,6 +180,22 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
return;
}
}
if (part instanceof ModifiedTestableItem modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
if (part instanceof TestableStack modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
}
}
@@ -156,6 +222,24 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
return;
}
}
if (part instanceof ModifiedTestableItem modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
event.setResult(Event.Result.DENY);
event.setCancelled(true);
return;
}
}
}
if (part instanceof TestableStack modified) {
if (modified.getHandle() instanceof MaterialTestableItem) {
if (Items.isCustomItem(itemStack)) {
event.getInventory().setResult(new ItemStack(Material.AIR));
return;
}
}
}
}
}

View File

@@ -15,6 +15,7 @@ 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.requirement.RequirementFactory
import com.willfp.eco.core.scheduling.Scheduler
import com.willfp.eco.internal.EcoCleaner
import com.willfp.eco.internal.Plugins
@@ -30,15 +31,17 @@ import com.willfp.eco.internal.gui.EcoGUIFactory
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
import com.willfp.eco.internal.logging.EcoLogger
import com.willfp.eco.internal.proxy.EcoProxyFactory
import com.willfp.eco.internal.requirement.EcoRequirementFactory
import com.willfp.eco.internal.scheduling.EcoScheduler
import com.willfp.eco.proxy.FastItemStackFactoryProxy
import com.willfp.eco.spigot.integrations.bstats.MetricHandler
import org.bukkit.inventory.ItemStack
import com.willfp.eco.proxy.FastItemStackFactoryProxy
import java.util.logging.Logger
@Suppress("UNUSED")
class EcoHandler : EcoSpigotPlugin(), Handler {
private val cleaner = EcoCleaner()
private val requirementFactory = EcoRequirementFactory()
override fun createScheduler(plugin: EcoPlugin): Scheduler {
return EcoScheduler(plugin)
@@ -105,7 +108,7 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
}
override fun getLoadedPlugins(): List<String> {
return ArrayList(Plugins.LOADED_ECO_PLUGINS.keys)
return Plugins.LOADED_ECO_PLUGINS.keys.toMutableList()
}
override fun getPluginByName(name: String): EcoPlugin? {
@@ -119,4 +122,8 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
override fun registerBStats(plugin: EcoPlugin) {
MetricHandler.createMetrics(plugin, this.ecoPlugin)
}
override fun getRequirementFactory(): RequirementFactory {
return requirementFactory
}
}

View File

@@ -8,6 +8,11 @@ import com.willfp.eco.core.integrations.anticheat.AnticheatManager
import com.willfp.eco.core.integrations.antigrief.AntigriefManager
import com.willfp.eco.core.integrations.customitems.CustomItemsManager
import com.willfp.eco.core.integrations.mcmmo.McmmoManager
import com.willfp.eco.core.integrations.shop.ShopManager
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.args.EnchantmentArgParser
import com.willfp.eco.core.items.args.TextureArgParser
import com.willfp.eco.internal.display.EcoDisplayHandler
import com.willfp.eco.internal.drops.DropManager
import com.willfp.eco.proxy.BlockBreakProxy
import com.willfp.eco.proxy.FastItemStackFactoryProxy
@@ -19,8 +24,10 @@ import com.willfp.eco.spigot.eventlisteners.*
import com.willfp.eco.spigot.gui.GUIListener
import com.willfp.eco.spigot.integrations.anticheat.*
import com.willfp.eco.spigot.integrations.antigrief.*
import com.willfp.eco.spigot.integrations.customitems.CustomItemsItemsAdder
import com.willfp.eco.spigot.integrations.customitems.CustomItemsOraxen
import com.willfp.eco.spigot.integrations.mcmmo.McmmoIntegrationImpl
import com.willfp.eco.spigot.integrations.shop.ShopShopGuiPlus
import com.willfp.eco.spigot.recipes.ShapedRecipeListener
import com.willfp.eco.util.BlockUtils
import com.willfp.eco.util.SkullUtils
@@ -39,13 +46,23 @@ abstract class EcoSpigotPlugin : EcoPlugin(
"&a"
) {
init {
Display.setFinalizeKey(namespacedKeyFactory.create("finalized"))
Items.registerArgParser(EnchantmentArgParser())
Items.registerArgParser(TextureArgParser())
val skullProxy = getProxy(SkullProxy::class.java)
SkullUtils.initialize { meta: SkullMeta, base64: String -> skullProxy.setSkullTexture(meta, base64) }
SkullUtils.initialize(
{ meta: SkullMeta, base64: String -> skullProxy.setSkullTexture(meta, base64) },
{ meta: SkullMeta -> skullProxy.getSkullTexture(meta) }
)
val blockBreakProxy = getProxy(BlockBreakProxy::class.java)
BlockUtils.initialize { player: Player, block: Block -> blockBreakProxy.breakBlock(player, block) }
postInit()
}
private fun postInit() {
Display.handler = EcoDisplayHandler(this)
}
override fun handleEnable() {
@@ -77,6 +94,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
override fun handleAfterLoad() {
CustomItemsManager.registerAllItems()
ShopManager.registerEcoProvider()
}
override fun loadIntegrationLoaders(): List<IntegrationLoader> {
@@ -109,6 +127,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
// Custom Items
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) },
IntegrationLoader("ItemsAdder") { CustomItemsManager.register(CustomItemsItemsAdder(this)) },
// Shop
IntegrationLoader("ShopGUIPlus") { ShopManager.register(ShopShopGuiPlus()) },
// Misc
IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) }
@@ -116,19 +138,14 @@ abstract class EcoSpigotPlugin : EcoPlugin(
}
override fun loadPacketAdapters(): List<AbstractPacketAdapter> {
val adapters = mutableListOf(
return listOf(
PacketAutoRecipe(this),
PacketChat(this),
PacketSetCreativeSlot(this),
PacketSetSlot(this),
PacketWindowItems(this)
PacketWindowItems(this),
PacketOpenWindowMerchant(this)
)
if (!configYml.getBool("disable-display-on-villagers")) {
adapters.add(PacketOpenWindowMerchant(this))
}
return adapters
}
override fun loadListeners(): List<Listener> {

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.spigot.arrows
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent
import org.bukkit.Material
import org.bukkit.entity.Arrow
import org.bukkit.entity.LivingEntity
@@ -11,8 +10,8 @@ import org.bukkit.event.Listener
import org.bukkit.event.entity.ProjectileLaunchEvent
class ArrowDataListener(
plugin: EcoPlugin
) : PluginDependent<EcoPlugin>(plugin), Listener {
private val plugin: EcoPlugin
) : Listener {
@EventHandler(priority = EventPriority.LOWEST)
fun onLaunch(event:ProjectileLaunchEvent) {

View File

@@ -19,7 +19,7 @@ class PacketOpenWindowMerchant(plugin: EcoPlugin) :
player: Player,
event: PacketEvent
) {
val recipes: MutableList<MerchantRecipe> = ArrayList()
val recipes = mutableListOf<MerchantRecipe>()
/*

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.spigot.eventlisteners
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent
import org.bukkit.entity.LivingEntity
import org.bukkit.event.EventHandler
import org.bukkit.event.EventPriority
@@ -11,8 +10,8 @@ import org.bukkit.event.entity.EntityDeathEvent
import java.util.concurrent.atomic.AtomicReference
class EntityDeathByEntityListeners(
plugin: EcoPlugin
) : PluginDependent<EcoPlugin>(plugin), Listener {
private val plugin: EcoPlugin
) : Listener {
private val events = HashSet<EntityDeathByEntityBuilder>()
@EventHandler(priority = EventPriority.HIGH)

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.spigot.gui
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent
import com.willfp.eco.core.drops.DropQueue
import com.willfp.eco.internal.gui.menu.EcoMenu
import com.willfp.eco.internal.gui.menu.MenuHandler
@@ -16,7 +15,7 @@ import org.bukkit.event.inventory.ClickType
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Listener {
class GUIListener(private val plugin: EcoPlugin) : Listener {
@EventHandler
fun handleSlotClick(event: InventoryClickEvent) {
val player = event.whoClicked
@@ -33,7 +32,13 @@ class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Liste
event.isCancelled = true
ecoSlot.handleInventoryClick(event, menu)
plugin.scheduler.run{ MenuHandler.getExtendedInventory(event.clickedInventory!!)!!.refresh(player) }
if (event.clickedInventory == null) {
return
}
val extendedInventory = MenuHandler.getExtendedInventory(event.clickedInventory!!) ?: return
plugin.scheduler.run { extendedInventory.refresh(player) }
}
@EventHandler
@@ -46,7 +51,7 @@ class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Liste
MenuHandler.getMenu(player.openInventory.topInventory) ?: return
MenuHandler.getExtendedInventory(player.openInventory.topInventory) ?: return
plugin.scheduler.run{ MenuHandler.getExtendedInventory(player.openInventory.topInventory)?.refresh(player) }
plugin.scheduler.run { MenuHandler.getExtendedInventory(player.openInventory.topInventory)?.refresh(player) }
}
@EventHandler
@@ -68,9 +73,7 @@ class GUIListener(plugin: EcoPlugin) : PluginDependent<EcoPlugin>(plugin), Liste
val menu = MenuHandler.getMenu(inv) ?: return
val rowColumn = MenuUtils.convertSlotToRowColumn(inv.firstEmpty())
val row = rowColumn.first!!
val column = rowColumn.second!!
val (row, column) = MenuUtils.convertSlotToRowColumn(inv.firstEmpty())
val slot = menu.getSlot(row, column)
if (!slot.isCaptive) {

View File

@@ -1,7 +1,6 @@
package com.willfp.eco.spigot.integrations.antigrief
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.PluginDependent
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
import me.angeschossen.lands.api.integration.LandsIntegration
import me.angeschossen.lands.api.role.enums.RoleSetting
@@ -10,8 +9,8 @@ import org.bukkit.block.Block
import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player
class AntigriefLands(plugin: EcoPlugin) : PluginDependent<EcoPlugin?>(plugin), AntigriefWrapper {
private val landsIntegration = LandsIntegration(this.plugin!!)
class AntigriefLands(private val plugin: EcoPlugin) : AntigriefWrapper {
private val landsIntegration = LandsIntegration(this.plugin)
override fun canBreakBlock(
player: Player,
block: Block

View File

@@ -0,0 +1,36 @@
package com.willfp.eco.spigot.integrations.customitems
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.integrations.customitems.CustomItemsWrapper
import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.util.NamespacedKeyUtils
import dev.lone.itemsadder.api.CustomStack
import dev.lone.itemsadder.api.ItemsAdder
import org.bukkit.inventory.ItemStack
import java.util.function.Predicate
class CustomItemsItemsAdder(
private val plugin: EcoPlugin
) : CustomItemsWrapper {
override fun registerAllItems() {
plugin.scheduler.runLater({
for (item in ItemsAdder.getAllItems()) {
val stack = item.itemStack
val id = item.id
val key = NamespacedKeyUtils.create("itemsadder", id.lowercase())
CustomItem(
key,
Predicate { test: ItemStack ->
val customStack = CustomStack.byItemStack(test) ?: return@Predicate false
customStack.id.equals(id, ignoreCase = true)
},
stack
).register()
}
}, 2)
}
override fun getPluginName(): String {
return "ItemsAdder"
}
}

View File

@@ -6,13 +6,15 @@ import com.willfp.eco.util.NamespacedKeyUtils
import io.th0rgal.oraxen.items.OraxenItems
import org.bukkit.NamespacedKey
import org.bukkit.inventory.ItemStack
import java.util.*
import java.util.function.Predicate
class CustomItemsOraxen : CustomItemsWrapper {
override fun registerAllItems() {
for (item in OraxenItems.getItems()) {
val stack = item.build()
val id: String = OraxenItems.getIdByItem(item)
val id: String = Objects.requireNonNullElse(OraxenItems.getIdByItem(item), "")
if (id.isEmpty()) continue
val key: NamespacedKey = NamespacedKeyUtils.create("oraxen", id.lowercase())
CustomItem(
key, Predicate { test: ItemStack ->
@@ -23,4 +25,8 @@ class CustomItemsOraxen : CustomItemsWrapper {
).register()
}
}
override fun getPluginName(): String {
return "Oraxen"
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.eco.spigot.integrations.shop
import com.willfp.eco.core.integrations.shop.ShopWrapper
import com.willfp.eco.core.items.Items
import net.brcdev.shopgui.ShopGuiPlusApi
import net.brcdev.shopgui.provider.item.ItemProvider
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.inventory.ItemStack
class ShopShopGuiPlus : ShopWrapper {
override fun registerEcoProvider() {
ShopGuiPlusApi.registerItemProvider(EcoShopGuiPlusProvider())
}
class EcoShopGuiPlusProvider : ItemProvider("eco") {
override fun isValidItem(itemStack: ItemStack?): Boolean {
itemStack ?: return false
return Items.isCustomItem(itemStack)
}
override fun loadItem(configurationSection: ConfigurationSection): ItemStack? {
val id = configurationSection.getString("eco")
return if (id == null) null else Items.lookup(id)?.item
}
override fun compare(itemStack1: ItemStack, itemStack2: ItemStack): Boolean {
return Items.getCustomItem(itemStack1)?.key == Items.getCustomItem(itemStack2)?.key
}
}
override fun getPluginName(): String {
return "ShopGUIPlus"
}
}

View File

@@ -5,7 +5,6 @@
# Options to fix villager bugs left behind from old (buggy) versions.
disable-display-on-villagers: false
villager-display-fix: false
# DropQueue by default uses a faster collated queue system where all drops

View File

@@ -4,6 +4,7 @@ main: com.willfp.eco.spigot.EcoHandler
api-version: 1.16
authors: [Auxilor]
website: willfp.com
load: STARTUP
depend:
- ProtocolLib
softdepend:
@@ -20,6 +21,10 @@ softdepend:
- PlaceholderAPI
- mcMMO
- CombatLogX
- ShopGUIPlus
- ItemsAdder
- Oraxen
- HeadDatabase
libraries:
- org.reflections:reflections:0.9.12
- org.apache.maven:maven-artifact:3.0.3

View File

@@ -8,4 +8,8 @@ interface SkullProxy : AbstractProxy {
meta: SkullMeta,
base64: String
)
fun getSkullTexture(
meta: SkullMeta
): String?
}

View File

@@ -1,2 +1,2 @@
version = 6.4.1
version = 6.8.0
plugin-name = eco