From 78fb3c94c922c924f91267735235e25773241d80 Mon Sep 17 00:00:00 2001 From: Roch Blonndiaux Date: Fri, 24 Feb 2023 14:27:50 +0100 Subject: [PATCH] New item type, manager update & introduction of categories --- .../api/item/category/MMOTypeCategory.java | 64 ++++++ .../mmoitems/api/item/type/MMOItemType.java | 162 ++++++++++++--- .../api/item/type/MMOPredefinedType.java | 165 --------------- .../api/item/type/set/AbstractTypeSet.java | 31 --- .../api/item/type/set/DummyTypeSet.java | 23 --- .../api/item/type/set/MMOTypeSet.java | 27 --- .../api/item/type/set/ScriptTypeSet.java | 53 ----- .../item/util/identify/UnidentifiedItem.java | 4 +- .../Indyuce/mmoitems/manager/TypeManager.java | 192 ++++++++++-------- .../src/main/resources/default/item-types.yml | 6 +- .../resources/default/type-categories.yml | 12 ++ 11 files changed, 323 insertions(+), 416 deletions(-) create mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/category/MMOTypeCategory.java delete mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOPredefinedType.java delete mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/AbstractTypeSet.java delete mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/DummyTypeSet.java delete mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/MMOTypeSet.java delete mode 100644 MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/ScriptTypeSet.java create mode 100644 MMOItems-Dist/src/main/resources/default/type-categories.yml diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/category/MMOTypeCategory.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/category/MMOTypeCategory.java new file mode 100644 index 00000000..19e98c27 --- /dev/null +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/category/MMOTypeCategory.java @@ -0,0 +1,64 @@ +package net.Indyuce.mmoitems.api.item.category; + +import net.Indyuce.mmoitems.api.item.type.MMOItemType; +import net.Indyuce.mmoitems.stat.type.ItemStat; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * mmoitems + * 24/02/2023 + * + * @author Roch Blondiaux (Kiwix). + */ +public class MMOTypeCategory { + + private final String id; + private final String name; + private final ItemStack item; + private final String loreFormat; + private final List> stats; + + public MMOTypeCategory(String id, String name, ItemStack item, String loreFormat, List> stats) { + this.id = id; + this.name = name; + this.item = item; + this.loreFormat = loreFormat; + this.stats = stats; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public ItemStack getItem() { + return item; + } + + public String getLoreFormat() { + return loreFormat; + } + + public List> getStats() { + return stats; + } + + public static MMOTypeCategory load(@NotNull ConfigurationSection section) { + final String id = section.getName(); + final String name = section.getString("name"); + final ItemStack item = MMOItemType.read(section.getString("display", Material.STONE.toString())); + final String loreFormat = section.getString("lore-format"); + final List> stats = new ArrayList<>(); + + return new MMOTypeCategory(id, name, item, loreFormat, stats); + } +} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOItemType.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOItemType.java index dd26b584..c14e1255 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOItemType.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOItemType.java @@ -1,61 +1,157 @@ package net.Indyuce.mmoitems.api.item.type; +import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.player.modifier.ModifierSource; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.ConfigFile; -import net.Indyuce.mmoitems.api.Type; -import net.Indyuce.mmoitems.api.item.type.set.MMOTypeSet; +import net.Indyuce.mmoitems.api.item.category.MMOTypeCategory; import net.Indyuce.mmoitems.api.item.util.identify.UnidentifiedItem; +import net.Indyuce.mmoitems.manager.TypeManager; import net.Indyuce.mmoitems.stat.type.ItemStat; +import org.apache.commons.lang.Validate; +import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * mmoitems - * 20/02/2023 + * 24/02/2023 * * @author Roch Blondiaux (Kiwix). */ -public interface MMOItemType { +public class MMOItemType { - @NotNull - String getId(); + private final String id; + private final String name; + private final ModifierSource modifierSource; + private final boolean weapon; + private final String loreFormat; + private final MMOTypeCategory category; + private final ItemStack item; + private final UnidentifiedItem unidentifiedTemplate; + private final List> stats; - @NotNull - String getName(); + private MMOItemType(String id, String name, ModifierSource modifierSource, boolean weapon, String loreFormat, MMOTypeCategory category, ItemStack item, List> stats) { + this.id = id; + this.name = name; + this.modifierSource = modifierSource; + this.weapon = weapon; + this.loreFormat = loreFormat; + this.category = category; + this.item = item; + this.unidentifiedTemplate = new UnidentifiedItem(this); + this.stats = stats; + } - boolean isWeapon(); + public String getId() { + return id; + } - ModifierSource getModifierSource(); + public String getName() { + return name; + } - ItemStack toItemStack(); + public ModifierSource getModifierSource() { + return modifierSource; + } - boolean isFourGUIMode(); + public boolean isWeapon() { + return weapon; + } - String getLoreFormat(); + public String getLoreFormat() { + return loreFormat; + } - List> getAvailableStats(); + public MMOTypeCategory getCategory() { + return category; + } - ConfigFile getConfiguration(); + public ItemStack getItem() { + return item; + } - UnidentifiedItem getUnidentifiedItem(); + public UnidentifiedItem getUnidentifiedTemplate() { + return unidentifiedTemplate; + } - void load(ConfigurationSection config); + public List> getStats() { + return stats; + } - /** - * Used in command executors and completions for easier manipulation - * - * @param id The type id - * @return If a registered type with this ID could be found - */ - static boolean isValid(@Nullable String id) { - return id != null && MMOItems.plugin.getTypes().has(id.toUpperCase().replace("-", "_").replace(" ", "_")); + public boolean isFourGUIMode() { + return this.modifierSource == ModifierSource.ARMOR; + } + + public ConfigFile getConfigFile() { + return new ConfigFile("/item", getId().toLowerCase()); + } + + public static MMOItemType load(@NotNull TypeManager manager, @NotNull ConfigurationSection section) { + final String id = section.getName(); + final String name = section.getString("name"); + final ModifierSource modifierSource = ModifierSource.valueOf(section.getString("modifier-source")); + final boolean weapon = section.getBoolean("weapon"); + final String loreFormat = section.getString("lore-format"); + final ItemStack item = read(section.getString("display", Material.STONE.toString())); + + + // TODO: Load the category + final String categoryId = section.getString("category"); + final MMOTypeCategory category = manager.getCategories() + .stream() + .filter(mmoTypeCategory -> mmoTypeCategory.getId().equalsIgnoreCase(categoryId)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(String.format("Category %s does not exist.", categoryId))); + + + // TODO: Load the stats + final List> stats = new ArrayList<>(); + + MMOItemType type = new MMOItemType(id, name, modifierSource, weapon, loreFormat, category, item, stats); + type.getUnidentifiedTemplate().update(section.getConfigurationSection("unident-item")); + return type; + } + + public static ItemStack read(String str) { + Validate.notNull(str, "Input must not be null"); + + String[] split = str.split(":"); + Material material = Material.valueOf(split[0]); + return split.length > 1 ? MythicLib.plugin.getVersion().getWrapper().textureItem(material, Integer.parseInt(split[1])) : new ItemStack(material); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MMOItemType type = (MMOItemType) o; + return id.equals(type.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public String toString() { + return "MMOItemType{" + + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", modifierSource=" + modifierSource + + ", weapon=" + weapon + + ", loreFormat='" + loreFormat + '\'' + + ", category=" + category + + '}'; } /** @@ -66,7 +162,8 @@ public interface MMOItemType { */ @Nullable @Contract("null -> null") - static MMOTypeSet get(@Nullable ItemStack item) { + public static MMOItemType get(@Nullable ItemStack item) { + if (item == null) return null; return get(NBTItem.get(item).getType()); } @@ -78,8 +175,19 @@ public interface MMOItemType { */ @Nullable @Contract("null -> null") - static MMOTypeSet get(@Nullable String id) { + public static MMOItemType get(@Nullable String id) { + if (id == null) return null; String format = id.toUpperCase().replace("-", "_").replace(" ", "_"); return MMOItems.plugin.getTypes().has(format) ? MMOItems.plugin.getTypes().get(format) : null; } + + /** + * Used in command executors and completions for easier manipulation + * + * @param id The type id + * @return If a registered type with this ID could be found + */ + public static boolean isValid(@Nullable String id) { + return id != null && MMOItems.plugin.getTypes().has(id.toUpperCase().replace("-", "_").replace(" ", "_")); + } } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOPredefinedType.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOPredefinedType.java deleted file mode 100644 index 9ffc6976..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/MMOPredefinedType.java +++ /dev/null @@ -1,165 +0,0 @@ -package net.Indyuce.mmoitems.api.item.type; - -import io.lumine.mythic.lib.MythicLib; -import io.lumine.mythic.lib.player.modifier.ModifierSource; -import net.Indyuce.mmoitems.api.ConfigFile; -import net.Indyuce.mmoitems.api.TypeSet; -import net.Indyuce.mmoitems.api.item.type.set.MMOTypeSet; -import net.Indyuce.mmoitems.api.item.util.identify.UnidentifiedItem; -import net.Indyuce.mmoitems.manager.TypeManager; -import net.Indyuce.mmoitems.stat.type.ItemStat; -import org.apache.commons.lang.Validate; -import org.bukkit.Material; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * mmoitems - * 20/02/2023 - * - * @author Roch Blondiaux (Kiwix). - */ -public class MMOPredefinedType implements MMOItemType { - - private final String id; - private final MMOTypeSet set; - private final ModifierSource modifierSource; - private final boolean weapon; - - // Configurable - private String name; - - @Nullable - private String loreFormat; - - /** - * Used to display the item in the item explorer and in the item recipes - * list in the advanced workbench. can also be edited using the config - * files. - */ - private ItemStack item; - private UnidentifiedItem unidentifiedTemplate; - - /** - * List of stats which can be applied onto an item which has this type. This - * improves performance when generating an item by a significant amount. - */ - private final List> stats = new ArrayList<>(); - - public MMOPredefinedType(String id, boolean weapon, ModifierSource modSource) { - this.id = id.toUpperCase().replace("-", "_").replace(" ", "_"); - this.modifierSource = modSource; - this.weapon = weapon; - this.loreFormat = null; - } - - public MMOPredefinedType(@NotNull TypeManager manager, @NotNull ConfigurationSection config) { - id = config.getName().toUpperCase().replace("-", "_").replace(" ", "_"); - - parent = manager.get(config.getString("parent", "").toUpperCase().replace("-", "_").replace(" ", "_")); - - set = (parent != null ? parent.set : TypeSet.EXTRA); - weapon = (parent != null && parent.weapon); - modifierSource = (parent != null ? parent.modifierSource : ModifierSource.OTHER); - this.loreFormat = config.getString("LoreFormat", (parent != null ? parent.loreFormat : null)); - } - - @NotNull - @Override - public String getId() { - return this.id; - } - - @NotNull - @Override - public String getName() { - return this.name; - } - - @Override - public boolean isWeapon() { - return this.weapon; - } - - @Override - public ModifierSource getModifierSource() { - return this.modifierSource; - } - - @Override - public ItemStack toItemStack() { - return this.item.clone(); - } - - @Override - public boolean isFourGUIMode() { - - } - - @Override - public String getLoreFormat() { - return this.loreFormat; - } - - @Override - public List> getAvailableStats() { - return this.stats; - } - - @Override - public ConfigFile getConfiguration() { - return new ConfigFile("/item", this.id.toLowerCase()); - } - - @Override - public UnidentifiedItem getUnidentifiedItem() { - return this.unidentifiedTemplate; - } - - @Override - public void load(ConfigurationSection config) { - Validate.notNull(config, String.format("Could not find config for %s", 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 : loreFormat)); - } - - private ItemStack read(String data) { - Validate.notNull(data, "Input must not be null"); - - String[] split = data.split(":"); - Material material = Material.valueOf(split[0]); - return split.length > 1 ? MythicLib.plugin.getVersion().getWrapper().textureItem(material, Integer.parseInt(split[1])) : new ItemStack(material); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MMOTypeSet type = (MMOTypeSet) o; - return id.equals(type.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } - - @Override - public String toString() { - return "Type{" + - "id='" + id + '\'' + - '}'; - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/AbstractTypeSet.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/AbstractTypeSet.java deleted file mode 100644 index 182f2bba..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/AbstractTypeSet.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.Indyuce.mmoitems.api.item.type.set; - -import org.jetbrains.annotations.ApiStatus; - -/** - * mmoitems - * 21/02/2023 - * - * @author Roch Blondiaux (Kiwix). - */ -@ApiStatus.Internal -public abstract class AbstractTypeSet implements MMOTypeSet { - - private final String name; - private final boolean hasAttackEffect; - - public AbstractTypeSet(String name, boolean hasAttackEffect) { - this.name = name; - this.hasAttackEffect = hasAttackEffect; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean hasAttackEffect() { - return hasAttackEffect; - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/DummyTypeSet.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/DummyTypeSet.java deleted file mode 100644 index cefa2bfd..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/DummyTypeSet.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.Indyuce.mmoitems.api.item.type.set; - -import io.lumine.mythic.lib.damage.AttackMetadata; -import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; -import net.Indyuce.mmoitems.api.player.PlayerData; -import org.bukkit.entity.LivingEntity; - -/** - * mmoitems - * 21/02/2023 - * - * @author Roch Blondiaux (Kiwix). - */ -public class DummyTypeSet extends AbstractTypeSet { - - public DummyTypeSet(String name) { - super(name, false); - } - - @Override - public void apply(AttackMetadata attackData, PlayerData source, LivingEntity target, Weapon weapon) { - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/MMOTypeSet.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/MMOTypeSet.java deleted file mode 100644 index 4c0e231d..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/MMOTypeSet.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.Indyuce.mmoitems.api.item.type.set; - -import io.lumine.mythic.lib.damage.AttackMetadata; -import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; -import net.Indyuce.mmoitems.api.player.PlayerData; -import org.bukkit.entity.LivingEntity; - -/** - * mmoitems - * 20/02/2023 - * - * @author Roch Blondiaux (Kiwix). - */ -public interface MMOTypeSet { - - String getName(); - - void apply(AttackMetadata attackData, PlayerData source, LivingEntity target, Weapon weapon); - - boolean hasAttackEffect(); - - default void applyAttackEffect(AttackMetadata attackMeta, PlayerData damager, LivingEntity target, Weapon weapon) { - if (this.hasAttackEffect()) - this.apply(attackMeta, damager, target, weapon); - } - -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/ScriptTypeSet.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/ScriptTypeSet.java deleted file mode 100644 index 8e1a5849..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/type/set/ScriptTypeSet.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.Indyuce.mmoitems.api.item.type.set; - -import io.lumine.mythic.lib.MythicLib; -import io.lumine.mythic.lib.damage.AttackMetadata; -import io.lumine.mythic.lib.script.Script; -import io.lumine.mythic.lib.skill.SkillMetadata; -import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; -import net.Indyuce.mmoitems.api.player.PlayerData; -import org.apache.commons.lang3.Validate; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.LivingEntity; -import org.jetbrains.annotations.NotNull; - -/** - * mmoitems - * 21/02/2023 - * - * @author Roch Blondiaux (Kiwix). - */ -public class ScriptTypeSet extends AbstractTypeSet { - - private final Script script; - - public ScriptTypeSet(String name, boolean hasAttackEffect, Script script) { - super(name, hasAttackEffect); - this.script = script; - } - - @Override - public void apply(AttackMetadata attackData, PlayerData source, LivingEntity target, Weapon weapon) { - final SkillMetadata skillMetadata = new SkillMetadata(null, source.getMMOPlayerData()); - // TODO: check if the scripts are working - script.cast(skillMetadata); - } - - - public Script getScript() { - return script; - } - - public static ScriptTypeSet load(@NotNull ConfigurationSection section) { - Validate.notNull(section, "The section cannot be null"); - Validate.isTrue(section.contains("name"), "The section must contain a name"); - Validate.isTrue(section.contains("attack-effect"), "The section must contain a has-attack-effect"); - Validate.isTrue(section.contains("script"), "The section must contain a script"); - - final String name = section.getString("name"); - final boolean hasAttackEffect = section.getBoolean("has-attack-effect"); - final Script script = MythicLib.plugin.getSkills().getScriptOrThrow(section.getString("script")); - - return new ScriptTypeSet(name, hasAttackEffect, script); - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/identify/UnidentifiedItem.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/identify/UnidentifiedItem.java index 9160a251..b768a31c 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/identify/UnidentifiedItem.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/identify/UnidentifiedItem.java @@ -6,9 +6,9 @@ import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.util.AdventureUtils; import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.api.ItemTier; -import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; +import net.Indyuce.mmoitems.api.item.type.MMOItemType; import net.Indyuce.mmoitems.api.item.util.ConfigItem; import net.Indyuce.mmoitems.stat.data.DoubleData; import org.bukkit.inventory.ItemFlag; @@ -22,7 +22,7 @@ import java.io.ByteArrayOutputStream; import java.util.*; public class UnidentifiedItem extends ConfigItem { - public UnidentifiedItem(Type type) { + public UnidentifiedItem(MMOItemType type) { super("unidentified", type.getItem().getType()); setName("#prefix#Unidentified " + type.getName()); 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 b2cbbec6..205c97f6 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 @@ -2,111 +2,129 @@ package net.Indyuce.mmoitems.manager; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.ConfigFile; -import net.Indyuce.mmoitems.api.Type; +import net.Indyuce.mmoitems.api.item.category.MMOTypeCategory; +import net.Indyuce.mmoitems.api.item.type.MMOItemType; import net.Indyuce.mmoitems.manager.ConfigManager.DefaultFile; -import org.apache.commons.lang.Validate; +import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.logging.Level; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; public class TypeManager implements Reloadable { - private final Map map = new LinkedHashMap<>(); - /** - * Reloads the type manager. It entirely empties the currently registered - * item types, registers default item types again and reads item-types.yml - */ - public void reload() { - map.clear(); + private final List types = new ArrayList<>(); + private final List categories = new ArrayList<>(); - // Load default types - for (Field field : Type.class.getFields()) - try { - if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && field.get(null) instanceof Type) - register((Type) field.get(null)); - } catch (Exception exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "Couldn't register type called '" + field.getName() + "': " + exception.getMessage()); - } + /** + * Reloads the type manager. It entirely empties the currently registered + * item types, registers default item types again and reads item-types.yml + */ + public void reload() { + this.categories.clear(); + this.types.clear(); - /* - * 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. - */ - DefaultFile.ITEM_TYPES.checkFile(); + /* + * 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. + */ + DefaultFile.ITEM_TYPES.checkFile(); - ConfigFile config = new ConfigFile("item-types"); - for (String id : config.getConfig().getKeys(false)) - if (!map.containsKey(id)) - try { - register(new Type(this, config.getConfig().getConfigurationSection(id))); - } catch (IllegalArgumentException exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "Could not register type '" + id + "': " + exception.getMessage()); - } + // Categories + ConfigFile categoriesConfig = new ConfigFile("type-categories.yml"); + ConfigurationSection section = categoriesConfig.getConfig(); + section.getKeys(false) + .stream() + .filter(section::isConfigurationSection) + .map(section::getConfigurationSection) + .filter(Objects::nonNull) + .map(MMOTypeCategory::load) + .peek(this.categories::add) + .peek(category -> category.getStats().clear()) + .forEach(category -> MMOItems.plugin.getStats() + .getAll() + .forEach(stat -> category.getStats().add(stat))); - for (Iterator iterator = map.values().iterator(); iterator.hasNext();) { - Type type = iterator.next(); + // DEBUG + MMOItems.log("Loaded " + this.categories.size() + " item categories."); - try { - type.load(config.getConfig().getConfigurationSection(type.getId())); - } catch (IllegalArgumentException exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "Could not register type '" + type.getId() + "': " + exception.getMessage()); - iterator.remove(); - continue; - } + // Types + ConfigFile typesConfig = new ConfigFile("item-types.yml"); + ConfigurationSection typesSection = typesConfig.getConfig(); + typesSection.getKeys(false) + .stream() + .filter(typesSection::isConfigurationSection) + .map(typesSection::getConfigurationSection) + .filter(Objects::nonNull) + .map(s -> MMOItemType.load(this, s)) + .peek(this.types::add) + .peek(mmoItemType -> mmoItemType.getStats().clear()) + .forEach(mmoItemType -> MMOItems.plugin.getStats() + .getAll() + .forEach(stat -> mmoItemType.getStats().add(stat))); + // TODO: Add stats from type category - /* - * caches all the stats which the type can have to reduce future - * both item generation (and GUI) calculations. probably the thing - * which takes the most time when loading item types. - */ - type.getAvailableStats().clear(); - MMOItems.plugin.getStats().getAll().stream().filter(stat -> stat.isCompatible(type)).forEach(stat -> type.getAvailableStats().add(stat)); - } - } + // DEBUG + MMOItems.log("Loaded " + this.types.size() + " item types."); + } - public void register(Type type) { - map.put(type.getId(), type); - } + public void register(MMOItemType type) { + this.types.add(type); + } - public void registerAll(Type... types) { - for (Type type : types) - register(type); - } + public void registerAll(MMOItemType... types) { + for (MMOItemType type : types) + register(type); + } - /** - * @param id Internal ID of the type - * - * @return The MMOItem Type if it found. - */ - @Nullable public Type get(@Nullable String id) { - if (id == null) { return null; } - return map.get(id); - } + /** + * @param id Internal ID of the type + * @return The MMOItem Type if it found. + */ + @Contract("null -> null") + @Nullable + public MMOItemType get(@Nullable String id) { + if (id == null) return null; + return this.types.stream() + .filter(mmoItemType -> mmoItemType.getId().equals(id)) + .findFirst() + .orElse(null); + } - @NotNull public Type getOrThrow(@Nullable String id) { - Validate.isTrue(map.containsKey(id), "Could not find item type with ID '" + id + "'"); - return map.get(id); - } + @Contract("null -> fail") + @NotNull + public MMOItemType getOrThrow(@Nullable String id) { + if (id == null) throw new IllegalArgumentException(String.format("No type found with id '%s'", id)); + return this.types.stream() + .filter(mmoItemType -> mmoItemType.getId().equals(id)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(String.format("No type found with id '%s'", id))); + } - public boolean has(String id) { - return map.containsKey(id); - } + public boolean has(String id) { + return this.types.stream() + .anyMatch(mmoItemType -> mmoItemType.getId().equals(id)); + } - public Collection getAll() { - return map.values(); - } + public List getAll() { + return this.types; + } - /** - * @return The names of all loaded types. - */ - public ArrayList getAllTypeNames() { - ArrayList ret = new ArrayList<>(); - for (Type t : getAll()) { ret.add(t.getId()); } - return ret; - } + public List getCategories() { + return this.categories; + } + + /** + * @return The names of all loaded types. + */ + public List getAllTypeNames() { + return this.types.stream() + .map(MMOItemType::getName) + .collect(Collectors.toList()); + } } diff --git a/MMOItems-Dist/src/main/resources/default/item-types.yml b/MMOItems-Dist/src/main/resources/default/item-types.yml index 1c601c1f..8a06245b 100644 --- a/MMOItems-Dist/src/main/resources/default/item-types.yml +++ b/MMOItems-Dist/src/main/resources/default/item-types.yml @@ -1,4 +1,3 @@ - # Default item types. These cannot be removed. They # may be used as 'parents' to create new item types # which will behave just like another item type. Parents @@ -19,6 +18,11 @@ SWORD: # Name displayed in the item lore. name: 'Sword' + + weapon: true + modifier: "MELEE_WEAPON" + lore-format: "" + category: "SPLASHING" # Template of an unidentified item. unident-item: diff --git a/MMOItems-Dist/src/main/resources/default/type-categories.yml b/MMOItems-Dist/src/main/resources/default/type-categories.yml new file mode 100644 index 00000000..58fdb4af --- /dev/null +++ b/MMOItems-Dist/src/main/resources/default/type-categories.yml @@ -0,0 +1,12 @@ +SPLASHING: + + # The display parameter is used to display the item in both + # the item brower and the recipe list when shifting a + # workbench. You can use durability for custom textures. + # In 1.14, durability is replaced by CustomModelData. + display: IRON_SWORD:0 + + # Name displayed in the item lore. + name: 'Splashing' + + lore-format: ""