
[5] **WORKING** add custom item and item group to game. primarily metaljacket items not added yet - but example item works. [5] initial add of custom blocks [5] Made adding blocks more dynamic - tested to work [5] Fixed metal jacket armor & created correct texture files to not break game. TEXTURES ARE RANDOM ON WEARING AS I DONT HAVE AN ACTUAL TEXTURE YET [5] Started attribute tree stuff [5] end of day commit. **NOT WORKING** [5] First successful attribute write using test commandsgit br
219 lines
8.6 KiB
Java
219 lines
8.6 KiB
Java
/*
|
|
*
|
|
* AttributeTree
|
|
*
|
|
* Handles a players individual attribute tree
|
|
*
|
|
*
|
|
*/
|
|
|
|
package jesse.keeblarcraft.AttributeMgr;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.HashMap;
|
|
|
|
import jesse.keeblarcraft.Keeblarcraft;
|
|
import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode;
|
|
import jesse.keeblarcraft.ConfigMgr.ConfigManager;
|
|
import jesse.keeblarcraft.Utils.ChatUtil;
|
|
import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR;
|
|
import jesse.keeblarcraft.Utils.CustomExceptions.FILE_WRITE_EXCEPTION;
|
|
|
|
public class AttributeTree {
|
|
|
|
PlayerTree playerAttributeTree = new PlayerTree();
|
|
ConfigManager config = new ConfigManager();
|
|
private AbstractNode root = new RootNode();
|
|
|
|
private class TreeNode {
|
|
|
|
public TreeNode(AbstractNode node, Integer maxLevel, List<String> parents, List<String> children) {
|
|
thisNode = node;
|
|
parentNodes = parents;
|
|
childrenNodes = children;
|
|
maxNodeLevel = maxLevel;
|
|
currentNodeLevel = 1;
|
|
}
|
|
|
|
AbstractNode thisNode;
|
|
Integer currentNodeLevel;
|
|
Integer maxNodeLevel;
|
|
|
|
// Store the names of the parent and children nodes; this lets a node have any number of parents and children
|
|
// NOTE TO DEVELOPERS: Be aware! The more nodes the harrier the tree will look in the GUI!!! Always test your
|
|
// code before just adding stuff willy-nilly!
|
|
List<String> parentNodes;
|
|
List<String> childrenNodes;
|
|
}
|
|
|
|
// Separate structure as this is written to the config file
|
|
private class PlayerTree {
|
|
String uuid;
|
|
// Key = name of AbstractNode
|
|
// Val = The attribute itself
|
|
HashMap<String, TreeNode> tree = new HashMap<String, TreeNode>();
|
|
}
|
|
|
|
private class RootNode extends AbstractNode {
|
|
@Override
|
|
public String GetNodeTitle() {
|
|
return "root";
|
|
}
|
|
|
|
@Override
|
|
public String GetNodeDescription() {
|
|
return "This is the players tree root! All attributes extend from here";
|
|
}
|
|
|
|
@Override
|
|
public HashMap<String, List<String>> GetDetails() {
|
|
HashMap<String, List<String>> ret = new HashMap<String, List<String>>();
|
|
|
|
ret.put("First Attribute", List.of("This is your skill tree", "All attributes grow from this root! Unlocking nodes requires all nodes connected to that previously to be unlocked first"));
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
// Add a new node to the tree arbitrarily
|
|
// Root can never be a child node
|
|
// parents can never be empty or null (null or empty would imply you are adding root)
|
|
//
|
|
// developer warning: you must personally verify your nodes are in the tree. anywhere is fine, and the tree
|
|
// is very dynamic (which is why self verification is required). When the tree is drawn in the GUI, it starts from
|
|
// the root node. As long as your node is attached to this node anywhere in the indirected graph; then your attribute
|
|
// will be drawn in the gui
|
|
public Boolean AddNewNode(AbstractNode newNode, Integer maxNodeLevel, List<String> parents, List<String> children) {
|
|
Boolean ret = false;
|
|
TreeNode nodeReference = playerAttributeTree.tree.get(newNode.GetNodeTitle());
|
|
|
|
System.out.println("Is node reference null? -> " + (nodeReference == null ? "YES":"NO"));
|
|
System.out.println("Is root reference null? -> " + (root == null ? "YES":"NO"));
|
|
System.out.println("Is parents null? -> " + (parents == null ? "YES":"NO"));
|
|
|
|
// Some special handling is required on checking child list in case it is null
|
|
Boolean validChildren = true;
|
|
if (children != null) {
|
|
validChildren = !children.contains(root.GetNodeTitle());
|
|
}
|
|
|
|
if (nodeReference == null && validChildren) {
|
|
// Since these values can be left as null, we want to guarentee they are at least initialized here
|
|
maxNodeLevel = (maxNodeLevel == null ? 1 : maxNodeLevel);
|
|
parents = (parents == null ? new ArrayList<String>() : parents);
|
|
children = (children == null ? new ArrayList<String>() : children);
|
|
|
|
System.out.println("Parent size: " + parents.size());
|
|
if (parents.size() == 0) {
|
|
System.out.println("Root node title: " + root.GetNodeTitle());
|
|
parents.add(root.GetNodeTitle()); // No disconnected nodes allowed! All parentless nodes are adopted by root by default
|
|
}
|
|
System.out.println("Parents size: " + parents.size());
|
|
|
|
// Node implementation here
|
|
playerAttributeTree.tree.put(newNode.GetNodeTitle(), new TreeNode(newNode, maxNodeLevel, parents, children));
|
|
|
|
long pSize = playerAttributeTree.tree.get(newNode.GetNodeTitle()).parentNodes.size();
|
|
System.out.println("parent size is " + pSize);
|
|
} else {
|
|
// Some fancy error handling for console log
|
|
if (nodeReference != null) {
|
|
Keeblarcraft.LOGGER.error("Attribute with name " + newNode.GetNodeTitle() + " was already found within the tree! Rename your node to add it");
|
|
} else {
|
|
Keeblarcraft.LOGGER.error("The attribute you attempted to add (name: " + newNode.GetNodeTitle() + "), has root in the children");
|
|
}
|
|
ret = false;
|
|
}
|
|
|
|
FlashConfig();
|
|
return ret;
|
|
}
|
|
|
|
public void ChangeNodeLevel(String nodeName, Integer newLevel) {
|
|
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
|
|
|
if (nodeReference != null) {
|
|
if (newLevel <= nodeReference.maxNodeLevel) {
|
|
nodeReference.currentNodeLevel = newLevel;
|
|
}
|
|
}
|
|
|
|
FlashConfig();
|
|
}
|
|
|
|
public void DeleteNode(String nodeName) {
|
|
// Do not delete root!
|
|
if (nodeName != root.GetNodeTitle()) {
|
|
playerAttributeTree.tree.remove(nodeName);
|
|
}
|
|
|
|
FlashConfig();
|
|
}
|
|
|
|
public HashMap<String, List<String>> GetNodeDetails(String nodeName) {
|
|
HashMap<String, List<String>> ret = null;
|
|
|
|
TreeNode nodeReference = playerAttributeTree.tree.get(nodeName);
|
|
|
|
if (nodeReference != null) {
|
|
ret = nodeReference.thisNode.GetDetails();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Returns the player's attribute tree
|
|
public PlayerTree GetPlayerTree() {
|
|
return playerAttributeTree;
|
|
}
|
|
|
|
public AttributeTree(String uuid) {
|
|
// DEVELOPER NOTE:
|
|
// If you are testing this part of the code, please be reminded that anonymous testing starts a new
|
|
// player instance everytime you launch. This means the UUID CAN CHANGE when you launch the
|
|
// game! This is not an issue with proper registered accounts in production
|
|
Boolean existingFile = false;
|
|
try {
|
|
playerAttributeTree = config.GetJsonObjectFromFile("attributes/" + uuid + ".json", PlayerTree.class);
|
|
existingFile = true;
|
|
} catch (Exception e) {
|
|
// Do nothing. This means the file does not exist
|
|
}
|
|
|
|
// In the event the above code failed out, this means a new file has to be created for the player's uuid
|
|
if (!existingFile)
|
|
{
|
|
System.out.println(ChatUtil.ColoredString("Trying to create new file", CONSOLE_COLOR.BLUE));
|
|
try {
|
|
playerAttributeTree.uuid = uuid;
|
|
FlashConfig();
|
|
} catch (Exception e) {
|
|
System.out.println(ChatUtil.ColoredString("Could not write to file", CONSOLE_COLOR.RED));
|
|
}
|
|
} else {
|
|
System.out.println(ChatUtil.ColoredString("Moving on", CONSOLE_COLOR.BLUE));
|
|
}
|
|
|
|
// It's possible the above code will return a blank class if a file doesn't exist. This will make
|
|
// a new file with this players uuid
|
|
if ("".equals(playerAttributeTree.uuid)) {
|
|
System.out.println(ChatUtil.ColoredString("Assigning new config file for this uuid. No previous existing", CONSOLE_COLOR.BLUE));
|
|
playerAttributeTree.uuid = uuid;
|
|
}
|
|
|
|
// If the tree is empty or missing root, add it!
|
|
if (playerAttributeTree.tree.size() == 0 || playerAttributeTree.tree.containsKey(root.GetNodeTitle()) == false) {
|
|
playerAttributeTree.tree.put(root.GetNodeTitle(), new TreeNode(root, 1, null, null));
|
|
}
|
|
}
|
|
|
|
public void FlashConfig() {
|
|
try {
|
|
config.WriteToJsonFile("attributes/" + playerAttributeTree.uuid + ".json", playerAttributeTree);
|
|
} catch (FILE_WRITE_EXCEPTION e) {
|
|
System.out.println(ChatUtil.ColoredString("Could not flash notes configuration file", CONSOLE_COLOR.RED));
|
|
}
|
|
}
|
|
}
|