From d93f0d70629c2bb1659d2bf555c5bb00e9a0f5ea Mon Sep 17 00:00:00 2001 From: Jules Date: Sun, 20 Jul 2025 19:11:39 +0200 Subject: [PATCH] More display options for skill, class skill tree node/paths icons --- .../api/player/profess/PlayerClass.java | 26 ++-- .../mmocore/api/util/MMOCoreUtils.java | 7 +- .../mmocore/gui/AbstractClassSelect.java | 4 +- .../net/Indyuce/mmocore/gui/ClassSelect.java | 3 +- .../net/Indyuce/mmocore/gui/SkillList.java | 6 +- .../gui/skilltree/SkillTreeViewer.java | 103 +++++-------- .../mmocore/manager/InventoryManager.java | 7 +- .../mmocore/skill/RegisteredSkill.java | 20 ++- .../Indyuce/mmocore/skilltree/NodeState.java | 3 +- .../Indyuce/mmocore/skilltree/PathState.java | 32 ++++ .../mmocore/skilltree/SkillTreeNode.java | 84 +++++----- .../mmocore/skilltree/SkillTreePath.java | 27 ++-- .../skilltree/display/DisplayInfo.java | 18 --- .../mmocore/skilltree/display/DisplayMap.java | 96 ++++++++++++ .../skilltree/display/NodeDisplayInfo.java | 29 ++-- .../{NodeType.java => display/NodeShape.java} | 4 +- .../skilltree/display/PathDisplayInfo.java | 34 ++-- .../{PathType.java => display/PathShape.java} | 4 +- .../mmocore/skilltree/tree/SkillTree.java | 71 ++++----- .../java/net/Indyuce/mmocore/util/Icon.java | 6 +- .../java/net/Indyuce/mmocore/util/Pair.java | 7 + .../waypoint/WaypointPathCalculation.java | 2 +- MMOCore-Dist/pom.xml | 3 +- .../main/resources/default/classes/human.yml | 15 +- .../default/classes/mage/arcane-mage.yml | 10 +- .../resources/default/classes/mage/mage.yml | 10 ++ .../resources/default/classes/marksman.yml | 10 ++ .../resources/default/classes/paladin.yml | 10 +- .../main/resources/default/classes/rogue.yml | 11 ++ .../resources/default/classes/warrior.yml | 11 +- .../main/resources/default/gui/skill-tree.yml | 64 ++------ .../specific-skill-tree-default.yml | 10 +- .../resources/default/skill-trees/combat.yml | 54 +++++-- .../resources/default/skill-trees/general.yml | 145 ++---------------- .../resources/default/skill-trees/loop.yml | 20 +++ .../default/skill-trees/mage-arcane-mage.yml | 20 +++ .../default/skill-trees/rogue-marksman.yml | 20 +++ .../default/skill-trees/warrior-paladin.yml | 20 +++ 38 files changed, 580 insertions(+), 446 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayInfo.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java rename MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/{NodeType.java => display/NodeShape.java} (78%) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/{PathType.java => display/PathShape.java} (88%) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java index a96b454c..ada8ab97 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/PlayerClass.java @@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.MMOLineConfig; import io.lumine.mythic.lib.api.player.EquipmentSlot; +import io.lumine.mythic.lib.gui.util.IconOptions; import io.lumine.mythic.lib.player.modifier.ModifierSource; import io.lumine.mythic.lib.player.skill.PassiveSkill; import io.lumine.mythic.lib.script.Script; @@ -33,15 +34,12 @@ import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.RegisteredSkill; import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.skill.cast.ComboMap; -import net.Indyuce.mmocore.util.Icon; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.md_5.bungee.api.ChatColor; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.SkullMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,7 +49,7 @@ import java.util.logging.Level; public class PlayerClass implements ExperienceObject, PreloadedObject { private final String name, id, actionBarFormat; private final List description = new ArrayList<>(), attrDescription = new ArrayList<>(); - private final ItemStack icon; + private final IconOptions icon; private final Map options = new HashMap<>(); private final int maxLevel, displayOrder; @@ -101,13 +99,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject { this.id = UtilityMethods.enumName(id); name = MythicLib.plugin.parseColors(config.getString("display.name", "INVALID DISPLAY NAME")); - icon = Icon.from(config.get("display.item", "BARRIER")).toItem(); - - if (config.contains("display.texture") && icon.getType() == Material.PLAYER_HEAD) { - ItemMeta meta = icon.getItemMeta(); - UtilityMethods.setTextureValue((SkullMeta) meta, config.getString("display.texture")); - icon.setItemMeta(meta); - } + icon = IconOptions.from(config.get("display.item")); for (String string : config.getStringList("display.lore")) description.add(ChatColor.GRAY + MythicLib.plugin.parseColors(string)); @@ -141,7 +133,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject { try { skillTrees.add(MMOCore.plugin.skillTreeManager.get(str)); } catch (Exception e) { - MMOCore.log(Level.WARNING, "Could not find skill tree with ID: " + str); + MMOCore.log(Level.WARNING, "Skill tree '" + str + "' not found for player class " + getId()); } // Class-specific scripts @@ -276,7 +268,7 @@ public class PlayerClass implements ExperienceObject, PreloadedObject { comboMap = null; castParticle = new CastingParticle(VParticle.INSTANT_EFFECT.get()); actionBarFormat = ""; - this.icon = new ItemStack(material); + this.icon = new IconOptions(material); setOption(ClassOption.DISPLAY, false); setOption(ClassOption.DEFAULT, false); for (PlayerResource resource : PlayerResource.values()) @@ -336,8 +328,14 @@ public class PlayerClass implements ExperienceObject, PreloadedObject { return expTable != null; } + @NotNull + public IconOptions getRawIcon() { + return icon; + } + + @Deprecated public ItemStack getIcon() { - return icon.clone(); + return icon.toItemStack(); } @Nullable diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java index 6a449313..d4d9d516 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/util/MMOCoreUtils.java @@ -61,7 +61,7 @@ public class MMOCoreUtils { * @param current Current value of resource * @param maxStat Maximum value of resource * @return Clamped resource value. If the provided current value is 0, - * this function will return the maximum resource value. + * this function will return the maximum resource value. */ public static double fixResource(double current, double maxStat) { return current == 0 ? maxStat : Math.max(0, Math.min(current, maxStat)); @@ -82,6 +82,11 @@ public class MMOCoreUtils { return builder.toString(); } + /** + * @see UtilityMethods#kebabCase(Enum) + * @see UtilityMethods#kebabCase(String) + */ + @Deprecated public static String ymlName(String str) { return str.toLowerCase().replace("_", "-").replace(" ", "-"); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java index 340ac83e..16107409 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/AbstractClassSelect.java @@ -55,8 +55,8 @@ public abstract class AbstractClassSelect extends EditableInventory { } @Override - public ItemStack getDisplayedItem(T inv, int n) { - ItemOptions options = n == 0 ? ItemOptions.item(n, playerClass.getIcon()) : ItemOptions.index(n); + public ItemStack getDisplayedItem(@NotNull T inv, int n) { + ItemOptions options = n == 0 ? new ItemOptions(n, playerClass.getRawIcon()) : ItemOptions.index(n); return super.getDisplayedItem(inv, options); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java index f6280364..434a3be6 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/ClassSelect.java @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.gui; +import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.gui.Navigator; import io.lumine.mythic.lib.gui.editable.item.InventoryItem; import net.Indyuce.mmocore.MMOCore; @@ -63,7 +64,7 @@ public class ClassSelect extends AbstractClassSelect { inv.getNavigator().unblockClosing(); final PlayerClass playerClass = findDeepestSubclass(inv.playerData, this.playerClass); - InventoryManager.CLASS_CONFIRM.get(MMOCoreUtils.ymlName(playerClass.getId())).newInventory(inv, inv.profileCallback != null).open(); + InventoryManager.CLASS_CONFIRM.get(UtilityMethods.kebabCase(playerClass.getId())).newInventory(inv, inv.profileCallback != null).open(); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java index a7fe2136..4d61c4d5 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillList.java @@ -150,7 +150,7 @@ public class SkillList extends EditableInventory { public ItemStack getDisplayedItem(SkillViewerInventory inv, int n) { if (inv.selected == null) return new ItemStack(Material.AIR); - return getDisplayedItem(inv, inv.selected.getSkill().getRawIcon().toItemOptions(n)); + return getDisplayedItem(inv, new ItemOptions(n, inv.selected.getSkill().getRawIcon())); } @Override @@ -269,7 +269,7 @@ public class SkillList extends EditableInventory { if (skillSlot == null || !inv.playerData.hasUnlocked(skillSlot)) return new ItemStack(Material.AIR); final @Nullable ClassSkill boundSkill = inv.playerData.getBoundSkill(n + 1); - final ItemOptions options = boundSkill == null ? ItemOptions.index(n) : filledItem == null ? boundSkill.getSkill().getRawIcon().toItemOptions(n) : ItemOptions.model(n, filledItem, filledCMD); + final ItemOptions options = boundSkill == null ? ItemOptions.index(n) : filledItem == null ? new ItemOptions(n, boundSkill.getSkill().getRawIcon()) : ItemOptions.model(n, filledItem, filledCMD); return super.getDisplayedItem(inv, options); } @@ -395,7 +395,7 @@ public class SkillList extends EditableInventory { if (index >= inv.skills.size()) return new ItemStack(Material.AIR); ClassSkill skill = inv.skills.get(index); - return getDisplayedItem(inv, skill.getSkill().getRawIcon().toItemOptions(n)); + return getDisplayedItem(inv, new ItemOptions(n, skill.getSkill().getRawIcon())); } @Override diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java index 904266c5..ae981e50 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java @@ -9,18 +9,19 @@ import io.lumine.mythic.lib.gui.editable.item.ItemOptions; import io.lumine.mythic.lib.gui.editable.item.PhysicalItem; import io.lumine.mythic.lib.gui.editable.item.SimpleItem; import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders; +import io.lumine.mythic.lib.gui.util.IconOptions; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.util.MMOCoreUtils; -import net.Indyuce.mmocore.skilltree.*; -import net.Indyuce.mmocore.skilltree.display.DisplayInfo; +import net.Indyuce.mmocore.skilltree.IntegerCoordinates; +import net.Indyuce.mmocore.skilltree.NodeState; +import net.Indyuce.mmocore.skilltree.ParentType; +import net.Indyuce.mmocore.skilltree.SkillTreeNode; +import net.Indyuce.mmocore.skilltree.display.DisplayMap; import net.Indyuce.mmocore.skilltree.display.NodeDisplayInfo; import net.Indyuce.mmocore.skilltree.display.PathDisplayInfo; import net.Indyuce.mmocore.skilltree.tree.SkillTree; -import net.Indyuce.mmocore.util.Icon; -import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -37,10 +38,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.logging.Level; public class SkillTreeViewer extends EditableInventory { - protected final Map icons = new HashMap<>(); + protected DisplayMap icons; protected final Map statusNames = new HashMap<>(); /** @@ -64,31 +64,11 @@ public class SkillTreeViewer extends EditableInventory { public void reload(@NotNull JavaPlugin plugin, @NotNull ConfigurationSection config) { super.reload(plugin, config); - if (config.contains("status-names")) - for (NodeState nodeState : NodeState.values()) - statusNames.put(nodeState, config.getString("status-names." + UtilityMethods.ymlName(nodeState.name()), nodeState.name())); + if (config.contains("status-names")) for (NodeState nodeState : NodeState.values()) + statusNames.put(nodeState, config.getString("status-names." + UtilityMethods.ymlName(nodeState.name()), nodeState.name())); - // Loads all the pathDisplayInfo - for (NodeState status : NodeState.values()) - for (PathType pathType : PathType.values()) { - final String configPath = "display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()); - if (!config.contains(configPath)) { - MMOCore.log(Level.WARNING, "An error occurred while loading skill tree GUI: Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); - continue; - } - icons.put(new PathDisplayInfo(pathType, status), Icon.from(config.get(configPath))); - } - - // Loads all the nodeDisplayInfo - for (NodeState status : NodeState.values()) - for (NodeType nodeType : NodeType.values()) { - final String configPath = "display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()); - if (!config.contains(configPath)) { - MMOCore.log(Level.WARNING, "An error occurred while loading skill tree GUI: Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); - continue; - } - icons.put(new NodeDisplayInfo(nodeType, status), Icon.from(config.get(configPath))); - } + // Loads display info + icons = DisplayMap.from(config.getConfigurationSection("display")); } @Override @@ -268,8 +248,7 @@ public class SkillTreeViewer extends EditableInventory { @Override public void onClick(@NotNull SkillTreeInventory inv, @NotNull InventoryClickEvent event) { - String id = event.getCurrentItem().getItemMeta().getPersistentDataContainer().get( - new NamespacedKey(MMOCore.plugin, "skill-tree-id"), PersistentDataType.STRING); + String id = event.getCurrentItem().getItemMeta().getPersistentDataContainer().get(new NamespacedKey(MMOCore.plugin, "skill-tree-id"), PersistentDataType.STRING); MMOCore.plugin.soundManager.getSound(SoundEvent.CHANGE_SKILL_TREE).playTo(inv.getPlayer()); inv.skillTree = MMOCore.plugin.skillTreeManager.get(id); inv.open(); @@ -317,8 +296,7 @@ public class SkillTreeViewer extends EditableInventory { public SkillTreeNodeItem(ConfigurationSection config) { super(config); - if (config.isList("path-lore")) - pathLore.addAll(config.getStringList("path-lore")); + if (config.isList("path-lore")) pathLore.addAll(config.getStringList("path-lore")); } @Override @@ -373,8 +351,8 @@ public class SkillTreeViewer extends EditableInventory { IntegerCoordinates coordinates = inv.getCoordinates(n); if (!inv.getSkillTree().isPathOrNode(coordinates)) return new ItemStack(Material.AIR); - Icon icon = inv.getIcon(coordinates); - ItemStack item = super.getDisplayedItem(inv, icon.toItemOptions(n)); + IconOptions icon = inv.getIcon(coordinates); + ItemStack item = super.getDisplayedItem(inv, new ItemOptions(n, icon)); ItemMeta meta = item.getItemMeta(); // Make sure name is not null @@ -513,17 +491,14 @@ public class SkillTreeViewer extends EditableInventory { this.skillTree = skillTree == null ? skillTrees.get(0) : skillTree; if (skillTree == null) maxTreeListPage = (skillTrees.size() - 1) / SkillTreeViewer.this.getByFunction("skill-tree").getSlots().size(); - else - maxTreeListPage = 0; + else maxTreeListPage = 0; //We get the width and height of the GUI(corresponding to the slots given) slots = SkillTreeViewer.this.getByFunction("skill-tree-node").getSlots(); minSlot = 64; maxSlot = 0; for (int slot : slots) { - if (slot < minSlot) - minSlot = slot; - if (slot > maxSlot) - maxSlot = slot; + if (slot < minSlot) minSlot = slot; + if (slot > maxSlot) maxSlot = slot; } width = (maxSlot - minSlot) % 9; height = (maxSlot - minSlot) / 9; @@ -551,32 +526,30 @@ public class SkillTreeViewer extends EditableInventory { return playerData; } - public Icon getIcon(IntegerCoordinates coordinates) { + public IconOptions getIcon(@NotNull IntegerCoordinates coordinates) { if (skillTree.isNode(coordinates)) { - SkillTreeNode node = skillTree.getNode(coordinates); - NodeType nodeType = node.getNodeType(); - NodeState nodeState = playerData.getNodeState(node); - //If the node has its own display, it will be shown. - if (node.hasIcon(nodeState)) - return node.getIcon(nodeState); - DisplayInfo displayInfo = new NodeDisplayInfo(nodeType, nodeState); - //Takes the display defined in the skill tree config if it exists. - if (skillTree.hasIcon(displayInfo)) - return skillTree.getIcon(displayInfo); + var node = skillTree.getNode(coordinates); + var nodeShape = node.getNodeType(); + var nodeState = playerData.getNodeState(node); + var displayInfo = new NodeDisplayInfo(nodeShape, nodeState); + + // Node > skill tree > skill tree UI + var icon = DisplayMap.getIcon(displayInfo, node.getIcons(), skillTree.getIcons(), icons); + if (icon == null) icon = DisplayMap.DEFAULT_ICON; + //Validate.notNull(icon, "Node " + node.getFullId() + " has no icon for shape " + nodeShape + " and state " + nodeState); - Icon icon = icons.get(displayInfo); - Validate.notNull(icon, "The node " + node.getFullId() + " has no icon for the type " + nodeType + " and the status " + nodeState); return icon; } else { - SkillTreePath path = skillTree.getPath(coordinates); - PathType pathType = path.getPathType(); - NodeState pathStatus = path.getStatus(playerData); - DisplayInfo displayInfo = new PathDisplayInfo(pathType, pathStatus); - //Takes the display defined in the skill tree config if it exists. - if (skillTree.hasIcon(displayInfo)) - return skillTree.getIcon(displayInfo); - Icon icon = icons.get(displayInfo); - Validate.notNull(icon, "There is no icon for the path type " + pathType + " and the status " + pathStatus); + var path = skillTree.getPath(coordinates); + var pathShape = path.getPathType(); + var pathStatus = path.getStatus(playerData); + var displayInfo = new PathDisplayInfo(pathShape, pathStatus); + + // Skill tree > Skill tree UI + var icon = DisplayMap.getIcon(displayInfo, skillTree.getIcons(), icons); + if (icon == null) icon = DisplayMap.DEFAULT_ICON; + //Validate.notNull(icon, "No icon for path shape " + pathShape + " and state " + pathStatus); + return icon; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java index b7126e08..cbce8eeb 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/InventoryManager.java @@ -69,7 +69,12 @@ public class InventoryManager { final var specificUi = invType.provider.apply(id, !configFile.exists()); ((Map) invType.inventories).put(formattedId, specificUi); - specificUi.reload(MMOCore.plugin, new ConfigFile("/gui/" + invType.name, specificUi.getId()).getConfig()); + + // try { + specificUi.reload(MMOCore.plugin, new ConfigFile("/gui/" + invType.name, specificUi.getId()).getConfig()); + /* } catch (Exception exception) { + MMOCore.log(Level.WARNING, "Could not load inventory 'gui/" + invType.name + "/" + invType.name + "-default" + "': " + exception.getMessage()); + } */ } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java index 96a16554..b1333f73 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java @@ -2,12 +2,12 @@ package net.Indyuce.mmocore.skill; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.gui.util.IconOptions; import io.lumine.mythic.lib.skill.handler.SkillHandler; import io.lumine.mythic.lib.skill.trigger.TriggerType; import io.lumine.mythic.lib.util.formula.BooleanExpression; import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue; import net.Indyuce.mmocore.api.util.math.formula.LinearValue; -import net.Indyuce.mmocore.util.Icon; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -23,7 +23,7 @@ public class RegisteredSkill { private final Map parameterDecimalFormats = new HashMap<>(); - private final Icon icon; + private final IconOptions icon; private final List lore; private final List categories; private final TriggerType triggerType; @@ -32,7 +32,7 @@ public class RegisteredSkill { this.handler = handler; name = Objects.requireNonNull(config.getString("name"), "Could not find skill name"); - icon = Icon.from(config.get("material")); + icon = IconOptions.from(config.get("material")); lore = Objects.requireNonNull(config.getStringList("lore"), "Could not find skill lore"); // Trigger type @@ -46,7 +46,6 @@ public class RegisteredSkill { else categories.add("ACTIVE"); - // Load default modifier formulas for (String param : handler.getParameters()) { if (config.contains(param + ".decimal-format")) @@ -62,15 +61,20 @@ public class RegisteredSkill { defaultParameters.put("level", new IntegerLinearValue(0, 1)); } - public RegisteredSkill(SkillHandler handler, String name, ItemStack icon, List lore, @Nullable TriggerType triggerType) { + public RegisteredSkill(SkillHandler handler, String name, IconOptions icon, List lore, @Nullable TriggerType triggerType) { this.handler = handler; this.name = name; - this.icon = Icon.fromItem(icon); + this.icon = IconOptions.from(icon); this.lore = lore; this.triggerType = triggerType; this.categories = new ArrayList<>(); } + @Deprecated + public RegisteredSkill(SkillHandler handler, String name, ItemStack icon, List lore, @Nullable TriggerType triggerType) { + this(handler, name, IconOptions.from(icon), lore, triggerType); + } + public SkillHandler getHandler() { return handler; } @@ -89,11 +93,11 @@ public class RegisteredSkill { @Deprecated public ItemStack getIcon() { - return icon.toItem(); + return icon.toItemStack(); } @NotNull - public Icon getRawIcon() { + public IconOptions getRawIcon() { return icon; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeState.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeState.java index a74280f4..8031c47a 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeState.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeState.java @@ -5,8 +5,7 @@ import net.Indyuce.mmocore.api.player.PlayerData; /** * State of one skill tree node, or path between nodes. * - * @see PlayerData#getNodeState(SkillTreeNode) - * @see SkillTreePath#getStatus(PlayerData) + * @see PlayerData#getNodeState(SkillTreeNode) */ public enum NodeState { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java new file mode 100644 index 00000000..3c5c743e --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathState.java @@ -0,0 +1,32 @@ +package net.Indyuce.mmocore.skilltree; + +import net.Indyuce.mmocore.api.player.PlayerData; + +/** + * @see SkillTreePath#getStatus(PlayerData) + */ +public enum PathState { + + /** + * The player has purchased and unlocked the skill tree node. + */ + UNLOCKED, + + /** + * The player has instant access to but has not unlocked the node. + */ + UNLOCKABLE, + + /** + * The player does not have access to this skill node but it + * remains a possibility to access it. + */ + LOCKED, + + /** + * The player made a choice making it now impossible to reach this + * node given its skill tree exploration. The player needs to + * re-spec to unlock that node. + */ + FULLY_LOCKED +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java index e3a4736f..4e4a5b02 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java @@ -2,14 +2,16 @@ package net.Indyuce.mmocore.skilltree; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.gui.editable.placeholder.Placeholders; +import io.lumine.mythic.lib.gui.util.IconOptions; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.experience.EXPSource; import net.Indyuce.mmocore.experience.ExpCurve; import net.Indyuce.mmocore.experience.ExperienceObject; import net.Indyuce.mmocore.experience.droptable.ExperienceTable; -import net.Indyuce.mmocore.util.Icon; +import net.Indyuce.mmocore.skilltree.display.DisplayMap; +import net.Indyuce.mmocore.skilltree.display.NodeDisplayInfo; +import net.Indyuce.mmocore.skilltree.display.NodeShape; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; import org.bukkit.Location; @@ -26,7 +28,7 @@ public class SkillTreeNode implements ExperienceObject { private final String name, id; private final String permissionRequired; private final int pointConsumption; - private final Map icons = new HashMap<>(); + private final DisplayMap icons; private final IntegerCoordinates coordinates; private final int maxLevel, maxChildren; private final ExperienceTable experienceTable; @@ -42,13 +44,7 @@ public class SkillTreeNode implements ExperienceObject { this.tree = tree; // Load icons for node states - if (config.isConfigurationSection("display")) for (NodeState state : NodeState.values()) { - final String ymlStatus = MMOCoreUtils.ymlName(state.name()); - if (config.isConfigurationSection("display." + ymlStatus)) - icons.put(state, Icon.from(config.get("display." + MMOCoreUtils.ymlName(state.name())))); - else - MMOCore.log("Could not find node display for state " + ymlStatus + " of node " + id + " in tree " + tree.getId() + ". Using default display."); - } + this.icons = DisplayMap.from(config.getConfigurationSection("display")); name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); root = config.getBoolean("root", config.getBoolean("is-root")); // backwards compatibility @@ -81,14 +77,6 @@ public class SkillTreeNode implements ExperienceObject { return tree; } - public boolean hasIcon(NodeState status) { - return icons.containsKey(status); - } - - public Icon getIcon(NodeState status) { - return icons.get(status); - } - public boolean isRoot() { return root; } @@ -167,7 +155,7 @@ public class SkillTreeNode implements ExperienceObject { /** * @return Full node identifier, containing both the node identifier AND - * the skill tree identifier, like "combat_extra_strength" + * the skill tree identifier, like "combat_extra_strength" */ @NotNull public String getFullId() { @@ -184,6 +172,11 @@ public class SkillTreeNode implements ExperienceObject { return coordinates; } + @NotNull + public DisplayMap getIcons() { + return icons; + } + public static final String KEY_PREFIX = "node"; @Override @@ -202,28 +195,28 @@ public class SkillTreeNode implements ExperienceObject { return experienceTable != null; } - public NodeType getNodeType() { + public NodeShape getNodeType() { boolean up = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1)); boolean down = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1)); boolean right = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY())); boolean left = tree.isPathOrNode(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY())); - if (up && right && down && left) return NodeType.UP_RIGHT_DOWN_LEFT; - else if (up && right && down) return NodeType.UP_RIGHT_DOWN; - else if (up && right && left) return NodeType.UP_RIGHT_LEFT; - else if (up && down && left) return NodeType.UP_DOWN_LEFT; - else if (down && right && left) return NodeType.DOWN_RIGHT_LEFT; - else if (up && right) return NodeType.UP_RIGHT; - else if (up && down) return NodeType.UP_DOWN; - else if (up && left) return NodeType.UP_LEFT; - else if (down && right) return NodeType.DOWN_RIGHT; - else if (down && left) return NodeType.DOWN_LEFT; - else if (right && left) return NodeType.RIGHT_LEFT; - else if (up) return NodeType.UP; - else if (down) return NodeType.DOWN; - else if (right) return NodeType.RIGHT; - else if (left) return NodeType.LEFT; - return NodeType.NO_PATH; + if (up && right && down && left) return NodeShape.UP_RIGHT_DOWN_LEFT; + else if (up && right && down) return NodeShape.UP_RIGHT_DOWN; + else if (up && right && left) return NodeShape.UP_RIGHT_LEFT; + else if (up && down && left) return NodeShape.UP_DOWN_LEFT; + else if (down && right && left) return NodeShape.DOWN_RIGHT_LEFT; + else if (up && right) return NodeShape.UP_RIGHT; + else if (up && down) return NodeShape.UP_DOWN; + else if (up && left) return NodeShape.UP_LEFT; + else if (down && right) return NodeShape.DOWN_RIGHT; + else if (down && left) return NodeShape.DOWN_LEFT; + else if (right && left) return NodeShape.RIGHT_LEFT; + else if (up) return NodeShape.UP; + else if (down) return NodeShape.DOWN; + else if (right) return NodeShape.RIGHT; + else if (left) return NodeShape.LEFT; + return NodeShape.NO_PATH; } @Override @@ -281,4 +274,23 @@ public class SkillTreeNode implements ExperienceObject { public ExpCurve getExpCurve() { throw new RuntimeException("Skill trees don't have experience"); } + + //region Deprecated + + @Deprecated + public boolean hasIcon(NodeState status) { + return getIcon(status) != null; + } + + @Deprecated + @Nullable + public IconOptions getIcon(NodeState status) { + for (var shape : NodeShape.values()) { + var found = DisplayMap.getIcon(new NodeDisplayInfo(shape, status), icons); + if (found != null) return found; + } + return null; + } + + //endregion } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java index 42f29abf..53165356 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java @@ -1,6 +1,7 @@ package net.Indyuce.mmocore.skilltree; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.skilltree.display.PathShape; import net.Indyuce.mmocore.skilltree.tree.SkillTree; public class SkillTreePath { @@ -20,25 +21,25 @@ public class SkillTreePath { * Defines the status of a path between two nodes, which is determined * by the pair of states of the two nodes. */ - public NodeState getStatus(PlayerData playerData) { + public PathState getStatus(PlayerData playerData) { var from = playerData.getNodeState(this.from); var to = playerData.getNodeState(this.to); // Either one is fully locked => gray out path - if (from == NodeState.FULLY_LOCKED || to == NodeState.FULLY_LOCKED) return NodeState.FULLY_LOCKED; + if (from == NodeState.FULLY_LOCKED || to == NodeState.FULLY_LOCKED) return PathState.FULLY_LOCKED; // Both are unlocked => path is taken, unlocked - if (from.isUnlocked() && to.isUnlocked()) return NodeState.UNLOCKED; + if (from.isUnlocked() && to.isUnlocked()) return PathState.UNLOCKED; // One of them is unlocked, other one is unlockable => path is not taken yet, but can be if ((from == NodeState.UNLOCKABLE && to.isUnlocked()) || (from.isUnlocked() && to == NodeState.UNLOCKABLE)) - return NodeState.UNLOCKABLE; + return PathState.UNLOCKABLE; // Otherwise, locked path - return NodeState.LOCKED; + return PathState.LOCKED; } - public PathType getPathType() { + public PathShape getPathType() { IntegerCoordinates upCoor = new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1); IntegerCoordinates downCoor = new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1); IntegerCoordinates rightCoor = new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY()); @@ -49,18 +50,18 @@ public class SkillTreePath { boolean hasLeft = tree.isPath(leftCoor) || leftCoor.equals(from.getCoordinates()) || leftCoor.equals(to.getCoordinates()); if ((hasUp || hasDown) && !hasLeft && !hasRight) { - return PathType.UP; + return PathShape.UP; } else if ((hasRight || hasLeft) && !hasUp && !hasDown) { - return PathType.RIGHT; + return PathShape.RIGHT; } else if (hasUp && hasRight) { - return PathType.UP_RIGHT; + return PathShape.UP_RIGHT; } else if (hasUp && hasLeft) { - return PathType.UP_LEFT; + return PathShape.UP_LEFT; } else if (hasDown && hasRight) { - return PathType.DOWN_RIGHT; + return PathShape.DOWN_RIGHT; } else if (hasDown && hasLeft) { - return PathType.DOWN_LEFT; + return PathShape.DOWN_LEFT; } - return PathType.DEFAULT; + return PathShape.DEFAULT; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayInfo.java deleted file mode 100644 index 0a06cace..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayInfo.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.Indyuce.mmocore.skilltree.display; - -import net.Indyuce.mmocore.skilltree.NodeState; - -/** - * The information needed to determine the display of a node/path depending on its context. - */ -public abstract class DisplayInfo { - protected final NodeState state; - - protected DisplayInfo(NodeState state) { - this.state = state; - } - - public NodeState getState() { - return state; - } -} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java new file mode 100644 index 00000000..04b6cfc4 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/DisplayMap.java @@ -0,0 +1,96 @@ +package net.Indyuce.mmocore.skilltree.display; + +import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.gui.util.IconOptions; +import net.Indyuce.mmocore.skilltree.NodeState; +import net.Indyuce.mmocore.skilltree.PathState; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +public class DisplayMap { + public final Map icons = new HashMap<>(); + + public static final IconOptions DEFAULT_ICON = new IconOptions(Material.BARRIER, 0); + public static final DisplayMap EMPTY = new DisplayMap(YamlConfiguration.loadConfiguration(new StringReader(""))); + + private DisplayMap(@NotNull ConfigurationSection config) { + + // Loads all the pathDisplayInfo + if (config.contains("paths")) for (var status : PathState.values()) + for (PathShape pathShape : PathShape.values()) + try { + final String configPath = "paths." + UtilityMethods.kebabCase(status.name() + "." + pathShape.name()); + icons.put(new PathDisplayInfo(pathShape, status), IconOptions.from(config.get(configPath))); + } catch (Exception exception) { + // Ignore + } + + // Loads all the nodeDisplayInfo + var nodeConfig = getNodeConfig(config); + if (nodeConfig != null) for (var state : NodeState.values()) { + final var statusConfig = nodeConfig.get(UtilityMethods.kebabCase(state.name())); + if (statusConfig == null) continue; + + // Check if it depends on state + if (statusConfig instanceof ConfigurationSection && UtilityMethods.containsOneKey((ConfigurationSection) statusConfig, NodeShape.values(), UtilityMethods::kebabCase)) + for (var shape : NodeShape.values()) { + try { + final var configPath = "nodes." + UtilityMethods.kebabCase(state.name() + "." + shape.name()); + icons.put(new NodeDisplayInfo(shape, state), IconOptions.from(nodeConfig.get(configPath))); + } catch (Exception exception) { + // Ignore + } + } + + // Depends on node type + else { + var iconFound = IconOptions.from(statusConfig); + for (var shape : NodeShape.values()) + icons.put(new NodeDisplayInfo(shape, state), iconFound); + } + } + } + + @Nullable + private ConfigurationSection getNodeConfig(@Nullable ConfigurationSection config) { + + // Null to null + if (config == null) return null; + + // 'nodes' subconfig + var subconfig = config.getConfigurationSection("nodes"); + if (subconfig != null) return subconfig; + + // Validate at least one state + // Not strictly necessary. + if (UtilityMethods.containsOneKey(config, NodeState.values(), UtilityMethods::kebabCase)) return config; + + // Wrong syntax.. + return null; + } + + /** + * @param nodeInfo Either a {@link NodeDisplayInfo} or {@link PathDisplayInfo} + * @return Icon/texture mapping of node/path display info + */ + @Nullable + public static IconOptions getIcon(Object nodeInfo, @NotNull DisplayMap... maps) { + int i = 0; + IconOptions found = null; + while (found == null && i < maps.length) found = maps[i++].icons.get(nodeInfo); + return found; + } + + @NotNull + public static DisplayMap from(@Nullable ConfigurationSection config) { + if (config == null) return EMPTY; + return new DisplayMap(config); + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeDisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeDisplayInfo.java index 6c884fd7..bdf72305 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeDisplayInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeDisplayInfo.java @@ -1,22 +1,27 @@ package net.Indyuce.mmocore.skilltree.display; -import net.Indyuce.mmocore.skilltree.NodeType; import net.Indyuce.mmocore.skilltree.NodeState; import org.jetbrains.annotations.NotNull; import java.util.Objects; -public class NodeDisplayInfo extends DisplayInfo { - private final NodeType type; +public class NodeDisplayInfo { + private final NodeShape shape; + private final NodeState state; - public NodeDisplayInfo(@NotNull NodeType type, @NotNull NodeState status) { - super(status); - - this.type = type; + public NodeDisplayInfo(@NotNull NodeShape shape, @NotNull NodeState status) { + this.state = status; + this.shape = shape; } - public NodeType getType() { - return type; + @NotNull + public NodeState getStatus() { + return state; + } + + @NotNull + public NodeShape getShape() { + return shape; } @Override @@ -24,16 +29,16 @@ public class NodeDisplayInfo extends DisplayInfo { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NodeDisplayInfo that = (NodeDisplayInfo) o; - return state == that.state && type == that.type; + return state == that.state && shape == that.shape; } @Override public int hashCode() { - return Objects.hash(state, type); + return Objects.hash(state, shape); } @Override public String toString() { - return "NodeDisplayInfo{" + "status=" + state + ", type=" + type + '}'; + return "NodeDisplayInfo{" + "status=" + state + ", type=" + shape + '}'; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeShape.java similarity index 78% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeType.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeShape.java index 0604775e..9a54372f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/NodeType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/NodeShape.java @@ -1,9 +1,9 @@ -package net.Indyuce.mmocore.skilltree; +package net.Indyuce.mmocore.skilltree.display; /** * TODO docs */ -public enum NodeType { +public enum NodeShape { UP_RIGHT_DOWN_LEFT, UP_RIGHT_DOWN, UP_RIGHT_LEFT, diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java index da8c28c3..be3b641e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathDisplayInfo.java @@ -1,30 +1,32 @@ package net.Indyuce.mmocore.skilltree.display; -import net.Indyuce.mmocore.skilltree.PathType; -import net.Indyuce.mmocore.skilltree.NodeState; +import net.Indyuce.mmocore.skilltree.PathState; +import org.jetbrains.annotations.NotNull; import java.util.Objects; -public class PathDisplayInfo extends DisplayInfo { - private final PathType type; +public class PathDisplayInfo { + private final PathShape shape; + private final PathState state; - public PathDisplayInfo(PathType type, NodeState status) { - super(status); - - this.type = type; + public PathDisplayInfo(@NotNull PathShape shape, @NotNull PathState status) { + this.state = status; + this.shape = shape; } - public PathType getType() { - return type; - } - - public NodeState getStatus() { + @NotNull + public PathState getStatus() { return state; } + @NotNull + public PathShape getShape() { + return shape; + } + @Override public int hashCode() { - return Objects.hash(type, state); + return Objects.hash(shape, state); } @Override @@ -32,11 +34,11 @@ public class PathDisplayInfo extends DisplayInfo { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PathDisplayInfo that = (PathDisplayInfo) o; - return type == that.type && state == that.state; + return shape == that.shape && state == that.state; } @Override public String toString() { - return "PathDisplayInfo{" + "type=" + type + ", status=" + state + '}'; + return "PathDisplayInfo{" + "type=" + shape + ", status=" + state + '}'; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathShape.java similarity index 88% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathType.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathShape.java index 067a898e..f98df420 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/PathType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/display/PathShape.java @@ -1,11 +1,11 @@ -package net.Indyuce.mmocore.skilltree; +package net.Indyuce.mmocore.skilltree.display; /** * These are the different textures that a path between * two nodes can have, just like a redstone wire which can take * turns, go straight, or be a one node path on its own. */ -public enum PathType { +public enum PathShape { /** * │ up, down diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java index 189303fe..be1c7070 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java @@ -2,15 +2,12 @@ package net.Indyuce.mmocore.skilltree.tree; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; +import io.lumine.mythic.lib.gui.util.IconOptions; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.manager.registry.RegisteredObject; import net.Indyuce.mmocore.skilltree.*; -import net.Indyuce.mmocore.skilltree.display.DisplayInfo; -import net.Indyuce.mmocore.skilltree.display.NodeDisplayInfo; -import net.Indyuce.mmocore.skilltree.display.PathDisplayInfo; -import net.Indyuce.mmocore.util.Icon; +import net.Indyuce.mmocore.skilltree.display.DisplayMap; import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -42,7 +39,7 @@ public abstract class SkillTree implements RegisteredObject { protected final Map nodes = new HashMap<>(); protected final int maxPointSpent; protected final List roots = new ArrayList<>(); - protected final Map icons = new HashMap<>(); + protected final DisplayMap icons; protected final Map coordNodes = new HashMap<>(); protected final Map coordPaths = new HashMap<>(); @@ -87,33 +84,8 @@ public abstract class SkillTree implements RegisteredObject { } } - // Loads all the pathDisplayInfo - for (NodeState status : NodeState.values()) - for (PathType pathType : PathType.values()) - try { - final String configPath = "display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()); - icons.put(new PathDisplayInfo(pathType, status), Icon.from(config.get(configPath))); - } catch (Exception exception) { - // Ignore - } - - // Loads all the nodeDisplayInfo - for (var status : NodeState.values()) { - final var anyType = config.get("display.nodes." + MMOCoreUtils.ymlName(status.name())); - - // Does not depend on node type. - if (anyType != null) for (var nodeType : NodeType.values()) - icons.put(new NodeDisplayInfo(nodeType, status), Icon.from(anyType)); - - // Depends on node type - else for (var nodeType : NodeType.values()) - try { - final var configPath = "display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()); - icons.put(new NodeDisplayInfo(nodeType, status), Icon.from(config.get(configPath))); - } catch (Exception exception) { - // Ignore - } - } + // Load icons + this.icons = DisplayMap.from(config.getConfigurationSection("display")); // Setup children and parents for each node for (SkillTreeNode node : nodes.values()) @@ -149,11 +121,6 @@ public abstract class SkillTree implements RegisteredObject { return customModelData; } - @Deprecated - public static SkillTree loadSkillTree(ConfigurationSection config) { - return MMOCore.plugin.skillTreeManager.loadSkillTree(config); - } - public void addRoot(@NotNull SkillTreeNode node) { roots.add(node); } @@ -366,12 +333,9 @@ public abstract class SkillTree implements RegisteredObject { return Objects.requireNonNull(nodes.get(name), "Could not find node in tree '" + id + "' with name '" + name + "'"); } - public boolean hasIcon(DisplayInfo displayInfo) { - return icons.containsKey(displayInfo); - } - - public Icon getIcon(DisplayInfo displayInfo) { - return icons.get(displayInfo); + @NotNull + public DisplayMap getIcons() { + return icons; } public boolean isNode(String name) { @@ -390,4 +354,23 @@ public abstract class SkillTree implements RegisteredObject { public int hashCode() { return Objects.hash(id); } + + //region Deprecated + + @Deprecated + public static SkillTree loadSkillTree(ConfigurationSection config) { + return MMOCore.plugin.skillTreeManager.loadSkillTree(config); + } + + @Deprecated + public boolean hasIcon(Object displayInfo) { + return DisplayMap.getIcon(displayInfo, icons) != null; + } + + @Deprecated + public IconOptions getIcon(Object displayInfo) { + return DisplayMap.getIcon(displayInfo, icons); + } + + //endregion } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java index 991e4a37..63b215b3 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Icon.java @@ -14,7 +14,11 @@ import java.util.Objects; /** * The material and custom model-data of a node + * + * @see io.lumine.mythic.lib.gui.util.IconOptions + * @deprecated */ +@Deprecated public class Icon { private final Material material; private final int modelData; @@ -77,7 +81,7 @@ public class Icon { if (object instanceof ConfigurationSection) { final ConfigurationSection config = (ConfigurationSection) object; - final Material material = Material.valueOf(UtilityMethods.enumName(((ConfigurationSection) object).getString("item"))); + final Material material = Material.valueOf(UtilityMethods.enumName(((ConfigurationSection) object).getString("item", "none"))); final int modelData = config.getInt("model-data", config.getInt("custom-model-data")); // Backwards compatibility return new Icon(material, modelData); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java index 01fb1a87..2a2ba840 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/util/Pair.java @@ -5,6 +5,13 @@ import org.jetbrains.annotations.NotNull; import java.util.Objects; +/** + * @param Left-hand side type + * @param Right-hand side type + * @see io.lumine.mythic.lib.util.Pair + * @deprecated + */ +@Deprecated public class Pair { private final L left; private final R right; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/waypoint/WaypointPathCalculation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/waypoint/WaypointPathCalculation.java index ef138f3e..cf3a04e1 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/waypoint/WaypointPathCalculation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/waypoint/WaypointPathCalculation.java @@ -1,8 +1,8 @@ package net.Indyuce.mmocore.waypoint; +import io.lumine.mythic.lib.util.Pair; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/MMOCore-Dist/pom.xml b/MMOCore-Dist/pom.xml index 5a501ecb..3241cc22 100644 --- a/MMOCore-Dist/pom.xml +++ b/MMOCore-Dist/pom.xml @@ -13,6 +13,8 @@ + MMOCore-${project.version} + @@ -34,7 +36,6 @@ maven-jar-plugin 3.1.0 - MMOCore-${project.version} ../target/ diff --git a/MMOCore-Dist/src/main/resources/default/classes/human.yml b/MMOCore-Dist/src/main/resources/default/classes/human.yml index 78befa74..5415bf4d 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/human.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/human.yml @@ -4,13 +4,16 @@ display: name: 'Human' -# This is the default class which players have when -# joining the server. They can level it up, but they -# cannot choose this class again after changing their -# class because it is not displayed in /class + # No need for an item since the default class is not displayed + # anywhere by default. + #item: LEATHER_CHESTPLATE + +# This is the default class granted to players when joining the server. +# They may level it up, but they cannot choose this class again +# after switching class, since it is not displayed in /class options: - default: true - display: false + default: true # Default class when joining the server for the first time + display: false # Does not display in the class UI needs-permission: false # False by default # Only regens when out of combat diff --git a/MMOCore-Dist/src/main/resources/default/classes/mage/arcane-mage.yml b/MMOCore-Dist/src/main/resources/default/classes/mage/arcane-mage.yml index a6cdd473..9ff26ae9 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/mage/arcane-mage.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/mage/arcane-mage.yml @@ -26,7 +26,15 @@ display: - '&7 Max Mana: &930 &7(+&91.3&7)' - '&7 Health Regen: &90.13 &7(+&90&7)' - '&7 Mana Regen: &90.2 &7(+&90.04&7)' - item: BLAZE_POWDER:1 # Supports custom model data/texture by durability + + item: 'BLAZE_POWDER:1' # Syntax: ':' + # Alternate syntax for string custom model data, item model.... + #item: + # item: BLAZE_POWDER + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/classes/mage/mage.yml b/MMOCore-Dist/src/main/resources/default/classes/mage/mage.yml index e0a94b98..8b8170a8 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/mage/mage.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/mage/mage.yml @@ -24,7 +24,17 @@ display: - '&7 Max Mana: &927 &7(+&91.2&7)' - '&7 Health Regen: &90.13 &7(+&90&7)' - '&7 Mana Regen: &90.2 &7(+&90.04&7)' + item: BLAZE_POWDER + # Alternate syntax for custom model data + #item: 'BLAZE_POWDER:10' + # Alternate syntax for custom model data, item model.... + #item: + # item: BLAZE_POWDER + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/classes/marksman.yml b/MMOCore-Dist/src/main/resources/default/classes/marksman.yml index 7a898a9b..ef545ca1 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/marksman.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/marksman.yml @@ -23,7 +23,17 @@ display: - '&7 Max Mana: &920 &7(+&90&7)' - '&7 Health Regen: &90.1 &7(+&90&7)' - '&7 Mana Regen: &90.166 &7(+&90&7)' + item: BOW + # Alternate syntax for custom model data + #item: 'BOW:10' + # Alternate syntax for custom model data, item model.... + #item: + # item: BOW + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/classes/paladin.yml b/MMOCore-Dist/src/main/resources/default/classes/paladin.yml index 5bf21af8..961053b3 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/paladin.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/paladin.yml @@ -25,7 +25,15 @@ display: - '&7 Max Mana: &920 &7(+&90&7)' - '&7 Health Regen: &90.1 &7(+&90&7)' - '&7 Mana Regen: &90.166 &7(+&90&7)' - item: ENCHANTED_GOLDEN_APPLE:0 # Supports custom model data/texture by durability + + item: 'ENCHANTED_GOLDEN_APPLE:100' + # Alternate syntax for custom model data, item model.... + #item: + # item: ENCHANTED_GOLDEN_APPLE + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/classes/rogue.yml b/MMOCore-Dist/src/main/resources/default/classes/rogue.yml index f3e4334b..1854bc8b 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/rogue.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/rogue.yml @@ -23,7 +23,18 @@ display: - '&7 Max Mana: &920 &7(+&90&7)' - '&7 Health Regen: &90.1 &7(+&90&7)' - '&7 Mana Regen: &90.166 &7(+&90&7)' + + # Change class icon here item: LEATHER_BOOTS + # Alternate syntax for custom model data + #item: 'LEATHER_BOOTS:10' + # Alternate syntax for custom model data, item model.... + #item: + # item: IRON_SWORD + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/classes/warrior.yml b/MMOCore-Dist/src/main/resources/default/classes/warrior.yml index 46ea0d14..76afe9ca 100644 --- a/MMOCore-Dist/src/main/resources/default/classes/warrior.yml +++ b/MMOCore-Dist/src/main/resources/default/classes/warrior.yml @@ -28,7 +28,16 @@ display: - '&7 Max Rage: &c20 &7(+&c1&7)' - '&7 Health Regen: &90.1 &7(+&90&7)' - '&7 Rage Degeneration: &9-0.5&7/s' - item: IRON_SWORD:0 # Supports custom model data/texture by durability + + # Change class icon here + item: 'IRON_SWORD:0' # Syntax: ':' + # Alternate syntax for custom model data, item model.... + #item: + # item: IRON_SWORD + # custom-model-data: 10 + # custom-model-data-string: 'whatever' + # item-model: 'minecraft:dirt' + # texture: '' # Skull texture (set 'item' to 'PLAYER_HEAD') # Must match an existing exp curve filename from the 'expcurves' folder exp-curve: levels diff --git a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml index 910f65fb..09b50084 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml @@ -210,54 +210,22 @@ display: custom-model-data: 0 nodes: unlocked: - up-right-down-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-right-down: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-right-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-down-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - down-right-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-right: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-down: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - down-right: - item: "WHITE_CONCRETE" - custom-model-data: 0 - down-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - right-left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - right: - item: "WHITE_CONCRETE" - custom-model-data: 0 - left: - item: "WHITE_CONCRETE" - custom-model-data: 0 - up: - item: "WHITE_CONCRETE" - custom-model-data: 0 - down: - item: "WHITE_CONCRETE" - custom-model-data: 0 - no-path: - item: "WHITE_CONCRETE" - custom-model-data: 0 + up-right-down-left: "WHITE_CONCRETE:0" + up-right-down: "WHITE_CONCRETE:0" + up-right-left: "WHITE_CONCRETE:0" + up-down-left: "WHITE_CONCRETE:0" + down-right-left: "WHITE_CONCRETE:0" + up-right: "WHITE_CONCRETE:0" + up-down: "WHITE_CONCRETE:0" + up-left: "WHITE_CONCRETE:0" + down-right: "WHITE_CONCRETE:0" + down-left: "WHITE_CONCRETE:0" + right-left: "WHITE_CONCRETE:0" + right: "WHITE_CONCRETE:0" + left: "WHITE_CONCRETE:0" + up: "WHITE_CONCRETE:0" + down: "WHITE_CONCRETE:0" + no-path: "WHITE_CONCRETE:0" locked: up-right-down-left: item: "GRAY_CONCRETE" diff --git a/MMOCore-Dist/src/main/resources/default/gui/specific-skill-tree/specific-skill-tree-default.yml b/MMOCore-Dist/src/main/resources/default/gui/specific-skill-tree/specific-skill-tree-default.yml index 439f7157..ae02af00 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/specific-skill-tree/specific-skill-tree-default.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/specific-skill-tree/specific-skill-tree-default.yml @@ -81,7 +81,15 @@ status-names: locked: 'Locked' fully-locked: 'Fully Locked' - +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? +# +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# Please refer to skill-tree/combat.yml for syntax examples. +##################### display: paths: unlocked: diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/combat.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/combat.yml index c9f0c4ae..8fbd8e14 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/combat.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/combat.yml @@ -430,15 +430,19 @@ nodes: 1: - "&eAdditional on-hit weapon damage in +%4" -# This section is to have a specific display for the skill tree in the GUI. -# It is optional as if you don't fill it the config in gui/skill-tree.yml will be used. -# For each node it will first look if the node has a specific display, if not it will look if -# the display is defined in this section. If not it will use the default display in gui/skill-tree.yml. +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? # +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +####################### #display: # paths: # unlocked: -# up: 'WHITE_DYE:0' +# up: 'WHITE_DYE:0' # Syntax is 'MATERIAL:INT_CUSTOM_MODEL_DATA' # up-right: 'WHITE_DYE:0' # up-left: 'WHITE_DYE:0' # down-right: 'WHITE_DYE:0' @@ -556,15 +560,39 @@ nodes: # down: 'BLACK_CONCRETE:0' # no-path: 'BLACK_CONCRETE:0' -# The following syntax works too, it applies the same texture -# no matter the neighboring paths. -# +# The following syntax shows how to use an item model, int custom model data +# or string custom model data. This works on both nodes and paths. +####################### +#display: +# paths: +# unlocked: +# up: +# item: DIAMOND +# item-model: 'minecraft:dirt' +# custom-model-data: 10 +# custom-model-data-string: 'whatever' +# ........ +# ...... +# nodes: +# unlocked: +# up-right-down-left: +# item: DIAMOND +# item-model: 'minecraft:dirt' +# custom-model-data: 10 +# custom-model-data-string: 'whatever' +# ....... +# ....... + +# To make your configs lighter, you can have the node textures +# only depend on their state (locked, unlocked...) and not shape. +####################### #display: # paths: # ....... # nodes: -# unlocked: 'WHITE_CONCRETE:0' -# maxed-out: 'GREEN_CONCRETE:0' -# locked: 'GRAY_CONCRETE:0' -# unlockable: 'BLUE_CONCRETE:0' -# fully-locked: 'BLACK_CONCRETE:0' +# unlocked: # No shape, only state! +# item: DIAMOND +# item-model: 'minecraft:dirt' +# custom-model-data: 10 +# custom-model-data-string: 'whatever' +# .... diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/general.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/general.yml index 8fa2e507..72f3cc7e 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/general.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/general.yml @@ -426,141 +426,22 @@ nodes: 1: - "Additional magic skill damage in +%3" -# This section is to have a specific display for the skill tree in the GUI. -# It is optional as if you don't fill it the config in gui/skill-tree.yml will be used. -# For each node it will first look if the node has a specific display, if not it will look if -# the display is defined in this section. If not it will use the default display in gui/skill-tree.yml. +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? # +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +# +# Please refer to the default config file 'combat.yml' for syntax examples and explanations. +######################### #display: # paths: # unlocked: # up: 'WHITE_DYE:0' -# up-right: 'WHITE_DYE:0' -# up-left: 'WHITE_DYE:0' -# down-right: 'WHITE_DYE:0' -# down-left: 'WHITE_DYE:0' -# right: 'WHITE_DYE:0' -# default: 'WHITE_DYE:0' -# unlockable: -# up: 'BLUE_DYE:0' -# up-right: 'BLUE_DYE:0' -# up-left: 'BLUE_DYE:0' -# down-right: 'BLUE_DYE:0' -# down-left: 'BLUE_DYE:0' -# right: 'BLUE_DYE:0' -# default: 'BLUE_DYE:0' -# locked: -# up: 'GRAY_DYE:0' -# up-right: 'GRAY_DYE:0' -# up-left: 'GRAY_DYE:0' -# down-right: 'GRAY_DYE:0' -# down-left: 'GRAY_DYE:0' -# right: 'GRAY_DYE:0' -# default: 'GRAY_DYE:0' -# fully-locked: -# up: 'BLACK_DYE:0' -# up-right: 'BLACK_DYE:0' -# up-left: 'BLACK_DYE:0' -# down-right: 'BLACK_DYE:0' -# down-left: 'BLACK_DYE:0' -# right: 'BLACK_DYE:0' -# default: 'BLACK_DYE:0' +# .... +# ... # nodes: -# unlocked: -# up-right-down-left: 'WHITE_CONCRETE:0' -# up-right-down: 'WHITE_CONCRETE:0' -# up-right-left: 'WHITE_CONCRETE:0' -# up-down-left: 'WHITE_CONCRETE:0' -# down-right-left: 'WHITE_CONCRETE:0' -# up-right: 'WHITE_CONCRETE:0' -# up-down: 'WHITE_CONCRETE:0' -# up-left: 'WHITE_CONCRETE:0' -# down-right: 'WHITE_CONCRETE:0' -# down-left: 'WHITE_CONCRETE:0' -# right-left: 'WHITE_CONCRETE:0' -# right: 'WHITE_CONCRETE:0' -# left: 'WHITE_CONCRETE:0' -# up: 'WHITE_CONCRETE:0' -# down: 'WHITE_CONCRETE:0' -# no-path: 'WHITE_CONCRETE:0' -# maxed-out: -# up-right-down-left: 'GREEN_CONCRETE:0' -# up-right-down: 'GREEN_CONCRETE:0' -# up-right-left: 'GREEN_CONCRETE:0' -# up-down-left: 'GREEN_CONCRETE:0' -# down-right-left: 'GREEN_CONCRETE:0' -# up-right: 'GREEN_CONCRETE:0' -# up-down: 'GREEN_CONCRETE:0' -# up-left: 'GREEN_CONCRETE:0' -# down-right: 'GREEN_CONCRETE:0' -# down-left: 'GREEN_CONCRETE:0' -# right-left: 'GREEN_CONCRETE:0' -# right: 'GREEN_CONCRETE:0' -# left: 'GREEN_CONCRETE:0' -# up: 'GREEN_CONCRETE:0' -# down: 'GREEN_CONCRETE:0' -# no-path: 'GREEN_CONCRETE:0' -# locked: -# up-right-down-left: 'GRAY_CONCRETE:0' -# up-right-down: 'GRAY_CONCRETE:0' -# up-right-left: 'GRAY_CONCRETE:0' -# up-down-left: 'GRAY_CONCRETE:0' -# down-right-left: 'GRAY_CONCRETE:0' -# up-right: 'GRAY_CONCRETE:0' -# up-down: 'GRAY_CONCRETE:0' -# up-left: 'GRAY_CONCRETE:0' -# down-right: 'GRAY_CONCRETE:0' -# down-left: 'GRAY_CONCRETE:0' -# right-left: 'GRAY_CONCRETE:0' -# right: 'GRAY_CONCRETE:0' -# left: 'GRAY_CONCRETE:0' -# up: 'GRAY_CONCRETE:0' -# down: 'GRAY_CONCRETE:0' -# no-path: 'GRAY_CONCRETE:0' -# unlockable: -# up-right-down-left: 'BLUE_CONCRETE:0' -# up-right-down: 'BLUE_CONCRETE:0' -# up-right-left: 'BLUE_CONCRETE:0' -# up-down-left: 'BLUE_CONCRETE:0' -# down-right-left: 'BLUE_CONCRETE:0' -# up-right: 'BLUE_CONCRETE:0' -# up-down: 'BLUE_CONCRETE:0' -# up-left: 'BLUE_CONCRETE:0' -# down-right: 'BLUE_CONCRETE:0' -# down-left: 'BLUE_CONCRETE:0' -# right-left: 'BLUE_CONCRETE:0' -# right: 'BLUE_CONCRETE:0' -# left: 'BLUE_CONCRETE:0' -# up: 'BLUE_CONCRETE:0' -# down: 'BLUE_CONCRETE:0' -# no-path: 'BLUE_CONCRETE:0' -# fully-locked: -# up-right-down-left: 'BLACK_CONCRETE:0' -# up-right-down: 'BLACK_CONCRETE:0' -# up-right-left: 'BLACK_CONCRETE:0' -# up-down-left: 'BLACK_CONCRETE:0' -# down-right-left: 'BLACK_CONCRETE:0' -# up-right: 'BLACK_CONCRETE:0' -# up-down: 'BLACK_CONCRETE:0' -# up-left: 'BLACK_CONCRETE:0' -# down-right: 'BLACK_CONCRETE:0' -# down-left: 'BLACK_CONCRETE:0' -# right-left: 'BLACK_CONCRETE:0' -# right: 'BLACK_CONCRETE:0' -# left: 'BLACK_CONCRETE:0' -# up: 'BLACK_CONCRETE:0' -# down: 'BLACK_CONCRETE:0' -# no-path: 'BLACK_CONCRETE:0' - -# The following syntax works too, it applies the same texture -# no matter the neighboring paths. -# -#display: -# paths: -# ....... -# nodes: -# unlocked: 'WHITE_CONCRETE:0' -# maxed-out: 'GREEN_CONCRETE:0' -# locked: 'GRAY_CONCRETE:0' -# unlockable: 'BLUE_CONCRETE:0' -# fully-locked: 'BLACK_CONCRETE:0' +# .... diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/loop.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/loop.yml index 7f7280c4..52b601e6 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/loop.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/loop.yml @@ -183,3 +183,23 @@ nodes: - "&eLorem ipsum dolor sit amet" coordinates: -2,0 + +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? +# +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +# +# Please refer to the default config file 'combat.yml' for syntax examples and explanations. +######################### +#display: +# paths: +# unlocked: +# up: 'WHITE_DYE:0' +# .... +# ... +# nodes: +# .... diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/mage-arcane-mage.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/mage-arcane-mage.yml index 4387bd67..faed671e 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/mage-arcane-mage.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/mage-arcane-mage.yml @@ -422,3 +422,23 @@ nodes: - "&eAdditional magic skill damage in +%2" 1: - "&eAdditional magic skill damage in +%2" + +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? +# +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +# +# Please refer to the default config file 'combat.yml' for syntax examples and explanations. +######################### +#display: +# paths: +# unlocked: +# up: 'WHITE_DYE:0' +# .... +# ... +# nodes: +# .... diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/rogue-marksman.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/rogue-marksman.yml index 8c035cbb..47da7122 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/rogue-marksman.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/rogue-marksman.yml @@ -422,3 +422,23 @@ nodes: - "&eAdditional skill/weapon projectile damage +%6" 1: - "&eAdditional skill/weapon projectile damage +%6" + +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? +# +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +# +# Please refer to the default config file 'combat.yml' for syntax examples and explanations. +######################### +#display: +# paths: +# unlocked: +# up: 'WHITE_DYE:0' +# .... +# ... +# nodes: +# .... diff --git a/MMOCore-Dist/src/main/resources/default/skill-trees/warrior-paladin.yml b/MMOCore-Dist/src/main/resources/default/skill-trees/warrior-paladin.yml index b8766983..68320d00 100644 --- a/MMOCore-Dist/src/main/resources/default/skill-trees/warrior-paladin.yml +++ b/MMOCore-Dist/src/main/resources/default/skill-trees/warrior-paladin.yml @@ -422,3 +422,23 @@ nodes: - "&eAdditional on-hit weapon damage in +%2." 1: - "&eAdditional on-hit weapon damage in +%2." + +# This section is to change display options for nodes and paths depending on: +# - their shape: each path has a shape given its neighboring connections (left + up, )... kind of like a vanilla redstone wire. +# - their state: is the node/path unlocked, locked, maxed out... ? +# +# All of this is to "hide" the grid pattern of the chest inventory UI and give the +# impression of a clean 2D skill tree UI. +# +# This config section is optional; if you do not provide it the one provided in the skill tree CUSTOM GUI CONFIG will be used. +# +# Please refer to the default config file 'combat.yml' for syntax examples and explanations. +######################### +#display: +# paths: +# unlocked: +# up: 'WHITE_DYE:0' +# .... +# ... +# nodes: +# ....