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.gui.skilltree.display.*;
|
||||||
import net.Indyuce.mmocore.skilltree.*;
|
import net.Indyuce.mmocore.skilltree.*;
|
||||||
import net.Indyuce.mmocore.skilltree.tree.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.ChatColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
@ -336,6 +338,7 @@ public class SkillTreeViewer extends EditableInventory {
|
|||||||
return maxTreeListPage;
|
return maxTreeListPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Icon getIcon(IntegerCoordinates coordinates) {
|
public Icon getIcon(IntegerCoordinates coordinates) {
|
||||||
boolean hasUpPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1));
|
boolean hasUpPath = skillTree.isPath(new IntegerCoordinates(coordinates.getX(), coordinates.getY() - 1));
|
||||||
boolean hasDownPath = 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);
|
return node.getIcon(nodeStatus);
|
||||||
|
|
||||||
NodeType nodeType = NodeType.getNodeType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath);
|
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 {
|
} else {
|
||||||
PathType pathType = PathType.getPathType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath);
|
PathType pathType = PathType.getPathType(hasUpPath, hasRightPath, hasDownPath, hasLeftPath);
|
||||||
SkillTreePath path = skillTree.getPath(coordinates);
|
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.ParentInformation;
|
||||||
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
|
import net.Indyuce.mmocore.skilltree.tree.SkillTree;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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());
|
return parents.entrySet().stream().filter(entry -> entry.getKey().type() == parentType).map((entry) -> entry.getKey().node()).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<SkillTreeNode> getChildren() {
|
public List<SkillTreeNode> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ public class CustomSkillTree extends SkillTree {
|
|||||||
|
|
||||||
// Setup the children and parents for each node.
|
// Setup the children and parents for each node.
|
||||||
for (SkillTreeNode node : nodes.values()) {
|
for (SkillTreeNode node : nodes.values()) {
|
||||||
if (config.isConfigurationSection("nodes." + node.getId() + ".children"))
|
if (config.isConfigurationSection("nodes." + node.getId() + ".parents"))
|
||||||
for (String key : config.getConfigurationSection("nodes." + node.getId() + "parents").getKeys(false)) {
|
for (String key : config.getConfigurationSection("nodes." + node.getId() + ".parents").getKeys(false)) {
|
||||||
ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key);
|
ConfigurationSection section = config.getConfigurationSection("nodes." + node.getId() + ".parents." + key);
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
for (String parent : section.getKeys(false)) {
|
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;
|
SkillTree skillTree = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String string = config.getString("type");
|
skillTree = new CustomSkillTree(config);
|
||||||
Validate.notNull(string, "You must precise a type for the skill tree.");
|
skillTree.postLoad();
|
||||||
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();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
MMOCore.log("Couldn't load skill tree " + config.getString("id") + ": " + e.getMessage());
|
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> softParents = node.getParents(ParentType.SOFT);
|
||||||
Set<SkillTreeNode> incompatibleParents = node.getParents(ParentType.INCOMPATIBLE);
|
Set<SkillTreeNode> incompatibleParents = node.getParents(ParentType.INCOMPATIBLE);
|
||||||
|
|
||||||
|
|
||||||
boolean isUnlockableFromStrongParent = true;
|
boolean isUnlockableFromStrongParent = true;
|
||||||
boolean isUnlockableFromSoftParent = softParents.size() == 0;
|
boolean isUnlockableFromSoftParent = softParents.size() == 0;
|
||||||
boolean isFullyLockedFromStrongParent = false;
|
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)) {
|
if (playerData.getNodeLevel(softParent) >= node.getParentNeededLevel(softParent, ParentType.SOFT)) {
|
||||||
isUnlockableFromSoftParent = true;
|
isUnlockableFromSoftParent = true;
|
||||||
}
|
}
|
||||||
@ -204,8 +194,8 @@ public abstract class SkillTree extends PostLoadObject implements RegisteredObje
|
|||||||
if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED)
|
if (numberChildren < softParent.getMaxChildren() && playerData.getNodeStatus(softParent) != NodeStatus.FULLY_LOCKED)
|
||||||
isFullyLockedFromSoftParent = false;
|
isFullyLockedFromSoftParent = false;
|
||||||
}
|
}
|
||||||
for (SkillTreeNode incompatibleParent : node.getParents(ParentType.INCOMPATIBLE)) {
|
for (SkillTreeNode incompatibleParent : incompatibleParents) {
|
||||||
if (playerData.getNodeLevel(incompatibleParent) > 0) {
|
if (playerData.getNodeLevel(incompatibleParent) >= node.getParentNeededLevel(incompatibleParent, ParentType.INCOMPATIBLE)) {
|
||||||
isFullyLockedFromIncompatibleParent = true;
|
isFullyLockedFromIncompatibleParent = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user