Compare commits

..

26 Commits

Author SHA1 Message Date
Auxilor
2e6463aed9 Fixed global placeholders 2022-01-17 11:15:18 +00:00
Auxilor
2501574eeb Updated to 6.20.0 2022-01-17 11:12:58 +00:00
Auxilor
3c237fd856 Codestyle 2022-01-17 11:12:45 +00:00
Auxilor
7b3fd1d0c2 Moved placeholders to be registered per-plugin 2022-01-17 11:11:46 +00:00
Auxilor
e599add6de Removed arg parsers that were marked for removal several versions ago 2022-01-12 16:27:43 +00:00
Auxilor
1bda970f6b Improved Items performance 2022-01-12 16:17:49 +00:00
Auxilor
eb1f694905 Added item-cache-ttl 2022-01-12 16:14:24 +00:00
Auxilor
efd3403eda Updated to 6.19.1 2022-01-12 16:02:14 +00:00
Auxilor
08b563d528 Improved Items#getCustomItem and Items#isCustomItem performance 2022-01-12 15:59:25 +00:00
Auxilor
c3f88bf7b0 Fixed updatechecker formatting 2022-01-12 11:23:01 +00:00
Auxilor
eb6d76e0c6 Updated to 6.19.0 2022-01-12 11:17:32 +00:00
Auxilor
f2d0e8c368 Merge branch 'master' into develop 2022-01-12 11:17:23 +00:00
Auxilor
5e7b9573a1 Switched try/catch blocks to runCatching in kotlin and improved async packet encoding 2022-01-12 11:17:03 +00:00
Auxilor
7d457ea496 Added more safety checks to compiled expressions 2022-01-12 08:31:45 +00:00
Auxilor
806bf9a43f Added getDouble/IntFromExpression to Config 2022-01-11 17:05:22 +00:00
Auxilor
316f134b71 NumberUtils changes 2022-01-11 16:54:32 +00:00
Auxilor
0d363b9fb6 Added error safety to CrunchHandler 2022-01-11 16:51:38 +00:00
Auxilor
2890083eaa Excluded lang3 2022-01-11 16:47:57 +00:00
Auxilor
694646431b Fixed commons lang issue 2022-01-11 16:45:30 +00:00
Auxilor
86d5e9d09e Added support for evaluating mathematical expressions via Crunch 2022-01-11 16:43:36 +00:00
Auxilor
8635e5f7a5 Updated to 6.18.5 2022-01-11 10:01:49 +00:00
Auxilor
aa718649eb Fixed v1_18_R1 remapping bugs 2022-01-11 10:01:40 +00:00
Auxilor
1dc0fa449b Updated to 6.18.4 2022-01-11 09:20:52 +00:00
Auxilor
19e3061a13 Fixed MythicMobs NPE 2022-01-11 09:20:43 +00:00
Auxilor
ecafbd76de Updated to 6.18.3 2022-01-10 11:11:44 +00:00
Auxilor
3728f2fc7a Fixed apache commons lang not existing on classpath 2022-01-10 11:11:31 +00:00
38 changed files with 435 additions and 341 deletions

View File

