Parcourir la source

Improved Command Structure, dungeon basis

Jan il y a 2 semaines
Parent
commit
1b05d38c59
23 fichiers modifiés avec 550 ajouts et 570 suppressions
  1. 2 1
      src/main/java/me/lethunderhawk/bazaarflux/service/Services.java
  2. 141 0
      src/main/java/me/lethunderhawk/bazaarflux/util/command/CustomCommand.java
  3. 11 3
      src/main/java/me/lethunderhawk/bazaarflux/util/interfaces/BazaarFluxModule.java
  4. 0 11
      src/main/java/me/lethunderhawk/clans/ClanModule.java
  5. 28 144
      src/main/java/me/lethunderhawk/clans/command/ClanCommand.java
  6. 1 1
      src/main/java/me/lethunderhawk/clans/gui/AdminMenuGUI.java
  7. 0 1
      src/main/java/me/lethunderhawk/custom/item/CustomItemModule.java
  8. 6 71
      src/main/java/me/lethunderhawk/custom/item/command/CustomItemCommand.java
  9. 6 6
      src/main/java/me/lethunderhawk/custom/item/concrete/ClaimTool.java
  10. 28 0
      src/main/java/me/lethunderhawk/dungeon/DungeonModule.java
  11. 34 0
      src/main/java/me/lethunderhawk/dungeon/command/DungeonCommand.java
  12. 136 0
      src/main/java/me/lethunderhawk/dungeon/generation/DungeonWorld.java
  13. 22 0
      src/main/java/me/lethunderhawk/dungeon/gui/DungeonGUI.java
  14. 102 0
      src/main/java/me/lethunderhawk/dungeon/manager/DungeonManager.java
  15. 0 12
      src/main/java/me/lethunderhawk/economy/EconomyModule.java
  16. 10 162
      src/main/java/me/lethunderhawk/economy/command/EcoCommand.java
  17. 2 21
      src/main/java/me/lethunderhawk/main/Main.java
  18. 0 1
      src/main/java/me/lethunderhawk/minion/MinionModule.java
  19. 5 120
      src/main/java/me/lethunderhawk/minion/command/MinionCommand.java
  20. 0 10
      src/main/java/me/lethunderhawk/tradeplugin/TradeModule.java
  21. 5 2
      src/main/java/me/lethunderhawk/tradeplugin/command/TradeAcceptCommand.java
  22. 7 4
      src/main/java/me/lethunderhawk/tradeplugin/command/TradeCommand.java
  23. 4 0
      src/main/resources/plugin.yml

+ 2 - 1
src/main/java/me/lethunderhawk/bazaarflux/service/Services.java

@@ -9,8 +9,9 @@ public final class Services {
 
     private static final Map<Class<?>, Object> services = new ConcurrentHashMap<>();
 
-    public static <T> void register(Class<T> type, T service) {
+    public static <T> T register(Class<T> type, T service) {
         services.put(type, service);
+        return service;
     }
     public static <T> void registerModule(Class<? extends BazaarFluxModule> type, T service) {
         services.put(type, service);

+ 141 - 0
src/main/java/me/lethunderhawk/bazaarflux/util/command/CustomCommand.java

@@ -0,0 +1,141 @@
+package me.lethunderhawk.bazaarflux.util.command;
+
+import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.TabCompleter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+public abstract class CustomCommand implements CommandExecutor, TabCompleter {
+
+    protected final CommandNode rootCommand;
+    protected final BazaarFluxModule module;
+    public CustomCommand(CommandNode rootCommand, BazaarFluxModule module) {
+        this.rootCommand = rootCommand;
+        this.module = module;
+        createHelpCommand();
+        createCommands();
+    }
+
+    private void createHelpCommand() {
+        rootCommand.addSubCommand(new CommandNode("help", "Displays this help menu", this::sendHelp));
+    }
+
+    public abstract void createCommands();
+
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+        if (args.length == 0) {
+            sendHelp(sender);
+            return true;
+        }
+
+        List<String> argList = new ArrayList<>(Arrays.asList(args));
+        CommandNode currentNode = rootCommand;
+        CommandNode targetNode = null;
+
+        // Traverse the command tree
+        while (!argList.isEmpty()) {
+            String nextArg = argList.get(0);
+            CommandNode nextNode = currentNode.getSubCommand(nextArg);
+
+            if (nextNode == null) {
+                // No matching subcommand found, use current node if it has an executor
+                targetNode = currentNode.getExecutor() != null ? currentNode : null;
+                break;
+            }
+
+            currentNode = nextNode;
+            argList.remove(0);
+
+            // If this is the last argument or node has no further subcommands
+            if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) {
+                targetNode = nextNode;
+                break;
+            }
+        }
+
+        if (targetNode == null) {
+            module.sendText(sender, Component.text("Unknown command. Use /" +rootCommand.getName() +" help for available commands.", NamedTextColor.RED));
+            return true;
+        }
+
+        if (targetNode.getExecutor() == null) {
+            module.sendText(sender,Component.text("This command requires additional arguments.", NamedTextColor.RED));
+            sendSubCommands(sender, targetNode);
+            return true;
+        }
+
+        // Execute the command with remaining arguments
+        String[] remainingArgs = argList.toArray(new String[0]);
+        targetNode.getExecutor().accept(sender, remainingArgs);
+        return true;
+    }
+    private void sendHelp(CommandSender sender, String[] strings) {
+        sendHelp(sender);
+    }
+    protected void sendHelp(CommandSender sender) {
+        sender.sendMessage("§6=== Available Commands ===");
+        for (CommandNode cmd : rootCommand.getSubCommands()) {
+            sender.sendMessage("/" + rootCommand.getName() + " " + cmd.getName() + " §7- " + cmd.getDescription());
+        }
+    }
+
+    private void sendSubCommands(CommandSender sender, CommandNode node) {
+        sender.sendMessage("§6Available subcommands:");
+        for (CommandNode subCmd : node.getSubCommands()) {
+            sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription());
+        }
+    }
+
+    public CommandNode registerCommand(String name, String description, BiConsumer<CommandSender, String[]> executor) {
+        return rootCommand.registerSubCommand(name, description, executor);
+    }
+
+    @Override
+    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
+        List<String> suggestions = new ArrayList<>();
+
+        if (args.length == 0) {
+            return suggestions;
+        }
+
+        // Start at root and traverse
+        CommandNode currentNode = rootCommand;
+        List<String> argList = new ArrayList<>(Arrays.asList(args));
+        String lastArg = args[args.length - 1].toLowerCase();
+
+        // Try to traverse as far as possible
+        for (int i = 0; i < argList.size() - 1; i++) {
+            String arg = argList.get(i);
+            CommandNode nextNode = currentNode.getSubCommand(arg);
+            if (nextNode == null) {
+                break;
+            }
+            currentNode = nextNode;
+        }
+
+        // Get suggestions from current node
+        if (currentNode.getTabCompleter() != null) {
+            suggestions.addAll(currentNode.getTabCompleter().apply(sender, args));
+        } else {
+            // Suggest subcommands
+            suggestions.addAll(currentNode.getSubCommandNames().stream()
+                    .filter(name -> name.toLowerCase().startsWith(lastArg))
+                    .collect(Collectors.toList()));
+        }
+
+        return suggestions;
+    }
+    public void reload(){
+        createCommands();
+    }
+}

+ 11 - 3
src/main/java/me/lethunderhawk/bazaarflux/util/interfaces/BazaarFluxModule.java

@@ -1,19 +1,27 @@
 package me.lethunderhawk.bazaarflux.util.interfaces;
 
+import me.lethunderhawk.bazaarflux.service.Services;
 import me.lethunderhawk.bazaarflux.util.MessageSender;
