diff --git a/pandalib-bungee-commands/pom.xml b/pandalib-bungee-commands/pom.xml
new file mode 100644
index 0000000..204c1e0
--- /dev/null
+++ b/pandalib-bungee-commands/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+ pandalib-parent
+ fr.pandacube.lib
+ 1.0-SNAPSHOT
+
+ 4.0.0
+
+ pandalib-bungee-commands
+ jar
+
+
+
+ bungeecord-repo
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+ fr.pandacube.lib
+ pandalib-util
+ ${project.version}
+
+
+ fr.pandacube.lib
+ pandalib-chat
+ ${project.version}
+
+
+ fr.pandacube.lib
+ pandalib-commands
+ ${project.version}
+
+
+
+ net.md-5
+ bungeecord-api
+ ${bungeecord.version}
+ provided
+
+
+
+
+
\ No newline at end of file
diff --git a/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierCommand.java b/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierCommand.java
new file mode 100644
index 0000000..53fdbf1
--- /dev/null
+++ b/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierCommand.java
@@ -0,0 +1,128 @@
+package fr.pandacube.lib.bungee.commands;
+
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.brigadier.context.ParsedCommandNode;
+import com.mojang.brigadier.context.StringRange;
+import com.mojang.brigadier.suggestion.Suggestion;
+import com.mojang.brigadier.suggestion.SuggestionProvider;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+import fr.pandacube.lib.commands.BrigadierCommand;
+import fr.pandacube.lib.commands.SuggestionsSupplier;
+import fr.pandacube.lib.reflect.Reflect;
+import fr.pandacube.lib.util.Log;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Command;
+import net.md_5.bungee.api.plugin.TabExecutor;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+public abstract class BungeeBrigadierCommand extends BrigadierCommand {
+
+ protected BungeeBrigadierDispatcher dispatcher;
+
+ public BungeeBrigadierCommand(BungeeBrigadierDispatcher d) {
+ if (d == null) {
+ throw new IllegalStateException("BungeeBrigadierDispatcher not provided.");
+ }
+ dispatcher = d;
+
+ LiteralCommandNode commandNode;
+ String[] aliases;
+
+ try {
+ commandNode = buildCommand().build();
+ postBuildCommand(commandNode);
+ aliases = getAliases();
+ } catch (Exception e) {
+ Log.severe("Exception encountered when building Brigadier command " + getClass().getName(), e);
+ return;
+ }
+ if (aliases == null)
+ aliases = new String[0];
+
+ dispatcher.register(commandNode);
+
+ // still have to be registered for console
+ ProxyServer.getInstance().getPluginManager().registerCommand(dispatcher.plugin, new CommandRelay(commandNode.getLiteral()));
+
+ for (String alias : aliases) {
+ dispatcher.register(literal(alias)
+ .requires(commandNode.getRequirement())
+ .executes(commandNode.getCommand())
+ .redirect(commandNode)
+ .build()
+ );
+
+ ProxyServer.getInstance().getPluginManager().registerCommand(dispatcher.plugin, new CommandRelay(alias));
+ }
+
+ }
+
+ private class CommandRelay extends Command implements TabExecutor {
+ private final String alias;
+ public CommandRelay(String alias) {
+ super(alias);
+ this.alias = alias;
+ }
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ dispatcher.execute(sender, alias + (args.length == 0 ? "" : (" " + String.join(" ", args))));
+ }
+ @Override
+ public Iterable onTabComplete(CommandSender sender, String[] args) {
+
+ String cursor = "/" + alias + " " + String.join(" ", args);
+
+ StringRange supportedRange = StringRange.between(cursor.lastIndexOf(' ') + 1, cursor.length());
+
+ Suggestions suggestions = dispatcher.getSuggestions(sender, cursor.substring(1));
+ if (!suggestions.getRange().equals(supportedRange))
+ return Collections.emptyList();
+
+ return suggestions.getList()
+ .stream()
+ .filter(s -> s.getRange().equals(supportedRange))
+ .map(Suggestion::getText)
+ .collect(Collectors.toList());
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ public boolean isConsole(CommandSender sender) {
+ return ProxyServer.getInstance().getConsole().equals(sender);
+ }
+ public boolean isPlayer(CommandSender sender) {
+ return sender instanceof ProxiedPlayer;
+ }
+ public Predicate hasPermission(String permission) {
+ return sender -> sender.hasPermission(permission);
+ }
+
+
+
+
+
+ protected SuggestionProvider wrapSuggestions(SuggestionsSupplier suggestions) {
+ return wrapSuggestions(suggestions, Function.identity());
+ }
+
+
+}
\ No newline at end of file
diff --git a/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierDispatcher.java b/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierDispatcher.java
new file mode 100644
index 0000000..46cdbc6
--- /dev/null
+++ b/pandalib-bungee-commands/src/main/java/fr/pandacube/lib/bungee/commands/BungeeBrigadierDispatcher.java
@@ -0,0 +1,72 @@
+package fr.pandacube.lib.bungee.commands;
+
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.ParseResults;
+import com.mojang.brigadier.context.CommandContextBuilder;
+import com.mojang.brigadier.context.StringRange;
+import com.mojang.brigadier.context.SuggestionContext;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;
+import com.mojang.brigadier.suggestion.Suggestion;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+import com.mojang.brigadier.tree.CommandNode;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+import fr.pandacube.lib.chat.Chat;
+import fr.pandacube.lib.commands.BrigadierCommand;
+import fr.pandacube.lib.commands.BrigadierDispatcher;
+import fr.pandacube.lib.commands.BrigadierSuggestionsUtil;
+import fr.pandacube.lib.util.Log;
+import net.kyori.adventure.text.ComponentLike;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.ChatEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.event.EventHandler;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+public class BungeeBrigadierDispatcher extends BrigadierDispatcher implements Listener {
+
+
+
+
+ /* package */ final Plugin plugin;
+
+ public BungeeBrigadierDispatcher(Plugin pl) {
+ plugin = pl;
+ ProxyServer.getInstance().getPluginManager().registerListener(plugin, this);
+ }
+
+
+
+
+
+ @EventHandler
+ public void onChat(ChatEvent event) {
+ if (!event.getMessage().startsWith("/"))
+ return;
+
+ String commandLine = event.getMessage().substring(1);
+
+ String commandName = commandLine.split(" ", -1)[0];
+
+ if (getDispatcher().getRoot().getChild(commandName) == null)
+ return;
+
+ event.setCancelled(true);
+
+ ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> execute((ProxiedPlayer) event.getSender(), commandLine));
+
+ }
+
+
+ @Override
+ protected void sendSenderMessage(CommandSender sender, ComponentLike message) {
+ sender.sendMessage(Chat.toBungee(message.asComponent()));
+ }
+}
diff --git a/pandalib-cli/pom.xml b/pandalib-cli/pom.xml
index 0c2f5a6..0d974e9 100644
--- a/pandalib-cli/pom.xml
+++ b/pandalib-cli/pom.xml
@@ -32,12 +32,16 @@
pandalib-core
${project.version}
-
fr.pandacube.lib
pandalib-reflect
${project.version}
+
+ fr.pandacube.lib
+ pandalib-commands
+ ${project.version}
+
net.md-5
@@ -50,12 +54,6 @@
${bungeecord.version}
-
- fr.pandacube.lib
- pandalib-commands
- ${project.version}
-
-
diff --git a/pandalib-cli/src/main/java/fr/pandacube/lib/cli/BrigadierCommand.java b/pandalib-cli/src/main/java/fr/pandacube/lib/cli/BrigadierCommand.java
deleted file mode 100644
index 1eb692c..0000000
--- a/pandalib-cli/src/main/java/fr/pandacube/lib/cli/BrigadierCommand.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package fr.pandacube.lib.cli;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-import com.mojang.brigadier.arguments.ArgumentType;
-import com.mojang.brigadier.builder.LiteralArgumentBuilder;
-import com.mojang.brigadier.builder.RequiredArgumentBuilder;
-import com.mojang.brigadier.context.CommandContext;
-import com.mojang.brigadier.context.ParsedCommandNode;
-import com.mojang.brigadier.suggestion.Suggestion;
-import com.mojang.brigadier.suggestion.SuggestionProvider;
-import com.mojang.brigadier.suggestion.Suggestions;
-import com.mojang.brigadier.suggestion.SuggestionsBuilder;
-import com.mojang.brigadier.tree.LiteralCommandNode;
-
-import fr.pandacube.lib.chat.ChatStatic;
-import fr.pandacube.lib.commands.SuggestionsSupplier;
-import fr.pandacube.lib.util.Log;
-import fr.pandacube.lib.reflect.Reflect;
-
-public abstract class BrigadierCommand extends ChatStatic {
-
- public BrigadierCommand() {
- LiteralArgumentBuilder