More fixes for custom item types

This commit is contained in:
Jules 2024-02-10 15:26:30 +01:00
parent e5a9fc9129
commit 1502465685
6 changed files with 142 additions and 71 deletions

View File

@ -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<ItemStat> 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;
}
/**

View File

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

View File

@ -23,6 +23,14 @@ import java.util.logging.Level;
public class StatManager {
private final Map<String, ItemStat<?, ?>> stats = new LinkedHashMap<>();
/**
* TODO refactor with stat categories
* <p>
* basically useless as of right now
*/
@Deprecated
private final Map<String, ItemStat<?, ?>> 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<ConsumableItemInteraction> consumableActions = new ArrayList<>();
private final List<PlayerConsumable> playerConsumables = new ArrayList<>();
/**
* Load default stats using java reflection, get all public static final
* fields in the ItemStat and register them as stat instances
* <p>
* 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
* <p>
* 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
* <p>
* 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
* <p>
* 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) {

View File

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

View File

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

View File

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