diff --git a/.idea/libraries/SpigotWizCompat.xml b/.idea/libraries/SpigotWizCompat.xml new file mode 100644 index 0000000..6418489 --- /dev/null +++ b/.idea/libraries/SpigotWizCompat.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/SpigotInvTweaks.iml b/SpigotInvTweaks.iml index 347538c..67e4969 100644 --- a/SpigotInvTweaks.iml +++ b/SpigotInvTweaks.iml @@ -9,5 +9,6 @@ + \ No newline at end of file diff --git a/res/plugin.yml b/res/plugin.yml index 808c757..f036d63 100644 --- a/res/plugin.yml +++ b/res/plugin.yml @@ -3,6 +3,8 @@ version: 1.3.3 author: IKEA_Jesus main: dev.w1zzrd.invtweaks.InvTweaksPlugin api-version: 1.13 +depend: + - WizCompat commands: sort: description: Sort chest you are looking at diff --git a/src/dev/w1zzrd/invtweaks/DataStore.java b/src/dev/w1zzrd/invtweaks/DataStore.java deleted file mode 100644 index 911cc91..0000000 --- a/src/dev/w1zzrd/invtweaks/DataStore.java +++ /dev/null @@ -1,93 +0,0 @@ -package dev.w1zzrd.invtweaks; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.InvalidConfigurationException; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.configuration.serialization.ConfigurationSerializable; -import org.bukkit.plugin.Plugin; - -import java.io.File; -import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Manager for persistent data storage for a plugin - */ -public class DataStore { - - private static final Logger logger = Bukkit.getLogger(); - - private final File storeFile; - private final FileConfiguration config; - - /** - * Create a data store with the given name. This will attempt to load a yaml file named after the store - * @param storeName Name of the store to load. File will be named storeName + ".yml" - * @param plugin Plugin to associate the data store with - */ - public DataStore(final String storeName, final Plugin plugin) { - storeFile = new File(plugin.getDataFolder(), storeName + ".yml"); - config = YamlConfiguration.loadConfiguration(storeFile); - - // Save config in case it doesn't exist - saveData(); - } - - /** - * Load a value from the data store - * @param path Path in the file to load the data from - * @param defaultValue Getter for a default value, in case the data does not exist in the store - * @param Type of the data to load - * @return Data at the given path, if available, else the default value - */ - public T loadData(final String path, final DefaultGetter defaultValue) { - final T value = (T) config.get(path); - return value == null ? defaultValue.get() : value; - } - - /** - * Save data at a given path in the store - * @param path Path to store data at - * @param value Data to store - * @param Type of {@link ConfigurationSerializable} data to store - */ - public void storeData(final String path, final T value) { - config.set(path, value); - } - - /** - * Save the current data store in memory to persistent memory - */ - public void saveData() { - try { - config.save(storeFile); - } catch (IOException e) { - logger.log(Level.SEVERE, Logger.GLOBAL_LOGGER_NAME + " Could not save data due to an I/O error", e); - } - } - - /** - * Reload data store from persistent memory, overwriting any current state - */ - public void loadData() { - try { - config.load(storeFile); - } catch (IOException | InvalidConfigurationException e) { - logger.log(Level.SEVERE, Logger.GLOBAL_LOGGER_NAME + " Could not load data due to an I/O error", e); - } - } - - /** - * Functional interface for constructing default values - * @param Type to construct - */ - public interface DefaultGetter { - /** - * Instantiate default value - * @return Default value that was instantiated - */ - T get(); - } -} diff --git a/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java b/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java index ee5581a..c570dea 100644 --- a/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java +++ b/src/dev/w1zzrd/invtweaks/InvTweaksPlugin.java @@ -6,17 +6,16 @@ import dev.w1zzrd.invtweaks.listener.*; import dev.w1zzrd.invtweaks.serialization.MagnetConfig; import dev.w1zzrd.invtweaks.serialization.MagnetData; import dev.w1zzrd.invtweaks.serialization.SearchConfig; -import dev.w1zzrd.invtweaks.serialization.UUIDList; +import dev.w1zzrd.spigot.wizcompat.enchantment.EnchantmentRegistryEntry; +import dev.w1zzrd.spigot.wizcompat.enchantment.ServerEnchantmentRegistry; +import dev.w1zzrd.spigot.wizcompat.serialization.PersistentData; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; import org.bukkit.configuration.serialization.ConfigurationSerialization; -import org.bukkit.enchantments.Enchantment; import org.bukkit.event.HandlerList; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; -import java.lang.reflect.Field; -import java.util.Map; import java.util.Objects; import java.util.logging.Logger; @@ -41,9 +40,8 @@ public final class InvTweaksPlugin extends JavaPlugin { private SearchCommandExecutor searchCommandExecutor; private NamedChestCommand namedChestCommandExecutor; private CapitatorCommand capitatorCommand; - private DataStore data; - private NamespacedKey capitatorEnchantmentKey; - private Enchantment capitatorEnchantment; + private PersistentData data; + private EnchantmentRegistryEntry capitatorEnchantment = null; @Override public void onEnable() { @@ -80,59 +78,28 @@ public final class InvTweaksPlugin extends JavaPlugin { /** * Get a reference to the persistent data store object for this plugin - * @return An instance of {@link DataStore} for this plugin + * @return An instance of {@link PersistentData} for this plugin */ - public DataStore getPersistentData() { + public PersistentData getPersistentData() { return data; } private void initEnchantments() { - final boolean activateCapitator = getConfig().getBoolean("capitator", true); - - if (activateCapitator) { - capitatorEnchantmentKey = new NamespacedKey(this, ENCHANTMENT_CAPITATOR_NAME); - capitatorEnchantment = new CapitatorEnchantment(ENCHANTMENT_CAPITATOR_NAME, capitatorEnchantmentKey); - } - - try { - final Field acceptingField = Enchantment.class.getDeclaredField("acceptingNew"); - acceptingField.setAccessible(true); - - acceptingField.set(null, true); - - if (activateCapitator) - Enchantment.registerEnchantment(capitatorEnchantment); - } catch (NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } + if (getConfig().getBoolean("capitator", true)) + capitatorEnchantment = ServerEnchantmentRegistry.registerEnchantment( + this, + new CapitatorEnchantment( + ENCHANTMENT_CAPITATOR_NAME, + new NamespacedKey(this, ENCHANTMENT_CAPITATOR_NAME) + ) + ); } private void disableEnchantments() { - final boolean activateCapitator = getConfig().getBoolean("capitator", true); - - try { - final Field byKeyField = Enchantment.class.getDeclaredField("byKey"); - final Field byNameField = Enchantment.class.getDeclaredField("byName"); - - byKeyField.setAccessible(true); - byNameField.setAccessible(true); - - final Object byKey = byKeyField.get(null); - final Object byName = byNameField.get(null); - - if (byKey instanceof final Map byKeyMap && byName instanceof final Map byNameMap) { - - if (activateCapitator) { - byKeyMap.remove(capitatorEnchantmentKey); - byNameMap.remove(ENCHANTMENT_CAPITATOR_NAME); - } - } - } catch (NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } + if (getConfig().getBoolean("capitator", true)) + ServerEnchantmentRegistry.unRegisterEnchantment(this, capitatorEnchantment); capitatorEnchantment = null; - capitatorEnchantmentKey = null; } /** @@ -150,7 +117,7 @@ public final class InvTweaksPlugin extends JavaPlugin { pluginManager.registerEvents(new SortListener(), this); pluginManager.registerEvents(new MagnetismListener(magnetCommandExecutor), this); pluginManager.registerEvents(new TabCompletionListener(), this); - pluginManager.registerEvents(new TreeCapitatorListener(activateCapitator ? capitatorEnchantment : null), this); + pluginManager.registerEvents(new TreeCapitatorListener(activateCapitator ? capitatorEnchantment.getEnchantment() : null), this); } /** @@ -173,7 +140,7 @@ public final class InvTweaksPlugin extends JavaPlugin { namedChestCommandExecutor = new NamedChestCommand(this); if (activateCapitator) - capitatorCommand = new CapitatorCommand(capitatorEnchantment); + capitatorCommand = new CapitatorCommand(capitatorEnchantment.getEnchantment()); // TODO: Bind command by annotation Objects.requireNonNull(getCommand("sort")).setExecutor(sortCommandExecutor); @@ -206,7 +173,6 @@ public final class InvTweaksPlugin extends JavaPlugin { private void registerSerializers() { ConfigurationSerialization.registerClass(MagnetConfig.class); ConfigurationSerialization.registerClass(MagnetData.class); - ConfigurationSerialization.registerClass(UUIDList.class); ConfigurationSerialization.registerClass(SearchConfig.class); } @@ -218,7 +184,6 @@ public final class InvTweaksPlugin extends JavaPlugin { private void unregisterSerializers() { ConfigurationSerialization.unregisterClass(MagnetConfig.class); ConfigurationSerialization.unregisterClass(MagnetData.class); - ConfigurationSerialization.unregisterClass(UUIDList.class); ConfigurationSerialization.unregisterClass(SearchConfig.class); } @@ -233,7 +198,7 @@ public final class InvTweaksPlugin extends JavaPlugin { saveConfig(); // Implicit load - data = new DataStore(PERSISTENT_DATA_NAME, this); + data = new PersistentData(PERSISTENT_DATA_NAME, this); } /** diff --git a/src/dev/w1zzrd/invtweaks/command/CapitatorCommand.java b/src/dev/w1zzrd/invtweaks/command/CapitatorCommand.java index 96f681b..63127fb 100644 --- a/src/dev/w1zzrd/invtweaks/command/CapitatorCommand.java +++ b/src/dev/w1zzrd/invtweaks/command/CapitatorCommand.java @@ -1,5 +1,6 @@ package dev.w1zzrd.invtweaks.command; +import dev.w1zzrd.spigot.wizcompat.command.CommandUtils; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; diff --git a/src/dev/w1zzrd/invtweaks/command/CommandUtils.java b/src/dev/w1zzrd/invtweaks/command/CommandUtils.java deleted file mode 100644 index 5a247a1..0000000 --- a/src/dev/w1zzrd/invtweaks/command/CommandUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.w1zzrd.invtweaks.command; - -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.command.CommandSender; - -public final class CommandUtils { - private CommandUtils() { throw new UnsupportedOperationException("Functional class"); } - - public static boolean assertTrue(final boolean condition, final String message, final CommandSender sender) { - if (!condition) { - final TextComponent errorMessage = new TextComponent(message); - errorMessage.setColor(ChatColor.DARK_RED); - sender.spigot().sendMessage(errorMessage); - } - - return !condition; - } - - public static BaseComponent errorMessage(final String message) { - final BaseComponent component = new TextComponent(message); - component.setColor(ChatColor.DARK_RED); - return component; - } - - public static BaseComponent successMessage(final String message) { - final BaseComponent component = new TextComponent(message); - component.setColor(ChatColor.GREEN); - return component; - } -} diff --git a/src/dev/w1zzrd/invtweaks/command/ConfigurableCommandExecutor.java b/src/dev/w1zzrd/invtweaks/command/ConfigurableCommandExecutor.java deleted file mode 100644 index 286de28..0000000 --- a/src/dev/w1zzrd/invtweaks/command/ConfigurableCommandExecutor.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.w1zzrd.invtweaks.command; - -import org.bukkit.command.CommandExecutor; -import org.bukkit.configuration.serialization.ConfigurationSerializable; -import org.bukkit.plugin.Plugin; - -public abstract class ConfigurableCommandExecutor implements CommandExecutor { - private final Plugin plugin; - private final String path; - private T config; - - public ConfigurableCommandExecutor( - final Plugin plugin, - final String path - ) { - this.plugin = plugin; - this.path = path; - reloadConfig(); - } - - public void reloadConfig() { - config = (T) plugin.getConfig().get(path, plugin.getConfig().getDefaults().get(path)); - } - - protected T getConfig() { - return config; - } - - protected Plugin getPlugin() { - return plugin; - } -} diff --git a/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java b/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java index bf18fba..b40d4f9 100644 --- a/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java +++ b/src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java @@ -1,13 +1,13 @@ package dev.w1zzrd.invtweaks.command; -import dev.w1zzrd.invtweaks.DataStore; import dev.w1zzrd.invtweaks.serialization.MagnetConfig; import dev.w1zzrd.invtweaks.serialization.MagnetData; +import dev.w1zzrd.spigot.wizcompat.command.ConfigurableCommandExecutor; +import dev.w1zzrd.spigot.wizcompat.serialization.PersistentData; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Item; import org.bukkit.entity.Player; @@ -28,7 +28,7 @@ public class MagnetCommandExecutor extends ConfigurableCommandExecutor 1, "Too many arguments for command", sender)) + if (assertTrue(args.length > 2, "Too many arguments for command", sender)) return true; assert sender instanceof Player; diff --git a/src/dev/w1zzrd/invtweaks/command/SearchCommandExecutor.java b/src/dev/w1zzrd/invtweaks/command/SearchCommandExecutor.java index 4d9edf0..6ae5a61 100644 --- a/src/dev/w1zzrd/invtweaks/command/SearchCommandExecutor.java +++ b/src/dev/w1zzrd/invtweaks/command/SearchCommandExecutor.java @@ -2,7 +2,11 @@ package dev.w1zzrd.invtweaks.command; import dev.w1zzrd.invtweaks.InvTweaksPlugin; import dev.w1zzrd.invtweaks.serialization.SearchConfig; -import org.bukkit.*; +import dev.w1zzrd.spigot.wizcompat.command.ConfigurableCommandExecutor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.*; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -13,11 +17,14 @@ import org.bukkit.plugin.Plugin; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.logging.Logger; -import static dev.w1zzrd.invtweaks.command.CommandUtils.assertTrue; import static dev.w1zzrd.invtweaks.listener.TabCompletionListener.getMaterialMatching; +import static dev.w1zzrd.spigot.wizcompat.command.CommandUtils.assertTrue; /** * Handler for executions of /search command diff --git a/src/dev/w1zzrd/invtweaks/command/SortCommandExecutor.java b/src/dev/w1zzrd/invtweaks/command/SortCommandExecutor.java index 88f577b..d5b9b46 100644 --- a/src/dev/w1zzrd/invtweaks/command/SortCommandExecutor.java +++ b/src/dev/w1zzrd/invtweaks/command/SortCommandExecutor.java @@ -19,8 +19,8 @@ import java.util.Optional; import java.util.logging.Logger; import static dev.w1zzrd.invtweaks.InvTweaksPlugin.LOG_PLUGIN_NAME; +import static dev.w1zzrd.spigot.wizcompat.command.CommandUtils.assertTrue; import static org.bukkit.Material.*; -import static dev.w1zzrd.invtweaks.command.CommandUtils.*; /** * Handler for executions of /sort command diff --git a/src/dev/w1zzrd/invtweaks/entity/EntityCreator.java b/src/dev/w1zzrd/invtweaks/entity/EntityCreator.java deleted file mode 100644 index 57533e6..0000000 --- a/src/dev/w1zzrd/invtweaks/entity/EntityCreator.java +++ /dev/null @@ -1,153 +0,0 @@ -package dev.w1zzrd.invtweaks.entity; - -import org.bukkit.entity.Player; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -import static dev.w1zzrd.invtweaks.entity.Reflect.*; - -public final class EntityCreator { - private EntityCreator() { throw new UnsupportedOperationException("Functional class"); } - - private static Package getNativeMonsterPackage(final Player from) { - // Given player wll be an instance of CraftPlayer - final Package bukkitEntityPackage = from.getClass().getPackage(); - final Class craftShulker = loadClass(bukkitEntityPackage, "CraftShulker"); - - assert craftShulker != null; - - // CraftShulker constructor accepts minecraft EntityShulker instance as second argument - final Class nativeEntityShulker = craftShulker.getDeclaredConstructors()[0].getParameterTypes()[1]; - - // EntityShulker is classified squarely as a monster, so it should be grouped with all other hostiles - return nativeEntityShulker.getPackage(); - } - - private static Package getNativePacketPackage(final Player from) { - final Method sendPacket = findDeclaredMethod( - reflectGetField(reflectGetField(from, "entity"), "playerConnection", "networkManager").getClass(), - new String[]{ "sendPacket" }, - new Object[]{ null } - ); - - return sendPacket.getParameterTypes()[0].getPackage(); - } - - private static Object getMinecraftServerFromWorld(final Object worldServer) { - return reflectGetField(worldServer, "server", "D"); - } - - private static Object getWorldServerFromPlayer(final Player from) { - return reflectGetField(from.getWorld(), "world"); - } - - private static Object getMonsterEntityType(final Class entityClass) { - final Class type_EntityTypes = entityClass.getDeclaredConstructors()[0].getParameterTypes()[0]; - - return reflectGetGenericStaticField(type_EntityTypes, type_EntityTypes, entityClass); - } - - private static Object createFakeMonster(final Player target, final String entityClassName) { - final Package versionPackage = getNativeMonsterPackage(target); - final Class type_Entity = loadClass(versionPackage, entityClassName); - - final Object nativeWorld = getWorldServerFromPlayer(target); - assert type_Entity != null; - final Object entityType = getMonsterEntityType(type_Entity); - - return reflectConstruct(type_Entity, entityType, nativeWorld); - } - - public static Object createFakeSlime(final Player target) { - return createFakeMonster(target, "EntitySlime"); - } - - public static Object createFakeShulker(final Player target) { - return createFakeMonster(target, "EntityShulker"); - } - - public static void sendPacket(final Player target, final Object packet) { - reflectInvoke(reflectGetField(reflectGetField(target, "entity"), "playerConnection", "networkManager"), new String[]{ "sendPacket" }, packet); - } - - public static void sendEntitySpawnPacket(final Player target, final Object entity) { - final Package versionPackage = getNativePacketPackage(target); - sendPacket(target, reflectConstruct(loadClass(versionPackage, "PacketPlayOutSpawnEntityLiving", "game.PacketPlayOutSpawnEntityLiving"), entity)); - } - - public static void sendEntityMetadataPacket(final Player target, final Object entity) { - final Package versionPackage = getNativePacketPackage(target); - - Object constr1; - try { - constr1 = reflectConstruct( - loadClass(versionPackage, "PacketPlayOutEntityMetadata", "game.PacketPlayOutEntityMetadata"), - getEntityID(entity), - reflectGetField(entity, "dataWatcher", "Y") - ); - } catch (Throwable t) { - constr1 = reflectConstruct( - loadClass(versionPackage, "PacketPlayOutEntityMetadata", "game.PacketPlayOutEntityMetadata"), - getEntityID(entity), - reflectGetField(entity, "dataWatcher", "Y"), - true - ); - } - - sendPacket( - target, - constr1 - ); - } - - public static void sendEntityDespawnPacket(final Player target, final int entityID) { - final Package versionPackage = getNativePacketPackage(target); - sendPacket(target, reflectConstruct(loadClass(versionPackage, "PacketPlayOutEntityDestroy", "game.PacketPlayOutEntityDestroy"), entityID)); - } - - public static int getEntityID(final Object entity) { - return (Integer)reflectInvoke(entity, new String[]{ "getId" }); - } - - public static void setEntityInvisible(final Object entity, final boolean invisible) { - reflectInvoke(entity, new String[]{ "setInvisible" }, invisible); - } - - public static void setEntityInvulnerable(final Object entity, final boolean invulnerable) { - reflectInvoke(entity, new String[]{ "setInvulnerable" }, invulnerable); - } - - public static void setEntityGlowing(final Object entity, final boolean isGlowing) { - reflectInvoke(entity, new String[]{ "setGlowingTag", "i" }, isGlowing); - } - - public static void setEntityLocation(final Object entity, final double x, final double y, final double z, final float yaw, final float pitch) { - reflectInvoke(entity, new String[]{ "setLocation" }, x, y, z, yaw, pitch); - } - - public static void setEntityCollision(final Object entity, final boolean collision) { - reflectSetField(entity, boolean.class, collision, "collides"); - } - - public static void setEntityCustomName(final Object entity, final String name) { - final Package versionPackage = entity.getClass().getPackage(); - final Method setCustomName = findDeclaredMethod(entity.getClass(), new String[]{ "setCustomName" }, new Object[]{ null }); - - final Package chatPackage = setCustomName.getParameterTypes()[0].getPackage(); - - setEntityCustomName(entity, reflectConstruct(loadClass(chatPackage, "ChatComponentText"), name)); - } - - public static void setEntityCustomName(final Object entity, final Object chatBaseComponent) { - reflectInvoke(entity, new String[]{ "setCustomName" }, chatBaseComponent); - } - - public static void setEntityCustomNameVisible(final Object entity, final boolean visible) { - reflectInvoke(entity, new String[] { "setCustomNameVisible" }, visible); - } - - public static void setSlimeSize(final Object slime, final int size) { - reflectInvoke(slime, new String[]{ "setSize" }, size, true); - } -} diff --git a/src/dev/w1zzrd/invtweaks/entity/Reflect.java b/src/dev/w1zzrd/invtweaks/entity/Reflect.java deleted file mode 100644 index 1f714ba..0000000 --- a/src/dev/w1zzrd/invtweaks/entity/Reflect.java +++ /dev/null @@ -1,201 +0,0 @@ -package dev.w1zzrd.invtweaks.entity; - -import java.lang.reflect.*; -import java.util.Objects; - -public final class Reflect { - private Reflect() { throw new UnsupportedOperationException("Functional class"); } - - public static boolean contains(final String[] array, final String find) { - for (final String check : array) - if (check.equals(find)) - return true; - return false; - } - - public static Method findDeclaredMethod(final Class rootType, final String[] methodNames, final Object[] args) { - Class current = rootType; - - do { - for (final Method check : current.getDeclaredMethods()) - if (contains(methodNames, check.getName()) && argsMatch(check.getParameterTypes(), args)) - return check; - - current = current.getSuperclass(); - } while (true); - } - - public static Field findDeclaredField(final Class rootType, final Class expectedType, final String... fieldNames) { - Class current = rootType; - - do { - for (final Field check : current.getDeclaredFields()) - if (contains(fieldNames, check.getName()) && (expectedType == null || check.getType().equals(expectedType))) - return check; - - current = current.getSuperclass(); - } while (true); - } - - public static Constructor findDeclaredConstructor(final Class type, final Object[] args) { - for (final Constructor check : type.getDeclaredConstructors()) - if (argsMatch(check.getParameterTypes(), args)) - return (Constructor) check; - return null; - } - - public static Object reflectInvoke(final Object target, final String[] methodNames, final Object... args) { - final Method targetMethod = findDeclaredMethod(target.getClass(), methodNames, args); - targetMethod.setAccessible(true); - - try { - return targetMethod.invoke(target, args); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - - return null; - } - - public static void reflectSetStaticField(final Class target, final Object value, final String... fieldNames) { - reflectSetStaticField(target, null, value, fieldNames); - } - public static void reflectSetStaticField(final Class target, final Class expectedType, final Object value, final String... fieldNames) { - final Field targetField = findDeclaredField(target, expectedType, fieldNames); - targetField.setAccessible(true); - - try { - targetField.set(null, value); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - public static T reflectGetStaticField(final Class target, final String... fieldNames) { - return (T) reflectGetStaticField(target, null, fieldNames); - } - - public static T reflectGetGenericStaticField(final Class target, final Class fieldType, final Class genericType) { - for (final Field check : target.getDeclaredFields()) { - if (fieldType.isAssignableFrom(check.getType())) { - final Type checkFieldType = check.getGenericType(); - - if (checkFieldType instanceof final ParameterizedType pCFT && pCFT.getActualTypeArguments().length != 0) { - for (final Type typeArg : pCFT.getActualTypeArguments()) { - if (typeArg == genericType) { - try { - return (T)check.get(null); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return null; - } - } - } - } - } - } - - return null; - } - - public static T reflectGetStaticField(final Class target, final Class expectedType, final String... fieldNames) { - final Field targetField = findDeclaredField(target, expectedType, fieldNames); - targetField.setAccessible(true); - - try { - return (T)targetField.get(null); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - public static void reflectSetField(final Object target, final Object value, final String... fieldNames) { - reflectSetField(target, null, value, fieldNames); - } - public static void reflectSetField(final Object target, final Class expectedType, final Object value, final String... fieldNames) { - final Field targetField = findDeclaredField(target.getClass(), expectedType, fieldNames); - targetField.setAccessible(true); - - try { - targetField.set(target, value); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - public static Object reflectGetField(final Object target, final String... fieldNames) { - return reflectGetField(target, null, fieldNames); - } - public static T reflectGetField(final Object target, final Class expectedType, final String... fieldNames) { - final Field targetField = findDeclaredField(target.getClass(), expectedType, fieldNames); - targetField.setAccessible(true); - - try { - return (T)targetField.get(target); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - - return null; - } - - public static T reflectConstruct(final Class targetType, final Object... args) { - final Constructor targetConstructor = findDeclaredConstructor(targetType, args); - - assert targetConstructor != null; - targetConstructor.setAccessible(true); - - try { - return targetConstructor.newInstance(args); - } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) { - e.printStackTrace(); - } - - return null; - } - - public static Class loadClass(final Package from, final String... names) { - for (final String possibleName : names) - try { - return Class.forName(from.getName() + "." + possibleName); - } catch (ClassNotFoundException e) { - - } - - return null; - } - - private static boolean argsMatch(final Class[] types, final Object[] args) { - if (types.length != args.length) - return false; - - for (int i = 0; i < args.length; ++i) - if (isNotSoftAssignable(types[i], args[i])) - return false; - - return true; - } - - private static boolean isNotSoftAssignable(final Class type, final Object arg) { - return (arg == null && type.isPrimitive()) || (arg != null && !type.isAssignableFrom(arg.getClass()) && !isBoxedPrimitive(type, arg.getClass())); - } - - private static boolean isBoxedPrimitive(final Class primitive, final Class objectType) { - return (primitive == boolean.class && objectType == Boolean.class) || - (primitive == byte.class && objectType == Byte.class) || - (primitive == short.class && objectType == Short.class) || - (primitive == int.class && objectType == Integer.class) || - (primitive == long.class && objectType == Long.class) || - (primitive == float.class && objectType == Float.class) || - (primitive == double.class && objectType == Double.class); - } - - private interface DeclarationGetter { - R[] getDeclared(final Class t); - } - - private interface NameGetter { - String getName(final T t); - } -} diff --git a/src/dev/w1zzrd/invtweaks/serialization/ChestNameConfig.java b/src/dev/w1zzrd/invtweaks/serialization/ChestNameConfig.java index 1b33736..88f1d59 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/ChestNameConfig.java +++ b/src/dev/w1zzrd/invtweaks/serialization/ChestNameConfig.java @@ -1,5 +1,7 @@ package dev.w1zzrd.invtweaks.serialization; +import dev.w1zzrd.spigot.wizcompat.serialization.SimpleReflectiveConfigItem; + import java.util.Map; public class ChestNameConfig extends SimpleReflectiveConfigItem { diff --git a/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java b/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java index 53186b4..ab0e50a 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java +++ b/src/dev/w1zzrd/invtweaks/serialization/MagnetConfig.java @@ -1,5 +1,6 @@ package dev.w1zzrd.invtweaks.serialization; +import dev.w1zzrd.spigot.wizcompat.serialization.SimpleReflectiveConfigItem; import org.bukkit.plugin.Plugin; import java.util.Map; diff --git a/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java b/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java index 52fda24..5d45b11 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java +++ b/src/dev/w1zzrd/invtweaks/serialization/MagnetData.java @@ -1,5 +1,7 @@ package dev.w1zzrd.invtweaks.serialization; +import dev.w1zzrd.spigot.wizcompat.serialization.SimpleReflectiveConfigItem; +import dev.w1zzrd.spigot.wizcompat.serialization.UUIDList; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/src/dev/w1zzrd/invtweaks/serialization/SearchConfig.java b/src/dev/w1zzrd/invtweaks/serialization/SearchConfig.java index 637dc64..f016bd6 100644 --- a/src/dev/w1zzrd/invtweaks/serialization/SearchConfig.java +++ b/src/dev/w1zzrd/invtweaks/serialization/SearchConfig.java @@ -1,5 +1,7 @@ package dev.w1zzrd.invtweaks.serialization; +import dev.w1zzrd.spigot.wizcompat.serialization.SimpleReflectiveConfigItem; + import java.util.Map; public class SearchConfig extends SimpleReflectiveConfigItem { diff --git a/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java b/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java deleted file mode 100644 index 9cb6e0c..0000000 --- a/src/dev/w1zzrd/invtweaks/serialization/SimpleReflectiveConfigItem.java +++ /dev/null @@ -1,126 +0,0 @@ -package dev.w1zzrd.invtweaks.serialization; - -import org.bukkit.configuration.serialization.ConfigurationSerializable; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; - -/** - * Configuration serializable type for automatically serializing/deserializing fields - */ -public class SimpleReflectiveConfigItem implements ConfigurationSerializable { - - /** - * Required constructor for deserializing data - * @param mappings Data to deserialize - */ - public SimpleReflectiveConfigItem(final Map mappings) { - deserializeMapped(mappings); - } - - @Override - public Map serialize() { - final HashMap values = new HashMap<>(); - Arrays.stream(getClass().getDeclaredFields()) - .filter(it -> !Modifier.isTransient(it.getModifiers()) && !Modifier.isStatic(it.getModifiers())) - .forEach(it -> { - try { - it.setAccessible(true); - values.put(it.getName(), it.get(this)); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - }); - return values; - } - - /** - * Deserialize mapped data by name - * @param mappings Data to deserialize - */ - private void deserializeMapped(final Map mappings) { - for (final Field field : getClass().getDeclaredFields()) { - if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) - continue; - - try { - // Try to find mappings by field name - if (mappings.containsKey(field.getName())) - parse(mappings.get(field.getName()), field, this); - } catch (IllegalAccessException | InvocationTargetException e) { - // This shouldn't happen - e.printStackTrace(); - } - } - } - - /** - * Attempt to parse a value such that it can be stored in the given field - * @param value Value to parse - * @param field Field to store value in - * @param instance Configuration object for which to parse the vaue - * @throws IllegalAccessException Should never be thrown - * @throws InvocationTargetException Should never be thrown - */ - private static void parse(final Object value, final Field field, final Object instance) throws IllegalAccessException, InvocationTargetException { - field.setAccessible(true); - - if (field.getType().isPrimitive() && value == null) - throw new NullPointerException("Attempt to assign null to a primitive field"); - - final Class boxed = getBoxedType(field.getType()); - - if (boxed.isAssignableFrom(value.getClass())) { - field.set(instance, value); - return; - } - - if (value instanceof String) { - final Method parser = locateParser(boxed, field.getType().isPrimitive() ? field.getType() : null); - if (parser != null) - field.set(instance, parser.invoke(null, value)); - } - - throw new IllegalArgumentException(String.format("No defined parser for value \"%s\"", value)); - } - - /** - * Converter for boxed primitives - * @param cls Primitive type - * @return Boxed type for primitive type, else the given type - */ - private static Class getBoxedType(final Class cls) { - if (cls == int.class) return Integer.class; - else if (cls == double.class) return Double.class; - else if (cls == long.class) return Long.class; - else if (cls == float.class) return Float.class; - else if (cls == char.class) return Character.class; - else if (cls == byte.class) return Byte.class; - else if (cls == short.class) return Short.class; - else if (cls == boolean.class) return Boolean.class; - else return cls; - } - - /** - * Attempt to find a parser method for the given type - * @param cls Type to find parser for - * @param prim Primitive type find parser for (if applicable) - * @return Static method which accepts a {@link String} argument and returns the desired type - */ - private static Method locateParser(final Class cls, final Class prim) { - for (final Method method : cls.getDeclaredMethods()) { - final Class[] params = method.getParameterTypes(); - if ((method.getName().startsWith("parse" + cls.getSimpleName()) || method.getName().equals("fromString")) && - Modifier.isStatic(method.getModifiers()) && - method.getReturnType().equals(prim != null ? prim : cls) && - params.length == 1 && params[0].equals(String.class)) - method.setAccessible(true); - return method; - } - - return null; - } -} diff --git a/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java b/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java deleted file mode 100644 index 6bac651..0000000 --- a/src/dev/w1zzrd/invtweaks/serialization/UUIDList.java +++ /dev/null @@ -1,47 +0,0 @@ -package dev.w1zzrd.invtweaks.serialization; - -import org.bukkit.configuration.serialization.ConfigurationSerializable; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * Serializable dataclass holding a collection of {@link UUID} objects - */ -public class UUIDList implements ConfigurationSerializable { - - /** - * This is public to decrease performance overhead - */ - public final List uuids; - - /** - * Wrap a backing list of {@link UUID} objects to enable configuration serialization - * @param backingList Modifiable, backing list of {@link UUID} objects - */ - public UUIDList(final List backingList) { - uuids = backingList; - } - - /** - * Create a blank list of {@link UUID} objects - */ - public UUIDList() { - this(new ArrayList<>()); - } - - /** - * Deserialize serialized UUID strings - * @param values Data to deserialize - */ - public UUIDList(final Map values) { - this(); - if (values.containsKey("values")) - uuids.addAll(((Collection)values.get("values")).stream().map(UUID::fromString).collect(Collectors.toSet())); - } - - @Override - public Map serialize() { - return Collections.singletonMap("values", uuids.stream().map(UUID::toString).collect(Collectors.toList())); - } -}