diff --git a/src/main/java/jesse/CommonServerUtils.java b/src/main/java/jesse/CommonServerUtils.java index b241354..0de60aa 100644 --- a/src/main/java/jesse/CommonServerUtils.java +++ b/src/main/java/jesse/CommonServerUtils.java @@ -13,5 +13,5 @@ public void SetServerInstance(MinecraftServer inputServer) { public static MinecraftServer GetServerInstance() { return server; } - + } diff --git a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java index aa0cb85..5b5ef87 100644 --- a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java +++ b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeMgr.java @@ -14,14 +14,21 @@ import java.util.HashMap; import jesse.keeblarcraft.Keeblarcraft; import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AbstractNode; import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeFlight; +import jesse.keeblarcraft.AttributeMgr.AttributeNodes.AttributeMetalJacket; import jesse.keeblarcraft.ConfigMgr.ConfigManager; import jesse.keeblarcraft.Utils.ChatUtil; +import net.minecraft.server.network.ServerPlayerEntity; public class AttributeMgr { ConfigManager config; + // Global list of attributes public static final HashMap attributes = new HashMap(); + // This is a list of all logged in player tree's. These are kept in memory until either the mod is torn down or + // players log out for optimization reasons + public static final HashMap activeTrees = new HashMap(); + @SuppressWarnings("deprecation") public static void RegisterAttributeClass(Class classObj) { AbstractNode test; @@ -44,19 +51,23 @@ public class AttributeMgr { public static String ApplyAttribute(String uuid, String attributeName) { String msg = ""; if (attributes.containsKey(attributeName)) { - AttributeTree playerTree = new AttributeTree(uuid); + AttributeTree playerTree = activeTrees.get(uuid); AbstractNode node = attributes.get(attributeName); - /////////// - // debug testing - String isNull = (node == null ? "NULL" : "NOT NULL"); - System.out.println("Node is " + isNull); - if (isNull.equals("NOT NULL")) { System.out.println("Node name: " + node.GetNodeTitle()); } - // end debug testing - /////////// + if (playerTree != null) { + /////////// + // debug testing + String isNull = (node == null ? "NULL" : "NOT NULL"); + System.out.println("Node is " + isNull); + if (isNull.equals("NOT NULL")) { System.out.println("Node name: " + node.GetNodeTitle()); } + // end debug testing + /////////// - playerTree.AddNewNode(node, 1, null, null); ///TODO: Make handling in AttributeTree of NULL parents list to be defaulted to ROOT - msg = "Applied attribute '" + attributeName + "' successfully"; + playerTree.AddNewNode(node, 1, null, null); + msg = "Applied attribute '" + attributeName + "' successfully"; + } else { + msg = "Player tree not found!"; + } } else { msg = "Could not apply attribute, attribute name does not exist!"; } @@ -68,5 +79,6 @@ public class AttributeMgr { /// TODO: Find a better way to do this more dynamically in the future RegisterAttributeClass(AttributeFlight.class); + RegisterAttributeClass(AttributeMetalJacket.class); } } diff --git a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AbstractNode.java b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AbstractNode.java index 37a9f47..03550dd 100644 --- a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AbstractNode.java +++ b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AbstractNode.java @@ -41,4 +41,12 @@ abstract public class AbstractNode { /// attributes. 1 string per description ///////////////////////////////////////////////////////////////////////////// public abstract HashMap> GetDetails(); + + ///////////////////////////////////////////////////////////////////////////// + /// @fn RegisterCallbacks + /// + /// @brief If your node has responsive callbacks; then this is the area + /// you will register your callbacks for everything + ///////////////////////////////////////////////////////////////////////////// + public abstract void RegisterCallbacks(); } diff --git a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeFlight.java b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeFlight.java index ebf01a7..98e0f79 100644 --- a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeFlight.java +++ b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeFlight.java @@ -12,9 +12,15 @@ package jesse.keeblarcraft.AttributeMgr.AttributeNodes; import java.util.HashMap; import java.util.List; +import jesse.keeblarcraft.Keeblarcraft; +import net.fabricmc.fabric.api.event.player.AttackBlockCallback; +import net.minecraft.block.BlockState; +import net.minecraft.util.ActionResult; + public class AttributeFlight extends AbstractNode { public AttributeFlight() { + } @Override @@ -39,4 +45,19 @@ public class AttributeFlight extends AbstractNode { return ret; } + @Override + public void RegisterCallbacks() { + // Register events here + AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> { + BlockState state = world.getBlockState(pos); + + Keeblarcraft.LOGGER.info("Callback for AttackBlockCallback called"); + // Manual spectator check is necessary because AttackBlockCallbacks fire before the spectator check + if (!player.isSpectator() && player.getMainHandStack().isEmpty() && state.isToolRequired()) { + player.damage(world.getDamageSources().generic(), 1.0F); + } + + return ActionResult.PASS; + }); + } } diff --git a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeMetalJacket.java b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeMetalJacket.java index d86d871..599f304 100644 --- a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeMetalJacket.java +++ b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeNodes/AttributeMetalJacket.java @@ -49,4 +49,8 @@ public final class AttributeMetalJacket extends AbstractNode { return ret; } + + @Override + public void RegisterCallbacks() { + } } diff --git a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java index ade0da2..c690039 100644 --- a/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java +++ b/src/main/java/jesse/keeblarcraft/AttributeMgr/AttributeTree.java @@ -11,6 +11,7 @@ package jesse.keeblarcraft.AttributeMgr; import java.util.ArrayList; import java.util.List; +import java.util.Map.Entry; import java.util.HashMap; import jesse.keeblarcraft.Keeblarcraft; @@ -47,6 +48,23 @@ public class AttributeTree { List childrenNodes; } + // This will enable the node registration of callbacks on any nodes thats level is not 0 + public void RegisterActiveCallbacks() { + for(Entry tree : playerAttributeTree.tree.entrySet()) { + if (tree.getValue().currentNodeLevel != 0) { + + // We need to construct the node object if it's null. If it's not null; we assume + // the callback registration process has already happened + if (tree.getValue().thisNode == null) { + System.out.println("REGISTERACTIVECALLBACKS - NULL NODE"); + tree.getValue().thisNode.RegisterCallbacks(); + } else { + System.out.println("REGISTERACTIVECALLBACKS - NOT NULL NODE"); + } + } + } + } + // Separate structure as this is written to the config file private class PlayerTree { String uuid; @@ -74,6 +92,10 @@ public class AttributeTree { return ret; } + + @Override + public void RegisterCallbacks() { + } } // Add a new node to the tree arbitrarily @@ -104,18 +126,17 @@ public class AttributeTree { parents = (parents == null ? new ArrayList() : parents); children = (children == null ? new ArrayList() : 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); + // if the new nodes level is not 0 we need to manually register the callbacks + if (playerAttributeTree.tree.get(newNode.GetNodeTitle()).currentNodeLevel != 0) { + playerAttributeTree.tree.get(newNode.GetNodeTitle()).thisNode.RegisterCallbacks(); + } } else { // Some fancy error handling for console log if (nodeReference != null) { diff --git a/src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java b/src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java index a64b57c..7ce3414 100644 --- a/src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java +++ b/src/main/java/jesse/keeblarcraft/Commands/AttributeCommands.java @@ -29,28 +29,50 @@ public class AttributeCommands { // Command Root: "/attributes apply " CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - dispatcher.register(CommandManager.literal("attributes") - .then(CommandManager.literal("apply") - .then(CommandManager.argument("username", EntityArgumentType.player())) - .then(CommandManager.argument("attributeName", StringArgumentType.string())) - .executes(context -> ApplyAttribute( - EntityArgumentType.getPlayer(context, "username"), - StringArgumentType.getString(context, "attributeName"), - context - )))); + var attributeNode = CommandManager.literal("attributes").build(); + + var applySubnode = CommandManager.literal("apply").build(); + + var playerArg = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build(); + + var attributeNameArg = CommandManager.argument("attributeName", StringArgumentType.greedyString()) + .executes(context -> ApplyAttribute + ( + EntityArgumentType.getPlayer(context, "targetPlayer"), + StringArgumentType.getString(context, "attributeName"), + context) + ) + .build(); + + // Build out the argument tree here + dispatcher.getRoot().addChild(attributeNode); + attributeNode.addChild(applySubnode); + applySubnode.addChild(playerArg); + playerArg.addChild(attributeNameArg); }); // Command Root: "/attributes remove " CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { - dispatcher.register(CommandManager.literal("attributes") - .then(CommandManager.literal("delete") - .then(CommandManager.argument("username", EntityArgumentType.player())) - .then(CommandManager.argument("attributeName", StringArgumentType.greedyString())) - .executes(context -> DeleteAttribute( - EntityArgumentType.getPlayer(context, "username"), - StringArgumentType.getString(context, "attributeName"), - context - )))); + var attributeNode = CommandManager.literal("attributes").build(); + + var applySubnode = CommandManager.literal("delete").build(); + + var playerArg = CommandManager.argument("targetPlayer", EntityArgumentType.player()).build(); + + var attributeNameArg = CommandManager.argument("attributeName", StringArgumentType.greedyString()) + .executes(context -> DeleteAttribute + ( + EntityArgumentType.getPlayer(context, "targetPlayer"), + StringArgumentType.getString(context, "attributeName"), + context) + ) + .build(); + + // Build out the argument tree here + dispatcher.getRoot().addChild(attributeNode); + attributeNode.addChild(applySubnode); + applySubnode.addChild(playerArg); + playerArg.addChild(attributeNameArg); }); // Command Root: "/attribute-test " diff --git a/src/main/java/jesse/keeblarcraft/EventMgr/EventManager.java b/src/main/java/jesse/keeblarcraft/EventMgr/EventManager.java index 57a06e4..e0b41c1 100644 --- a/src/main/java/jesse/keeblarcraft/EventMgr/EventManager.java +++ b/src/main/java/jesse/keeblarcraft/EventMgr/EventManager.java @@ -10,6 +10,7 @@ package jesse.keeblarcraft.EventMgr; + public class EventManager { -} +} \ No newline at end of file diff --git a/src/main/java/jesse/keeblarcraft/Utils/ServerTickListener.java b/src/main/java/jesse/keeblarcraft/EventMgr/ServerTickListener.java similarity index 62% rename from src/main/java/jesse/keeblarcraft/Utils/ServerTickListener.java rename to src/main/java/jesse/keeblarcraft/EventMgr/ServerTickListener.java index 4637cb3..25c4d3b 100644 --- a/src/main/java/jesse/keeblarcraft/Utils/ServerTickListener.java +++ b/src/main/java/jesse/keeblarcraft/EventMgr/ServerTickListener.java @@ -1,20 +1,21 @@ -package jesse.keeblarcraft.Utils; +package jesse.keeblarcraft.EventMgr; import jesse.CommonServerUtils; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; -//this lets get the MinecraftServer instance and also do stuff on the end of the tick if we wanted to +// This interface is responsible for the end tick of a server world event tick public class ServerTickListener implements ServerTickEvents.EndTick { CommonServerUtils config = new CommonServerUtils(); @Override public void onEndTick(MinecraftServer server) { - //Code that runs on end of each tick yes this actually works and tested - config.SetServerInstance(server); + if (server != null) { + config.SetServerInstance(server); + } } // Static method to register the server tick listener - public static void initialize() { + public static void InitializeServerTicks() { ServerTickEvents.END_SERVER_TICK.register(new ServerTickListener()); } } diff --git a/src/main/java/jesse/keeblarcraft/Keeblarcraft.java b/src/main/java/jesse/keeblarcraft/Keeblarcraft.java index d20f1ec..25b0318 100644 --- a/src/main/java/jesse/keeblarcraft/Keeblarcraft.java +++ b/src/main/java/jesse/keeblarcraft/Keeblarcraft.java @@ -11,14 +11,17 @@ package jesse.keeblarcraft; import net.fabricmc.api.ModInitializer; // import net.minecraft.server.command.ServerCommandSource; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jesse.keeblarcraft.AttributeMgr.AttributeMgr; +import jesse.keeblarcraft.AttributeMgr.AttributeTree; import jesse.keeblarcraft.Commands.CustomCommandManager; import jesse.keeblarcraft.CustomBlocks.BlockManager; import jesse.keeblarcraft.CustomItems.ItemManager; +import jesse.keeblarcraft.EventMgr.ServerTickListener; import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION; import jesse.keeblarcraft.Utils.ChatUtil; import jesse.keeblarcraft.Utils.Setup; @@ -28,9 +31,6 @@ import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR; public class Keeblarcraft implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. public static String MOD_ID = "keeblarcraft"; public static final Logger LOGGER = LoggerFactory.getLogger("keeblarcraft"); CustomCommandManager cmdMgr = new CustomCommandManager(); @@ -50,6 +50,29 @@ public class Keeblarcraft implements ModInitializer { LOGGER.info("\033[34m Running setup stage \033[0m"); setup.RunSetup(); + // This is a very special case where this must be in this classes' initializer + // method + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { + var player = handler.player; + Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged in. Creating tree..."); + + if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == false) { + AttributeMgr.activeTrees.put(player.getUuidAsString(), new AttributeTree(player.getUuidAsString())); + } + }); + + ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { + var player = handler.player; + Keeblarcraft.LOGGER.info("Player " + player.getName() + " has logged out. Deleting tree..."); + + if (AttributeMgr.activeTrees.containsKey(player.getUuidAsString()) == true) { + AttributeMgr.activeTrees.remove(player.getUuidAsString()); + } + }); + + // Initialize our ticks!! + ServerTickListener.InitializeServerTicks(); + // Run command registrations from the command manager LOGGER.info("\033[34m Running command registration \033[0m"); cmdMgr.RegisterCustomCommands(); diff --git a/src/main/java/jesse/keeblarcraft/Utils/Setup.java b/src/main/java/jesse/keeblarcraft/Utils/Setup.java index 1981fc2..1897695 100644 --- a/src/main/java/jesse/keeblarcraft/Utils/Setup.java +++ b/src/main/java/jesse/keeblarcraft/Utils/Setup.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.ArrayList; import jesse.keeblarcraft.ConfigMgr.ConfigManager; +import jesse.keeblarcraft.EventMgr.ServerTickListener; import jesse.keeblarcraft.Utils.ChatUtil.CONSOLE_COLOR; import jesse.keeblarcraft.Utils.CustomExceptions.DIRECTORY_CREATE_EXCEPTION; import jesse.keeblarcraft.Utils.CustomExceptions.SETUP_FAILED_EXCEPTION; @@ -155,21 +156,8 @@ public final class Setup { throw new SETUP_FAILED_EXCEPTION(); } - //testing for this - try { - onInitialize(); - } catch (Exception e){ - System.out.println(ChatUtil.ColoredString("servertick failed to inilize.", CONSOLE_COLOR.RED)); - throw new SETUP_FAILED_EXCEPTION(); - } - System.out.println(ChatUtil.ColoredString("DID SETUP COMPLETE SUCCESSFULLY? ", CONSOLE_COLOR.YELLOW) + (ret ? ChatUtil.ColoredString("YES", CONSOLE_COLOR.YELLOW) : ChatUtil.ColoredString("NO", CONSOLE_COLOR.YELLOW))); return ret; } - - public void onInitialize() { - // Call the setup file to register event listeners and other setup tasks - ServerTickListener.initialize(); - } }