the_big_one/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java
Jkibbels 3795875cdf [5] Initial implementation of some attribute stuff. Nothing in this commit actually works but the game still launches! Will need to move item and armor stuff to a more generic file as well to make it less unique so it can be used broadly. Directory structure extended to add items and resources
[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
2024-09-01 00:15:11 -04:00

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