+import me.lethunderhawk.main.Main;
 import net.kyori.adventure.audience.Audience;
 import net.kyori.adventure.text.Component;
+import org.bukkit.command.CommandSender;
 import org.bukkit.plugin.java.JavaPlugin;
 
 public abstract class BazaarFluxModule{
     protected JavaPlugin plugin;
-    public BazaarFluxModule(JavaPlugin plugin) {
-        this.plugin = plugin;
+    public BazaarFluxModule() {
+        this.plugin = Services.get(Main.class);
     }
     public abstract String getPrefix();
     public abstract void onEnable();
     public abstract void onDisable();
-    void sendText(Audience receiver, Component infoText){
+    public void sendText(Audience receiver, Component infoText){
         MessageSender.sendText(receiver, infoText, getPrefix());
     }
+
+    public void reload(CommandSender sender, String[] strings) {
+        onDisable();
+        onEnable();
+    }
 }

+ 0 - 11
src/main/java/me/lethunderhawk/clans/ClanModule.java

@@ -1,22 +1,17 @@
 package me.lethunderhawk.clans;
 
 import me.lethunderhawk.bazaarflux.service.Services;
-import me.lethunderhawk.bazaarflux.util.MessageSender;
 import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
 import me.lethunderhawk.clans.claim.ClaimListener;
 import me.lethunderhawk.clans.claim.ClaimManager;
 import me.lethunderhawk.clans.command.ClanCommand;
 import me.lethunderhawk.clans.placeholder.ClanPlaceHolder;
 import me.lethunderhawk.main.Main;
-import net.kyori.adventure.audience.Audience;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.format.NamedTextColor;
 import org.bukkit.event.HandlerList;
 
 public class ClanModule extends BazaarFluxModule {
 
     public ClanModule() {
-        super(Services.get(Main.class));
     }
 
     public String getPrefix(){
@@ -46,12 +41,6 @@ public class ClanModule extends BazaarFluxModule {
         }
 
     }
-    public static void sendText(Audience receiver, String infoText){
-        MessageSender.sendText(receiver, Component.text(infoText, NamedTextColor.GRAY), "[Clan]");
-    }
-    public static void sendText(Audience receiver, Component infoText){
-        MessageSender.sendText(receiver, infoText, "[Clan]");
-    }
 
     public void onDisable(){
         HandlerList.unregisterAll(Services.get(ClaimListener.class));

+ 28 - 144
src/main/java/me/lethunderhawk/clans/command/ClanCommand.java

@@ -2,6 +2,7 @@ package me.lethunderhawk.clans.command;
 
 import me.lethunderhawk.bazaarflux.service.Services;
 import me.lethunderhawk.bazaarflux.util.command.CommandNode;
+import me.lethunderhawk.bazaarflux.util.command.CustomCommand;
 import me.lethunderhawk.bazaarflux.util.gui.InventoryManager;
 import me.lethunderhawk.clans.Clan;
 import me.lethunderhawk.clans.ClanManager;
@@ -15,32 +16,23 @@ import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.format.NamedTextColor;
 import net.kyori.adventure.text.format.TextDecoration;
 import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
 import org.bukkit.entity.Player;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.UUID;
-import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
-public class ClanCommand implements CommandExecutor, TabCompleter {
+public class ClanCommand extends CustomCommand{
     private final ClanManager manager;
-    private final CommandNode rootCommand;
 
     public ClanCommand(ClanManager manager) {
+        super(new CommandNode("clan", "Main clan command", null), Services.get(ClanModule.class));
         this.manager = manager;
-        this.rootCommand = new CommandNode("clan", "Main clan command", null);
-        setupDefaultCommands();
     }
-    private void setupDefaultCommands() {
-
+    @Override
+    public void createCommands() {
         registerCommand("list", "List all clans", this::handleList);
-        registerCommand("help", "Gives information about the use of clan commands", this::handleHelp);
         registerCommand("leave", "Leave your current clan", this::handleLeaveClan);
         registerCommand("reload", "Reload the clan Plugin", this::handleReload);
         registerCommand("members", "Show the members of your clan", this::handleShowMembers);
@@ -68,7 +60,7 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
     private void getClaimTool(CommandSender sender, String[] strings) {
         if(!(sender instanceof Player p)) return;
         p.getInventory().addItem(new ClaimTool(Services.get(Main.class)).createItem());
-        ClanModule.sendText(p, Component.text("The tool magically appears in your inventory! How convenient!"));
+        module.sendText(p, Component.text("The tool magically appears in your inventory! How convenient!"));
     }
 
     private void handleSave(CommandSender sender, String[] strings) {
@@ -86,14 +78,14 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
         UUID uuid = player.getUniqueId();
         Clan myClan = manager.getMyClan(uuid);
         if(myClan == null) return;
-        ClanModule.sendText(player, Component.text("List of all claims in clan " + myClan.getName(), NamedTextColor.GREEN, TextDecoration.UNDERLINED));
+        module.sendText(player, Component.text("List of all claims in clan " + myClan.getName(), NamedTextColor.GREEN, TextDecoration.UNDERLINED));
         for(Claim claim : myClan.getClaims()){
-            ClanModule.sendText(player, Component.text("Claim: " + claim.getName(), NamedTextColor.GOLD));
-            ClanModule.sendText(player, Component.text("This claim spans from X: " + claim.getMaxX() + " to X: " + claim.getMinX(), NamedTextColor.GRAY)
+            module.sendText(player, Component.text("Claim: " + claim.getName(), NamedTextColor.GOLD));
+            module.sendText(player, Component.text("This claim spans from X: " + claim.getMaxX() + " to X: " + claim.getMinX(), NamedTextColor.GRAY)
                     .appendNewline()
                     .append(Component.text( "        and from Z: " + claim.getMaxZ() + " to Z: " + claim.getMinZ(), NamedTextColor.GRAY)));
 
-            ClanModule.sendText(player, "Volume of this claim is " + claim.getVolume() + " Blocks");
+            module.sendText(player, Component.text("Volume of this claim is " + claim.getVolume() + " Blocks", NamedTextColor.GRAY));
         }
     }
 
@@ -114,9 +106,9 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
         UUID uuid = player.getUniqueId();
         Clan clan = manager.getMyClan(uuid);
         if(clan.denyRequest(uuid, strings[0])){
-            ClanModule.sendText(player, "You declined the request from " + strings[0] + ".");
+            module.sendText(player, Component.text("You declined the request from " + strings[0] + "."));
         }else{
-            ClanModule.sendText(player, "You are not the owner, or " + strings[0] + " hasn't requested to join your clan.");
+            module.sendText(player, Component.text("You are not the owner, or " + strings[0] + " hasn't requested to join your clan."));
         }
     }
 
@@ -125,9 +117,9 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
         UUID uuid = player.getUniqueId();
         Clan clan = manager.getMyClan(uuid);
         if(clan.acceptRequest(uuid, strings[0])){
-            ClanModule.sendText(player, "You accepted the request from " + strings[0] + ".");
+            module.sendText(player, Component.text("You accepted the request from " + strings[0] + "."));
         }else{
-            ClanModule.sendText(player, "You are not the owner, or " + strings[0] + " hasn't requested to join your clan.");
+            module.sendText(player, Component.text("You are not the owner, or " + strings[0] + " hasn't requested to join your clan."));
         }
 
     }
@@ -137,22 +129,22 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
         UUID uuid = player.getUniqueId();
         Clan clan = manager.getMyClan(uuid);
         if(clan == null) return;
-        ClanModule.sendText(player, "§6=== Clan Members - " + clan.getName() + " ===");
+        module.sendText(player, Component.text("§6=== Clan Members - " + clan.getName() + " ==="));
         Player owner = clan.getOwner();
-        ClanModule.sendText(player,
+        module.sendText(player,
                 Component.text("Owner: ", NamedTextColor.RED)
                 .append(Component.text(owner.getName(), NamedTextColor.GRAY)));
         for(UUID member : clan.getMembers()){
             Player p = Bukkit.getPlayer(member);
             if(p == null) continue;
-            ClanModule.sendText(player, p.getName());
+            module.sendText(player, Component.text(p.getName()));
         }
     }
 
     private void handleReload(CommandSender sender, String[] strings) {
         if(sender.isOp()) {
             reload();
-            ClanModule.sendText(sender, "Reloading...");
+            module.sendText(sender, Component.text("Reloading..."));
         }
     }
 
@@ -161,13 +153,13 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
         UUID uuid = player.getUniqueId();
         Clan clan = manager.getMyClan(uuid);
         if(manager.leaveClan(uuid)){
-            ClanModule.sendText(player,"You left your Clan ");
+            module.sendText(player,Component.text("You left your Clan "));
             if(clan.getOwner().equals(player)){
                 manager.removeClan(clan.getName());
-                ClanModule.sendText(player,"The clan was deleted since you are the only one left!");
+                module.sendText(player,Component.text("The clan was deleted since you are the only one left!"));
             }
         }else{
-            ClanModule.sendText(player,"You cannot leave this clan! Either join a clan or if you are an owner, please remove all members first!");
+            module.sendText(player,Component.text("You cannot leave this clan! Either join a clan or if you are an owner, please remove all members first!"));
         }
     }
 
@@ -185,132 +177,28 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
 
         String name = String.join("-", strings);
         if (manager.getMyClan(player.getUniqueId()) != null){
-            ClanModule.sendText(player,"You are already in a clan! Leave your clan first!");
+            module.sendText(player,Component.text("You are already in a clan! Leave your clan first!"));
             return;
         }
-        if(manager.createClan(player, name)) ClanModule.sendText(player,"Creating the Clan " + name + " ...");
-        else ClanModule.sendText(player,"The Name for the Clan " + name + " is already taken or you are already in a clan!");
-    }
-
-    // Helper method to easily register commands
-    public CommandNode registerCommand(String name, String description, BiConsumer<CommandSender, String[]> executor) {
-        return rootCommand.registerSubCommand(name, description, executor);
-    }
-
-    @Override
-    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (args.length == 0) {
-            sendHelp(sender);
-            return true;
-        }
-
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        CommandNode currentNode = rootCommand;
-        CommandNode targetNode = null;
-
-        // Traverse the command tree
-        while (!argList.isEmpty()) {
-            String nextArg = argList.get(0);
-            CommandNode nextNode = currentNode.getSubCommand(nextArg);
-
-            if (nextNode == null) {
-                // No matching subcommand found, use current node if it has an executor
-                targetNode = currentNode.getExecutor() != null ? currentNode : null;
-                break;
-            }
-
-            currentNode = nextNode;
-            argList.remove(0);
-
-            // If this is the last argument or node has no further subcommands
-            if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) {
-                targetNode = nextNode;
-                break;
-            }
-        }
-
-        if (targetNode == null) {
-            ClanModule.sendText(sender,"§cUnknown command. Use /clan help for available commands.");
-            return true;
-        }
-
-        if (targetNode.getExecutor() == null) {
-            ClanModule.sendText(sender,"§cThis command requires additional arguments.");
-            sendSubCommands(sender, targetNode);
-            return true;
-        }
-
-        // Execute the command with remaining arguments
-        String[] remainingArgs = argList.toArray(new String[0]);
-        targetNode.getExecutor().accept(sender, remainingArgs);
-        return true;
-    }
-
-    @Override
-    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
-        List<String> suggestions = new ArrayList<>();
-
-        if (args.length == 0) {
-            return suggestions;
-        }
-
-        // Start at root and traverse
-        CommandNode currentNode = rootCommand;
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        String lastArg = args[args.length - 1].toLowerCase();
-
-        // Try to traverse as far as possible
-        for (int i = 0; i < argList.size() - 1; i++) {
-            String arg = argList.get(i);
-            CommandNode nextNode = currentNode.getSubCommand(arg);
-            if (nextNode == null) {
-                break;
-            }
-            currentNode = nextNode;
-        }
-
-        // Get suggestions from current node
-        if (currentNode.getTabCompleter() != null) {
-            suggestions.addAll(currentNode.getTabCompleter().apply(sender, args));
-        } else {
-            // Suggest subcommands
-            suggestions.addAll(currentNode.getSubCommandNames().stream()
-                    .filter(name -> name.toLowerCase().startsWith(lastArg))
-                    .collect(Collectors.toList()));
-        }
-
-        return suggestions;
-    }
-
-    private void sendHelp(CommandSender sender) {
-        sender.sendMessage("§6=== Clan Commands ===");
-        for (CommandNode cmd : rootCommand.getSubCommands()) {
-            sender.sendMessage("§e/clan " + cmd.getName() + " §7- " + cmd.getDescription());
-        }
-    }
-
-    private void sendSubCommands(CommandSender sender, CommandNode node) {
-        sender.sendMessage("§6Available subcommands:");
-        for (CommandNode subCmd : node.getSubCommands()) {
-            sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription());
-        }
+        if(manager.createClan(player, name)) module.sendText(player,Component.text("Creating the Clan " + name + " ..."));
+        else module.sendText(player,Component.text("The Name for the Clan " + name + " is already taken or you are already in a clan!"));
     }
 
     // Example command handlers
     private void handleList(CommandSender sender, String[] args) {
-        ClanModule.sendText(sender,"Aktuelle Liste an Clans: ");
+        module.sendText(sender,Component.text("Aktuelle Liste an Clans: "));
         for (Clan clan : manager.getClans()) {
-            ClanModule.sendText(sender,clan.getName());
+            module.sendText(sender,Component.text(clan.getName()));
         }
     }
 
     private void handleJoin(CommandSender sender, String[] args) {
         if (!(sender instanceof Player player)) return;
         if (args.length < 1) {
-            ClanModule.sendText(sender,"Usage: /clan join <clan>");
+            module.sendText(sender,Component.text("Usage: /clan join <clan>"));
             return;
         }
-        if(manager.joinClan(player.getUniqueId(), args[0])) ClanModule.sendText(player, "Sent a request to join the clan " + args[0]);
+        if(manager.joinClan(player.getUniqueId(), args[0])) module.sendText(player, Component.text("Sent a request to join the clan " + args[0]));
     }
 
     private List<String> completeClans(CommandSender sender, String[] args) {
@@ -333,8 +221,4 @@ public class ClanCommand implements CommandExecutor, TabCompleter {
                 .filter(name -> name.toLowerCase().startsWith(partial))
                 .collect(Collectors.toList());
     }
-
-    private void reload() {
-        setupDefaultCommands();
-    }
 }

+ 1 - 1
src/main/java/me/lethunderhawk/clans/gui/AdminMenuGUI.java

@@ -41,7 +41,7 @@ public class AdminMenuGUI extends InventoryGUI {
             setItemWithClickAction(i, descriptor, (p, type) ->{
                 if(type == ClickType.RIGHT){
                     ConfirmationMenu menu = new ConfirmationMenu("Remove clan " + clan.getName(), (player) -> {
-                        ClanModule.sendText(player, "You removed the clan " + clan.getName());
+                        Services.get(ClanModule.class).sendText(player, Component.text("You removed the clan " + clan.getName()));
                         removeClan(clan);
                         openPrevious(player);
                     });

+ 0 - 1
src/main/java/me/lethunderhawk/custom/item/CustomItemModule.java

@@ -15,7 +15,6 @@ public class CustomItemModule extends BazaarFluxModule{
     private CustomItemListener listener;
 
     public CustomItemModule() {
-        super(Services.get(Main.class));
     }
     private void registerCustomItems(){
         itemManager.registerItem(new ClaimTool(plugin));

+ 6 - 71
src/main/java/me/lethunderhawk/custom/item/command/CustomItemCommand.java

@@ -1,33 +1,24 @@
 package me.lethunderhawk.custom.item.command;
 
 import me.lethunderhawk.bazaarflux.util.command.CommandNode;
+import me.lethunderhawk.bazaarflux.util.command.CustomCommand;
 import me.lethunderhawk.custom.item.CustomItemModule;
 import me.lethunderhawk.custom.item.abstraction.CustomItem;
 import me.lethunderhawk.custom.item.manager.CustomItemManager;
-import me.lethunderhawk.economy.EconomyModule;
 import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
 import org.bukkit.entity.Player;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
-public class CustomItemCommand implements CommandExecutor, TabCompleter {
+public class CustomItemCommand extends CustomCommand {
     private final CustomItemManager manager;
-    private final CommandNode rootCommand;
-    private final CustomItemModule module;
 
     public CustomItemCommand(CustomItemManager manager, CustomItemModule customItemModule) {
+        super(new CommandNode("customItems", "Main Custom Item Command", null), customItemModule);
         this.manager = manager;
-        this.module = customItemModule;
-        this.rootCommand = new CommandNode("customItems", "Main Custom Item Command", null);
-        CommandNode getAll = rootCommand.registerSubCommand("getAll", "Get all custom items", this::getAllItems);
-        CommandNode reload = rootCommand.registerSubCommand("reload", "Reload", module::reload);
     }
 
     private void getAllItems(CommandSender sender, String[] strings) {
@@ -40,65 +31,9 @@ public class CustomItemCommand implements CommandExecutor, TabCompleter {
     }
 
     @Override
-    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
-        if (args.length == 0) {
-            sendHelp(sender);
-            return true;
-        }
-
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        CommandNode currentNode = rootCommand;
-        CommandNode targetNode = null;
-
-        // Traverse the command tree
-        while (!argList.isEmpty()) {
-            String nextArg = argList.get(0);
-            CommandNode nextNode = currentNode.getSubCommand(nextArg);
-
-            if (nextNode == null) {
-                // No matching subcommand found, use current node if it has an executor
-                targetNode = currentNode.getExecutor() != null ? currentNode : null;
-                break;
-            }
-
-            currentNode = nextNode;
-            argList.remove(0);
-
-            // If this is the last argument or node has no further subcommands
-            if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) {
-                targetNode = nextNode;
-                break;
-            }
-        }
-
-        if (targetNode == null) {
-            EconomyModule.sendText(sender,"§cUnknown command. Use /customItem help for available commands.");
-            return true;
-        }
-
-        if (targetNode.getExecutor() == null) {
-            EconomyModule.sendText(sender,"§cThis command requires additional arguments.");
-            sendSubCommands(sender, targetNode);
-            return true;
-        }
-
-        // Execute the command with remaining arguments
-        String[] remainingArgs = argList.toArray(new String[0]);
-        targetNode.getExecutor().accept(sender, remainingArgs);
-        return true;
-    }
-    private void sendHelp(CommandSender sender) {
-        sender.sendMessage("§6=== Custom Item Commands ===");
-        for (CommandNode cmd : rootCommand.getSubCommands()) {
-            sender.sendMessage("§e/customItem " + cmd.getName() + " §7- " + cmd.getDescription());
-        }
-    }
-
-    private void sendSubCommands(CommandSender sender, CommandNode node) {
-        sender.sendMessage("§6Available subcommands:");
-        for (CommandNode subCmd : node.getSubCommands()) {
-            sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription());
-        }
+    public void createCommands() {
+        //rootCommand.registerSubCommand("getAll", "Get all custom items", this::getAllItems);
+        //rootCommand.registerSubCommand("reload", "Reload", module::reload);
     }
 
     @Override

+ 6 - 6
src/main/java/me/lethunderhawk/custom/item/concrete/ClaimTool.java

@@ -50,17 +50,17 @@ public class ClaimTool extends CustomItem {
         Block block = e.getClickedBlock();
         if(block == null) return;
         Location second = block.getLocation();
-
+        ClanModule module = Services.get(ClanModule.class);
         UUID uuid = p.getUniqueId();
         Clan clan = Services.get(ClanManager.class).getMyClan(uuid);
         if(clan == null){
             e.setCancelled(true);
-            ClanModule.sendText(p,"§cJoin a clan first!");
+            module.sendText(p,Component.text("Join a clan first!", NamedTextColor.RED));
             return;
         }
         if (!firstCorner.containsKey(uuid)) {
             firstCorner.put(uuid, second);
-            ClanModule.sendText(p,"§aFirst corner of your claim set.");
+            module.sendText(p,Component.text("First corner of your claim set.", NamedTextColor.GREEN));
         } else {
             Location first = firstCorner.remove(uuid);
 
@@ -79,7 +79,7 @@ public class ClaimTool extends CustomItem {
                 Clan overlappingClan = Services.get(ClanManager.class).getClanById(overlapping.getClanId());
 
                 if (overlappingClan != null) {
-                    ClanModule.sendText(p,"§cThis area is overlapping with already claimed land from Clan " + overlappingClan.getName() + ".");
+                    module.sendText(p,Component.text("This area is overlapping with already claimed land from Clan " + overlappingClan.getName() + ".", NamedTextColor.RED));
                     e.setCancelled(true);
                     return;
                 }
@@ -88,8 +88,8 @@ public class ClaimTool extends CustomItem {
 
             Services.get(ClaimManager.class).registerClaim(claim);
             clan.addClaim(claim);
-            ClanModule.sendText(p,"§aSecond corner set.");
-            ClanModule.sendText(p,"§aClaim created.");
+            module.sendText(p,Component.text("Second corner set.", NamedTextColor.GREEN));
+            module.sendText(p,Component.text("Claim created.", NamedTextColor.GREEN));
         }
 
         e.setCancelled(true);

+ 28 - 0
src/main/java/me/lethunderhawk/dungeon/DungeonModule.java

@@ -0,0 +1,28 @@
+package me.lethunderhawk.dungeon;
+
+import me.lethunderhawk.bazaarflux.service.Services;
+import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
+import me.lethunderhawk.dungeon.command.DungeonCommand;
+import me.lethunderhawk.main.Main;
+
+public class DungeonModule extends BazaarFluxModule {
+
+    @Override
+    public String getPrefix() {
+        return "[Dungeons] ";
+    }
+
+    @Override
+    public void onEnable() {
+
+        Main mainPlugin = Services.get(Main.class);
+
+        mainPlugin.getCommand("dungeon").setExecutor(new DungeonCommand());
+        mainPlugin.getCommand("dungeon").setTabCompleter(new DungeonCommand());
+    }
+
+    @Override
+    public void onDisable() {
+
+    }
+}

+ 34 - 0
src/main/java/me/lethunderhawk/dungeon/command/DungeonCommand.java

@@ -0,0 +1,34 @@
+package me.lethunderhawk.dungeon.command;
+
+import me.lethunderhawk.bazaarflux.service.Services;
+import me.lethunderhawk.bazaarflux.util.command.CommandNode;
+import me.lethunderhawk.bazaarflux.util.command.CustomCommand;
+import me.lethunderhawk.dungeon.DungeonModule;
+import me.lethunderhawk.dungeon.generation.DungeonWorld;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class DungeonCommand extends CustomCommand {
+    public DungeonCommand() {
+        super(new CommandNode("dungeon", "Main Dungeon command", null), Services.get(DungeonModule.class));
+    }
+
+    @Override
+    public void createCommands() {
+        registerCommand("test", "creates a test instance of a dungeon and teleports you there", this::testDungeon);
+        registerCommand("back", "go back to the world you were previously in", this::backFromDungeon);
+    }
+    private void backFromDungeon(CommandSender sender, String[] strings) {
+        if(!(sender instanceof Player pl)) return;
+
+        DungeonWorld world = new DungeonWorld();
+        world.createWorld();
+        world.sendPlayerToDungeon(pl);
+    }
+    private void testDungeon(CommandSender sender, String[] strings) {
+        if(!(sender instanceof Player pl)) return;
+        DungeonWorld world = new DungeonWorld();
+        world.createWorld();
+        world.sendPlayerToDungeon(pl);
+    }
+}

+ 136 - 0
src/main/java/me/lethunderhawk/dungeon/generation/DungeonWorld.java

@@ -0,0 +1,136 @@
+package me.lethunderhawk.dungeon.generation;
+
+import me.lethunderhawk.bazaarflux.service.Services;
+import me.lethunderhawk.main.Main;
+import org.bukkit.*;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.generator.ChunkGenerator;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.*;
+
+public class DungeonWorld implements Listener {
+
+    private final JavaPlugin plugin;
+    private World world;
+    private UUID uuid;
+
+    // Tracks where players came from
+    private final Map<UUID, Location> returnLocations = new HashMap<>();
+
+    public DungeonWorld() {
+        this.plugin = Services.get(Main.class);
+        this.uuid  = UUID.randomUUID();
+
+        Bukkit.getPluginManager().registerEvents(this, plugin);
+    }
+
+    /* =========================
+       WORLD CREATION
+       ========================= */
+
+    public void createWorld() {
+        if (Bukkit.getWorld(uuid.toString()) != null) {
+            world = Bukkit.getWorld(uuid.toString());
+            return;
+        }
+
+        WorldCreator creator = new WorldCreator(uuid.toString());
+        creator.environment(World.Environment.NORMAL);
+        creator.type(WorldType.FLAT);
+        creator.generator(new EmptyChunkGenerator());
+
+        world = creator.createWorld();
+
+        if (world == null) {
+            throw new IllegalStateException("Failed to create dungeon world");
+        }
+
+        world.setGameRule(GameRule.KEEP_INVENTORY, true);
+        world.setGameRule(GameRule.DO_MOB_SPAWNING, false);
+        world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
+        world.setTime(18000);
+
+        // Hook: start dungeon generation async/sync later
+        startDungeonGeneration();
+    }
+
+    private void startDungeonGeneration() {
+        // NOT IMPLEMENTED
+        // This is where you queue structure generation, rooms, corridors, etc.
+    }
+
+    /* =========================
+       PLAYER HANDLING
+       ========================= */
+
+    public void sendPlayerToDungeon(Player player) {
+        if (world == null) {
+            throw new IllegalStateException("Dungeon world not created");
+        }
+
+        // Save return location
+        returnLocations.put(player.getUniqueId(), player.getLocation());
+
+        Location spawn = new Location(world, 0.5, 100, 0.5);
+        player.teleport(spawn);
+    }
+
+    public void returnPlayer(Player player) {
+        Location returnLoc = returnLocations.remove(player.getUniqueId());
+        if (returnLoc != null) {
+            player.teleport(returnLoc);
+        }
+    }
+
+    public boolean isInDungeon(Player player) {
+        return player.getWorld().equals(world);
+    }
+
+    /* =========================
+       DEATH HANDLING
+       ========================= */
+
+    @EventHandler
+    public void onPlayerDeath(PlayerDeathEvent event) {
+        Player player = event.getEntity();
+
+        if (!isInDungeon(player)) return;
+
+        // Delay teleport to avoid respawn conflicts
+        Bukkit.getScheduler().runTask(plugin, () -> returnPlayer(player));
+    }
+
+    public UUID getUUID() {
+        return uuid;
+    }
+
+    public void returnAllPlayers() {
+        for (UUID playerUUID : new HashSet<>(returnLocations.keySet())) {
+            Player player = Bukkit.getPlayer(playerUUID);
+            if (player == null) continue;
+
+            Bukkit.getScheduler().runTask(plugin, () -> returnPlayer(player));
+        }
+    }
+
+    /* =========================
+       EMPTY WORLD GENERATOR
+       ========================= */
+
+    private static class EmptyChunkGenerator extends ChunkGenerator {
+        @Override
+        public ChunkData generateChunkData(
+                World world,
+                Random random,
+                int chunkX,
+                int chunkZ,
+                BiomeGrid biome
+        ) {
+            return createChunkData(world);
+        }
+    }
+}

+ 22 - 0
src/main/java/me/lethunderhawk/dungeon/gui/DungeonGUI.java

@@ -0,0 +1,22 @@
+package me.lethunderhawk.dungeon.gui;
+
+import me.lethunderhawk.bazaarflux.util.gui.InventoryGUI;
+
+public class DungeonGUI extends InventoryGUI {
+
+    public DungeonGUI() {
+        super("Dungeon Browser", 36);
+        buildItems();
+    }
+
+    private void buildItems() {
+        fillGlassPaneBackground();
+        setCloseButton(31);
+
+    }
+
+    @Override
+    public void update() {
+
+    }
+}

+ 102 - 0
src/main/java/me/lethunderhawk/dungeon/manager/DungeonManager.java

@@ -0,0 +1,102 @@
+package me.lethunderhawk.dungeon.manager;
+
+import me.lethunderhawk.dungeon.generation.DungeonWorld;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.io.File;
+import java.util.*;
+
+public class DungeonManager {
+
+    private final JavaPlugin plugin;
+
+    // dungeonUUID -> DungeonWorld
+    private final Map<UUID, DungeonWorld> activeDungeons = new HashMap<>();
+
+    public DungeonManager(JavaPlugin plugin) {
+        this.plugin = plugin;
+    }
+
+    /* =========================
+       CREATION
+       ========================= */
+
+    public DungeonWorld createDungeon() {
+        DungeonWorld dungeon = new DungeonWorld();
+        dungeon.createWorld();
+
+        activeDungeons.put(dungeon.getUUID(), dungeon);
+        return dungeon;
+    }
+
+    /* =========================
+       SINGLE DUNGEON DELETION
+       ========================= */
+
+    public void deleteDungeon(UUID dungeonUUID) {
+        DungeonWorld dungeon = activeDungeons.remove(dungeonUUID);
+        if (dungeon == null) return;
+
+        World world = Bukkit.getWorld(dungeonUUID.toString());
+        if (world == null) return;
+
+        // Return all players safely
+        dungeon.returnAllPlayers();
+
+        // Kick any remaining players as a fallback
+        for (Player player : world.getPlayers()) {
+            player.teleport(Bukkit.getWorlds().get(0).getSpawnLocation());
+        }
+
+        Bukkit.unloadWorld(world, false);
+        deleteWorldFolder(world.getWorldFolder());
+    }
+
+    /* =========================
+       GLOBAL CLEANUP (onDisable)
+       ========================= */
+
+    public void deleteAllDungeons() {
+        // Copy to avoid ConcurrentModificationException
+        List<UUID> dungeonIds = new ArrayList<>(activeDungeons.keySet());
+
+        for (UUID uuid : dungeonIds) {
+            deleteDungeon(uuid);
+        }
+
+        activeDungeons.clear();
+    }
+
+    /* =========================
+       LOOKUPS
+       ========================= */
+
+    public DungeonWorld getDungeon(UUID uuid) {
+        return activeDungeons.get(uuid);
+    }
+
+    public boolean isDungeonWorld(World world) {
+        if (world == null) return false;
+        return activeDungeons.containsKey(UUID.fromString(world.getName()));
+    }
+
+    /* =========================
+       FILE DELETION
+       ========================= */
+
+    private void deleteWorldFolder(File folder) {
+        if (folder == null || !folder.exists()) return;
+
+        File[] files = folder.listFiles();
+        if (files != null) {
+            for (File file : files) {
+                deleteWorldFolder(file);
+            }
+        }
+
+        folder.delete();
+    }
+}

+ 0 - 12
src/main/java/me/lethunderhawk/economy/EconomyModule.java

@@ -1,7 +1,6 @@
 package me.lethunderhawk.economy;
 
 import me.lethunderhawk.bazaarflux.service.Services;
-import me.lethunderhawk.bazaarflux.util.MessageSender;
 import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
 import me.lethunderhawk.economy.api.EconomyAPI;
 import me.lethunderhawk.economy.api.EconomyPlaceholder;
@@ -9,10 +8,7 @@ import me.lethunderhawk.economy.command.EcoCommand;
 import me.lethunderhawk.economy.currency.EconomyManager;
 import me.lethunderhawk.economy.listener.PlayerJoinListener;
 import me.lethunderhawk.economy.scoreboard.ScoreboardManager;
-import me.lethunderhawk.main.Main;
 import me.lethunderhawk.tradeplugin.api.TradePlaceholder;
-import net.kyori.adventure.audience.Audience;
-import net.kyori.adventure.text.Component;
 import org.bukkit.plugin.java.JavaPlugin;
 
 public class EconomyModule extends BazaarFluxModule {
@@ -20,7 +16,6 @@ public class EconomyModule extends BazaarFluxModule {
     private EconomyAPI economyAPI;
     private ScoreboardManager scoreboardManager;
     public EconomyModule() {
-        super(Services.get(Main.class));
     }
 
     @Override
@@ -54,13 +49,6 @@ public class EconomyModule extends BazaarFluxModule {
     public void onDisable() {
 
     }
-
-    public static void sendText(Audience receiver, Component infoText){
-        MessageSender.sendText(receiver, infoText, "[Eco]");
-    }
-    public static void sendText(Audience receiver, String infoText){
-        MessageSender.sendText(receiver, Component.text(infoText), "[Eco]");
-    }
     public void reload(){
         scoreboardManager.reload();
     }

+ 10 - 162
src/main/java/me/lethunderhawk/economy/command/EcoCommand.java

@@ -1,37 +1,29 @@
 package me.lethunderhawk.economy.command;
 
 import me.lethunderhawk.bazaarflux.util.command.CommandNode;
+import me.lethunderhawk.bazaarflux.util.command.CustomCommand;
 import me.lethunderhawk.economy.EconomyModule;
 import me.lethunderhawk.economy.api.EconomyAPI;
 import net.kyori.adventure.text.Component;
 import net.kyori.adventure.text.format.NamedTextColor;
 import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
 import org.bukkit.entity.Player;
 
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
-public class EcoCommand implements CommandExecutor, TabCompleter {
+public class EcoCommand extends CustomCommand {
     private static final List<String> AMOUNTS = List.of("1", "5", "10", "50", "100", "500", "1000");
     private final EconomyModule module;
-    private final CommandNode rootCommand;
 
     public EcoCommand(EconomyModule module) {
+        super(new CommandNode("eco", "Main economy command", null), module);
         this.module = module;
-        this.rootCommand = new CommandNode("eco", "Main economy command", null);
-        setupDefaultCommands();
     }
-
-    private void setupDefaultCommands() {
-        registerCommand("help", "Get a list of available commands", this::sendHelp);
+    @Override
+    public void createCommands() {
         CommandNode set = registerCommand("set", "Set the balance of a player", this::setEco);
         set.setTabCompleter(this::completeAllEcoCommands);
 
@@ -74,10 +66,11 @@ public class EcoCommand implements CommandExecutor, TabCompleter {
 
     private void getBalance(CommandSender commandSender, String[] strings) {
         Player target = Bukkit.getPlayer(strings[0]);
+
         if (target == null) {
-            EconomyModule.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
+            module.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
         }else{
-            EconomyModule.sendText(commandSender, Component.text("Spieler " + target.getName() + " hat " + getAPI().getMoney(target.getUniqueId()),  NamedTextColor.GRAY));
+            module.sendText(commandSender, Component.text("Spieler " + target.getName() + " hat " + getAPI().getMoney(target.getUniqueId()),  NamedTextColor.GRAY));
         }
     }
 
@@ -88,7 +81,7 @@ public class EcoCommand implements CommandExecutor, TabCompleter {
         if(!commandSender.isOp()) return;
         Player target = Bukkit.getPlayer(strings[0]);
         if (target == null) {
-            EconomyModule.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
+            module.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
         }else{
             getAPI().addMoney(target.getUniqueId(), Long.parseLong(strings[1]));
         }
@@ -98,7 +91,7 @@ public class EcoCommand implements CommandExecutor, TabCompleter {
         if(!commandSender.isOp()) return;
         Player target = Bukkit.getPlayer(strings[0]);
         if (target == null) {
-            EconomyModule.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
+            module.sendText(commandSender, Component.text("Spieler nicht gefunden.",  NamedTextColor.RED));
         }else{
             getAPI().setMoney(target.getUniqueId(), Long.parseLong(strings[1]));
         }
@@ -107,150 +100,5 @@ public class EcoCommand implements CommandExecutor, TabCompleter {
         return module.getEconomyAPI();
     }
 
-    public CommandNode registerCommand(String name, String description, BiConsumer<CommandSender, String[]> executor) {
-        return rootCommand.registerSubCommand(name, description, executor);
-    }
-
-    @Override
-    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (args.length == 0) {
-            sendHelp(sender, args);
-            return true;
-        }
-
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        CommandNode currentNode = rootCommand;
-        CommandNode targetNode = null;
-
-        // Traverse the command tree
-        while (!argList.isEmpty()) {
-            String nextArg = argList.get(0);
-            CommandNode nextNode = currentNode.getSubCommand(nextArg);
 
-            if (nextNode == null) {
-                // No matching subcommand found, use current node if it has an executor
-                targetNode = currentNode.getExecutor() != null ? currentNode : null;
-                break;
-            }
-
-            currentNode = nextNode;
-            argList.remove(0);
-
-            // If this is the last argument or node has no further subcommands
-            if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) {
-                targetNode = nextNode;
-                break;
-            }
-        }
-
-        if (targetNode == null) {
-            EconomyModule.sendText(sender,"§cUnknown command. Use /eco help for available commands.");
-            return true;
-        }
-
-        if (targetNode.getExecutor() == null) {
-            EconomyModule.sendText(sender,"§cThis command requires additional arguments.");
-            sendSubCommands(sender, targetNode);
-            return true;
-        }
-
-        // Execute the command with remaining arguments
-        String[] remainingArgs = argList.toArray(new String[0]);
-        targetNode.getExecutor().accept(sender, remainingArgs);
-        return true;
-    }
-    private void sendHelp(CommandSender sender, String[] strings) {
-        sender.sendMessage("§6=== Eco Commands ===");
-        for (CommandNode cmd : rootCommand.getSubCommands()) {
-            sender.sendMessage("§e/eco " + cmd.getName() + " §7- " + cmd.getDescription());
-        }
-    }
-
-    private void sendSubCommands(CommandSender sender, CommandNode node) {
-        sender.sendMessage("§6Available subcommands:");
-        for (CommandNode subCmd : node.getSubCommands()) {
-            sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription());
-        }
-    }/*
-    @Override
-    public boolean onCommand(CommandSender s, Command cmd, String label, String[] args) {
-
-        String mode = args[0].toLowerCase();
-        if (args.length < 3 && ! (mode.equals("get") || mode.equals("reload"))) {
-            s.sendMessage("/eco <set|add|remove|get> <player> <amount>");
-            return true;
-        }
-        if(mode.equals("reload")){
-            module.reload();
-            s.sendMessage("Reloading...");
-            return true;
-        }
-        Player target = Bukkit.getPlayer(args[1]);
-        if (target == null) {
-            s.sendMessage("Spieler nicht gefunden.");
-            return true;
-        }
-
-        EconomyAPI api = module.getEconomyAPI();
-
-        switch (mode) {
-            case "set":
-                api.setMoney(target.getUniqueId(), Integer.parseInt(args[2]));
-                s.sendMessage("Flux gesetzt: " + Integer.parseInt(args[2]));
-                break;
-
-            case "add":
-                api.addMoney(target.getUniqueId(), Integer.parseInt(args[2]));
-                s.sendMessage(Integer.parseInt(args[2]) + " Flux hinzugefügt: " + api.getMoney(target.getUniqueId()));
-                break;
-
-            case "remove":
-                api.removeMoney(target.getUniqueId(), Integer.parseInt(args[2]));
-                s.sendMessage(Integer.parseInt(args[2]) + " Flux entfernt: " + api.getMoney(target.getUniqueId()));
-                break;
-
-            case "get":
-                s.sendMessage("Flux: " + api.getMoney(target.getUniqueId()));
-                break;
-            default:
-                s.sendMessage("Ungültiger Modus.");
-        }
-
-        return true;
-    }*/
-    @Override
-    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
-        List<String> suggestions = new ArrayList<>();
-
-        if (args.length == 0) {
-            return suggestions;
-        }
-
-        // Start at root and traverse
-        CommandNode currentNode = rootCommand;
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        String lastArg = args[args.length - 1].toLowerCase();
-
-        // Try to traverse as far as possible
-        for (int i = 0; i < argList.size() - 1; i++) {
-            String arg = argList.get(i);
-            CommandNode nextNode = currentNode.getSubCommand(arg);
-            if (nextNode == null) {
-                break;
-            }
-            currentNode = nextNode;
-        }
-
-        // Get suggestions from current node
-        if (currentNode.getTabCompleter() != null) {
-            suggestions.addAll(currentNode.getTabCompleter().apply(sender, args));
-        } else {
-            // Suggest subcommands
-            suggestions.addAll(currentNode.getSubCommandNames().stream()
-                    .filter(name -> name.toLowerCase().startsWith(lastArg))
-                    .collect(Collectors.toList()));
-        }
-
-        return suggestions;
-    }
 }

+ 2 - 21
src/main/java/me/lethunderhawk/main/Main.java

@@ -5,6 +5,7 @@ import me.lethunderhawk.bazaarflux.util.gui.InventoryManager;
 import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
 import me.lethunderhawk.clans.ClanModule;
 import me.lethunderhawk.custom.item.CustomItemModule;
+import me.lethunderhawk.dungeon.DungeonModule;
 import me.lethunderhawk.economy.EconomyModule;
 import me.lethunderhawk.minion.MinionModule;
 import me.lethunderhawk.tradeplugin.TradeModule;
@@ -21,27 +22,7 @@ public class Main extends JavaPlugin{
         Services.register(Main.class, this);
 
         InventoryManager.register(this);
-        registerAllModules(new CustomItemModule(), new TradeModule(), new ClanModule(), new EconomyModule(), new MinionModule());
-
-        /*CustomItemModule customItemModule = new CustomItemModule();
-        customItemModule.onEnable();
-        Services.register(CustomItemModule.class, customItemModule);
-
-        TradeModule tradeModule = new TradeModule();
-        tradeModule.onEnable();
-        Services.register(TradeModule.class, tradeModule);
-
-        ClanModule clanModule = new ClanModule();
-        clanModule.onEnable();
-        Services.register(ClanModule.class, clanModule);
-
-        EconomyModule economyModule = new EconomyModule();
-        economyModule.onEnable();
-        Services.register(EconomyModule.class, economyModule);
-
-        MinionModule minionModule = new MinionModule();
-        minionModule.onEnable();
-        Services.register(MinionModule.class, minionModule);*/
+        registerAllModules(new CustomItemModule(), new TradeModule(), new ClanModule(), new EconomyModule(), new MinionModule(), new DungeonModule());
     }
     private void registerAllModules(BazaarFluxModule... modules){
         for(BazaarFluxModule module : modules){

+ 0 - 1
src/main/java/me/lethunderhawk/minion/MinionModule.java

@@ -34,7 +34,6 @@ public class MinionModule extends BazaarFluxModule {
     private RecipeManager recipeManager;
 
     public MinionModule() {
-        super(Services.get(Main.class));
     }
 
     @Override

+ 5 - 120
src/main/java/me/lethunderhawk/minion/command/MinionCommand.java

@@ -1,37 +1,26 @@
 package me.lethunderhawk.minion.command;
 
 import me.lethunderhawk.bazaarflux.util.command.CommandNode;
+import me.lethunderhawk.bazaarflux.util.command.CustomCommand;
 import me.lethunderhawk.bazaarflux.util.gui.InventoryManager;
-import me.lethunderhawk.clans.ClanModule;
 import me.lethunderhawk.minion.MinionModule;
 import me.lethunderhawk.minion.manager.MinionManager;
 import me.lethunderhawk.minion.ui.minionList.MinionLevelListMenu;
 import me.lethunderhawk.minion.ui.minionList.MinionListMenu;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.BiConsumer;
-import java.util.stream.Collectors;
+public class MinionCommand extends CustomCommand {
 
-public class MinionCommand implements CommandExecutor, TabCompleter {
-
-    private final CommandNode rootCommand;
     private final MinionModule module;
 
     public MinionCommand(MinionModule minionModule) {
+        super(new CommandNode("clan", "Main clan command", null), minionModule);
         this.module = minionModule;
-        this.rootCommand = new CommandNode("clan", "Main clan command", null);
-        setupDefaultCommands();
     }
-
-    private void setupDefaultCommands() {
+    @Override
+    public void createCommands() {
         registerCommand("all", "get all minions", this::getAll);
         registerCommand("reload", "reload", this::reload);
         registerCommand("removeAll", "remove all minions", this::removeAll);
@@ -68,108 +57,4 @@ public class MinionCommand implements CommandExecutor, TabCompleter {
             p.getInventory().addItem(minion);
         }
     }
-
-    // Helper method to easily register commands
-    public CommandNode registerCommand(String name, String description, BiConsumer<CommandSender, String[]> executor) {
-        return rootCommand.registerSubCommand(name, description, executor);
-    }
-
-    @Override
-    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
-        if (args.length == 0) {
-            sendHelp(sender);
-            return true;
-        }
-
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        CommandNode currentNode = rootCommand;
-        CommandNode targetNode = null;
-
-        // Traverse the command tree
-        while (!argList.isEmpty()) {
-            String nextArg = argList.get(0);
-            CommandNode nextNode = currentNode.getSubCommand(nextArg);
-
-            if (nextNode == null) {
-                // No matching subcommand found, use current node if it has an executor
-                targetNode = currentNode.getExecutor() != null ? currentNode : null;
-                break;
-            }
-
-            currentNode = nextNode;
-            argList.remove(0);
-
-            // If this is the last argument or node has no further subcommands
-            if (argList.isEmpty() || nextNode.getSubCommands().isEmpty()) {
-                targetNode = nextNode;
-                break;
-            }
-        }
-
-        if (targetNode == null) {
-            ClanModule.sendText(sender,"§cUnknown command. Use /minion help for available commands.");
-            return true;
-        }
-
-        if (targetNode.getExecutor() == null) {
-            ClanModule.sendText(sender,"§cThis command requires additional arguments.");
-            sendSubCommands(sender, targetNode);
-            return true;
-        }
-
-        // Execute the command with remaining arguments
-        String[] remainingArgs = argList.toArray(new String[0]);
-        targetNode.getExecutor().accept(sender, remainingArgs);
-        return true;
-    }
-
-    @Override
-    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
-        List<String> suggestions = new ArrayList<>();
-
-        if (args.length == 0) {
-            return suggestions;
-        }
-
-        // Start at root and traverse
-        CommandNode currentNode = rootCommand;
-        List<String> argList = new ArrayList<>(Arrays.asList(args));
-        String lastArg = args[args.length - 1].toLowerCase();
-
-        // Try to traverse as far as possible
-        for (int i = 0; i < argList.size() - 1; i++) {
-            String arg = argList.get(i);
-            CommandNode nextNode = currentNode.getSubCommand(arg);
-            if (nextNode == null) {
-                break;
-            }
-            currentNode = nextNode;
-        }
-
-        // Get suggestions from current node
-        if (currentNode.getTabCompleter() != null) {
-            suggestions.addAll(currentNode.getTabCompleter().apply(sender, args));
-        } else {
-            // Suggest subcommands
-            suggestions.addAll(currentNode.getSubCommandNames().stream()
-                    .filter(name -> name.toLowerCase().startsWith(lastArg))
-                    .collect(Collectors.toList()));
-        }
-
-        return suggestions;
-    }
-
-    private void sendHelp(CommandSender sender) {
-        sender.sendMessage("§6=== Minion Commands ===");
-        for (CommandNode cmd : rootCommand.getSubCommands()) {
-            sender.sendMessage("§e/minion " + cmd.getName() + " §7- " + cmd.getDescription());
-        }
-    }
-
-    private void sendSubCommands(CommandSender sender, CommandNode node) {
-        sender.sendMessage("§6Available subcommands:");
-        for (CommandNode subCmd : node.getSubCommands()) {
-            sender.sendMessage("§e" + subCmd.getName() + " §7- " + subCmd.getDescription());
-        }
-    }
 }

+ 0 - 10
src/main/java/me/lethunderhawk/tradeplugin/TradeModule.java

@@ -1,17 +1,12 @@
 package me.lethunderhawk.tradeplugin;
 
-import me.lethunderhawk.bazaarflux.service.Services;
-import me.lethunderhawk.bazaarflux.util.MessageSender;
 import me.lethunderhawk.bazaarflux.util.interfaces.BazaarFluxModule;
-import me.lethunderhawk.main.Main;
 import me.lethunderhawk.tradeplugin.command.TradeAcceptCommand;
 import me.lethunderhawk.tradeplugin.command.TradeCommand;
 import me.lethunderhawk.tradeplugin.listener.PlayerInteractListener;
 import me.lethunderhawk.tradeplugin.listener.TradeInventoryListener;
 import me.lethunderhawk.tradeplugin.trade.TradeManager;
 import me.lethunderhawk.tradeplugin.trade.TradeRequestManager;
-import net.kyori.adventure.audience.Audience;
-import net.kyori.adventure.text.Component;
 
 public class TradeModule extends BazaarFluxModule {
 
@@ -19,7 +14,6 @@ public class TradeModule extends BazaarFluxModule {
     private static TradeRequestManager requestManager;
 
     public TradeModule() {
-        super(Services.get(Main.class));
     }
 
     @Override
@@ -43,10 +37,6 @@ public class TradeModule extends BazaarFluxModule {
 
     }
 
-    public static void sendText(Audience receiver, Component infoText){
-        MessageSender.sendText(receiver, infoText, "[Trade]");
-    }
-
     public static TradeManager getTradeManager() {
         return tradeManager;
     }

+ 5 - 2
src/main/java/me/lethunderhawk/tradeplugin/command/TradeAcceptCommand.java

@@ -1,5 +1,6 @@
 package me.lethunderhawk.tradeplugin.command;
 
+import me.lethunderhawk.bazaarflux.service.Services;
 import me.lethunderhawk.tradeplugin.TradeModule;
 import me.lethunderhawk.tradeplugin.trade.TradeManager;
 import me.lethunderhawk.tradeplugin.trade.TradeRequestManager;
@@ -15,10 +16,12 @@ public class TradeAcceptCommand implements CommandExecutor {
 
     private final TradeRequestManager requestManager;
     private final TradeManager tradeManager;
+    private final TradeModule tradeModule;
 
     public TradeAcceptCommand() {
         this.requestManager = TradeModule.getRequestManager();
         this.tradeManager = TradeModule.getTradeManager();
+        this.tradeModule = Services.get(TradeModule.class);
     }
 
     @Override
@@ -29,12 +32,12 @@ public class TradeAcceptCommand implements CommandExecutor {
 
         Player requester = Bukkit.getPlayerExact(args[0]);
         if (requester == null) {
-            TradeModule.sendText(target, Component.text("Spieler ist nicht online.",  NamedTextColor.RED));
+            tradeModule.sendText(target, Component.text("Spieler ist nicht online.",  NamedTextColor.RED));
             return true;
         }
 
         if (!requestManager.isPending(target, requester)) {
-            TradeModule.sendText(target, Component.text("Keine Anfrage von diesem Spieler offen.",  NamedTextColor.RED));
+            tradeModule.sendText(target, Component.text("Keine Anfrage von diesem Spieler offen.",  NamedTextColor.RED));
             return true;
         }
 

+ 7 - 4
src/main/java/me/lethunderhawk/tradeplugin/command/TradeCommand.java

@@ -1,5 +1,6 @@
 package me.lethunderhawk.tradeplugin.command;
 
+import me.lethunderhawk.bazaarflux.service.Services;
 import me.lethunderhawk.tradeplugin.TradeModule;
 import me.lethunderhawk.tradeplugin.trade.TradeManager;
 import me.lethunderhawk.tradeplugin.trade.TradeRequestManager;
@@ -15,10 +16,12 @@ public class TradeCommand implements CommandExecutor {
 
     private final TradeManager tradeManager;
     private final TradeRequestManager requestManager;
+    private final TradeModule tradeModule;
 
     public TradeCommand() {
         this.tradeManager = TradeModule.getTradeManager();
         this.requestManager = TradeModule.getRequestManager();
+        this.tradeModule = Services.get(TradeModule.class);
     }
 
     @Override
@@ -26,23 +29,23 @@ public class TradeCommand implements CommandExecutor {
         if (!(sender instanceof Player p)) return true;
 
         if (args.length != 1) {
-            TradeModule.sendText(p, Component.text("Verwendung: /trade <Spieler>", NamedTextColor.RED));
+            tradeModule.sendText(p, Component.text("Verwendung: /trade <Spieler>", NamedTextColor.RED));
             return true;
         }
 
         Player target = Bukkit.getPlayerExact(args[0]);
         if (target == null) {
-            TradeModule.sendText(p, Component.text("Spieler nicht gefunden.", NamedTextColor.RED));
+            tradeModule.sendText(p, Component.text("Spieler nicht gefunden.", NamedTextColor.RED));
             return true;
         }
 
         if (p.equals(target)) {
-            TradeModule.sendText(p, Component.text("Du kannst nicht mit dir selbst handeln.", NamedTextColor.RED));
+            tradeModule.sendText(p, Component.text("Du kannst nicht mit dir selbst handeln.", NamedTextColor.RED));
             return true;
         }
 
         if (tradeManager.isInTrade(p) || tradeManager.isInTrade(target)) {
-            TradeModule.sendText(p, Component.text("Einer von euch handelt bereits.", NamedTextColor.RED));
+            tradeModule.sendText(p, Component.text("Einer von euch handelt bereits.", NamedTextColor.RED));
             return true;
         }
 

+ 4 - 0
src/main/resources/plugin.yml

@@ -23,6 +23,10 @@ commands:
     description: Minion management command
     usage: /minion
     permission: minion.commands
+  dungeon:
+    description: Dungeons command
+    usage: /dungeon
+    permission: dungeons.commands
 
 permissions:
   minion.commands: