Big modification for the skilltree GUI. Make sure to reload gui/skilltree.yml and look at the wiki.

This commit is contained in:
Ka0rX 2023-04-20 19:52:09 +01:00
parent 77f543f347
commit 8b3d553183
14 changed files with 539 additions and 137 deletions

View File

@ -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);

View File

@ -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<DisplayInfo, Icon> 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;
}
}

View File

@ -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 {
}

View File

@ -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) {

View File

@ -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 +
'}';
}
}

View File

@ -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;
}
}

View File

@ -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 +
'}';
}
}

View File

@ -0,0 +1,7 @@
package net.Indyuce.mmocore.gui.skilltree.display;
public enum PathStatus {
LOCKED,
FULLY_LOCKED,
UNLOCKED;
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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<IntegerCoordinates> paths = new ArrayList<>();
//Represents all the nodes
/**
* Represents all the nodes
* Key: the coordinates of the node
* Value: the node
*/
protected final Map<IntegerCoordinates, SkillTreeNode> coordinatesNodes = new HashMap<>();
/**
* Represents all the paths between nodes.
*/
protected final Map<IntegerCoordinates, SkillTreePath> coordinatesPaths = new HashMap<>();
protected final Map<String, SkillTreeNode> nodes = new HashMap<>();
protected final int maxPointSpent;
//Caches the height of the skill tree
protected int minX, minY, maxX, maxY;
protected final HashMap<DisplayInfo, Icon> icons = new HashMap<>();
protected final List<SkillTreeNode> 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);
}

View File

@ -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 +
'}';
}
}

View File

@ -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