forked from Upstream/mmocore
Heavy debugging and refactor for skill trees.
This commit is contained in:
parent
a64faa02fd
commit
a18a42ea2f
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<SkillTreeNode> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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<SkillTreeNode> 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<IntegerCoordinates> 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;
|
||||
}
|
||||
}
|
@ -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<SkillTreeNode> softParents = node.getParents(ParentType.SOFT);
|
||||
Set<SkillTreeNode> 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user