@@ -64,6 +64,9 @@ allprojects {
// MythicMobs
maven("https://mvn.lumine.io/repository/maven-public/")
// Crunch
maven("https://redempt.dev")
}
dependencies {
@@ -91,12 +94,14 @@ allprojects {
exclude(group = "org.spongepowered", module = "configurate-hocon")
exclude(group = "com.darkblade12", module = "particleeffect")
exclude(group = "com.github.cryptomorin", module = "XSeries")
exclude(group = "org.apache.commons", module = "commons-lang3")
}
tasks {
shadowJar {
relocate("org.bstats", "com.willfp.eco.shaded.bstats")
relocate("net.kyori.adventure.text.minimessage", "com.willfp.eco.shaded.minimessage")
relocate("redempt.crunch", "com.willfp.eco.shaded.crunch")
}
compileJava {

View File

@@ -15,6 +15,7 @@ dependencies {
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.1-SNAPSHOT'
compileOnly 'com.google.code.gson:gson:2.8.8'
compileOnly 'org.apache.commons:commons-lang3:3.0'
}
java {

View File

@@ -327,7 +327,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version);
if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
this.outdated = true;
this.getLogger().warning("&c " + this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
this.getLogger().warning("&c" + this.getName() + " is out of date! (Version " + this.getDescription().getVersion() + ")");
this.getLogger().warning("&cThe newest version is &f" + version);
this.getLogger().warning("&cDownload the new version!");
}

View File

@@ -2,7 +2,9 @@ package com.willfp.eco.core.config.interfaces;
import com.willfp.eco.core.config.ConfigType;
import com.willfp.eco.core.config.TransientConfig;
import com.willfp.eco.util.NumberUtils;
import com.willfp.eco.util.StringUtils;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -108,6 +110,29 @@ public interface Config extends Cloneable {
return Objects.requireNonNullElse(getIntOrNull(path), def);
}
/**
* Get a decimal value via a mathematical expression.
*
* @param path The key to fetch the value from.
* @return The computed value, or 0 if not found or invalid.
*/
default int getIntFromExpression(@NotNull String path) {
return getIntFromExpression(path, null);
}
/**
* Get a decimal value via a mathematical expression.
*
* @param path The key to fetch the value from.
* @param player The player to evaluate placeholders with respect to.
* @return The computed value, or 0 if not found or invalid.
*/
default int getIntFromExpression(@NotNull String path,
@Nullable Player player) {
return Double.valueOf(getDoubleFromExpression(path, player)).intValue();
}
/**
* Get an integer from config.
*
@@ -519,6 +544,28 @@ public interface Config extends Cloneable {
return Objects.requireNonNullElse(getDoubleOrNull(path), 0.0);
}
/**
* Get a decimal value via a mathematical expression.
*
* @param path The key to fetch the value from.
* @return The computed value, or 0 if not found or invalid.
*/
default double getDoubleFromExpression(@NotNull String path) {
return getDoubleFromExpression(path, null);
}
/**
* Get a decimal value via a mathematical expression.
*
* @param path The key to fetch the value from.
* @param player The player to evaluate placeholders with respect to.
* @return The computed value, or 0 if not found or invalid.
*/
default double getDoubleFromExpression(@NotNull String path,
@Nullable Player player) {
return NumberUtils.evaluateExpression(this.getString(path), player);
}
/**
* Get a decimal from config.
*

View File

@@ -53,15 +53,6 @@ public class PersistentDataKey<T> {
+ '}';
}
/**
* Get all persistent data keys.
*
* @return The keys.
*/
public static Set<PersistentDataKey<?>> values() {
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
}
/**
* Get the key.
*
@@ -88,4 +79,13 @@ public class PersistentDataKey<T> {
public PersistentDataKeyType getType() {
return this.type;
}
/**
* Get all persistent data keys.
*
* @return The keys.
*/
public static Set<PersistentDataKey<?>> values() {
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
}
}

View File

@@ -1,6 +1,6 @@
package com.willfp.eco.core.entities;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;

View File

@@ -2,7 +2,7 @@ package com.willfp.eco.core.entities.impl;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.entities.TestableEntity;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package com.willfp.eco.core.entities.impl;
import com.willfp.eco.core.entities.TestableEntity;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;

View File

@@ -1,7 +1,7 @@
package com.willfp.eco.core.entities.impl;
import com.willfp.eco.core.entities.TestableEntity;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.integrations.placeholder;
import com.willfp.eco.core.EcoPlugin;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@@ -28,12 +29,20 @@ public class PlaceholderEntry {
*/
private final boolean requiresPlayer;
/**
* The plugin for the placeholder.
*/
@Nullable
private final EcoPlugin plugin;
/**
* Create a placeholder entry that doesn't require a player.
*
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder given a player.
* @deprecated Specify a plugin.
*/
@Deprecated
public PlaceholderEntry(@NotNull final String identifier,
@NotNull final Function<Player, String> function) {
this(identifier, function, false);
@@ -45,10 +54,41 @@ public class PlaceholderEntry {
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder.
* @param requiresPlayer If the placeholder requires a player.
* @deprecated Specify a plugin.
*/
@Deprecated
public PlaceholderEntry(@NotNull final String identifier,
@NotNull final Function<Player, String> function,
final boolean requiresPlayer) {
this(null, identifier, function, requiresPlayer);
}
/**
* Create a placeholder entry that doesn't require a player.
*
* @param plugin The plugin for the placeholder.
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder given a player.
*/
public PlaceholderEntry(@Nullable final EcoPlugin plugin,
@NotNull final String identifier,
@NotNull final Function<Player, String> function) {
this(plugin, identifier, function, false);
}
/**
* Create a placeholder entry that may require a player.
*
* @param plugin The plugin for the placeholder.
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder.
* @param requiresPlayer If the placeholder requires a player.
*/
public PlaceholderEntry(@Nullable final EcoPlugin plugin,
@NotNull final String identifier,
@NotNull final Function<Player, String> function,
final boolean requiresPlayer) {
this.plugin = plugin;
this.identifier = identifier;
this.function = function;
this.requiresPlayer = requiresPlayer;
@@ -85,6 +125,16 @@ public class PlaceholderEntry {
return identifier;
}
/**
* Get the plugin.
*
* @return The plugin.
*/
@Nullable
public EcoPlugin getPlugin() {
return plugin;
}
/**
* Register the placeholder.
*/

View File

@@ -5,6 +5,9 @@ import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* Wrapper class for placeholder integrations.
*/
@@ -24,4 +27,14 @@ public interface PlaceholderIntegration extends Integration {
*/
String translate(@NotNull String text,
@Nullable Player player);
/**
* Find all placeholders in a given text.
*
* @param text The text.
* @return The placeholders.
*/
default List<String> findPlaceholdersIn(@NotNull String text) {
return new ArrayList<>();
}
}

View File

@@ -1,11 +1,15 @@
package com.willfp.eco.core.integrations.placeholder;
import com.willfp.eco.core.Eco;
import com.willfp.eco.core.EcoPlugin;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -16,7 +20,7 @@ public final class PlaceholderManager {
/**
* All registered placeholders.
*/
private static final Map<String, PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashMap<>();
private static final Map<EcoPlugin, Map<String, PlaceholderEntry>> REGISTERED_PLACEHOLDERS = new HashMap<>();
/**
* All registered placeholder integrations.
@@ -39,8 +43,11 @@ public final class PlaceholderManager {
* @param expansion The {@link PlaceholderEntry} to register.
*/
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
REGISTERED_PLACEHOLDERS.remove(expansion.getIdentifier());
REGISTERED_PLACEHOLDERS.put(expansion.getIdentifier(), expansion);
EcoPlugin plugin = expansion.getPlugin() == null ? Eco.getHandler().getEcoPlugin() : expansion.getPlugin();
Map<String, PlaceholderEntry> pluginPlaceholders = REGISTERED_PLACEHOLDERS
.getOrDefault(plugin, new HashMap<>());
pluginPlaceholders.put(expansion.getIdentifier(), expansion);
REGISTERED_PLACEHOLDERS.put(plugin, pluginPlaceholders);
}
/**
@@ -49,10 +56,36 @@ public final class PlaceholderManager {
* @param player The player to get the result from.
* @param identifier The placeholder identifier.
* @return The value of the placeholder.
* @deprecated Specify a plugin to get the result from.
*/
@Deprecated
public static String getResult(@Nullable final Player player,
@NotNull final String identifier) {
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.get(identifier.toLowerCase());
return getResult(player, identifier, null);
}
/**
* Get the result of a placeholder with respect to a player.
*
* @param player The player to get the result from.
* @param identifier The placeholder identifier.
* @param plugin The plugin for the placeholder.
* @return The value of the placeholder.
*/
public static String getResult(@Nullable final Player player,
@NotNull final String identifier,
@Nullable final EcoPlugin plugin) {
EcoPlugin owner = player == null ? Eco.getHandler().getEcoPlugin() : plugin;
PlaceholderEntry entry = REGISTERED_PLACEHOLDERS.getOrDefault(owner, new HashMap<>()).get(identifier.toLowerCase());
if (entry == null && plugin != null) {
PlaceholderEntry alternate = REGISTERED_PLACEHOLDERS.getOrDefault(Eco.getHandler().getEcoPlugin(), new HashMap<>())
.get(identifier.toLowerCase());
if (alternate != null) {
entry = alternate;
}
}
if (entry == null) {
return "";
}
@@ -80,6 +113,21 @@ public final class PlaceholderManager {
return processed;
}
/**
* Find all placeholders in a given text.
*
* @param text The text.
* @return The placeholders.
*/
public static List<String> findPlaceholdersIn(@NotNull final String text) {
List<String> found = new ArrayList<>();
for (PlaceholderIntegration integration : REGISTERED_INTEGRATIONS) {
found.addAll(integration.findPlaceholdersIn(text));
}
return found;
}
private PlaceholderManager() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.core.items;
import com.willfp.eco.core.fast.FastItemStack;
import com.willfp.eco.core.items.args.LookupArgParser;
import com.willfp.eco.core.items.provider.ItemProvider;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
@@ -13,6 +14,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,6 +36,11 @@ public final class Items {
*/
private static final Map<NamespacedKey, TestableItem> REGISTRY = new ConcurrentHashMap<>();
/**
* Cached custom item lookups, using {@link FastItemStack#hashCode()}.
*/
private static final Map<Integer, TestableItem> CACHE = new ConcurrentHashMap<>();
/**
* All item providers.
*/
@@ -276,12 +283,7 @@ public final class Items {
* @return If is recipe.
*/
public static boolean isCustomItem(@NotNull final ItemStack itemStack) {
for (TestableItem item : REGISTRY.values()) {
if (item.matches(itemStack)) {
return true;
}
}
return false;
return getCustomItem(itemStack) != null;
}
/**
@@ -292,12 +294,30 @@ public final class Items {
*/
@Nullable
public static CustomItem getCustomItem(@NotNull final ItemStack itemStack) {
int hash = FastItemStack.wrap(itemStack).hashCode();
TestableItem cached = CACHE.get(hash);
if (cached != null) {
return getOrWrap(cached);
} else {
CACHE.remove(hash);
}
TestableItem match = null;
for (TestableItem item : REGISTRY.values()) {
if (item.matches(itemStack)) {
return getOrWrap(item);
match = item;
break;
}
}
return null;
if (match == null) {
return null;
}
CACHE.put(hash, match);
return getOrWrap(match);
}
/**
@@ -331,6 +351,14 @@ public final class Items {
}
}
/**
* Clear the lookup cache.
*/
@ApiStatus.Internal
public static void clearCache() {
CACHE.clear();
}
private Items() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

View File

@@ -1,36 +0,0 @@
package com.willfp.eco.core.items.args;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parse leather armor colors.
*
* @deprecated Moved to internals.
*/
@Deprecated(since = "6.16.0", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
public class ColorArgParser implements LookupArgParser {
/**
* Instantiate arg parser.
*/
public ColorArgParser() {
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
}
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
return null;
}
static {
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + ColorArgParser.class.getName() + "), this will throw an error in the next release!");
}
}

View File

@@ -1,36 +0,0 @@
package com.willfp.eco.core.items.args;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parse custom model data.
*
* @deprecated Moved to internals.
*/
@Deprecated(since = "6.16.0", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
public class CustomModelDataArgParser implements LookupArgParser {
/**
* Instantiate arg parser.
*/
public CustomModelDataArgParser() {
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
}
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
return null;
}
static {
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + CustomModelDataArgParser.class.getName() + "), this will throw an error in the next release!");
}
}

View File

@@ -1,36 +0,0 @@
package com.willfp.eco.core.items.args;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parses enchantment arguments.
*
* @deprecated Moved to internals.
*/
@Deprecated(since = "6.16.0", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
public class EnchantmentArgParser implements LookupArgParser {
/**
* Instantiate arg parser.
*/
public EnchantmentArgParser() {
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
}
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
return null;
}
static {
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + EnchantmentArgParser.class.getName() + "), this will throw an error in the next release!");
}
}

View File

@@ -1,36 +0,0 @@
package com.willfp.eco.core.items.args;
import org.bukkit.Bukkit;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* Parse skull textures.
*
* @deprecated Moved to internals.
*/
@Deprecated(since = "6.16.0", forRemoval = true)
@ApiStatus.ScheduledForRemoval(inVersion = "6.18.2")
public class TextureArgParser implements LookupArgParser {
/**
* Instantiate arg parser.
*/
public TextureArgParser() {
Bukkit.getLogger().severe("Instantiation of class marked for removal! (" + this.getClass().getName() + "), this will throw an error in a future release!");
}
@Override
public @Nullable Predicate<ItemStack> parseArguments(@NotNull final String[] args,
@NotNull final ItemMeta meta) {
return null;
}
static {
Bukkit.getLogger().severe("Referencing a class marked for removal! (" + TextureArgParser.class.getName() + "), this will throw an error in the next release!");
}
}

View File

@@ -1,11 +1,16 @@
package com.willfp.eco.util;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.text.DecimalFormat;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiFunction;
/**
* Utilities / API methods for numbers.
@@ -16,6 +21,11 @@ public final class NumberUtils {
*/
private static final double[] SIN_LOOKUP = new double[65536];
/**
* Crunch handler.
*/
private static BiFunction<String, Player, Double> crunch = null;
/**
* Set of roman numerals to look up.
*/
@@ -83,7 +93,9 @@ public final class NumberUtils {
* @param toChange The value to test.
* @param limit The maximum.
* @return The new value.
* @deprecated Pointless method.
*/
@Deprecated(since = "6.19.0")
public static int equalIfOver(final int toChange,
final int limit) {
return Math.min(toChange, limit);
@@ -95,7 +107,9 @@ public final class NumberUtils {
* @param toChange The value to test.
* @param limit The maximum.
* @return The new value.
* @deprecated Pointless method.
*/
@Deprecated(since = "6.19.0")
public static double equalIfOver(final double toChange,
final double limit) {
return Math.min(toChange, limit);
@@ -218,6 +232,39 @@ public final class NumberUtils {
return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted;
}
/**
* Evaluate an expression.
*
* @param expression The expression.
* @return The value of the expression, or zero if invalid.
*/
public static double evaluateExpression(@NotNull final String expression) {
return evaluateExpression(expression, null);
}
/**
* Evaluate an expression with respect to a player (for placeholders).
*
* @param expression The expression.
* @param player The player.
* @return The value of the expression, or zero if invalid.
*/
public static double evaluateExpression(@NotNull final String expression,
@Nullable final Player player) {
return crunch.apply(expression, player);
}
/**
* Init crunch handler.
*
* @param handler The handler.
*/
@ApiStatus.Internal
public static void initCrunch(@NotNull final BiFunction<String, Player, Double> handler) {
Validate.isTrue(crunch == null, "Already initialized!");
crunch = handler;
}
private NumberUtils() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

View File

@@ -24,11 +24,7 @@ open class EcoLoadableJSONConfig(
private val name: String = "$configName.json"
fun reloadFromFile() {
try {
init(configFile)
} catch (e: IOException) {
e.printStackTrace()
}
runCatching { init(configFile) }.onFailure { it.printStackTrace() }
}
final override fun createFile() {
@@ -94,11 +90,7 @@ open class EcoLoadableJSONConfig(
createFile()
}
configFile = File(directory, name)
try {
init(configFile)
} catch (e: IOException) {
e.printStackTrace()
}
init(configFile)
plugin.configHandler.addConfig(this)
}
}

View File

@@ -1,10 +1,8 @@
package com.willfp.eco.internal.config.json
import com.willfp.eco.core.PluginLike
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
@@ -21,34 +19,28 @@ open class EcoUpdatableJSONConfig(
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()
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()
}
private val configInJar: YamlConfiguration
@@ -56,13 +48,7 @@ open class EcoUpdatableJSONConfig(
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()
}
newConfig.load(reader)
return newConfig
}

View File

@@ -24,15 +24,15 @@ class EcoConfigHandler(
override fun callUpdate() {
for (method in reflections.getMethodsAnnotatedWith(ConfigUpdater::class.java)) {
try {
kotlin.runCatching {
when (method.parameterCount) {
0 -> method.invoke(null)
1 -> method.invoke(null, this.plugin)
else -> throw InvalidUpdateMethodException("Update method must have 0 parameters or a plugin parameter.")
}
} catch (e: ReflectiveOperationException) {
e.printStackTrace()
throw InvalidUpdateMethodException("Update method generated an exception")
}.onFailure {
it.printStackTrace()
plugin.logger.severe("Update method ${method.toGenericString()} generated an exception")
}
}
}

View File

@@ -5,7 +5,6 @@ package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.PluginLike
import com.willfp.eco.core.config.interfaces.LoadableConfig
import com.willfp.eco.core.config.interfaces.WrappedYamlConfiguration
import org.bukkit.configuration.InvalidConfigurationException
import org.bukkit.configuration.file.YamlConfiguration
import java.io.File
import java.io.FileOutputStream
@@ -23,13 +22,7 @@ open class EcoLoadableYamlConfig(
private val name: String = "$configName.yml"
fun reloadFromFile() {
try {
handle.load(getConfigFile())
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
}
handle.load(getConfigFile())
}
final override fun createFile() {

View File

@@ -1,10 +1,8 @@
package com.willfp.eco.internal.config.yaml
import com.willfp.eco.core.PluginLike
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
@@ -21,34 +19,28 @@ class EcoUpdatableYamlConfig(
fun update() {
super.clearCache()
try {
this.handle.load(configFile)
val newConfig = configInJar
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
return
}
newConfig.getKeys(true).forEach { key ->
if (!this.handle.getKeys(true).contains(key)) {
if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
this.handle.set(key, newConfig[key])
}
}
}
if (removeUnused) {
this.handle.getKeys(true).forEach { s ->
if (!newConfig.getKeys(true).contains(s)) {
if (updateBlacklist.stream().noneMatch(s::contains)) {
this.handle.set(s, null)
}
}
}
}
this.handle.save(configFile)
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
this.handle.load(configFile)
val newConfig = configInJar
if (newConfig.getKeys(true) == this.handle.getKeys(true)) {
return
}
newConfig.getKeys(true).forEach { key ->
if (!this.handle.getKeys(true).contains(key)) {
if (updateBlacklist.stream().noneMatch { key.contains(it) }) {
this.handle.set(key, newConfig[key])
}
}
}
if (removeUnused) {
this.handle.getKeys(true).forEach { s ->
if (!newConfig.getKeys(true).contains(s)) {
if (updateBlacklist.stream().noneMatch(s::contains)) {
this.handle.set(s, null)
}
}
}
}
this.handle.save(configFile)
}
private val configInJar: YamlConfiguration
@@ -56,13 +48,7 @@ class EcoUpdatableYamlConfig(
val newIn = source.getResourceAsStream(resourcePath) ?: throw NullPointerException("$name is null?")
val reader = BufferedReader(InputStreamReader(newIn, StandardCharsets.UTF_8))
val newConfig = YamlConfiguration()
try {
newConfig.load(reader)
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InvalidConfigurationException) {
e.printStackTrace()
}
newConfig.load(reader)
return newConfig
}

View File

@@ -10,8 +10,6 @@ import com.willfp.eco.core.extensions.MalformedExtensionException
import org.bukkit.configuration.file.YamlConfiguration
import java.io.File
import java.io.InputStreamReader
import java.net.MalformedURLException
import java.net.URL
import java.net.URLClassLoader
class EcoExtensionLoader(
@@ -32,9 +30,7 @@ class EcoExtensionLoader(
continue
}
try {
loadExtension(extensionJar)
} catch (e: MalformedExtensionException) {
runCatching { loadExtension(extensionJar) }.onFailure {
this.plugin.logger.warning(extensionJar.name + " caused an error!")
}
}
@@ -42,13 +38,7 @@ class EcoExtensionLoader(
@Throws(MalformedExtensionException::class)
private fun loadExtension(extensionJar: File) {
lateinit var url: URL
try {
url = extensionJar.toURI().toURL()
} catch (e: MalformedURLException) {
e.printStackTrace()
}
val url = extensionJar.toURI().toURL()
val classLoader = URLClassLoader(arrayOf(url), this.plugin::class.java.classLoader)
val ymlIn = classLoader.getResourceAsStream("extension.yml")

View File

@@ -32,7 +32,7 @@ class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExp
player: Player?,
identifier: String
): String {
return PlaceholderManager.getResult(player, identifier)
return PlaceholderManager.getResult(player, identifier, plugin)
}
override fun registerIntegration() {
@@ -49,4 +49,14 @@ class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExp
): String {
return PlaceholderAPI.setPlaceholders(player, text)
}
override fun findPlaceholdersIn(text: String): MutableList<String> {
val placeholders = mutableListOf<String>()
val matcher = PlaceholderAPI.getPlaceholderPattern().matcher(text)
while (matcher.find()) {
placeholders.add(matcher.group())
}
return placeholders
}
}

View File

@@ -11,12 +11,7 @@ class ArgParserFlag : LookupArgParser {
val flags = mutableSetOf<ItemFlag>()
for (arg in args) {
val flag = try {
ItemFlag.valueOf(arg.uppercase())
} catch (e: Exception) {
null
} ?: continue
val flag = kotlin.runCatching { ItemFlag.valueOf(arg.uppercase()) }.getOrNull() ?: continue
flags.add(flag)
}

View File

@@ -1,4 +1,5 @@
package com.willfp.eco.internal.spigot.proxy.v1_16_R3
import com.willfp.eco.core.display.Display
import com.willfp.eco.internal.spigot.proxy.VillagerTradeProxy
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftMerchantRecipe
@@ -30,21 +31,11 @@ class VillagerTrade : VillagerTradeProxy {
}
private fun getHandle(recipe: CraftMerchantRecipe): net.minecraft.server.v1_16_R3.MerchantRecipe {
try {
return handle[recipe] as net.minecraft.server.v1_16_R3.MerchantRecipe
} catch (e: IllegalAccessException) {
e.printStackTrace()
}
throw IllegalArgumentException("Not CMR")
return handle[recipe] as net.minecraft.server.v1_16_R3.MerchantRecipe
}
init {
try {
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
handle.isAccessible = true
} catch (e: NoSuchFieldException) {
e.printStackTrace()
throw RuntimeException("Error!")
}
handle = CraftMerchantRecipe::class.java.getDeclaredField("handle")
handle.isAccessible = true
}
}

View File

@@ -24,9 +24,9 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> {
val enchantmentNBT =
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle
) else handle.enchantmentTags
) else handle.getEnchantmentTags()
val foundEnchantments: MutableMap<Enchantment, Int> = HashMap()
for (base in enchantmentNBT) {
val compound = base as CompoundTag
@@ -45,9 +45,9 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
checkStored: Boolean
): Int {
val enchantmentNBT =
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
if (checkStored && handle.getItem() === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle
) else handle.enchantmentTags
) else handle.getEnchantmentTags()
for (base in enchantmentNBT) {
val compound = base as CompoundTag
val key = compound.getString("id")
@@ -152,16 +152,16 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
private var flagBits: Int
get() =
if (handle.hasTag() && handle.tag!!.contains(
if (handle.hasTag() && handle.getTag()!!.contains(
"HideFlags",
99
)
) handle.tag!!.getInt("HideFlags") else 0
) handle.getTag()!!.getInt("HideFlags") else 0
set(value) =
handle.orCreateTag.putInt("HideFlags", value)
handle.getOrCreateTag().putInt("HideFlags", value)
override fun getRepairCost(): Int {
return handle.baseRepairCost
return handle.getBaseRepairCost()
}
override fun setRepairCost(cost: Int) {
@@ -177,7 +177,7 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
}
override fun hashCode(): Int {
return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.getItem()))
return handle.getTag()?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.getItem()))
}
private fun apply() {

View File

@@ -5,6 +5,7 @@ dependencies {
implementation('net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT') {
exclude group: 'net.kyori', module: 'adventure-api'
}
implementation 'com.github.Redempt:Crunch:1.0'
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
compileOnly 'org.apache.maven:maven-artifact:3.8.1'
compileOnly 'com.google.code.gson:gson:2.8.8'

View File

@@ -94,12 +94,14 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicD
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
import com.willfp.eco.internal.spigot.integrations.shop.ShopShopGuiPlus
import com.willfp.eco.internal.spigot.math.evaluateExpression
import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
import com.willfp.eco.internal.spigot.proxy.SkullProxy
import com.willfp.eco.internal.spigot.proxy.TPSProxy
import com.willfp.eco.internal.spigot.recipes.ShapedRecipeListener
import com.willfp.eco.util.BlockUtils
import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.ServerUtils
import com.willfp.eco.util.SkullUtils
import net.kyori.adventure.platform.bukkit.BukkitAudiences
@@ -154,6 +156,8 @@ abstract class EcoSpigotPlugin : EcoPlugin(
val tpsProxy = getProxy(TPSProxy::class.java)
ServerUtils.initialize { tpsProxy.getTPS() }
NumberUtils.initCrunch { exp, player -> evaluateExpression(exp, player) }
postInit()
}
@@ -186,6 +190,11 @@ abstract class EcoSpigotPlugin : EcoPlugin(
CollatedRunnable(this)
DropManager.update(this)
ProfileSaver(this)
this.scheduler.runTimer(
{ Items.clearCache() },
this.configYml.getInt("item-cache-ttl").toLong(),
this.configYml.getInt("item-cache-ttl").toLong()
)
this.scheduler.runTimer(
{ clearFrames() },
this.configYml.getInt("display-frame-ttl").toLong(),
@@ -234,7 +243,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
IntegrationLoader("Alice") { AnticheatManager.register(this, AnticheatAlice()) },
// Custom Entities
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs())},
IntegrationLoader("MythicMobs") { CustomEntitiesManager.register(CustomEntitiesMythicMobs()) },
// Custom Items
IntegrationLoader("Oraxen") { CustomItemsManager.register(CustomItemsOraxen()) },

View File

@@ -55,7 +55,7 @@ class MySQLDataHandler(
}
// Get Exposed to shut the hell up
try {
runCatching {
exposedLogger::class.java.getDeclaredField("logger").apply { isAccessible = true }
.apply {
get(exposedLogger).apply {
@@ -63,8 +63,6 @@ class MySQLDataHandler(
.invoke(this, Level.OFF)
}
}
} catch (e: Exception) {
Eco.getHandler().ecoPlugin.logger.warning("Failed to silence Exposed logger! You might get some console spam")
}
}

View File

@@ -8,7 +8,6 @@ import com.willfp.eco.core.AbstractPacketAdapter
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.internal.spigot.proxy.AutoCraftProxy
import org.bukkit.entity.Player
import java.lang.reflect.InvocationTargetException
class PacketAutoRecipe(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.AUTO_RECIPE, false) {
override fun onSend(
@@ -27,10 +26,6 @@ class PacketAutoRecipe(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packet
getPlugin().getProxy(AutoCraftProxy::class.java).modifyPacket(packet.handle)
val newAutoRecipe = PacketContainer(PacketType.Play.Server.AUTO_RECIPE)
newAutoRecipe.minecraftKeys.write(0, packet.minecraftKeys.read(0))
try {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newAutoRecipe)
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newAutoRecipe)
}
}

View File

@@ -47,34 +47,42 @@ class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, Packe
handleRateLimit(player)
if (usingAsync(player)) {
val newPacket = packet.shallowClone()
fun modifyAndSend(itemStacks: MutableList<ItemStack>, windowId: Int, player: Player) {
modifyWindowItems(itemStacks, windowId, player)
newPacket.itemListModifier.write(0, itemStacks)
ignorePacketList.add(player.name)
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket)
}
executor.execute {
try {
modifyAndSend(itemStacks, windowId, player)
} catch (e: Exception) {
runCatching {
modifyAndSend(packet.shallowClone(), itemStacks, windowId, player)
}.onFailure {
if (this.getPlugin().configYml.getBool("async-display.log-errors")) {
this.getPlugin().logger.warning("Error happened in async processing! Disable async display (/plugins/eco/config.yml)" +
"if this is a frequent issue. (Remember to disable ratelimit and emergency too)")
}
this.getPlugin().scheduler.run {
modifyAndSend(itemStacks, windowId, player)
this.getPlugin().logger.warning(
"Error happened in async processing! Disable async display (/plugins/eco/config.yml)" +
"if this is a frequent issue. (Remember to disable ratelimit and emergency too)"
)
}
}
}
} else {
packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player))
modifyPacket(packet, itemStacks, windowId, player)
}
}
private fun modifyPacket(
packet: PacketContainer,
itemStacks: MutableList<ItemStack>,
windowId: Int,
player: Player
) {
packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player))
}
private fun modifyAndSend(
packet: PacketContainer,
itemStacks: MutableList<ItemStack>,
windowId: Int,
player: Player
) {
modifyPacket(packet, itemStacks, windowId, player)
ignorePacketList.add(player.name)
this.getPlugin().scheduler.run {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet)
}
}

View File

@@ -2,8 +2,8 @@ package com.willfp.eco.internal.spigot.integrations.customentities
import com.willfp.eco.core.entities.CustomEntity
import com.willfp.eco.core.integrations.customentities.CustomEntitiesWrapper
import com.willfp.eco.util.NamespacedKeyUtils
import io.lumine.xikage.mythicmobs.MythicMobs
import org.bukkit.NamespacedKey
class CustomEntitiesMythicMobs : CustomEntitiesWrapper {
override fun registerAllEntities() {
@@ -11,7 +11,8 @@ class CustomEntitiesMythicMobs : CustomEntitiesWrapper {
val api = MythicMobs.inst().apiHelper
for (id in mobManager.mobNames) {
val key = NamespacedKeyUtils.create("mythicmobs", id.lowercase())
val key = NamespacedKey.fromString("mythicmobs:${id.lowercase()}")
key ?: continue
CustomEntity(
key,
{

View File

@@ -0,0 +1,38 @@
package com.willfp.eco.internal.spigot.math
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import org.bukkit.entity.Player
import redempt.crunch.CompiledExpression
import redempt.crunch.Crunch
import redempt.crunch.data.FastNumberParsing
import redempt.crunch.functional.EvaluationEnvironment
private val cache = mutableMapOf<String, CompiledExpression>()
private val goToZero = Crunch.compileExpression("0")
fun evaluateExpression(expression: String, player: Player?): Double {
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
.map { PlaceholderManager.translatePlaceholders(expression, player) }
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
.toDoubleArray()
val compiled = generateExpression(expression)
return runCatching { compiled.evaluate(*placeholderValues) }.getOrDefault(0.0)
}
private fun generateExpression(expression: String): CompiledExpression {
val cached = cache[expression]
if (cached != null) {
return cached
}
val placeholders = PlaceholderManager.findPlaceholdersIn(expression)
val env = EvaluationEnvironment()
env.setVariableNames(*placeholders.toTypedArray())
val compiled = runCatching { Crunch.compileExpression(expression, env) }.getOrDefault(goToZero)
cache[expression] = compiled
return compiled
}

View File

@@ -41,6 +41,11 @@ use-display-frame: true
# that display frames will be cleared / deleted.
display-frame-ttl: 17
# Time to live for storing hashes against custom item keys. Increasing this value
# can benefit performance under load (e.g. from ShopGUI+ sells) but can increase
# memory use.
item-cache-ttl: 6000
# Window items packets have the option to be run asynchronously. This may cause
# some bugs and is considered experimental, however it has been tested without
# any apparent issues. Enable this if performance is absolutely crucial or if you

View File

@@ -53,4 +53,5 @@ libraries:
- 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
- 'mysql:mysql-connector-java:8.0.25'
- 'com.google.guava:guava:31.0.1-jre'
- 'com.zaxxer:HikariCP:5.0.0'
- 'com.zaxxer:HikariCP:5.0.0'
- 'org.apache.commons:commons-lang3:3.0'

View File

@@ -1,3 +1,3 @@
version = 6.18.2
version = 6.20.0
plugin-name = eco
kotlin.code.style = official