diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java index 73b8d8d3..53d431c2 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java @@ -5,7 +5,10 @@ import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.player.cooldown.CooldownObject; import io.lumine.mythic.lib.player.modifier.ModifierSource; +import io.lumine.mythic.lib.script.Script; import io.lumine.mythic.lib.skill.handler.SkillHandler; +import io.lumine.mythic.lib.util.PostLoadAction; +import io.lumine.mythic.lib.util.PreloadedObject; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.item.util.identify.UnidentifiedItem; import net.Indyuce.mmoitems.manager.TypeManager; @@ -22,7 +25,7 @@ import java.util.List; import java.util.Objects; @SuppressWarnings("unused") -public class Type implements CooldownObject { +public class Type implements CooldownObject, PreloadedObject { // Slashing public static final Type SWORD = new Type("SWORD", true, ModifierSource.MELEE_WEAPON); @@ -93,6 +96,8 @@ public class Type implements CooldownObject { private SkillHandler onLeftClick, onRightClick, onAttack, onEntityInteract; + public Script ent; + private boolean meleeAttacks; /** @@ -101,44 +106,53 @@ public class Type implements CooldownObject { */ private final List available = new ArrayList<>(); - public Type(String id, boolean weapon, ModifierSource modSource) { - this.id = id.toUpperCase().replace("-", "_").replace(" ", "_"); - this.modifierSource = modSource; - this.weapon = weapon; - this.loreFormat = null; - } - - public Type(@NotNull TypeManager manager, @NotNull ConfigurationSection config) { - id = config.getName().toUpperCase().replace("-", "_").replace(" ", "_"); - - parent = manager.get(config.getString("parent", "").toUpperCase().replace("-", "_").replace(" ", "_")); - - weapon = (parent != null && parent.weapon); - modifierSource = (parent != null ? parent.modifierSource : ModifierSource.OTHER); - this.loreFormat = config.getString("LoreFormat", (parent != null ? parent.loreFormat : null)); - } - - public void load(ConfigurationSection config) { - Validate.notNull(config, "Could not find config for " + getId()); - - name = config.getString("name", name); - item = read(config.getString("display", item == null ? Material.STONE.toString() : item.getType().toString())); - - (unidentifiedTemplate = new UnidentifiedItem(this)).update(config.getConfigurationSection("unident-item")); - - // Getting overridden? - loreFormat = config.getString("LoreFormat", parent != null ? parent.loreFormat : null); - - attackCooldownKey = config.getString("attack-cooldown-key", "default"); - - meleeAttacks = !config.getBoolean("disable-melee-attacks"); - } - - public void postload(ConfigurationSection config) { + private final PostLoadAction postLoadAction = new PostLoadAction(config -> { onLeftClick = config.contains("on-left-click") ? MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-left-click")) : null; onRightClick = config.contains("on-right-click") ? MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-right-click")) : null; onAttack = config.contains("on-attack") ? MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-attack")) : null; onEntityInteract = config.contains("on-entity-interact") ? MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-entity-interact")) : null; + }); + + /** + * Hard-coded type with given parameters + */ + public Type(String id, boolean weapon, ModifierSource modSource) { + this.id = UtilityMethods.enumName(id); + this.modifierSource = modSource; + this.weapon = weapon; + } + + /** + * Custom type + */ + public Type(@NotNull TypeManager manager, @NotNull ConfigurationSection config) { + id = UtilityMethods.enumName(config.getName()); + parent = manager.get(config.getString("parent", "").toUpperCase().replace("-", "_").replace(" ", "_")); + weapon = config.getBoolean("weapon", parent != null && parent.weapon); + modifierSource = config.contains("modifier-source") ? ModifierSource.valueOf(UtilityMethods.enumName(config.getString("modifier-source"))) : (parent != null ? parent.modifierSource : ModifierSource.OTHER); + } + + public void load(@NotNull ConfigurationSection config) { + postLoadAction.cacheConfig(config); + + name = config.getString("name", name); + item = read(config.getString("display", item == null ? Material.STONE.toString() : item.getType().toString())); + (unidentifiedTemplate = new UnidentifiedItem(this)).update(config.getConfigurationSection("unident-item")); + loreFormat = config.getString("LoreFormat", (parent != null ? parent.loreFormat : null)); + attackCooldownKey = config.getString("attack-cooldown-key", "default"); + meleeAttacks = !config.getBoolean("disable-melee-attacks"); + } + + @Deprecated + public void postload(ConfigurationSection config) { + postLoadAction.cacheConfig(config); + postLoadAction.performAction(); + } + + @NotNull + @Override + public PostLoadAction getPostLoadAction() { + return postLoadAction; } /** diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java index 2668f6b2..4d557be4 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java @@ -10,7 +10,6 @@ import io.lumine.mythic.lib.damage.MeleeAttackMetadata; import io.lumine.mythic.lib.entity.ProjectileMetadata; import io.lumine.mythic.lib.entity.ProjectileType; import io.lumine.mythic.lib.skill.SimpleSkill; -import io.lumine.mythic.lib.skill.Skill; import io.lumine.mythic.lib.skill.handler.SkillHandler; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; import io.lumine.mythic.lib.skill.trigger.TriggerType; @@ -151,13 +150,13 @@ public class ItemUse implements Listener { @EventHandler public void rightClickWeaponInteractions(PlayerInteractEntityEvent event) { - Player player = event.getPlayer(); + final Player player = event.getPlayer(); if (!(event.getRightClicked() instanceof LivingEntity)) return; - NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand()); + final NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItem(event.getHand())); if (!item.hasType()) return; - LivingEntity target = (LivingEntity) event.getRightClicked(); + final LivingEntity target = (LivingEntity) event.getRightClicked(); if (!UtilityMethods.canTarget(player, target, InteractionType.OFFENSE_ACTION)) return; // Check for usability diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/StatManager.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/StatManager.java index 0bc75118..d40066e0 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/StatManager.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/StatManager.java @@ -23,6 +23,14 @@ import java.util.logging.Level; public class StatManager { private final Map> stats = new LinkedHashMap<>(); + /** + * TODO refactor with stat categories + *

+ * basically useless as of right now + */ + @Deprecated + private final Map> legacyAliases = new HashMap<>(); + /* * These lists are sets of stats collected when the stats are registered for * the first time to make their access easier. Check the classes @@ -33,11 +41,13 @@ public class StatManager { private final List consumableActions = new ArrayList<>(); private final List playerConsumables = new ArrayList<>(); + /** * Load default stats using java reflection, get all public static final * fields in the ItemStat and register them as stat instances + *

+ * TODO refactor */ - @Deprecated public void load() { for (Field field : ItemStats.class.getFields()) try { @@ -53,9 +63,9 @@ public class StatManager { /** * @see FictiveNumericStat - * @deprecated Needs refactor + *

+ * TODO refactor */ - @Deprecated public void reload(boolean cleanFirst) { // Clean fictive numeric stats before @@ -81,10 +91,9 @@ public class StatManager { /** * Load custom stats - * - * @deprecated Needs refactor + *

+ * TODO refactor */ - @Deprecated public void loadCustom() { ConfigManager.DefaultFile.CUSTOM_STATS.checkFile(); ConfigFile config = new ConfigFile("custom-stats"); @@ -95,10 +104,9 @@ public class StatManager { /** * Register all MythicLib elements as stats - * - * @deprecated Needs refactor + *

+ * TODO refactor */ - @Deprecated public void loadElements() { for (ElementStatType type : ElementStatType.values()) for (Element element : MythicLib.plugin.getElements().getAll()) @@ -154,11 +162,21 @@ public class StatManager { @Nullable public ItemStat get(String id) { - ItemStat stat = stats.getOrDefault(id, null); - if (stat == null) { - stat = numeric.stream().filter(doubleStat -> doubleStat.getId().equals(id)).findFirst().orElse(null); - } - return stat; + + // Default registry + ItemStat stat = stats.get(id); + if (stat != null) return stat; + + // Numeric registry (see to-do) + stat = numeric.stream().filter(doubleStat -> doubleStat.getId().equals(id)).findFirst().orElse(null); + if (stat != null) return stat; + + // Legacy liases + stat = legacyAliases.get(id); + if (stat != null) return stat; + + // Non existing stat + return null; } /** @@ -189,13 +207,14 @@ public class StatManager { return; } + // Main registry stats.put(stat.getId(), stat); - // Register aliases (does NOT support custom registries) + // Register aliases for (String alias : stat.getAliases()) - stats.put(alias, stat); + legacyAliases.put(alias, stat); - // Custom registries + // Use-case specific registries if (stat instanceof DoubleStat && !(stat instanceof GemStoneStat) && stat.isCompatible(Type.GEM_STONE)) numeric.add((DoubleStat) stat); if (stat instanceof ItemRestriction) itemRestriction.add((ItemRestriction) stat); @@ -248,8 +267,7 @@ public class StatManager { // Create a new stat instance try { - ItemStat stat = statClass.getConstructor(String.class, Material.class, String.class, String[].class, String[].class, Material[].class) - .newInstance(statId, Material.PAPER, name, lore, new String[]{"!miscellaneous", "!block", "all"}, new Material[0]); + ItemStat stat = statClass.getConstructor(String.class, Material.class, String.class, String[].class, String[].class, Material[].class).newInstance(statId, Material.PAPER, name, lore, new String[]{"!miscellaneous", "!block", "all"}, new Material[0]); register(stat); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/TypeManager.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/TypeManager.java index 65610423..f2c704ee 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/TypeManager.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/TypeManager.java @@ -34,13 +34,8 @@ public class TypeManager { MMOItems.plugin.getLogger().log(Level.WARNING, "Couldn't register type called '" + field.getName() + "': " + exception.getMessage()); } - /* - * Register all other types. Important: check if the map already - * contains the id, this way the DEFAULT types are not registered twice, - * and only custom types are registered with a parent. - */ + // Load custom types DefaultFile.ITEM_TYPES.checkFile(); - FileConfiguration config = new ConfigFile("item-types").getConfig(); for (String id : config.getKeys(false)) if (!map.containsKey(id)) @@ -55,8 +50,9 @@ public class TypeManager { try { ConfigurationSection section = config.getConfigurationSection(type.getId()); + Validate.notNull(section, "Could not find config section for type '" + type.getId() + "'"); type.load(section); - if (clearBefore) type.postload(section); + if (clearBefore) type.getPostLoadAction().performAction(); } catch (RuntimeException exception) { MMOItems.plugin.getLogger().log(Level.WARNING, "Could not register type '" + type.getId() + "': " + exception.getMessage()); iterator.remove(); @@ -74,12 +70,11 @@ public class TypeManager { } public void postload() { - FileConfiguration config = new ConfigFile("item-types").getConfig(); for (Type type : map.values()) try { - type.postload(config.getConfigurationSection(type.getId())); + type.getPostLoadAction().performAction(); } catch (RuntimeException exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "An error occured while loading type '" + type.getId() + "': " + exception.getMessage()); + MMOItems.plugin.getLogger().log(Level.WARNING, "An error occured while post-loading type '" + type.getId() + "': " + exception.getMessage()); } } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/ActionLeftClick.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/ActionLeftClick.java index 111be615..922d12cb 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/ActionLeftClick.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/ActionLeftClick.java @@ -3,20 +3,25 @@ package net.Indyuce.mmoitems.stat; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.item.ItemTag; +import io.lumine.mythic.lib.api.item.SupportedNBTTagValues; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder; +import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem; import net.Indyuce.mmoitems.gui.edition.EditionInventory; import net.Indyuce.mmoitems.stat.data.StringData; import net.Indyuce.mmoitems.stat.type.StringStat; import org.bukkit.Material; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; public class ActionLeftClick extends StringStat { public ActionLeftClick() { super("ON_LEFT_CLICK", Material.COMMAND_BLOCK_MINECART, "Left Click Action", new String[]{"ID of skill ran when left clicking. When used,", "The item will naturally apply item costs like", "mana, stamina, cooldown. This option overrides the", "script provided by the item type."}, new String[]{"weapon"}); // Staff spirit set as alias - setAliases("STAFF_SPIRIT"); + setAliases(LEGACY_PATH); } @Override @@ -33,5 +38,45 @@ public class ActionLeftClick extends StringStat { item.addItemTag(new ItemTag(getNBTPath(), UtilityMethods.enumName(data.toString()))); // No lore insertion } + + private static final String LEGACY_PATH = "STAFF_SPIRIT"; + + // TODO refactor with stat categories + @Override + @Deprecated + public void whenLoaded(@NotNull ReadMMOItem mmoitem) { + ArrayList relevantTags = new ArrayList<>(); + // New path + if (mmoitem.getNBT().hasTag(getNBTPath())) + relevantTags.add(ItemTag.getTagAtPath(getNBTPath(), mmoitem.getNBT(), SupportedNBTTagValues.STRING)); + // Legacy path + if (mmoitem.getNBT().hasTag(LEGACY_PATH)) + relevantTags.add(ItemTag.getTagAtPath(LEGACY_PATH, mmoitem.getNBT(), SupportedNBTTagValues.STRING)); + StringData bakedData = getLoadedNBT(relevantTags); + if (bakedData != null) mmoitem.setData(this, bakedData); + } + + // TODO refactor with stat categories + @Nullable + @Override + @Deprecated + public StringData getLoadedNBT(@NotNull ArrayList storedTags) { + + // New path + ItemTag tg = ItemTag.getTagAtPath(getNBTPath(), storedTags); + if (tg != null) { + String value = (String) tg.getValue(); + return new StringData(value); + } + + // Legacy path + tg = ItemTag.getTagAtPath(LEGACY_PATH, storedTags); + if (tg != null) { + String value = (String) tg.getValue(); + return new StringData(value); + } + + return null; + } } diff --git a/MMOItems-Dist/src/main/resources/default/item-types.yml b/MMOItems-Dist/src/main/resources/default/item-types.yml index 8df29d26..c2887291 100644 --- a/MMOItems-Dist/src/main/resources/default/item-types.yml +++ b/MMOItems-Dist/src/main/resources/default/item-types.yml @@ -109,8 +109,8 @@ WHIP: - '{tier}&8- &7Item Tier: #prefix##tier#' disable-melee-attacks: true - on-left-click: - + on-left-click: whip_attack_effect + on-attack: slashing_attack_effect STAFF: display: DIAMOND_HOE