From 8b3d55318327f3c955af3ed11b4cf28a394ca44a Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 19:52:09 +0100 Subject: [PATCH 01/31] Big modification for the skilltree GUI. Make sure to reload gui/skilltree.yml and look at the wiki. --- .../mmocore/api/player/PlayerData.java | 25 +- .../gui/{ => skilltree}/SkillTreeViewer.java | 66 ++++-- .../gui/skilltree/display/DisplayInfo.java | 7 + .../tree => gui/skilltree}/display/Icon.java | 4 +- .../skilltree/display/NodeDisplayInfo.java | 49 ++++ .../gui/skilltree/display/NodeType.java | 45 ++++ .../skilltree/display/PathDisplayInfo.java | 44 ++++ .../gui/skilltree/display/PathStatus.java | 7 + .../gui/skilltree/display/PathType.java | 40 ++++ .../mmocore/manager/InventoryManager.java | 1 + .../mmocore/skilltree/SkillTreePath.java | 17 ++ .../mmocore/skilltree/tree/SkillTree.java | 97 ++++---- .../skilltree/tree/display/DisplayInfo.java | 57 ----- .../main/resources/default/gui/skill-tree.yml | 217 ++++++++++++++++++ 14 files changed, 539 insertions(+), 137 deletions(-) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/{ => skilltree}/SkillTreeViewer.java (86%) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/DisplayInfo.java rename MMOCore-API/src/main/java/net/Indyuce/mmocore/{skilltree/tree => gui/skilltree}/display/Icon.java (88%) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeDisplayInfo.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathDisplayInfo.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathStatus.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/DisplayInfo.java diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 7b688d54..8c8e1d21 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -49,8 +49,8 @@ import net.Indyuce.mmocore.skilltree.IntegerCoordinates; import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.tree.SkillTree; -import net.Indyuce.mmocore.skilltree.tree.display.DisplayInfo; -import net.Indyuce.mmocore.skilltree.tree.display.Icon; +import net.Indyuce.mmocore.gui.skilltree.display.DisplayInfo; +import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.waypoint.Waypoint; import net.Indyuce.mmocore.waypoint.WaypointOption; import net.md_5.bungee.api.ChatMessageType; @@ -308,27 +308,6 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc node.getTree().setupNodeStates(this); } - /** - * Returns the icon the node should have. - */ - public Icon getIcon(SkillTreeNode node) { - SkillTree skillTree = node.getTree(); - - DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); - - return skillTree.getIcon(displayInfo); - } - - public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) { - - if (skillTree.isNode(coordinates)) { - SkillTreeNode node = skillTree.getNode(coordinates); - DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); - return skillTree.getIcon(displayInfo); - } - if (skillTree.isPath(coordinates)) return skillTree.getIcon(DisplayInfo.pathInfo); - return null; - } public int getSkillTreePoint(String treeId) { return skillTreePoints.getOrDefault(treeId, 0); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillTreeViewer.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java similarity index 86% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillTreeViewer.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java index 2c3d0208..5aeb7ac0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SkillTreeViewer.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java @@ -1,24 +1,27 @@ -package net.Indyuce.mmocore.gui; +package net.Indyuce.mmocore.gui.skilltree; import io.lumine.mythic.lib.MythicLib; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.skilltree.NodeStatus; -import net.Indyuce.mmocore.skilltree.tree.SkillTree; -import net.Indyuce.mmocore.skilltree.tree.display.Icon; import net.Indyuce.mmocore.api.SoundEvent; +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.gui.api.EditableInventory; import net.Indyuce.mmocore.gui.api.GeneratedInventory; import net.Indyuce.mmocore.gui.api.InventoryClickContext; import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; +import net.Indyuce.mmocore.gui.skilltree.display.*; import net.Indyuce.mmocore.skilltree.IntegerCoordinates; +import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; +import net.Indyuce.mmocore.skilltree.SkillTreePath; +import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -26,17 +29,39 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import java.util.*; public class SkillTreeViewer extends EditableInventory { - + protected final Map icons = new HashMap<>(); public SkillTreeViewer() { super("skill-tree"); } + @Override + public void reload(FileConfiguration config) { + super.reload(config); + //Loads all the pathDisplayInfo + for (PathStatus status : PathStatus.values()) + for (PathType pathType :PathType.values()){ + if(!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))){ + MMOCore.log("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name())); + MMOCore.log("Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); + continue; + } + icons.put(new PathDisplayInfo(pathType, status), new Icon(config.getConfigurationSection("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name())))); + } + //Loads all the nodeDisplayInfo + for (NodeStatus status : NodeStatus.values()) + for (NodeType nodeType :NodeType.values()){ + if(!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))){ + MMOCore.log("Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); + continue; + } + icons.put(new NodeDisplayInfo(nodeType, status), new Icon(config.getConfigurationSection("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name())))); + } + } + @Override public InventoryItem load(String function, ConfigurationSection config) { if (function.equals("skill-tree")) { @@ -190,7 +215,7 @@ public class SkillTreeViewer extends EditableInventory { public ItemStack display(SkillTreeInventory inv, int n) { IntegerCoordinates coordinates = inv.getCoordinates(n); if (inv.getSkillTree().isNode(coordinates) || inv.getSkillTree().isPath(coordinates)) { - Icon icon = inv.getPlayerData().getIcon(inv.getSkillTree(), coordinates); + Icon icon = inv.getIcon(coordinates); ItemStack item = super.display(inv, n, icon.getMaterial(), icon.getCustomModelData()); ItemMeta meta = item.getItemMeta(); if (inv.getSkillTree().isNode(coordinates)) { @@ -313,6 +338,23 @@ public class SkillTreeViewer extends EditableInventory { return maxTreeListPage; } + public Icon getIcon(IntegerCoordinates coordinates) { + boolean hasNorthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1)); + boolean hasSouthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1)); + boolean hasEastPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY())); + boolean hasWestPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY())); + + if (skillTree.isNode(coordinates)) { + SkillTreeNode node = skillTree.getNode(coordinates); + NodeType nodeType = NodeType.getNodeType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath); + return icons.get(new NodeDisplayInfo(nodeType, playerData.getNodeState(node))); + } else { + PathType pathType = PathType.getPathType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath); + SkillTreePath path = skillTree.getPath(coordinates); + return icons.get(new PathDisplayInfo(pathType, path.getStatus(playerData))); + } + } + @Override public String calculateName() { return getEditable().getName().replace("{skill-tree-name}", skillTree.getName()).replace("{skill-tree-id}", skillTree.getId()); @@ -434,18 +476,15 @@ public class SkillTreeViewer extends EditableInventory { MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer()); open(); event.setCancelled(true); - return; } else if (playerData.getNodeState(node) == NodeStatus.LOCKED || playerData.getNodeState(node) == NodeStatus.FULLY_LOCKED) { MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); event.setCancelled(true); - return; } else if (playerData.getNodeLevel(node) >= node.getMaxLevel()) { MMOCore.plugin.configManager.getSimpleMessage("skill-node-max-level-hit").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); event.setCancelled(true); - return; } //Else the player doesn't doesn't have the skill tree points @@ -453,7 +492,6 @@ public class SkillTreeViewer extends EditableInventory { MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-tree-points", "point", "" + node.getSkillTreePointsConsumed()).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); event.setCancelled(true); - return; } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/DisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/DisplayInfo.java new file mode 100644 index 00000000..9d4bdc49 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/DisplayInfo.java @@ -0,0 +1,7 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +/** + * The information needed to determine the display of a node/path depending on its context. + */ +public interface DisplayInfo { +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/Icon.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/Icon.java similarity index 88% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/Icon.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/Icon.java index 7e41218e..db334f0f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/Icon.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/Icon.java @@ -1,4 +1,4 @@ -package net.Indyuce.mmocore.skilltree.tree.display; +package net.Indyuce.mmocore.gui.skilltree.display; import io.lumine.mythic.lib.UtilityMethods; import org.bukkit.Material; @@ -23,7 +23,7 @@ public class Icon { public Icon(ConfigurationSection config) { this(Material.valueOf(Objects.requireNonNull(UtilityMethods.enumName( - config.getString("item")))), config.contains("model-data") ? config.getInt("model-data") : 0); + config.getString("item")))), config.contains("custom-model-data") ? config.getInt("custom-model-data") : 0); } public Icon(Material material, int customModelData) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeDisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeDisplayInfo.java new file mode 100644 index 00000000..f6398d1f --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeDisplayInfo.java @@ -0,0 +1,49 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +import net.Indyuce.mmocore.skilltree.NodeStatus; + +import java.util.Objects; + +public class NodeDisplayInfo implements DisplayInfo{ + + private NodeStatus nodeStatus; + private NodeType nodeType; + + public NodeDisplayInfo(NodeType nodeType,NodeStatus nodeStatus) { + this.nodeStatus = nodeStatus; + this.nodeType = nodeType; + } + + public NodeStatus getNodeState() { + return nodeStatus; + } + + public NodeStatus getNodeStatus() { + return nodeStatus; + } + + public NodeType getNodeType() { + return nodeType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NodeDisplayInfo that = (NodeDisplayInfo) o; + return nodeStatus == that.nodeStatus && nodeType == that.nodeType; + } + + @Override + public int hashCode() { + return Objects.hash(nodeStatus, nodeType); + } + + @Override + public String toString() { + return "NodeDisplayInfo{" + + "nodeStatus=" + nodeStatus + + ", nodeType=" + nodeType + + '}'; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java new file mode 100644 index 00000000..80a7011f --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java @@ -0,0 +1,45 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +public enum NodeType { + NORTH_EAST_SOUTH_WEST, + NORTH_EAST_SOUTH, + NORTH_EAST_WEST, + NORTH_SOUTH_WEST, + SOUTH_EAST_WEST, + NORTH_EAST, + NORTH_SOUTH, + NORTH_WEST, + SOUTH_EAST, + SOUTH_WEST, + EAST_WEST, + NO_PATH; + + public static NodeType getNodeType(boolean hasNorthPath, boolean hasEastPath, boolean hasSouthPath, boolean hasWestPath) { + if (hasNorthPath && hasEastPath && hasSouthPath && hasWestPath) { + return NORTH_EAST_SOUTH_WEST; + } else if (hasNorthPath && hasEastPath && hasSouthPath) { + return NORTH_EAST_SOUTH; + } else if (hasNorthPath && hasEastPath && hasWestPath) { + return NORTH_EAST_WEST; + } else if (hasNorthPath && hasSouthPath && hasWestPath) { + return NORTH_SOUTH_WEST; + } else if (hasSouthPath && hasEastPath && hasWestPath) { + return SOUTH_EAST_WEST; + } else if (hasNorthPath && hasEastPath) { + return NORTH_EAST; + } else if (hasNorthPath && hasSouthPath) { + return NORTH_SOUTH; + } else if (hasNorthPath && hasWestPath) { + return NORTH_WEST; + } else if (hasSouthPath && hasEastPath) { + return SOUTH_EAST; + } else if (hasSouthPath && hasWestPath) { + return SOUTH_WEST; + } else if (hasEastPath && hasWestPath) { + return EAST_WEST; + } + return NO_PATH; + } +} + + diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathDisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathDisplayInfo.java new file mode 100644 index 00000000..158c4376 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathDisplayInfo.java @@ -0,0 +1,44 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +import java.util.Objects; + +public class PathDisplayInfo implements DisplayInfo{ + + private PathType pathType; + private PathStatus pathStatus; + + public PathDisplayInfo(PathType pathType, PathStatus pathStatus) { + this.pathType = pathType; + this.pathStatus = pathStatus; + } + + public PathType getPathType() { + return pathType; + } + + public PathStatus getPathStatus() { + return pathStatus; + } + + @Override + public int hashCode() { + return Objects.hash(pathType, pathStatus); + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PathDisplayInfo that = (PathDisplayInfo) o; + return pathType == that.pathType && pathStatus == that.pathStatus; + } + + @Override + public String toString() { + return "PathDisplayInfo{" + + "pathType=" + pathType + + ", pathStatus=" + pathStatus + + '}'; + } +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathStatus.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathStatus.java new file mode 100644 index 00000000..2ef266c5 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathStatus.java @@ -0,0 +1,7 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +public enum PathStatus { + LOCKED, + FULLY_LOCKED, + UNLOCKED; +} diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java new file mode 100644 index 00000000..79758a50 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java @@ -0,0 +1,40 @@ +package net.Indyuce.mmocore.gui.skilltree.display; + +/** + * The direction of the path. + */ +public enum PathType { + + NORTH, + /** + * Goes to north then east/ goes to west then south. + */ + NORTH_EAST, + NORTH_WEST, + SOUTH_EAST, + SOUTH_WEST, + EAST, + + DEFAULT; + + public static PathType getPathType(boolean hasNorth,boolean hasEast,boolean hasSouth,boolean hasWest) { + if ((hasNorth || hasSouth) && !hasWest && hasEast) { + return NORTH; + } else if ((hasEast || hasWest)&& !hasNorth && !hasSouth) { + return EAST; + } else if (hasNorth && hasEast) { + return NORTH_EAST; + } + else if (hasNorth && hasWest) { + return NORTH_WEST; + } + else if (hasSouth && hasEast) { + return SOUTH_EAST; + } + else if (hasSouth && hasWest) { + return SOUTH_WEST; + } + return DEFAULT; + } + +} 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 47d0b33c..3186e776 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 @@ -6,6 +6,7 @@ import java.util.logging.Level; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.util.MMOCoreUtils; +import net.Indyuce.mmocore.gui.skilltree.SkillTreeViewer; import net.Indyuce.mmocore.gui.social.friend.EditableFriendList; import net.Indyuce.mmocore.gui.*; import net.Indyuce.mmocore.gui.social.friend.EditableFriendRemoval; 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 new file mode 100644 index 00000000..b094e397 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/SkillTreePath.java @@ -0,0 +1,17 @@ +package net.Indyuce.mmocore.skilltree; + +import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.gui.skilltree.display.PathStatus; +import net.Indyuce.mmocore.skilltree.tree.SkillTree; + +public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode to) { + + public PathStatus getStatus(PlayerData playerData) { + if (playerData.getNodeState(from) == NodeStatus.UNLOCKED && playerData.getNodeState(to) == NodeStatus.UNLOCKED) { + return PathStatus.UNLOCKED; + } + return PathStatus.LOCKED; + } + + +} 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 afc2db25..3b33d0f5 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 @@ -5,12 +5,15 @@ import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.util.PostLoadObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; +import net.Indyuce.mmocore.gui.skilltree.display.DisplayInfo; +import net.Indyuce.mmocore.gui.skilltree.display.Icon; +import net.Indyuce.mmocore.gui.skilltree.display.NodeDisplayInfo; +import net.Indyuce.mmocore.gui.skilltree.display.NodeType; import net.Indyuce.mmocore.manager.registry.RegisteredObject; -import net.Indyuce.mmocore.skilltree.tree.display.DisplayInfo; -import net.Indyuce.mmocore.skilltree.tree.display.Icon; import net.Indyuce.mmocore.skilltree.IntegerCoordinates; import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; +import net.Indyuce.mmocore.skilltree.SkillTreePath; import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -42,16 +45,21 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje private final int customModelData; //2 different maps to get the nodes - - //Represents all the coordinates that will be displayed as a path (between 2 nodes of the tree) - protected final ArrayList paths = new ArrayList<>(); - //Represents all the nodes + /** + * Represents all the nodes + * Key: the coordinates of the node + * Value: the node + */ protected final Map coordinatesNodes = new HashMap<>(); + /** + * Represents all the paths between nodes. + */ + protected final Map coordinatesPaths = new HashMap<>(); + protected final Map nodes = new HashMap<>(); protected final int maxPointSpent; //Caches the height of the skill tree protected int minX, minY, maxX, maxY; - protected final HashMap icons = new HashMap<>(); protected final List roots = new ArrayList<>(); public SkillTree(ConfigurationSection config) { @@ -66,45 +74,30 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje this.maxPointSpent = config.getInt("max-point-spent", Integer.MAX_VALUE); for (String key : config.getConfigurationSection("nodes").getKeys(false)) { try { - - SkillTreeNode node = new SkillTreeNode(this, config.getConfigurationSection("nodes." + key)); + ConfigurationSection section = config.getConfigurationSection("nodes." + key); + SkillTreeNode node = new SkillTreeNode(this, section); nodes.put(node.getId(), node); - } catch (Exception e) { MMOCore.log("Couldn't load skill tree node " + id + "." + key + ": " + e.getMessage()); } } - try { - if (config.contains("paths")) { - ConfigurationSection section = config.getConfigurationSection("paths"); - for (String key : section.getKeys(false)) { - if (section.contains(key + ".x") && section.contains(key + ".y")) { - paths.add(new IntegerCoordinates(section.getInt(key + ".x"), section.getInt(key + ".y"))); + for (String from : config.getConfigurationSection("nodes").getKeys(false)) { + ConfigurationSection section = config.getConfigurationSection("nodes." + from); + MMOCore.log("skilltree:" + id + " " + (section.contains("paths"))); + if (section.contains("paths")) { + for (String to : section.getConfigurationSection("paths").getKeys(false)) { + SkillTreeNode node1 = nodes.get(to); + if (node1 == null) { + MMOCore.log("Couldn't find node " + to + " for path in node " + from + "."); + continue; + } + for (String pathKey : section.getConfigurationSection("paths." + to).getKeys(false)) { + IntegerCoordinates coordinates = new IntegerCoordinates(section.getInt("paths." + to + "." + pathKey + ".x"), section.getInt("paths." + to + "." + pathKey + ".y")); + coordinatesPaths.put(coordinates, new SkillTreePath(this, coordinates, nodes.get(from), node1)); } - } } - } catch (Exception e) { - MMOCore.log(Level.WARNING, "Couldn't load paths for skill tree: " + id); - } - try { - //Load the icons of the skill tree. - for (String key : config.getConfigurationSection("icons").getKeys(false)) { - if (key.equalsIgnoreCase("path")) { - icons.put(DisplayInfo.pathInfo, new Icon(config.getConfigurationSection("icons." + key))); - continue; - } - for (String size : config.getConfigurationSection("icons." + key).getKeys(false)) { - DisplayInfo displayInfo = new DisplayInfo(NodeStatus.valueOf(UtilityMethods.enumName(key)), Integer.parseInt(size)); - Icon icon = new Icon(config.getConfigurationSection("icons." + key + "." + size)); - icons.put(displayInfo, icon); - - } - } - } catch (Exception e) { - MMOCore.log("Couldn't load icons for the skill tree " + id); - e.printStackTrace(); } } @@ -121,12 +114,28 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje @Override protected abstract void whenPostLoaded(@NotNull ConfigurationSection configurationSection); +/* - public Icon getIcon(DisplayInfo info) { - Validate.isTrue(icons.containsKey(info), "The icon corresponding to " + info + " doesn't exist for the skill tree " + id + "."); - return icons.get(info); + public Icon getIcon(SkillTreeNode node) { + SkillTree skillTree = node.getTree(); + + DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); + + return skillTree.getIcon(displayInfo); } + public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) { + + if (skillTree.isNode(coordinates)) { + SkillTreeNode node = skillTree.getNode(coordinates); + DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); + return skillTree.getIcon(displayInfo); + } + if (skillTree.isPath(coordinates)) return skillTree.getIcon(DisplayInfo.pathInfo); + return null; + } + */ + public int getMaxX() { return maxX; } @@ -266,7 +275,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje } public boolean isPath(IntegerCoordinates coordinates) { - return paths.contains(coordinates); + return coordinatesPaths.keySet().contains(coordinates); } public Material getItem() { @@ -291,11 +300,17 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje return Objects.requireNonNull(coordinatesNodes.get(coords), "Could not find node in tree '" + id + "' with coordinates '" + coords.toString() + "'"); } + @NotNull + public SkillTreePath getPath(IntegerCoordinates coords) { + return Objects.requireNonNull(coordinatesPaths.get(coords), "Could not find path in tree '" + id + "' with coordinates '" + coords.toString() + "'"); + } + @NotNull public SkillTreeNode getNode(String name) { return Objects.requireNonNull(nodes.get(name), "Could not find node in tree '" + id + "' with name '" + name + "'"); } + public boolean isNode(String name) { return nodes.containsKey(name); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/DisplayInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/DisplayInfo.java deleted file mode 100644 index be3426ff..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/display/DisplayInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.Indyuce.mmocore.skilltree.tree.display; - -import net.Indyuce.mmocore.skilltree.NodeStatus; - -import java.util.Objects; - -/** - * The information needed to determine the display type of a node - */ -public class DisplayInfo { - private NodeStatus nodeStatus; - private int size; - - //this NodeDisplayInfo represent a path - public static DisplayInfo pathInfo= new DisplayInfo(); - - - public DisplayInfo() { - } - - public DisplayInfo(NodeStatus nodeStatus, int size) { - this.nodeStatus = nodeStatus; - this.size = size; - } - - public NodeStatus getNodeState() { - return nodeStatus; - } - - public int getSize() { - return size; - } - - - @Override - public int hashCode() { - return Objects.hash(nodeStatus, size); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof DisplayInfo)) - return false; - DisplayInfo displayInfo= (DisplayInfo) obj; - if(nodeStatus ==null) - return displayInfo.getNodeState()==null; - return nodeStatus ==displayInfo.getNodeState()&&size==displayInfo.getSize(); - } - - @Override - public String toString() { - return "DisplayInfo{" + - "nodeState=" + nodeStatus + - ", size=" + size + - '}'; - } -} 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 ce9abe2c..55f0d2ae 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml @@ -99,4 +99,221 @@ items: - '&e◆Points spent for {skill-tree}&e:&6 {point-spent}' - '&e◆Current {skill-tree} &epoints: &6{skill-tree-points}' - '&e◆Current &6global&e points: &6{global-points}' +display: + paths: + unlocked: + north: + item: "WHITE_DYE" + custom-model-data: 0 + north-east: + item: "WHITE_DYE" + custom-model-data: 0 + north-west: + item: "WHITE_DYE" + custom-model-data: 0 + south-east: + item: "WHITE_DYE" + custom-model-data: 0 + south-west: + item: "WHITE_DYE" + custom-model-data: 0 + east: + item: "WHITE_DYE" + custom-model-data: 0 + default: + item: "WHITE_DYE" + custom-model-data: 0 + locked: + north: + item: "GRAY_DYE" + custom-model-data: 0 + north-east: + item: "GRAY_DYE" + custom-model-data: 0 + north-west: + item: "GRAY_DYE" + custom-model-data: 0 + south-east: + item: "GRAY_DYE" + custom-model-data: 0 + south-west: + item: "GRAY_DYE" + custom-model-data: 0 + east: + item: "GRAY_DYE" + custom-model-data: 0 + default: + item: "GRAY_DYE" + custom-model-data: 0 + fully-locked: + north: + item: "BLACK_DYE" + custom-model-data: 0 + north-east: + item: "BLACK_DYE" + custom-model-data: 0 + north-west: + item: "BLACK_DYE" + custom-model-data: 0 + south-east: + item: "BLACK_DYE" + custom-model-data: 0 + south-west: + item: "BLACK_DYE" + custom-model-data: 0 + east: + item: "BLACK_DYE" + custom-model-data: 0 + default: + item: "BLACK_DYE" + custom-model-data: 0 + nodes: + unlocked: + north-east-south-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-east-south: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-east-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-south-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + south-east-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-east: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-south: + item: "WHITE_CONCRETE" + custom-model-data: 0 + north-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + south-east: + item: "WHITE_CONCRETE" + custom-model-data: 0 + south-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + east-west: + item: "WHITE_CONCRETE" + custom-model-data: 0 + no-path: + item: "WHITE_CONCRETE" + custom-model-data: 0 + locked: + north-east-south-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-east-south: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-east-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-south-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + south-east-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-east: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-south: + item: "GRAY_CONCRETE" + custom-model-data: 0 + north-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + south-east: + item: "GRAY_CONCRETE" + custom-model-data: 0 + south-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + east-west: + item: "GRAY_CONCRETE" + custom-model-data: 0 + no-path: + item: "GRAY_CONCRETE" + custom-model-data: 0 + unlockable: + north-east-south-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-east-south: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-east-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-south-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + south-east-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-east: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-south: + item: "BLUE_CONCRETE" + custom-model-data: 0 + north-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + south-east: + item: "BLUE_CONCRETE" + custom-model-data: 0 + south-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + east-west: + item: "BLUE_CONCRETE" + custom-model-data: 0 + no-path: + item: "BLUE_CONCRETE" + custom-model-data: 0 + fully-locked: + north-east-south-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-east-south: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-east-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-south-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + south-east-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-east: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-south: + item: "BLACK_CONCRETE" + custom-model-data: 0 + north-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + south-east: + item: "BLACK_CONCRETE" + custom-model-data: 0 + south-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + east-west: + item: "BLACK_CONCRETE" + custom-model-data: 0 + no-path: + item: "BLACK_CONCRETE" + custom-model-data: 0 From c99caff22d8fa96f51bba4730f38b3fb4f8f512b Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 20:01:17 +0100 Subject: [PATCH 02/31] Passive skill bug fixing. --- .../java/net/Indyuce/mmocore/api/player/PlayerData.java | 7 ++----- .../net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 8c8e1d21..d5db2be9 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -19,12 +19,11 @@ import net.Indyuce.mmocore.api.player.profess.PlayerClass; import net.Indyuce.mmocore.api.player.profess.SavedClassInformation; import net.Indyuce.mmocore.api.player.profess.Subclass; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; -import net.Indyuce.mmocore.api.quest.trigger.Trigger; -import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.api.player.social.FriendRequest; import net.Indyuce.mmocore.api.player.stats.PlayerStats; import net.Indyuce.mmocore.api.quest.PlayerQuests; import net.Indyuce.mmocore.api.quest.trigger.StatTrigger; +import net.Indyuce.mmocore.api.quest.trigger.Trigger; import net.Indyuce.mmocore.api.util.Closable; import net.Indyuce.mmocore.api.util.MMOCoreUtils; import net.Indyuce.mmocore.experience.EXPSource; @@ -43,14 +42,12 @@ import net.Indyuce.mmocore.player.CombatHandler; import net.Indyuce.mmocore.player.Unlockable; import net.Indyuce.mmocore.skill.ClassSkill; import net.Indyuce.mmocore.skill.RegisteredSkill; +import net.Indyuce.mmocore.skill.binding.BoundSkillInfo; import net.Indyuce.mmocore.skill.binding.SkillSlot; import net.Indyuce.mmocore.skill.cast.SkillCastingHandler; -import net.Indyuce.mmocore.skilltree.IntegerCoordinates; import net.Indyuce.mmocore.skilltree.NodeStatus; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import net.Indyuce.mmocore.skilltree.tree.SkillTree; -import net.Indyuce.mmocore.gui.skilltree.display.DisplayInfo; -import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.waypoint.Waypoint; import net.Indyuce.mmocore.waypoint.WaypointOption; import net.md_5.bungee.api.ChatMessageType; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java index 3d9683d7..3e954ef1 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java @@ -37,7 +37,6 @@ public class BoundSkillInfo implements Closable { if (classSkill.getSkill().getTrigger().isPassive()) { registered = classSkill.toPassive(playerData); registered.register(playerData.getMMOPlayerData()); - Bukkit.broadcastMessage("Registering passive skill " + classSkill.getSkill().getHandler().getId()); } else registered = null; } From d1be5cbce72c63cf8618fb26c7a0f6980045bcc2 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 20:12:03 +0100 Subject: [PATCH 03/31] Fixed issue #794 about passive-skill-need-bound being disabled. --- .../mmocore/api/player/stats/PlayerStats.java | 12 ++++++------ MMOCore-Dist/src/main/resources/config.yml | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java index 19070ae6..ed6a2e92 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java @@ -99,12 +99,12 @@ public class PlayerStats { */ final PassiveSkillMap skillMap = data.getMMOPlayerData().getPassiveSkillMap(); - //if (!MMOCore.plugin.configManager.passiveSkillNeedBound) { - // skillMap.removeModifiers("MMOCorePassiveSkill"); - // for (ClassSkill skill : data.getProfess().getSkills()) - // if (skill.getSkill().getTrigger().isPassive()) - // skillMap.addModifier(skill.toPassive(data)); - //} + if (!MMOCore.plugin.configManager.passiveSkillNeedBound) { + skillMap.removeModifiers("MMOCorePassiveSkill"); + for (ClassSkill skill : data.getProfess().getSkills()) + if (skill.getSkill().getTrigger().isPassive()) + skillMap.addModifier(skill.toPassive(data)); + } // This updates the player's class SCRIPTS skillMap.removeModifiers("MMOCoreClassScript"); diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index 6744a1da..6ed89c5a 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -209,8 +209,7 @@ max-skill-slots: 8 # When set to true, passive skills must be bound in order to take effect. # When set to false, unlocked skills will take effect right away. -# Temporarily disabled. -# passive-skill-need-bound: true +passive-skill-need-bound: true # Fun extra RPG feature that switches the player's hotbar with # the 9 lower row items of his inventory. This allows the player From ebed0d3983a3113aed2fbc6b04dbe11f68d94296 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 20:33:03 +0100 Subject: [PATCH 04/31] Fixed issue #795 about bugs linked to the party GUI. --- .../Indyuce/mmocore/gui/social/friend/EditableFriendList.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java index 32163ea2..eeb88cb9 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/social/friend/EditableFriendList.java @@ -144,11 +144,10 @@ public class EditableFriendList extends EditableInventory { if (inv.getPlayerData().getFriends().size() <= n) return super.display(inv, n); - final OfflinePlayer friend = getEffectivePlayer(inv, n); + final OfflinePlayer friend = Bukkit.getOfflinePlayer(inv.getPlayerData().getFriends().get(n)); ItemStack disp = (friend.isOnline() ? online : offline).display(inv, n); ItemMeta meta = disp.getItemMeta(); meta.getPersistentDataContainer().set(UUID_NAMESPACEDKEY, PersistentDataType.STRING, friend.getUniqueId().toString()); - if (meta instanceof SkullMeta) inv.dynamicallyUpdateItem(this, n, disp, current -> { ((SkullMeta) meta).setOwningPlayer(friend); From 4d8df79dc2ac98945c11cc07f7c4328a882aa483 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 20:45:34 +0100 Subject: [PATCH 05/31] Removed debugging message. --- .../java/net/Indyuce/mmocore/gui/skilltree/SkillTreeViewer.java | 1 - .../java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java | 1 - .../main/java/net/Indyuce/mmocore/skilltree/tree/SkillTree.java | 1 - 3 files changed, 3 deletions(-) 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 5aeb7ac0..40df148a 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 @@ -45,7 +45,6 @@ public class SkillTreeViewer extends EditableInventory { for (PathStatus status : PathStatus.values()) for (PathType pathType :PathType.values()){ if(!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))){ - MMOCore.log("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name())); MMOCore.log("Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); continue; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java index 3e954ef1..cfbe1d42 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/binding/BoundSkillInfo.java @@ -66,7 +66,6 @@ public class BoundSkillInfo implements Closable { // Unregister skill if passive if (isPassive()) { - Bukkit.broadcastMessage("Unregistered passive skill " + classSkill.getSkill().getHandler().getId()); registered.unregister(playerData.getMMOPlayerData()); } 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 3b33d0f5..3f267381 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 @@ -83,7 +83,6 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje } for (String from : config.getConfigurationSection("nodes").getKeys(false)) { ConfigurationSection section = config.getConfigurationSection("nodes." + from); - MMOCore.log("skilltree:" + id + " " + (section.contains("paths"))); if (section.contains("paths")) { for (String to : section.getConfigurationSection("paths").getKeys(false)) { SkillTreeNode node1 = nodes.get(to); From f4be0ab4091e0b93c74f3e7e574ddfed5f5b3f50 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 20:54:15 +0100 Subject: [PATCH 06/31] Fixed issue #796. --- .../mmocore/api/player/PlayerData.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index d5db2be9..a2742ded 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -168,19 +168,19 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc MMOCore.log(Level.SEVERE, "[Userdata] Could not find class " + getProfess().getId() + " while refreshing player data."); } //We remove all the stats and buffs associated to triggers. - mmoData.getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(key ->key.startsWith(Trigger.TRIGGER_PREFIX))); - mmoData.getSkillModifierMap().getInstances().forEach(skillModifierInstance -> skillModifierInstance.removeIf(key ->key.startsWith(Trigger.TRIGGER_PREFIX))); - final Iterator> ite = boundSkills.entrySet().iterator(); - while (ite.hasNext()) + mmoData.getStatMap().getInstances().forEach(statInstance -> statInstance.removeIf(key -> key.startsWith(Trigger.TRIGGER_PREFIX))); + mmoData.getSkillModifierMap().getInstances().forEach(skillModifierInstance -> skillModifierInstance.removeIf(key -> key.startsWith(Trigger.TRIGGER_PREFIX))); + Map boundSkillsToRemove = new HashMap<>(boundSkills); + for (int slot : boundSkillsToRemove.keySet()) try { - final Map.Entry entry = ite.next(); - final @Nullable SkillSlot skillSlot = getProfess().getSkillSlot(entry.getKey()); - final String skillId = entry.getValue().getClassSkill().getSkill().getHandler().getId(); + final BoundSkillInfo info = boundSkills.get(slot); + final @Nullable SkillSlot skillSlot = getProfess().getSkillSlot(slot); + final String skillId = info.getClassSkill().getSkill().getHandler().getId(); final @Nullable ClassSkill classSkill = getProfess().getSkill(skillId); - Validate.notNull(skillSlot, "Could not find skill slot n" + entry.getKey()); + Validate.notNull(skillSlot, "Could not find skill slot n" + slot); Validate.notNull(classSkill, "Could not find skill with ID '" + skillId + "'"); - unbindSkill(entry.getKey()); - bindSkill(entry.getKey(), classSkill); + unbindSkill(slot); + bindSkill(slot, classSkill); } catch (Exception exception) { MMOCore.plugin.getLogger().log(Level.WARNING, "Could not reload data of '" + getPlayer().getName() + "': " + exception.getMessage()); } @@ -364,7 +364,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc /** * @return If the item is unlocked by the player - * This is used for skills that can be locked & unlocked. + * This is used for skills that can be locked & unlocked. */ public boolean hasUnlocked(Unlockable unlockable) { return unlockable.isUnlockedByDefault() || unlockedItems.contains(unlockable.getUnlockNamespacedKey()); @@ -810,7 +810,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc * If it's null, no hologram will be displayed * @param splitExp Should the exp be split among party members */ - public void giveExperience(double value, @NotNull EXPSource source, @Nullable Location hologramLocation, boolean splitExp) { + public void giveExperience(double value, @NotNull EXPSource source, @Nullable Location hologramLocation, + boolean splitExp) { if (value <= 0) { experience = Math.max(0, experience + value); return; @@ -863,7 +864,8 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc level = getLevel() + 1; // Apply class experience table - if (getProfess().hasExperienceTable()) getProfess().getExperienceTable().claim(this, level, getProfess()); + if (getProfess().hasExperienceTable()) + getProfess().getExperienceTable().claim(this, level, getProfess()); } if (level > oldLevel) { @@ -1184,7 +1186,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc * checks if they could potentially upgrade to one of these * * @return If the player can change its current class to - * a subclass + * a subclass */ @Deprecated public boolean canChooseSubclass() { From 50f2de287cc0629dce8ae7b6d5fbb755cf6e7389 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 20 Apr 2023 21:27:28 +0100 Subject: [PATCH 07/31] Fixed a bug linked to perm stats not being modified when changing class. --- .../api/player/profess/SavedClassInformation.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java index fca842f2..37a4961b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/profess/SavedClassInformation.java @@ -293,6 +293,13 @@ public class SavedClassInformation implements ClassDataContainer { if (!player.getProfess().hasOption(ClassOption.DEFAULT) || MMOCore.plugin.configManager.saveDefaultClassInfo) player.applyClassInfo(player.getProfess(), new SavedClassInformation(player)); + // Remove perm stats for nodes and class + for (SkillTree skillTree : player.getProfess().getSkillTrees()) + for (SkillTreeNode node : skillTree.getNodes()) + node.getExperienceTable().removePermStats(player, node); + if (player.getProfess().hasExperienceTable()) + player.getProfess().getExperienceTable().removePermStats(player, player.getProfess()); + /* * Resets information which much be reset after everything is saved. */ @@ -303,13 +310,6 @@ public class SavedClassInformation implements ClassDataContainer { player.clearNodeStates(); player.clearNodeTimesClaimed(); - // Remove perm stats for nodes and class - for (SkillTree skillTree : player.getProfess().getSkillTrees()) - for (SkillTreeNode node : skillTree.getNodes()) - node.getExperienceTable().removePermStats(player, node); - if (player.getProfess().hasExperienceTable()) - player.getProfess().getExperienceTable().removePermStats(player, player.getProfess()); - /* * Reads this class info, applies it to the player. set class after * changing level so the player stats can be calculated based on new level From ad6b7fa0ff5c3719b4f06359036528c768c59d30 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 21 Apr 2023 07:22:59 +0100 Subject: [PATCH 08/31] Enabled each skillTreeNode to have its own display by filling item & custom-model-data in its config. --- .../mmocore/gui/skilltree/SkillTreeViewer.java | 4 ++++ .../Indyuce/mmocore/skilltree/SkillTreeNode.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) 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 40df148a..4c3a0305 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 @@ -345,6 +345,10 @@ public class SkillTreeViewer extends EditableInventory { if (skillTree.isNode(coordinates)) { SkillTreeNode node = skillTree.getNode(coordinates); + //If the node has its own display, it will be shown. + if(node.getItem()!=null) + return new Icon(node.getItem(),node.getCustomModelData()); + NodeType nodeType = NodeType.getNodeType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath); return icons.get(new NodeDisplayInfo(nodeType, playerData.getNodeState(node))); } else { 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 81b25a98..7a5f1636 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 @@ -11,6 +11,7 @@ import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,6 +22,9 @@ import java.util.*; public class SkillTreeNode implements ExperienceObject { private final SkillTree tree; private final String name, id; + + private Material item; + private int customModelData; private IntegerCoordinates coordinates; /** * The number of skill tree points this node requires. @@ -57,6 +61,9 @@ public class SkillTreeNode implements ExperienceObject { Validate.notNull(config, "Config cannot be null"); this.id = config.getName(); this.tree = tree; + if(config.contains("item")) + item = Material.valueOf(config.getString("item")); + customModelData= config.getInt("custom-model-data",0); name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); size = Objects.requireNonNull(config.getInt("size")); isRoot = config.getBoolean("is-root", false); @@ -84,6 +91,14 @@ public class SkillTreeNode implements ExperienceObject { return tree; } + public Material getItem() { + return item; + } + + public int getCustomModelData() { + return customModelData; + } + public void setIsRoot() { isRoot = true; } From 5fdfc36fcc8c83eadb9030cc9dc8cc2697c9452d Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 21 Apr 2023 08:06:40 +0100 Subject: [PATCH 09/31] Renaming for skill tree GUI. --- .../gui/skilltree/SkillTreeViewer.java | 12 +- .../gui/skilltree/display/NodeType.java | 68 +++++----- .../gui/skilltree/display/PathType.java | 40 +++--- .../main/resources/default/gui/skill-tree.yml | 124 +++++++++--------- 4 files changed, 122 insertions(+), 122 deletions(-) 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 4c3a0305..4db8f3fe 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 @@ -338,10 +338,10 @@ public class SkillTreeViewer extends EditableInventory { } public Icon getIcon(IntegerCoordinates coordinates) { - boolean hasNorthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1)); - boolean hasSouthPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1)); - boolean hasEastPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY())); - boolean hasWestPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY())); + boolean hasUpPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1)); + boolean hasDownPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1)); + boolean hasRightPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() + 1, coordinates.getY())); + boolean hasLeftPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX() - 1, coordinates.getY())); if (skillTree.isNode(coordinates)) { SkillTreeNode node = skillTree.getNode(coordinates); @@ -349,10 +349,10 @@ public class SkillTreeViewer extends EditableInventory { if(node.getItem()!=null) return new Icon(node.getItem(),node.getCustomModelData()); - NodeType nodeType = NodeType.getNodeType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath); + NodeType nodeType = NodeType.getNodeType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); return icons.get(new NodeDisplayInfo(nodeType, playerData.getNodeState(node))); } else { - PathType pathType = PathType.getPathType(hasNorthPath, hasEastPath, hasSouthPath, hasWestPath); + PathType pathType = PathType.getPathType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); SkillTreePath path = skillTree.getPath(coordinates); return icons.get(new PathDisplayInfo(pathType, path.getStatus(playerData))); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java index 80a7011f..89d99764 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/NodeType.java @@ -1,42 +1,42 @@ package net.Indyuce.mmocore.gui.skilltree.display; public enum NodeType { - NORTH_EAST_SOUTH_WEST, - NORTH_EAST_SOUTH, - NORTH_EAST_WEST, - NORTH_SOUTH_WEST, - SOUTH_EAST_WEST, - NORTH_EAST, - NORTH_SOUTH, - NORTH_WEST, - SOUTH_EAST, - SOUTH_WEST, - EAST_WEST, + UP_RIGHT_DOWN_LEFT, + UP_RIGHT_DOWN, + UP_RIGHT_LEFT, + UP_DOWN_LEFT, + DOWN_RIGHT_LEFT, + UP_RIGHT, + UP_DOWN, + UP_LEFT, + DOWN_RIGHT, + DOWN_LEFT, + RIGHT_LEFT, NO_PATH; - public static NodeType getNodeType(boolean hasNorthPath, boolean hasEastPath, boolean hasSouthPath, boolean hasWestPath) { - if (hasNorthPath && hasEastPath && hasSouthPath && hasWestPath) { - return NORTH_EAST_SOUTH_WEST; - } else if (hasNorthPath && hasEastPath && hasSouthPath) { - return NORTH_EAST_SOUTH; - } else if (hasNorthPath && hasEastPath && hasWestPath) { - return NORTH_EAST_WEST; - } else if (hasNorthPath && hasSouthPath && hasWestPath) { - return NORTH_SOUTH_WEST; - } else if (hasSouthPath && hasEastPath && hasWestPath) { - return SOUTH_EAST_WEST; - } else if (hasNorthPath && hasEastPath) { - return NORTH_EAST; - } else if (hasNorthPath && hasSouthPath) { - return NORTH_SOUTH; - } else if (hasNorthPath && hasWestPath) { - return NORTH_WEST; - } else if (hasSouthPath && hasEastPath) { - return SOUTH_EAST; - } else if (hasSouthPath && hasWestPath) { - return SOUTH_WEST; - } else if (hasEastPath && hasWestPath) { - return EAST_WEST; + public static NodeType getNodeType(boolean hasUpPath, boolean hasRightPath, boolean hasDownPath, boolean hasLeftPath) { + if (hasUpPath && hasRightPath && hasDownPath && hasLeftPath) { + return UP_RIGHT_DOWN_LEFT; + } else if (hasUpPath && hasRightPath && hasDownPath) { + return UP_RIGHT_DOWN; + } else if (hasUpPath && hasRightPath && hasLeftPath) { + return UP_RIGHT_LEFT; + } else if (hasUpPath && hasDownPath && hasLeftPath) { + return UP_DOWN_LEFT; + } else if (hasDownPath && hasRightPath && hasLeftPath) { + return DOWN_RIGHT_LEFT; + } else if (hasUpPath && hasRightPath) { + return UP_RIGHT; + } else if (hasUpPath && hasDownPath) { + return UP_DOWN; + } else if (hasUpPath && hasLeftPath) { + return UP_LEFT; + } else if (hasDownPath && hasRightPath) { + return DOWN_RIGHT; + } else if (hasDownPath && hasLeftPath) { + return DOWN_LEFT; + } else if (hasRightPath && hasLeftPath) { + return RIGHT_LEFT; } return NO_PATH; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java index 79758a50..1769fb20 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java @@ -5,34 +5,34 @@ package net.Indyuce.mmocore.gui.skilltree.display; */ public enum PathType { - NORTH, + UP, /** - * Goes to north then east/ goes to west then south. + * Goes to up then east/ goes to left then down. */ - NORTH_EAST, - NORTH_WEST, - SOUTH_EAST, - SOUTH_WEST, - EAST, + UP_RIGHT, + UP_LEFT, + DOWN_RIGHT, + DOWN_LEFT, + RIGHT, DEFAULT; - public static PathType getPathType(boolean hasNorth,boolean hasEast,boolean hasSouth,boolean hasWest) { - if ((hasNorth || hasSouth) && !hasWest && hasEast) { - return NORTH; - } else if ((hasEast || hasWest)&& !hasNorth && !hasSouth) { - return EAST; - } else if (hasNorth && hasEast) { - return NORTH_EAST; + public static PathType getPathType(boolean hasUp,boolean hasRight,boolean hasDown,boolean hasLeft) { + if ((hasUp || hasDown) && !hasLeft && hasRight) { + return UP; + } else if ((hasRight || hasLeft)&& !hasUp && !hasDown) { + return RIGHT; + } else if (hasUp && hasRight) { + return UP_RIGHT; } - else if (hasNorth && hasWest) { - return NORTH_WEST; + else if (hasUp && hasLeft) { + return UP_LEFT; } - else if (hasSouth && hasEast) { - return SOUTH_EAST; + else if (hasDown && hasRight) { + return DOWN_RIGHT; } - else if (hasSouth && hasWest) { - return SOUTH_WEST; + else if (hasDown && hasLeft) { + return DOWN_LEFT; } return DEFAULT; } 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 55f0d2ae..68385469 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/skill-tree.yml @@ -102,66 +102,66 @@ items: display: paths: unlocked: - north: + up: item: "WHITE_DYE" custom-model-data: 0 - north-east: + up-right: item: "WHITE_DYE" custom-model-data: 0 - north-west: + up-left: item: "WHITE_DYE" custom-model-data: 0 - south-east: + down-right: item: "WHITE_DYE" custom-model-data: 0 - south-west: + down-left: item: "WHITE_DYE" custom-model-data: 0 - east: + right: item: "WHITE_DYE" custom-model-data: 0 default: item: "WHITE_DYE" custom-model-data: 0 locked: - north: + up: item: "GRAY_DYE" custom-model-data: 0 - north-east: + up-right: item: "GRAY_DYE" custom-model-data: 0 - north-west: + up-left: item: "GRAY_DYE" custom-model-data: 0 - south-east: + down-right: item: "GRAY_DYE" custom-model-data: 0 - south-west: + down-left: item: "GRAY_DYE" custom-model-data: 0 - east: + right: item: "GRAY_DYE" custom-model-data: 0 default: item: "GRAY_DYE" custom-model-data: 0 fully-locked: - north: + up: item: "BLACK_DYE" custom-model-data: 0 - north-east: + up-right: item: "BLACK_DYE" custom-model-data: 0 - north-west: + up-left: item: "BLACK_DYE" custom-model-data: 0 - south-east: + down-right: item: "BLACK_DYE" custom-model-data: 0 - south-west: + down-left: item: "BLACK_DYE" custom-model-data: 0 - east: + right: item: "BLACK_DYE" custom-model-data: 0 default: @@ -169,148 +169,148 @@ display: custom-model-data: 0 nodes: unlocked: - north-east-south-west: + up-right-down-left: item: "WHITE_CONCRETE" custom-model-data: 0 - north-east-south: + up-right-down: item: "WHITE_CONCRETE" custom-model-data: 0 - north-east-west: + up-right-left: item: "WHITE_CONCRETE" custom-model-data: 0 - north-south-west: + up-down-left: item: "WHITE_CONCRETE" custom-model-data: 0 - south-east-west: + down-right-left: item: "WHITE_CONCRETE" custom-model-data: 0 - north-east: + up-right: item: "WHITE_CONCRETE" custom-model-data: 0 - north-south: + up-down: item: "WHITE_CONCRETE" custom-model-data: 0 - north-west: + up-left: item: "WHITE_CONCRETE" custom-model-data: 0 - south-east: + down-right: item: "WHITE_CONCRETE" custom-model-data: 0 - south-west: + down-left: item: "WHITE_CONCRETE" custom-model-data: 0 - east-west: + right-left: item: "WHITE_CONCRETE" custom-model-data: 0 no-path: item: "WHITE_CONCRETE" custom-model-data: 0 locked: - north-east-south-west: + up-right-down-left: item: "GRAY_CONCRETE" custom-model-data: 0 - north-east-south: + up-right-down: item: "GRAY_CONCRETE" custom-model-data: 0 - north-east-west: + up-right-left: item: "GRAY_CONCRETE" custom-model-data: 0 - north-south-west: + up-down-left: item: "GRAY_CONCRETE" custom-model-data: 0 - south-east-west: + down-right-left: item: "GRAY_CONCRETE" custom-model-data: 0 - north-east: + up-right: item: "GRAY_CONCRETE" custom-model-data: 0 - north-south: + up-down: item: "GRAY_CONCRETE" custom-model-data: 0 - north-west: + up-left: item: "GRAY_CONCRETE" custom-model-data: 0 - south-east: + down-right: item: "GRAY_CONCRETE" custom-model-data: 0 - south-west: + down-left: item: "GRAY_CONCRETE" custom-model-data: 0 - east-west: + right-left: item: "GRAY_CONCRETE" custom-model-data: 0 no-path: item: "GRAY_CONCRETE" custom-model-data: 0 unlockable: - north-east-south-west: + up-right-down-left: item: "BLUE_CONCRETE" custom-model-data: 0 - north-east-south: + up-right-down: item: "BLUE_CONCRETE" custom-model-data: 0 - north-east-west: + up-right-left: item: "BLUE_CONCRETE" custom-model-data: 0 - north-south-west: + up-down-left: item: "BLUE_CONCRETE" custom-model-data: 0 - south-east-west: + down-right-left: item: "BLUE_CONCRETE" custom-model-data: 0 - north-east: + up-right: item: "BLUE_CONCRETE" custom-model-data: 0 - north-south: + up-down: item: "BLUE_CONCRETE" custom-model-data: 0 - north-west: + up-left: item: "BLUE_CONCRETE" custom-model-data: 0 - south-east: + down-right: item: "BLUE_CONCRETE" custom-model-data: 0 - south-west: + down-left: item: "BLUE_CONCRETE" custom-model-data: 0 - east-west: + right-left: item: "BLUE_CONCRETE" custom-model-data: 0 no-path: item: "BLUE_CONCRETE" custom-model-data: 0 fully-locked: - north-east-south-west: + up-right-down-left: item: "BLACK_CONCRETE" custom-model-data: 0 - north-east-south: + up-right-down: item: "BLACK_CONCRETE" custom-model-data: 0 - north-east-west: + up-right-left: item: "BLACK_CONCRETE" custom-model-data: 0 - north-south-west: + up-down-left: item: "BLACK_CONCRETE" custom-model-data: 0 - south-east-west: + down-right-left: item: "BLACK_CONCRETE" custom-model-data: 0 - north-east: + up-right: item: "BLACK_CONCRETE" custom-model-data: 0 - north-south: + up-down: item: "BLACK_CONCRETE" custom-model-data: 0 - north-west: + up-left: item: "BLACK_CONCRETE" custom-model-data: 0 - south-east: + down-right: item: "BLACK_CONCRETE" custom-model-data: 0 - south-west: + down-left: item: "BLACK_CONCRETE" custom-model-data: 0 - east-west: + right-left: item: "BLACK_CONCRETE" custom-model-data: 0 no-path: From 523f91011313b0c63883d847cd53c196ee14acad Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 21 Apr 2023 08:07:08 +0100 Subject: [PATCH 10/31] Bug Fixing for the specific display associated to each node. --- .../mmocore/skilltree/SkillTreeNode.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) 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 7a5f1636..3ee7a830 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 @@ -8,6 +8,7 @@ import net.Indyuce.mmocore.experience.ExpCurve; import net.Indyuce.mmocore.experience.ExperienceObject; import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.gui.api.item.Placeholders; +import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; import org.bukkit.Location; @@ -23,8 +24,8 @@ public class SkillTreeNode implements ExperienceObject { private final SkillTree tree; private final String name, id; - private Material item; - private int customModelData; + private final Map icons = new HashMap<>(); + private IntegerCoordinates coordinates; /** * The number of skill tree points this node requires. @@ -61,14 +62,20 @@ public class SkillTreeNode implements ExperienceObject { Validate.notNull(config, "Config cannot be null"); this.id = config.getName(); this.tree = tree; - if(config.contains("item")) - item = Material.valueOf(config.getString("item")); - customModelData= config.getInt("custom-model-data",0); + if (config.isConfigurationSection("display")) { + for (NodeStatus status : NodeStatus.values()) { + if (!config.isConfigurationSection("display." + status.name().toLowerCase())) { + MMOCore.log("Could not find node display for status " + status.name().toLowerCase() + " for node " + id + " in tree " + tree.getId() + ". Using default display."); + continue; + } + icons.put(status, new Icon(config.getConfigurationSection("display." + status.name().toLowerCase()))); + } + } name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); size = Objects.requireNonNull(config.getInt("size")); isRoot = config.getBoolean("is-root", false); - skillTreePointsConsumed=config.getInt("point-consumed",1); - Validate.isTrue(skillTreePointsConsumed>0,"The skill tree points consumed by a node must be greater than 0."); + skillTreePointsConsumed = config.getInt("point-consumed", 1); + Validate.isTrue(skillTreePointsConsumed > 0, "The skill tree points consumed by a node must be greater than 0."); if (config.contains("lores")) for (String key : config.getConfigurationSection("lores").getKeys(false)) try { @@ -91,12 +98,12 @@ public class SkillTreeNode implements ExperienceObject { return tree; } - public Material getItem() { - return item; + public boolean hasIcon(NodeStatus status) { + return icons.containsKey(status); } - public int getCustomModelData() { - return customModelData; + public Icon getIcon(NodeStatus status) { + return icons.get(status); } public void setIsRoot() { @@ -168,7 +175,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" */ public String getFullId() { return tree.getId() + "_" + id; From a37287cf0cbd110a244b4764877bf0113ecf89b0 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sat, 22 Apr 2023 11:39:40 +0100 Subject: [PATCH 11/31] Refactor /typo --- .../net/Indyuce/mmocore/api/player/PlayerData.java | 2 +- .../mmocore/gui/skilltree/SkillTreeViewer.java | 11 ++++++----- .../net/Indyuce/mmocore/skilltree/SkillTreeNode.java | 3 +-- .../net/Indyuce/mmocore/skilltree/SkillTreePath.java | 2 +- .../mmocore/skilltree/tree/LinkedSkillTree.java | 4 ++-- .../net/Indyuce/mmocore/skilltree/tree/SkillTree.java | 9 ++------- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index a2742ded..3b446677 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -318,7 +318,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc nodeStates.put(node, nodeStatus); } - public NodeStatus getNodeState(SkillTreeNode node) { + public NodeStatus getNodeStatus(SkillTreeNode node) { return nodeStates.get(node); } 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 4db8f3fe..4bf5728e 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 @@ -271,7 +271,7 @@ public class SkillTreeViewer extends EditableInventory { if (inv.getSkillTree().isNode(inv.getCoordinates(n))) { SkillTreeNode node = inv.getNode(n); holders.register("current-level", inv.getPlayerData().getNodeLevel(node)); - holders.register("current-state", inv.getPlayerData().getNodeState(node)); + holders.register("current-state", inv.getPlayerData().getNodeStatus(node)); holders.register("max-level", node.getMaxLevel()); holders.register("max-children", node.getMaxChildren()); holders.register("size", node.getSize()); @@ -345,12 +345,13 @@ public class SkillTreeViewer extends EditableInventory { if (skillTree.isNode(coordinates)) { SkillTreeNode node = skillTree.getNode(coordinates); + NodeStatus nodeStatus =playerData.getNodeStatus(node); //If the node has its own display, it will be shown. - if(node.getItem()!=null) - return new Icon(node.getItem(),node.getCustomModelData()); + if(node.hasIcon(nodeStatus)) + return node.getIcon(nodeStatus); NodeType nodeType = NodeType.getNodeType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); - return icons.get(new NodeDisplayInfo(nodeType, playerData.getNodeState(node))); + return icons.get(new NodeDisplayInfo(nodeType, nodeStatus)); } else { PathType pathType = PathType.getPathType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); SkillTreePath path = skillTree.getPath(coordinates); @@ -479,7 +480,7 @@ public class SkillTreeViewer extends EditableInventory { MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer()); open(); event.setCancelled(true); - } else if (playerData.getNodeState(node) == NodeStatus.LOCKED || playerData.getNodeState(node) == NodeStatus.FULLY_LOCKED) { + } else if (playerData.getNodeStatus(node) == NodeStatus.LOCKED || playerData.getNodeStatus(node) == NodeStatus.FULLY_LOCKED) { MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); event.setCancelled(true); 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 3ee7a830..a72b8a25 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 @@ -12,7 +12,6 @@ import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -227,7 +226,7 @@ public class SkillTreeNode implements ExperienceObject { public Placeholders getPlaceholders(PlayerData playerData) { Placeholders holders = new Placeholders(); holders.register("name", getName()); - holders.register("node-state", playerData.getNodeState(this)); + holders.register("node-state", playerData.getNodeStatus(this)); holders.register("size", getSize()); holders.register("level", playerData.getNodeLevel(this)); holders.register("max-level", getMaxLevel()); 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 b094e397..7bef7757 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 @@ -7,7 +7,7 @@ import net.Indyuce.mmocore.skilltree.tree.SkillTree; public record SkillTreePath(SkillTree tree, IntegerCoordinates coordinates, SkillTreeNode from, SkillTreeNode to) { public PathStatus getStatus(PlayerData playerData) { - if (playerData.getNodeState(from) == NodeStatus.UNLOCKED && playerData.getNodeState(to) == NodeStatus.UNLOCKED) { + if (playerData.getNodeStatus(from) == NodeStatus.UNLOCKED && playerData.getNodeStatus(to) == NodeStatus.UNLOCKED) { return PathStatus.UNLOCKED; } return PathStatus.LOCKED; diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java index 3808041c..c3f4108f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java @@ -84,7 +84,7 @@ public class LinkedSkillTree extends SkillTree { * We recursively label all the locked nodes who are connected to an unlockable node. **/ private void labelLockedNodes(PlayerData playerData) { - List unlockableNodes = nodes.values().stream().filter(node -> playerData.getNodeState(node) == NodeStatus.UNLOCKABLE).toList(); + List unlockableNodes = nodes.values().stream().filter(node -> playerData.getNodeStatus(node) == NodeStatus.UNLOCKABLE).toList(); for (SkillTreeNode node : unlockableNodes) { labelLockedNodesFrom(playerData, node); } @@ -109,7 +109,7 @@ public class LinkedSkillTree extends SkillTree { boolean isUnlockable = false; for (IntegerCoordinates coordinates : getCheckCoordinates(node.getCoordinates())) { if (isNode(coordinates)) - if (isNode(coordinates) && playerData.getNodeState(getNode(coordinates)) == NodeStatus.UNLOCKED && countUnlockedNeighbours(coordinates, playerData) <= getNode(coordinates).getMaxChildren()) + if (isNode(coordinates) && playerData.getNodeStatus(getNode(coordinates)) == NodeStatus.UNLOCKED && countUnlockedNeighbours(coordinates, playerData) <= getNode(coordinates).getMaxChildren()) isUnlockable = true; } return isUnlockable; 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 3f267381..cc6b6e37 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 @@ -5,10 +5,6 @@ import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.util.PostLoadObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.gui.skilltree.display.DisplayInfo; -import net.Indyuce.mmocore.gui.skilltree.display.Icon; -import net.Indyuce.mmocore.gui.skilltree.display.NodeDisplayInfo; -import net.Indyuce.mmocore.gui.skilltree.display.NodeType; import net.Indyuce.mmocore.manager.registry.RegisteredObject; import net.Indyuce.mmocore.skilltree.IntegerCoordinates; import net.Indyuce.mmocore.skilltree.NodeStatus; @@ -21,7 +17,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.logging.Level; /** * A passive skill tree that features nodes, or passive skills. @@ -228,7 +223,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje numberChildren++; //We must check if the parent is Fully Locked or not and if it can unlock a new node(with its max children constraint) - if (numberChildren >= strongParent.getMaxChildren() || playerData.getNodeState(strongParent) == NodeStatus.FULLY_LOCKED) + if (numberChildren >= strongParent.getMaxChildren() || playerData.getNodeStatus(strongParent) == NodeStatus.FULLY_LOCKED) isFullyLockedFromStrongParent = true; } @@ -242,7 +237,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje for (SkillTreeNode child : softParent.getChildren()) if (playerData.getNodeLevel(child) > 0) numberChildren++; - if (numberChildren < softParent.getMaxChildren() && playerData.getNodeState(softParent) != NodeStatus.FULLY_LOCKED) + if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED) isFullyLockedFromSoftParent = false; } From fa9c24589bff7c45cbb3983d740534acd4b72ec8 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:10:16 +0100 Subject: [PATCH 12/31] Fixed issue #817 about skill tree path not working as intented in GUI. --- .../net/Indyuce/mmocore/gui/skilltree/display/PathType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java index 1769fb20..10b4f67e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/skilltree/display/PathType.java @@ -18,7 +18,7 @@ public enum PathType { DEFAULT; public static PathType getPathType(boolean hasUp,boolean hasRight,boolean hasDown,boolean hasLeft) { - if ((hasUp || hasDown) && !hasLeft && hasRight) { + if ((hasUp || hasDown) && !hasLeft && !hasRight) { return UP; } else if ((hasRight || hasLeft)&& !hasUp && !hasDown) { return RIGHT; From 061ced2207eaf241e03c77622acdc91cb0bd02bd Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:10:36 +0100 Subject: [PATCH 13/31] Better error handling for slot lock command. --- .../mmocore/command/rpg/admin/SlotCommandTreeNode.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java index f7fd32fe..d274b5ca 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/rpg/admin/SlotCommandTreeNode.java @@ -53,7 +53,15 @@ public class SlotCommandTreeNode extends CommandTreeNode { sender.sendMessage(ChatColor.RED + "The slot can't be negative."); return CommandResult.FAILURE; } + if (slot > MMOCore.plugin.configManager.maxSkillSlots) { + sender.sendMessage(ChatColor.RED + "The slot can't be higher than " + MMOCore.plugin.configManager.maxSkillSlots + "."); + return CommandResult.FAILURE; + } SkillSlot skillSlot = playerData.getProfess().getSkillSlot(slot); + if(skillSlot.isUnlockedByDefault()){ + sender.sendMessage(ChatColor.RED + "You can't lock a skill that is unlocked by default."); + return CommandResult.FAILURE; + } if (lock) { if (!playerData.hasUnlocked(skillSlot)) { CommandVerbose.verbose(sender, CommandVerbose.CommandType.SKILL, ChatColor.RED + "The skill slot " + skillSlot.getName() + " is already locked" + " for " + player.getName()); From f3aa07288f14c001404cb2f64217fbcac2587dc0 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:11:17 +0100 Subject: [PATCH 14/31] Fixed issue #812 about a bug with slot_unlock trigger. --- .../mmocore/api/quest/trigger/UnlockSlotTrigger.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java index 0495b9fe..429b2d2e 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/quest/trigger/UnlockSlotTrigger.java @@ -14,7 +14,11 @@ public class UnlockSlotTrigger extends Trigger implements Removable { public UnlockSlotTrigger(MMOLineConfig config) { super(config); config.validateKeys("slot"); - slot = Integer.parseInt("slot"); + try { + slot = Integer.parseInt(config.getString("slot")); + }catch(NumberFormatException e){ + throw new IllegalArgumentException("The slot should be a number"); + } Validate.isTrue(slot > 0 && slot <= MMOCore.plugin.configManager.maxSkillSlots, "The slot should be between 1 and " + MMOCore.plugin.configManager.maxSkillSlots); } From fc91ace14332c058de71e15eff8f9e3b09cf64d4 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:12:26 +0100 Subject: [PATCH 15/31] Fixed issue #806 about skill slot lore not displaying on GUI and modified slightly skill-list.yml GUI for that. --- .../net/Indyuce/mmocore/gui/SkillList.java | 22 +++++++++++++------ .../main/resources/default/gui/skill-list.yml | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) 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 5d3b8b4e..7dfeb3c8 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 @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.gui; +import io.lumine.mythic.core.utils.MythicUtil; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.api.item.NBTItem; @@ -193,6 +194,7 @@ public class SkillList extends EditableInventory { final @Nullable ClassSkill boundSkill = inv.getPlayerData().getBoundSkill(n + 1); final ItemStack item = super.display(inv, n); + Placeholders holders = getPlaceholders(inv, n); // Same material as skill if (boundSkill != null) @@ -201,6 +203,17 @@ public class SkillList extends EditableInventory { final ItemMeta meta = item.getItemMeta(); meta.setDisplayName(MMOCore.plugin.placeholderParser.parse(inv.getPlayerData().getPlayer(), skillSlot.getName())); + List lore = new ArrayList<>(getLore()); + + int index = lore.indexOf("{slot-lore}"); + lore.remove(index); + List slotLore = skillSlot.getLore(); + for (int j = 0; j < slotLore.size(); j++) + lore.add(index + j, slotLore.get(j)); + + for (int j = 0; j < lore.size(); j++) + lore.set(j, ChatColor.GRAY + holders.apply(inv.getPlayer(), lore.get(j))); + meta.setLore(lore); // Same CMD as skill icon if (boundSkill != null && boundSkill.getSkill().getIcon().hasItemMeta() && boundSkill.getSkill().getIcon().getItemMeta().hasCustomModelData()) meta.setCustomModelData(boundSkill.getSkill().getIcon().getItemMeta().getCustomModelData()); @@ -209,17 +222,12 @@ public class SkillList extends EditableInventory { return item; } - /** - * This should only be called when there is a skill bound. - */ @Override public Placeholders getPlaceholders(SkillViewerInventory inv, int n) { RegisteredSkill selected = inv.selected.getSkill(); - + final @NotNull SkillSlot skillSlot = inv.getPlayerData().getProfess().getSkillSlot(n + 1); Placeholders holders = new Placeholders(); - - holders.register("index", "" + (n + 1)); - holders.register("slot", MMOCoreUtils.intToRoman(n + 1)); + holders.register("slot", skillSlot.getName()); holders.register("selected", selected == null ? none : selected.getName()); RegisteredSkill skill = inv.getPlayerData().hasSkillBound(n + 1) ? inv.getPlayerData().getBoundSkill(n + 1).getSkill() : null; holders.register("skill", skill == null ? none : skill.getName()); diff --git a/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml b/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml index 7f60ca0a..c2d561c3 100644 --- a/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml +++ b/MMOCore-Dist/src/main/resources/default/gui/skill-list.yml @@ -56,6 +56,8 @@ items: lore: - '&7Current Skill: &6{skill}' - '' + - '{slot-lore}' + - '' - '&7&oCast this spell by pressing [F] followed' - '&7&oby the keybind displayed on the action bar.' - '' From 4b2cc5ea610499bcc8901ccbebf7ca3f78c13e7c Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:14:34 +0100 Subject: [PATCH 16/31] Fixed issue #810 about %mmocore_bound_% placeholder bug. --- .../net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java index 639c922d..16f998e8 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/comp/placeholder/RPGPlaceholders.java @@ -124,7 +124,7 @@ public class RPGPlaceholders extends PlaceholderExpansion { return playerData.isInCombat() ? MythicLib.plugin.getMMOConfig().decimal.format((System.currentTimeMillis() - playerData.getCombat().getLastHit()) / 1000.) : "-1"; else if (identifier.startsWith("bound_")) { - int slot = Math.max(0, Integer.parseInt(identifier.substring(6)) - 1); + int slot = Math.max(0, Integer.parseInt(identifier.substring(6))); return playerData.hasSkillBound(slot) ? playerData.getBoundSkill(slot).getSkill().getName() : MMOCore.plugin.configManager.noSkillBoundPlaceholder; From 9344ff99a6a8b6a1e148a4ebf148bc1100d49ec5 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:30:16 +0100 Subject: [PATCH 17/31] Fixed issue #805 about placeholders not being parsed in the profile GUI. --- .../java/net/Indyuce/mmocore/gui/PlayerStats.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java index 80217dd7..aa67f709 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/PlayerStats.java @@ -21,6 +21,7 @@ import net.Indyuce.mmocore.player.stats.StatInfo; import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute; import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -122,9 +123,13 @@ public class PlayerStats extends EditableInventory { return new Placeholders() { final net.Indyuce.mmocore.api.player.stats.PlayerStats stats = inv.target.getStats(); - public String apply(Player player, String str) { - while (str.contains("{") && str.substring(str.indexOf("{")).contains("}")) { - final String holder = str.substring(str.indexOf("{") + 1, str.indexOf("}")); + @Override + public String apply(OfflinePlayer player, String str) { + String explored = str; + // Internal placeholders + while (explored.contains("{") && explored.substring(explored.indexOf("{")).contains("}")) { + final int begin = explored.indexOf("{"), end = explored.indexOf("}"); + final String holder = explored.substring(begin + 1, end); String replaced; if (holder.endsWith("_base")) { final String stat = UtilityMethods.enumName(holder.substring(0, holder.length() - 5)); @@ -141,6 +146,9 @@ public class PlayerStats extends EditableInventory { } str = str.replace("{" + holder + "}", replaced); + + // Increase counter + explored = explored.substring(end + 1); } // External placeholders From edc873a6c760fc7834b3c8fec4544e49e8e81ca6 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:34:22 +0100 Subject: [PATCH 18/31] Fixed issue #804 about custom display not working properly for the status fully-locked. --- .../java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 a72b8a25..48da591d 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 @@ -3,6 +3,7 @@ package net.Indyuce.mmocore.skilltree; import io.lumine.mythic.lib.MythicLib; 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; @@ -63,8 +64,9 @@ public class SkillTreeNode implements ExperienceObject { this.tree = tree; if (config.isConfigurationSection("display")) { for (NodeStatus status : NodeStatus.values()) { - if (!config.isConfigurationSection("display." + status.name().toLowerCase())) { - MMOCore.log("Could not find node display for status " + status.name().toLowerCase() + " for node " + id + " in tree " + tree.getId() + ". Using default display."); + String ymlStatus=MMOCoreUtils.ymlName(status.name()); + if (!config.isConfigurationSection("display." + ymlStatus)) { + MMOCore.log("Could not find node display for status " + ymlStatus + " for node " + id + " in tree " + tree.getId() + ". Using default display."); continue; } icons.put(status, new Icon(config.getConfigurationSection("display." + status.name().toLowerCase()))); From d2d03e322c0438afb16cc740095b8328ab8fbd81 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:40:25 +0100 Subject: [PATCH 19/31] Fixed issue #809 about passive skill being shown in the skill casting bar. --- .../Indyuce/mmocore/skill/cast/listener/SkillBar.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java index 66bfcdf4..d46edaa4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/cast/listener/SkillBar.java @@ -119,11 +119,12 @@ public class SkillBar implements Listener { if (!data.isOnline()) return str.toString(); for (int slot : data.mapBoundSkills().keySet()) { ClassSkill skill = data.getBoundSkill(slot); - str.append(str.isEmpty() ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}", - String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina( - data, skill) ? noStamina : ready)).replace("{index}", - String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))) - .replace("{skill}", data.getBoundSkill(slot).getSkill().getName())); + if (!skill.getSkill().getTrigger().isPassive()) + str.append(str.isEmpty() ? "" : split).append((onCooldown(data, skill) ? onCooldown.replace("{cooldown}", + String.valueOf(data.getCooldownMap().getInfo(skill).getRemaining() / 1000)) : noMana(data, skill) ? noMana : (noStamina( + data, skill) ? noStamina : ready)).replace("{index}", + String.valueOf(slot + (data.getPlayer().getInventory().getHeldItemSlot() < slot ? 1 : 0))) + .replace("{skill}", data.getBoundSkill(slot).getSkill().getName())); } return MMOCore.plugin.placeholderParser.parse(data.getPlayer(), str.toString()); } From 1cdbd08d6b6b245c8628e35d82a42835c7610002 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 09:48:54 +0100 Subject: [PATCH 20/31] Fixed issue #818 about decimal format not being applied to some placeholders. --- .../src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java index 8c6f5ae1..1cabaf0b 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java @@ -1,10 +1,12 @@ package net.Indyuce.mmocore.skill; +import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.player.cooldown.CooldownObject; import io.lumine.mythic.lib.player.modifier.ModifierSource; import io.lumine.mythic.lib.player.skill.PassiveSkill; import io.lumine.mythic.lib.script.condition.Condition; +import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.util.math.formula.IntegerLinearValue; import net.Indyuce.mmocore.api.util.math.formula.LinearValue; @@ -116,7 +118,7 @@ public class ClassSkill implements CooldownObject, Unlockable { // Calculate placeholders Placeholders placeholders = new Placeholders(); - modifiers.keySet().forEach(modifier -> placeholders.register(modifier, data.getMMOPlayerData().getSkillModifierMap().getInstance(skill.getHandler(), modifier).getTotal(modifiers.get(modifier).calculate(x)))); + modifiers.keySet().forEach(modifier -> placeholders.register(modifier, MythicLib.plugin.getMMOConfig().decimal.format(data.getMMOPlayerData().getSkillModifierMap().getInstance(skill.getHandler(), modifier).getTotal(modifiers.get(modifier).calculate(x))))); placeholders.register("mana_name", data.getProfess().getManaDisplay().getName()); placeholders.register("mana_color", data.getProfess().getManaDisplay().getFull().toString()); From b0cab10da274aad2983abd12c97869703f70ca19 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 10:05:38 +0100 Subject: [PATCH 21/31] Fixed issue #811. --- .../java/net/Indyuce/mmocore/api/player/PlayerData.java | 7 ++++++- .../src/main/java/net/Indyuce/mmocore/gui/SkillList.java | 8 +++----- .../java/net/Indyuce/mmocore/skill/CastableSkill.java | 5 ++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 3b446677..a8774c5f 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -1073,6 +1073,11 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc return getProfess().hasSkill(skill.getHandler().getId()) && hasSkillUnlocked(getProfess().getSkill(skill.getHandler().getId())); } + + @Deprecated + public boolean hasSkillUnlocked(ClassSkill skill) { + return hasUnlockedLevel(skill); + } /** * Checks for the player's level and compares it to the skill unlock level. *

@@ -1083,7 +1088,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc * * @return If the player unlocked the skill */ - public boolean hasSkillUnlocked(ClassSkill skill) { + public boolean hasUnlockedLevel(ClassSkill skill){ return getLevel() >= skill.getUnlockLevel(); } 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 7dfeb3c8..0284aea4 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 @@ -1,10 +1,8 @@ package net.Indyuce.mmocore.gui; -import io.lumine.mythic.core.utils.MythicUtil; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.api.item.NBTItem; -import me.ulrich.clans.manager.I; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.player.PlayerData; @@ -442,7 +440,7 @@ public class SkillList extends EditableInventory { return; } - if (!playerData.hasSkillUnlocked(selected)) { + if (!playerData.hasUnlockedLevel(selected)) { MMOCore.plugin.configManager.getSimpleMessage("skill-level-not-met").send(player); player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2); return; @@ -470,8 +468,8 @@ public class SkillList extends EditableInventory { if (item.getFunction().equals("upgrade")) { int shiftCost = ((UpgradeItem) item).shiftCost; - if (!playerData.hasSkillUnlocked(selected)) { - MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(player); + if (!playerData.hasUnlockedLevel(selected)) { + MMOCore.plugin.configManager.getSimpleMessage("skill-level-not-met").send(player); player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2); return; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java index fdff5f3c..77d0dbfb 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/CastableSkill.java @@ -1,7 +1,6 @@ package net.Indyuce.mmocore.skill; import io.lumine.mythic.lib.MythicLib; -import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.comp.flags.CustomFlag; import io.lumine.mythic.lib.player.cooldown.CooldownInfo; import io.lumine.mythic.lib.skill.Skill; @@ -48,8 +47,8 @@ public class CastableSkill extends Skill { boolean loud = !getTrigger().isSilent(); // Skill is not usable yet - if (!playerData.hasSkillUnlocked(skill)) { - if (loud) MMOCore.plugin.configManager.getSimpleMessage("not-unlocked-skill").send(playerData.getPlayer()); + if (!playerData.hasUnlockedLevel(skill)) { + if (loud) MMOCore.plugin.configManager.getSimpleMessage("skill-level-not-met").send(playerData.getPlayer()); return false; } From 528606628d9e0edb3cf2f301a7d4c7c9e04828e2 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 10:46:19 +0100 Subject: [PATCH 22/31] Removed HotbarSwap option because of a dupe bug that has been found. --- .../net/Indyuce/mmocore/MMOCoreBukkit.java | 7 ---- .../mmocore/listener/option/HotbarSwap.java | 41 ------------------- MMOCore-Dist/src/main/resources/config.yml | 16 +------- 3 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/option/HotbarSwap.java diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java index 160c0922..e29443db 100644 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java +++ b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/MMOCoreBukkit.java @@ -19,13 +19,6 @@ public class MMOCoreBukkit { if (plugin.configManager.overrideVanillaExp) Bukkit.getPluginManager().registerEvents(new VanillaExperienceOverride(), plugin); - if (plugin.getConfig().getBoolean("hotbar-swapping.enabled")) - try { - Bukkit.getPluginManager().registerEvents(new HotbarSwap(plugin.getConfig().getConfigurationSection("hotbar-swapping")), plugin); - } catch (RuntimeException exception) { - plugin.getLogger().log(Level.WARNING, "Could not load hotbar swapping: " + exception.getMessage()); - } - if (plugin.getConfig().getBoolean("prevent-spawner-xp")) Bukkit.getPluginManager().registerEvents(new NoSpawnerEXP(), plugin); diff --git a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/option/HotbarSwap.java b/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/option/HotbarSwap.java deleted file mode 100644 index 6945b610..00000000 --- a/MMOCore-Dist/src/main/java/net/Indyuce/mmocore/listener/option/HotbarSwap.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.Indyuce.mmocore.listener.option; - -import io.lumine.mythic.lib.UtilityMethods; -import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.api.event.PlayerKeyPressEvent; -import net.Indyuce.mmocore.api.SoundEvent; -import net.Indyuce.mmocore.skill.cast.PlayerKey; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemStack; - -import java.util.Objects; - -public class HotbarSwap implements Listener { - private final PlayerKey keybind; - private final boolean crouching; - - public HotbarSwap(ConfigurationSection config) { - this.keybind = PlayerKey.valueOf(UtilityMethods.enumName(Objects.requireNonNull(config.getString("keybind"), "Could not find keybind"))); - this.crouching = config.getBoolean("crouching"); - } - - @EventHandler - public void keyPress(PlayerKeyPressEvent event) { - Player player = event.getPlayer(); - if (event.getPressed() == keybind && event.getPlayer().isSneaking() == crouching) { - - if (event.getPressed().shouldCancelEvent()) - event.setCancelled(true); - - MMOCore.plugin.soundManager.getSound(SoundEvent.HOTBAR_SWAP).playTo(player); - for (int j = 0; j < 9; j++) { - ItemStack replaced = player.getInventory().getItem(j + 9 * 3); - player.getInventory().setItem(j + 9 * 3, player.getInventory().getItem(j)); - player.getInventory().setItem(j, replaced); - } - } - } -} diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index bbec0727..c54a6032 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -15,7 +15,7 @@ mysql: port: 3306 database: minecraft user: mmolover - pass: ILoveAria + pass: ILovePhoenixDev properties: cachePrepStmts: true prepStmtCacheSize: 250 @@ -213,20 +213,6 @@ max-skill-slots: 8 # When set to false, unlocked skills will take effect right away. passive-skill-need-bound: true -# Fun extra RPG feature that switches the player's hotbar with -# the 9 lower row items of his inventory. This allows the player -# to have two different item sets or quickly have access to pots -# Requires a SERVER reload when changed. -hotbar-swapping: - enabled: true - - # Keybind which triggers - # Available keybinds - keybind: SWAP_HANDS - - # If the player has to sneak to swap hotbars - crouching: true - # Set this to true to allow players in # creative mode to enter casting mode can-creative-cast: false From 5523e875cfc12eb3315623d0578107bb45d72d7f Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Thu, 4 May 2023 11:21:11 +0100 Subject: [PATCH 23/31] Permission requirement for skill tree node according to ticket #801. Check the wiki for further info. Make sure to reload messages.yml. --- .../net/Indyuce/mmocore/api/player/PlayerData.java | 2 +- .../mmocore/gui/skilltree/SkillTreeViewer.java | 14 +++----------- .../Indyuce/mmocore/skilltree/SkillTreeNode.java | 7 +++++++ .../src/main/resources/default/messages.yml | 1 + 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index a8774c5f..002c5dd4 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -278,7 +278,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc NodeStatus nodeStatus = nodeStates.get(node); //Check the State of the node if (nodeStatus != NodeStatus.UNLOCKED && nodeStatus != NodeStatus.UNLOCKABLE) return false; - return getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) + skillTreePoints.getOrDefault("global", 0) >= node.getSkillTreePointsConsumed()); + return node.hasPermissionRequirement(this)&&getNodeLevel(node) < node.getMaxLevel() && (skillTreePoints.getOrDefault(node.getTree().getId(), 0) + skillTreePoints.getOrDefault("global", 0) >= node.getSkillTreePointsConsumed()); } /** 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 4bf5728e..b67bc46d 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 @@ -421,14 +421,12 @@ public class SkillTreeViewer extends EditableInventory { if (spent < 1) { MMOCore.plugin.configManager.getSimpleMessage("no-skill-tree-points-spent").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); return; } if (getPlayerData().getSkillTreeReallocationPoints() <= 0) { MMOCore.plugin.configManager.getSimpleMessage("not-skill-tree-reallocation-point").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); return; } else { int reallocated = playerData.getPointSpent(skillTree); @@ -439,7 +437,6 @@ public class SkillTreeViewer extends EditableInventory { skillTree.setupNodeStates(playerData); MMOCore.plugin.configManager.getSimpleMessage("reallocated-points", "points", "" + playerData.getSkillTreePoint(skillTree.getId()), "skill-tree", skillTree.getName()).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.RESET_SKILL_TREE).playTo(player); - event.setCancelled(true); open(); return; @@ -452,7 +449,6 @@ public class SkillTreeViewer extends EditableInventory { MMOCore.plugin.soundManager.getSound(SoundEvent.CHANGE_SKILL_TREE).playTo(player); skillTree = MMOCore.plugin.skillTreeManager.get(id); open(); - event.setCancelled(true); return; } @@ -462,16 +458,13 @@ public class SkillTreeViewer extends EditableInventory { int x = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.x"), PersistentDataType.INTEGER); int y = container.get(new NamespacedKey(MMOCore.plugin, "coordinates.y"), PersistentDataType.INTEGER); if (!skillTree.isNode(new IntegerCoordinates(x, y))) { - event.setCancelled(true); return; } SkillTreeNode node = skillTree.getNode(new IntegerCoordinates(x, y)); if (playerData.getPointSpent(skillTree) >= skillTree.getMaxPointSpent()) { MMOCore.plugin.configManager.getSimpleMessage("max-points-reached").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); return; - } if (playerData.canIncrementNodeLevel(node)) { @@ -479,23 +472,22 @@ public class SkillTreeViewer extends EditableInventory { MMOCore.plugin.configManager.getSimpleMessage("upgrade-skill-node", "skill-node", node.getName(), "level", "" + playerData.getNodeLevel(node)).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.LEVEL_UP).playTo(getPlayer()); open(); - event.setCancelled(true); } else if (playerData.getNodeStatus(node) == NodeStatus.LOCKED || playerData.getNodeStatus(node) == NodeStatus.FULLY_LOCKED) { MMOCore.plugin.configManager.getSimpleMessage("locked-node").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); } else if (playerData.getNodeLevel(node) >= node.getMaxLevel()) { MMOCore.plugin.configManager.getSimpleMessage("skill-node-max-level-hit").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); + }else if(!node.hasPermissionRequirement(playerData)){ + MMOCore.plugin.configManager.getSimpleMessage("missing-skill-node-permission").send(player); + MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); } //Else the player doesn't doesn't have the skill tree points else { MMOCore.plugin.configManager.getSimpleMessage("not-enough-skill-tree-points", "point", "" + node.getSkillTreePointsConsumed()).send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - event.setCancelled(true); } } 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 48da591d..1a7f1788 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 @@ -24,6 +24,8 @@ public class SkillTreeNode implements ExperienceObject { private final SkillTree tree; private final String name, id; + private String permissionRequired; + private final Map icons = new HashMap<>(); private IntegerCoordinates coordinates; @@ -76,6 +78,7 @@ public class SkillTreeNode implements ExperienceObject { size = Objects.requireNonNull(config.getInt("size")); isRoot = config.getBoolean("is-root", false); skillTreePointsConsumed = config.getInt("point-consumed", 1); + permissionRequired = config.getString("permission-required"); Validate.isTrue(skillTreePointsConsumed > 0, "The skill tree points consumed by a node must be greater than 0."); if (config.contains("lores")) for (String key : config.getConfigurationSection("lores").getKeys(false)) @@ -151,6 +154,10 @@ public class SkillTreeNode implements ExperienceObject { return maxChildren; } + public boolean hasPermissionRequirement(PlayerData playerData){ + return permissionRequired == null || playerData.getPlayer().hasPermission(permissionRequired); + } + public Set getSoftParents() { return softParents.keySet(); } diff --git a/MMOCore-Dist/src/main/resources/default/messages.yml b/MMOCore-Dist/src/main/resources/default/messages.yml index 33d8687b..c6c9bd57 100644 --- a/MMOCore-Dist/src/main/resources/default/messages.yml +++ b/MMOCore-Dist/src/main/resources/default/messages.yml @@ -216,6 +216,7 @@ no-skill-tree-points-spent: '&cYou have not spent any skill tree points.' locked-node: '&cThis skill is locked!' upgrade-skill-node: '&eYour skill node &6{skill-node} &eis now Level &6{level}&e!' skill-node-max-level-hit: '&cYou already hit the max level for that skill node.' +missing-skill-node-permission: '&cYou do not have the permission to unlock this skill node.' not-enough-skill-tree-points: '&cYou need {point} skill tree point.' reallocated-points: '&eYou successfully reset the skill tree {skill-tree}. &eYou now have &6{points} &eskill tree points.' not-skill-tree-reallocation-point: '&cYou do not have 1 skill tree reallocation point.' From fe0996b01b63ba8f5efaa8ce68351d932b6ade7d Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Fri, 5 May 2023 11:18:40 +0100 Subject: [PATCH 24/31] Little modifications for the formula parser. --- .../main/java/net/Indyuce/mmocore/skill/RegisteredSkill.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 901d19b2..7cb8c6f9 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 @@ -121,7 +121,7 @@ public class RegisteredSkill { parsedExpression = parsedExpression.replace("<" + category + ">", "true"); parsedExpression = parsedExpression.replaceAll("<.*?>", "false"); try { - return (boolean) MythicLib.plugin.getInterpreter().eval(parsedExpression); + return (boolean) MythicLib.plugin.getFormulaParser().eval(parsedExpression); } catch (EvalError error) { throw new RuntimeException(error); } From 13440600a8ff1d13e4f11d70b14e9729110cdeda Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 14:29:27 +0100 Subject: [PATCH 25/31] Fixed issue #821 about skill tree nodes not loading properly. --- .../main/java/net/Indyuce/mmocore/skilltree/SkillTreeNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1a7f1788..430ab4d8 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 @@ -71,7 +71,7 @@ public class SkillTreeNode implements ExperienceObject { MMOCore.log("Could not find node display for status " + ymlStatus + " for node " + id + " in tree " + tree.getId() + ". Using default display."); continue; } - icons.put(status, new Icon(config.getConfigurationSection("display." + status.name().toLowerCase()))); + icons.put(status, new Icon(config.getConfigurationSection("display." +MMOCoreUtils.ymlName(status.name())))); } } name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); From aa6a1d710151bb4b111f97894a51d2c5a2027e28 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 15:11:20 +0100 Subject: [PATCH 26/31] Fixed issue #820 about skills not being locked when reallocating skill tree. --- .../main/java/net/Indyuce/mmocore/api/player/PlayerData.java | 2 ++ .../src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java index 002c5dd4..b6ae0281 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/PlayerData.java @@ -377,6 +377,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc */ public boolean unlock(Unlockable unlockable) { Validate.isTrue(!unlockable.isUnlockedByDefault(), "Cannot unlock an item unlocked by default"); + unlockable.whenUnlocked(this); final boolean wasLocked = unlockedItems.add(unlockable.getUnlockNamespacedKey()); // Call the event synchronously if (wasLocked) @@ -392,6 +393,7 @@ public class PlayerData extends OfflinePlayerData implements Closable, Experienc */ public boolean lock(Unlockable unlockable) { Validate.isTrue(!unlockable.isUnlockedByDefault(), "Cannot lock an item unlocked by default"); + unlockable.whenLocked(this); boolean wasUnlocked = unlockedItems.remove(unlockable.getUnlockNamespacedKey()); if (wasUnlocked) //Calls the event synchronously diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java index 1cabaf0b..7f35e287 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java @@ -87,7 +87,7 @@ public class ClassSkill implements CooldownObject, Unlockable { @Override public void whenLocked(PlayerData playerData) { playerData.mapBoundSkills().forEach((slot, skill) -> { - if (skill.equals(getUnlockNamespacedKey().split(":")[1])) + if (skill.equalsIgnoreCase(getUnlockNamespacedKey().split(":")[1])) playerData.unbindSkill(slot); }); } From a125320dd0451f23f3d8846836165b58ea671d02 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 16:26:37 +0100 Subject: [PATCH 27/31] Fixed a bug related to SubClassSelect GUI. --- .../main/java/net/Indyuce/mmocore/gui/SubclassSelect.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java index ad21f793..65e0a41d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/gui/SubclassSelect.java @@ -16,6 +16,7 @@ import net.Indyuce.mmocore.api.ConfigMessage; import net.Indyuce.mmocore.api.SoundEvent; import net.Indyuce.mmocore.api.player.profess.Subclass; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.configuration.ConfigurationSection; @@ -112,8 +113,8 @@ public class SubclassSelect extends EditableInventory { InventoryManager.CLASS_SELECT.newInventory(playerData).open(); if (item.getFunction().startsWith("sub-class")) { - String classId = item.getFunction().substring(10); - PlayerClass profess = MMOCore.plugin.classManager.get(classId); + String classId = UtilityMethods.ymlName(item.getFunction().substring(10)); + PlayerClass profess = MMOCore.plugin.classManager.get(UtilityMethods.enumName(classId)); if (playerData.getClassPoints() < 1) { player.closeInventory(); MMOCore.plugin.soundManager.getSound(SoundEvent.CANT_SELECT_CLASS).playTo(getPlayer()); From 8e504e1a109ce6132931740a69aa7a6998d26c5d Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 16:28:18 +0100 Subject: [PATCH 28/31] Implemented feature associated to ticket #824 by adding incompatible-parents field in skill tree node config. --- .../gui/skilltree/SkillTreeViewer.java | 25 +++---- .../mmocore/manager/SkillTreeManager.java | 3 +- .../Indyuce/mmocore/skilltree/ParentType.java | 5 +- .../mmocore/skilltree/SkillTreeNode.java | 44 +++++++---- .../skilltree/tree/CustomSkillTree.java | 23 +++--- .../skilltree/tree/ParentInformation.java | 7 ++ .../mmocore/skilltree/tree/SkillTree.java | 74 ++++++------------- 7 files changed, 84 insertions(+), 97 deletions(-) create mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ParentInformation.java 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 b67bc46d..cb8973eb 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 @@ -12,10 +12,7 @@ import net.Indyuce.mmocore.gui.api.item.InventoryItem; import net.Indyuce.mmocore.gui.api.item.Placeholders; import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; import net.Indyuce.mmocore.gui.skilltree.display.*; -import net.Indyuce.mmocore.skilltree.IntegerCoordinates; -import net.Indyuce.mmocore.skilltree.NodeStatus; -import net.Indyuce.mmocore.skilltree.SkillTreeNode; -import net.Indyuce.mmocore.skilltree.SkillTreePath; +import net.Indyuce.mmocore.skilltree.*; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -43,8 +40,8 @@ public class SkillTreeViewer extends EditableInventory { super.reload(config); //Loads all the pathDisplayInfo for (PathStatus status : PathStatus.values()) - for (PathType pathType :PathType.values()){ - if(!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))){ + for (PathType pathType : PathType.values()) { + if (!config.contains("display.paths." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(pathType.name()))) { MMOCore.log("Missing path type: " + MMOCoreUtils.ymlName(pathType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); continue; } @@ -52,8 +49,8 @@ public class SkillTreeViewer extends EditableInventory { } //Loads all the nodeDisplayInfo for (NodeStatus status : NodeStatus.values()) - for (NodeType nodeType :NodeType.values()){ - if(!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))){ + for (NodeType nodeType : NodeType.values()) { + if (!config.contains("display.nodes." + MMOCoreUtils.ymlName(status.name()) + "." + MMOCoreUtils.ymlName(nodeType.name()))) { MMOCore.log("Missing node type: " + MMOCoreUtils.ymlName(nodeType.name()) + " for status: " + MMOCoreUtils.ymlName(status.name())); continue; } @@ -225,9 +222,11 @@ public class SkillTreeViewer extends EditableInventory { if (str.contains("{node-lore}")) { lore.addAll(node.getLore(inv.getPlayerData())); } else if (str.contains("{strong-parents}")) { - lore.addAll(getParentsLore(inv, node, node.getStrongParents())); + lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.STRONG))); } else if (str.contains("{soft-parents}")) { - lore.addAll(getParentsLore(inv, node, node.getSoftParents())); + lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.SOFT))); + } else if (str.contains("{incompatible-parents}")) { + lore.addAll(getParentsLore(inv, node, node.getParents(ParentType.INCOMPATIBLE))); } else lore.add(getPlaceholders(inv, n).apply(inv.getPlayer(), str)); }); @@ -345,9 +344,9 @@ public class SkillTreeViewer extends EditableInventory { if (skillTree.isNode(coordinates)) { SkillTreeNode node = skillTree.getNode(coordinates); - NodeStatus nodeStatus =playerData.getNodeStatus(node); + NodeStatus nodeStatus = playerData.getNodeStatus(node); //If the node has its own display, it will be shown. - if(node.hasIcon(nodeStatus)) + if (node.hasIcon(nodeStatus)) return node.getIcon(nodeStatus); NodeType nodeType = NodeType.getNodeType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); @@ -479,7 +478,7 @@ public class SkillTreeViewer extends EditableInventory { } else if (playerData.getNodeLevel(node) >= node.getMaxLevel()) { MMOCore.plugin.configManager.getSimpleMessage("skill-node-max-level-hit").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); - }else if(!node.hasPermissionRequirement(playerData)){ + } else if (!node.hasPermissionRequirement(playerData)) { MMOCore.plugin.configManager.getSimpleMessage("missing-skill-node-permission").send(player); MMOCore.plugin.soundManager.getSound(SoundEvent.NOT_ENOUGH_POINTS).playTo(getPlayer()); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java index c9d14a22..49d0684d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/SkillTreeManager.java @@ -1,6 +1,7 @@ package net.Indyuce.mmocore.manager; import net.Indyuce.mmocore.MMOCore; +import net.Indyuce.mmocore.skilltree.ParentType; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import net.Indyuce.mmocore.manager.registry.MMOCoreRegister; import net.Indyuce.mmocore.skilltree.SkillTreeNode; @@ -35,7 +36,7 @@ public class SkillTreeManager extends MMOCoreRegister { * @return The list of all the roots (e.g the nodes without any parents */ public List getRootNodes() { - return skillTreeNodes.values().stream().filter(treeNode -> treeNode.getSoftParents().size() == 0).collect(Collectors.toList()); + return skillTreeNodes.values().stream().filter(treeNode -> treeNode.getParents(ParentType.SOFT).size() == 0).collect(Collectors.toList()); } public Collection getAllNodes() { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentType.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentType.java index 667e5ea5..c2161234 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentType.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/ParentType.java @@ -3,5 +3,8 @@ package net.Indyuce.mmocore.skilltree; public enum ParentType { SOFT, - STRONG + STRONG, + + INCOMPATIBLE; + } 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 430ab4d8..cedfce56 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 @@ -9,7 +9,9 @@ import net.Indyuce.mmocore.experience.ExpCurve; import net.Indyuce.mmocore.experience.ExperienceObject; import net.Indyuce.mmocore.experience.droptable.ExperienceTable; import net.Indyuce.mmocore.gui.api.item.Placeholders; +import net.Indyuce.mmocore.gui.skilltree.SkillTreeViewer; import net.Indyuce.mmocore.gui.skilltree.display.Icon; +import net.Indyuce.mmocore.skilltree.tree.ParentInformation; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; import org.bukkit.Location; @@ -18,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.stream.Collectors; // We must use generics to get the type of the corresponding tree public class SkillTreeNode implements ExperienceObject { @@ -52,8 +55,7 @@ public class SkillTreeNode implements ExperienceObject { * You only need to have the requirement for one of your softParents * but you need to fulfill the requirements of all of your strong parents. **/ - private final Map softParents = new HashMap<>(); - private final Map strongParents = new HashMap<>(); + private final Map parents = new HashMap<>(); /** * Prefix used in node key @@ -66,12 +68,12 @@ public class SkillTreeNode implements ExperienceObject { this.tree = tree; if (config.isConfigurationSection("display")) { for (NodeStatus status : NodeStatus.values()) { - String ymlStatus=MMOCoreUtils.ymlName(status.name()); + String ymlStatus = MMOCoreUtils.ymlName(status.name()); if (!config.isConfigurationSection("display." + ymlStatus)) { MMOCore.log("Could not find node display for status " + ymlStatus + " for node " + id + " in tree " + tree.getId() + ". Using default display."); continue; } - icons.put(status, new Icon(config.getConfigurationSection("display." +MMOCoreUtils.ymlName(status.name())))); + icons.put(status, new Icon(config.getConfigurationSection("display." + MMOCoreUtils.ymlName(status.name())))); } } name = Objects.requireNonNull(config.getString("name"), "Could not find node name"); @@ -120,10 +122,7 @@ public class SkillTreeNode implements ExperienceObject { // Used when postLoaded public void addParent(SkillTreeNode parent, int requiredLevel, ParentType parentType) { - if (parentType == ParentType.SOFT) - softParents.put(parent, requiredLevel); - else - strongParents.put(parent, requiredLevel); + parents.put(new ParentInformation(parent, parentType), requiredLevel); } public void addChild(SkillTreeNode child) { @@ -138,12 +137,23 @@ public class SkillTreeNode implements ExperienceObject { this.coordinates = coordinates; } + public int getParentNeededLevel(SkillTreeNode parent) { - return softParents.containsKey(parent) ? softParents.get(parent) : strongParents.containsKey(parent) ? strongParents.get(parent) : 0; + for (Map.Entry entry : parents.entrySet()) + if (entry.getKey().node().equals(parent)) + return entry.getValue(); + throw new RuntimeException("Could not find parent " + parent.getId() + " for node " + id); + } + + public int getParentNeededLevel(SkillTreeNode parent, ParentType parentType) { + return parents.get(new ParentInformation(parent, parentType)); } public boolean hasParent(SkillTreeNode parent) { - return softParents.containsKey(parent) || strongParents.containsKey(parent); + for (Map.Entry entry : parents.entrySet()) + if (entry.getKey().node() == parent) + return true; + return false; } public int getMaxLevel() { @@ -154,18 +164,19 @@ public class SkillTreeNode implements ExperienceObject { return maxChildren; } - public boolean hasPermissionRequirement(PlayerData playerData){ + public boolean hasPermissionRequirement(PlayerData playerData) { return permissionRequired == null || playerData.getPlayer().hasPermission(permissionRequired); } - public Set getSoftParents() { - return softParents.keySet(); + public Set getParents() { + return parents.keySet().stream().map(ParentInformation::node).collect(Collectors.toSet()); } - public Set getStrongParents() { - return strongParents.keySet(); + public Set getParents(ParentType parentType) { + return parents.entrySet().stream().filter(entry -> entry.getKey().type() == parentType).map((entry) -> entry.getKey().node()).collect(Collectors.toSet()); } + public List getChildren() { return children; } @@ -256,7 +267,8 @@ public class SkillTreeNode implements ExperienceObject { } @Override - public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, @NotNull EXPSource source) { + public void giveExperience(PlayerData playerData, double experience, @Nullable Location hologramLocation, + @NotNull EXPSource source) { throw new RuntimeException("Attributes don't have experience"); } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java index bd13ab63..682f9d97 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java @@ -1,5 +1,6 @@ package net.Indyuce.mmocore.skilltree.tree; +import io.lumine.mythic.lib.UtilityMethods; import net.Indyuce.mmocore.skilltree.ParentType; import net.Indyuce.mmocore.skilltree.SkillTreeNode; import org.bukkit.configuration.ConfigurationSection; @@ -18,19 +19,13 @@ public class CustomSkillTree extends SkillTree { // Setup the children and parents for each node. for (SkillTreeNode node : nodes.values()) { - - ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents.soft"); - if (section != null) { - for (String parent : section.getKeys(false)) { - node.addParent(getNode(parent), section.getInt(parent), ParentType.SOFT); - getNode(parent).addChild(node); - } - } - section = config.getConfigurationSection("nodes." + node.getId() + ".parents.strong"); - if (section != null) { - for (String parent : section.getKeys(false)) { - node.addParent(getNode(parent), section.getInt(parent), ParentType.STRONG); - getNode(parent).addChild(node); + for (String key : config.getConfigurationSection("nodes." + node.getId() + "parents").getKeys(false)) { + ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key); + if (section != null) { + for (String parent : section.getKeys(false)) { + node.addParent(getNode(parent), section.getInt(parent), ParentType.valueOf(UtilityMethods.enumName(key))); + getNode(parent).addChild(node); + } } } } @@ -41,7 +36,7 @@ public class CustomSkillTree extends SkillTree { // Find the tree roots which don't have any parents for (SkillTreeNode node : nodes.values()) { - if (node.getSoftParents().size() + node.getStrongParents().size() == 0) { + if (node.getParents().size() == 0) { // We mark the node as a root also roots.add(node); node.setIsRoot(); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ParentInformation.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ParentInformation.java new file mode 100644 index 00000000..9999a9a3 --- /dev/null +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/ParentInformation.java @@ -0,0 +1,7 @@ +package net.Indyuce.mmocore.skilltree.tree; + +import net.Indyuce.mmocore.skilltree.ParentType; +import net.Indyuce.mmocore.skilltree.SkillTreeNode; + +public record ParentInformation(SkillTreeNode node, ParentType type) { +} 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 cc6b6e37..113ab54e 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 @@ -6,10 +6,7 @@ import io.lumine.mythic.lib.api.util.PostLoadObject; import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.manager.registry.RegisteredObject; -import net.Indyuce.mmocore.skilltree.IntegerCoordinates; -import net.Indyuce.mmocore.skilltree.NodeStatus; -import net.Indyuce.mmocore.skilltree.SkillTreeNode; -import net.Indyuce.mmocore.skilltree.SkillTreePath; +import net.Indyuce.mmocore.skilltree.*; import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; @@ -54,7 +51,6 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje protected final Map nodes = new HashMap<>(); protected final int maxPointSpent; //Caches the height of the skill tree - protected int minX, minY, maxX, maxY; protected final List roots = new ArrayList<>(); public SkillTree(ConfigurationSection config) { @@ -108,43 +104,6 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje @Override protected abstract void whenPostLoaded(@NotNull ConfigurationSection configurationSection); -/* - - public Icon getIcon(SkillTreeNode node) { - SkillTree skillTree = node.getTree(); - - DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); - - return skillTree.getIcon(displayInfo); - } - - public Icon getIcon(SkillTree skillTree, IntegerCoordinates coordinates) { - - if (skillTree.isNode(coordinates)) { - SkillTreeNode node = skillTree.getNode(coordinates); - DisplayInfo displayInfo = new DisplayInfo(nodeStates.get(node), node.getSize()); - return skillTree.getIcon(displayInfo); - } - if (skillTree.isPath(coordinates)) return skillTree.getIcon(DisplayInfo.pathInfo); - return null; - } - */ - - public int getMaxX() { - return maxX; - } - - public int getMinX() { - return minX; - } - - public int getMinY() { - return minY; - } - - public int getMaxY() { - return maxY; - } public List getLore() { return lore; @@ -207,13 +166,18 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje } else if (playerData.getNodeLevel(node) == 0 && node.isRoot()) { playerData.setNodeState(node, NodeStatus.UNLOCKABLE); } else { - boolean isUnlockableFromStrongParent = node.getStrongParents().size() == 0 ? true : true; - boolean isUnlockableFromSoftParent = node.getSoftParents().size() == 0 ? true : false; - boolean isFullyLockedFromStrongParent = node.getStrongParents().size() == 0 ? false : false; - boolean isFullyLockedFromSoftParent = node.getSoftParents().size() == 0 ? false : true; + Set strongParents = node.getParents(ParentType.STRONG); + Set softParents = node.getParents(ParentType.SOFT); + Set incompatibleParents = node.getParents(ParentType.INCOMPATIBLE); - for (SkillTreeNode strongParent : node.getStrongParents()) { - if (playerData.getNodeLevel(strongParent) < node.getParentNeededLevel(strongParent)) { + boolean isUnlockableFromStrongParent = true; + boolean isUnlockableFromSoftParent = softParents.size() == 0; + boolean isFullyLockedFromStrongParent = false; + boolean isFullyLockedFromSoftParent = softParents.size() != 0; + boolean isFullyLockedFromIncompatibleParent = false; + + for (SkillTreeNode strongParent : strongParents) { + if (playerData.getNodeLevel(strongParent) < node.getParentNeededLevel(strongParent, ParentType.STRONG)) { isUnlockableFromStrongParent = false; } //We count the number of children the parent @@ -228,11 +192,11 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje } - for (SkillTreeNode softParent : node.getSoftParents()) { - if (playerData.getNodeLevel(softParent) >= node.getParentNeededLevel(softParent)) { + for (SkillTreeNode softParent : node.getParents(ParentType.SOFT)) { + if (playerData.getNodeLevel(softParent) >= node.getParentNeededLevel(softParent, ParentType.SOFT)) { isUnlockableFromSoftParent = true; } - //We count the number of children the parent + //We count the number of children the parent has int numberChildren = 0; for (SkillTreeNode child : softParent.getChildren()) if (playerData.getNodeLevel(child) > 0) @@ -240,8 +204,14 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED) isFullyLockedFromSoftParent = false; } + for (SkillTreeNode incompatibleParent : node.getParents(ParentType.INCOMPATIBLE)) { + if (playerData.getNodeLevel(incompatibleParent) > 0) { + isFullyLockedFromIncompatibleParent = true; + break; + } + } - boolean isFullyLocked = isFullyLockedFromSoftParent || isFullyLockedFromStrongParent; + boolean isFullyLocked = isFullyLockedFromSoftParent || isFullyLockedFromStrongParent || isFullyLockedFromIncompatibleParent; boolean isUnlockable = isUnlockableFromSoftParent && isUnlockableFromStrongParent; if (isFullyLocked) playerData.setNodeState(node, NodeStatus.FULLY_LOCKED); From a64faa02fd0038356ba8dc7d6f8cde71e87f8f37 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 16:50:43 +0100 Subject: [PATCH 29/31] Bug Fixing for Skill Tree --- .../mmocore/skilltree/tree/CustomSkillTree.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java index 682f9d97..1e60fb65 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java @@ -19,15 +19,16 @@ public class CustomSkillTree extends SkillTree { // Setup the children and parents for each node. for (SkillTreeNode node : nodes.values()) { - for (String key : config.getConfigurationSection("nodes." + node.getId() + "parents").getKeys(false)) { - ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key); - if (section != null) { - for (String parent : section.getKeys(false)) { - node.addParent(getNode(parent), section.getInt(parent), ParentType.valueOf(UtilityMethods.enumName(key))); - getNode(parent).addChild(node); + if (config.isConfigurationSection("nodes." + node.getId() + ".children")) + for (String key : config.getConfigurationSection("nodes." + node.getId() + "parents").getKeys(false)) { + ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key); + if (section != null) { + for (String parent : section.getKeys(false)) { + node.addParent(getNode(parent), section.getInt(parent), ParentType.valueOf(UtilityMethods.enumName(key))); + getNode(parent).addChild(node); + } } } - } } setupRoots(); } From a18a42ea2fb5a2ac331e73ae3fbd780a2dcf08f6 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 18:12:37 +0100 Subject: [PATCH 30/31] Heavy debugging and refactor for skill trees. --- .../gui/skilltree/SkillTreeViewer.java | 11 +- .../mmocore/skilltree/SkillTreeNode.java | 2 +- .../skilltree/tree/CustomSkillTree.java | 4 +- .../skilltree/tree/LinkedSkillTree.java | 129 ------------------ .../mmocore/skilltree/tree/SkillTree.java | 22 +-- 5 files changed, 18 insertions(+), 150 deletions(-) delete mode 100644 MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java 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 cb8973eb..5f4834e3 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 @@ -14,6 +14,8 @@ import net.Indyuce.mmocore.gui.api.item.SimplePlaceholderItem; import net.Indyuce.mmocore.gui.skilltree.display.*; import net.Indyuce.mmocore.skilltree.*; import net.Indyuce.mmocore.skilltree.tree.SkillTree; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -336,6 +338,7 @@ public class SkillTreeViewer extends EditableInventory { return maxTreeListPage; } + public Icon getIcon(IntegerCoordinates coordinates) { boolean hasUpPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1)); boolean hasDownPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() + 1)); @@ -350,11 +353,15 @@ public class SkillTreeViewer extends EditableInventory { return node.getIcon(nodeStatus); NodeType nodeType = NodeType.getNodeType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); - return icons.get(new NodeDisplayInfo(nodeType, nodeStatus)); + Icon icon = icons.get(new NodeDisplayInfo(nodeType, nodeStatus)); + Validate.notNull(icon, "The node " + node.getFullId() + " has no icon for the type " + nodeType + " and the status " + nodeStatus); + return icon; } else { PathType pathType = PathType.getPathType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath); SkillTreePath path = skillTree.getPath(coordinates); - return icons.get(new PathDisplayInfo(pathType, path.getStatus(playerData))); + Icon icon = icons.get(new PathDisplayInfo(pathType, path.getStatus(playerData))); + Validate.notNull(icon, "There is no icon for the path type " + pathType + " and the status " + path.getStatus(playerData)); + return icon; } } 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 cedfce56..5b604491 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 @@ -14,6 +14,7 @@ import net.Indyuce.mmocore.gui.skilltree.display.Icon; import net.Indyuce.mmocore.skilltree.tree.ParentInformation; import net.Indyuce.mmocore.skilltree.tree.SkillTree; import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; @@ -176,7 +177,6 @@ public class SkillTreeNode implements ExperienceObject { return parents.entrySet().stream().filter(entry -> entry.getKey().type() == parentType).map((entry) -> entry.getKey().node()).collect(Collectors.toSet()); } - public List getChildren() { return children; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java index 1e60fb65..0f3e17c6 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/CustomSkillTree.java @@ -19,8 +19,8 @@ public class CustomSkillTree extends SkillTree { // Setup the children and parents for each node. for (SkillTreeNode node : nodes.values()) { - if (config.isConfigurationSection("nodes." + node.getId() + ".children")) - for (String key : config.getConfigurationSection("nodes." + node.getId() + "parents").getKeys(false)) { + if (config.isConfigurationSection("nodes." + node.getId() + ".parents")) + for (String key : config.getConfigurationSection("nodes." + node.getId() + ".parents").getKeys(false)) { ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key); if (section != null) { for (String parent : section.getKeys(false)) { diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java deleted file mode 100644 index c3f4108f..00000000 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skilltree/tree/LinkedSkillTree.java +++ /dev/null @@ -1,129 +0,0 @@ -package net.Indyuce.mmocore.skilltree.tree; - -import net.Indyuce.mmocore.api.player.PlayerData; -import net.Indyuce.mmocore.skilltree.IntegerCoordinates; -import net.Indyuce.mmocore.skilltree.NodeStatus; -import net.Indyuce.mmocore.skilltree.ParentType; -import net.Indyuce.mmocore.skilltree.SkillTreeNode; -import org.apache.commons.lang.Validate; -import org.bukkit.configuration.ConfigurationSection; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.List; - -/** - * For linked skillTrees there is no notion of children and - * parents you must have some neighbours unlocked in order to - * be unlockable. All the relationships in the tree are - * defined by the coordinates you nodes have. - */ -public class LinkedSkillTree extends SkillTree { - public LinkedSkillTree(ConfigurationSection config) { - super(config); - - // Setup the coordinate map because coordinates are given in the yml for linked skill tree - coordinatesSetup(); - } - - @Override - protected void whenPostLoaded(@NotNull ConfigurationSection config) { - // Setup the children and parents if a node precise a required level for upgrade. - // If it is not filled the algorithm will put the required level to 1 - for (SkillTreeNode node : nodes.values()) { - if (config.contains(node.getId() + ".children")) { - ConfigurationSection section = config.getConfigurationSection(node.getId() + ".children.soft"); - if (section != null) { - for (String child : section.getKeys(false)) { - node.addChild(getNode(child)); - getNode(child).addParent(node, section.getInt(child), ParentType.SOFT); - } - } - section = config.getConfigurationSection(node.getId() + ".children.strong"); - if (section != null) { - for (String child : section.getKeys(false)) { - node.addChild(getNode(child)); - getNode(child).addParent(node, section.getInt(child), ParentType.STRONG); - } - } - - } - } - - SkillTreeNode root = getNode(new IntegerCoordinates(0, 0)); - Validate.notNull(root, "Their must be a node(the root of the tree) at the coordinates (0,0) "); - } - - @Override - public void setupNodeStates(PlayerData playerData) { - - // Values are labelled as unlockable - for (SkillTreeNode root : roots) - playerData.setNodeState(root, NodeStatus.UNLOCKABLE); - - // All the nodes with level >0 are unlocked - for (SkillTreeNode node : nodes.values()) { - if (playerData.getNodeLevel(node) > 0) - playerData.setNodeState(node, NodeStatus.UNLOCKED); - } - // Setup unlockable nodes - for (SkillTreeNode node : nodes.values()) { - if (isUnlockable(node, playerData) && !playerData.hasNodeState(node)) - playerData.setNodeState(node, NodeStatus.UNLOCKABLE); - } - - labelLockedNodes(playerData); - - // Label all the remaining nodes to FULLY LOCKED - for (SkillTreeNode node : nodes.values()) - if (!playerData.hasNodeState(node)) - playerData.setNodeState(node, NodeStatus.FULLY_LOCKED); - } - - /** - * We recursively label all the locked nodes who are connected to an unlockable node. - **/ - private void labelLockedNodes(PlayerData playerData) { - List unlockableNodes = nodes.values().stream().filter(node -> playerData.getNodeStatus(node) == NodeStatus.UNLOCKABLE).toList(); - for (SkillTreeNode node : unlockableNodes) { - labelLockedNodesFrom(playerData, node); - } - } - - private void labelLockedNodesFrom(PlayerData data, SkillTreeNode node) { - for (IntegerCoordinates coor : getCheckCoordinates(node.getCoordinates())) { - if (isNode(coor) && !data.hasNodeState(getNode(coor))) { - data.setNodeState(getNode(coor), NodeStatus.LOCKED); - labelLockedNodesFrom(data, getNode(coor)); - } - } - } - - private List getCheckCoordinates(IntegerCoordinates coor) { - return Arrays.asList(new IntegerCoordinates(coor.getX() + 1, coor.getY()), - new IntegerCoordinates(coor.getX() - 1, coor.getY()), new IntegerCoordinates(coor.getX(), coor.getY() + 1), new IntegerCoordinates(coor.getX(), coor.getY() - 1)); - } - - private boolean isUnlockable(SkillTreeNode node, PlayerData playerData) { - - boolean isUnlockable = false; - for (IntegerCoordinates coordinates : getCheckCoordinates(node.getCoordinates())) { - if (isNode(coordinates)) - if (isNode(coordinates) && playerData.getNodeStatus(getNode(coordinates)) == NodeStatus.UNLOCKED && countUnlockedNeighbours(coordinates, playerData) <= getNode(coordinates).getMaxChildren()) - isUnlockable = true; - } - return isUnlockable; - } - - /** - * Counts the number of unlocked neighbours of a node for a certain playerData - **/ - private int countUnlockedNeighbours(IntegerCoordinates coor, PlayerData playerData) { - int number = 0; - for (IntegerCoordinates coordinates : getCheckCoordinates(coor)) { - if (isNode(coordinates) && playerData.getNodeLevel(getNode(coordinates)) > 0) - number++; - } - return number; - } -} 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 113ab54e..d129f4aa 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 @@ -121,19 +121,8 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje SkillTree skillTree = null; try { - String string = config.getString("type"); - Validate.notNull(string, "You must precise a type for the skill tree."); - Validate.isTrue(string.equals("linked") || string.equals("custom"), "You must precise the type of the skill tree in the yml!" + - "\nAllowed values: 'linked','custom'"); - - if (string.equals("linked")) { - skillTree = new LinkedSkillTree(config); - skillTree.postLoad(); - } - if (string.equals("custom")) { - skillTree = new CustomSkillTree(config); - skillTree.postLoad(); - } + skillTree = new CustomSkillTree(config); + skillTree.postLoad(); } catch (Exception e) { MMOCore.log("Couldn't load skill tree " + config.getString("id") + ": " + e.getMessage()); } @@ -170,6 +159,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje Set softParents = node.getParents(ParentType.SOFT); Set incompatibleParents = node.getParents(ParentType.INCOMPATIBLE); + boolean isUnlockableFromStrongParent = true; boolean isUnlockableFromSoftParent = softParents.size() == 0; boolean isFullyLockedFromStrongParent = false; @@ -192,7 +182,7 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje } - for (SkillTreeNode softParent : node.getParents(ParentType.SOFT)) { + for (SkillTreeNode softParent : softParents) { if (playerData.getNodeLevel(softParent) >= node.getParentNeededLevel(softParent, ParentType.SOFT)) { isUnlockableFromSoftParent = true; } @@ -204,8 +194,8 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED) isFullyLockedFromSoftParent = false; } - for (SkillTreeNode incompatibleParent : node.getParents(ParentType.INCOMPATIBLE)) { - if (playerData.getNodeLevel(incompatibleParent) > 0) { + for (SkillTreeNode incompatibleParent : incompatibleParents) { + if (playerData.getNodeLevel(incompatibleParent) >= node.getParentNeededLevel(incompatibleParent, ParentType.INCOMPATIBLE)) { isFullyLockedFromIncompatibleParent = true; break; } From 7bf3b9ace745fdf11ea33d590aff442d90c23668 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Tue, 9 May 2023 08:32:48 +0100 Subject: [PATCH 31/31] Bug Fixing for Issue#802 about passive-skill-need-bound not working. --- .../mmocore/api/player/stats/PlayerStats.java | 12 +++++++++--- .../java/net/Indyuce/mmocore/skill/ClassSkill.java | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java index ed6a2e92..1bf46c04 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/api/player/stats/PlayerStats.java @@ -14,6 +14,10 @@ import net.Indyuce.mmocore.experience.Profession; import net.Indyuce.mmocore.player.stats.StatInfo; import net.Indyuce.mmocore.skill.ClassSkill; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + public class PlayerStats { private final PlayerData data; @@ -101,9 +105,11 @@ public class PlayerStats { if (!MMOCore.plugin.configManager.passiveSkillNeedBound) { skillMap.removeModifiers("MMOCorePassiveSkill"); - for (ClassSkill skill : data.getProfess().getSkills()) - if (skill.getSkill().getTrigger().isPassive()) - skillMap.addModifier(skill.toPassive(data)); + data.getProfess().getSkills() + .stream() + .filter((classSkill) -> classSkill.getSkill().getTrigger().isPassive() && data.hasUnlocked(classSkill) && data.hasUnlockedLevel(classSkill)) + .forEach(classSkill -> skillMap.addModifier(classSkill.toPassive(data))); + } // This updates the player's class SCRIPTS diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java index 7f35e287..5c889c22 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/skill/ClassSkill.java @@ -90,11 +90,15 @@ public class ClassSkill implements CooldownObject, Unlockable { if (skill.equalsIgnoreCase(getUnlockNamespacedKey().split(":")[1])) playerData.unbindSkill(slot); }); + //Update the stats to remove the passive skill if it is locked + if (!MMOCore.plugin.configManager.passiveSkillNeedBound && getSkill().getTrigger().isPassive()) + playerData.getStats().updateStats(); } @Override public void whenUnlocked(PlayerData playerData) { - + if (!MMOCore.plugin.configManager.passiveSkillNeedBound && getSkill().getTrigger().isPassive()) + playerData.getStats().updateStats(); } /**