From a18a42ea2fb5a2ac331e73ae3fbd780a2dcf08f6 Mon Sep 17 00:00:00 2001 From: Ka0rX Date: Sun, 7 May 2023 18:12:37 +0100 Subject: [PATCH] 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; }