diff --git a/pom.xml b/pom.xml
index 1d5c02f..b675bcd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
https://www.spigotmc.org/resources/
- Forwards commands from Bukkit to BungeeCord to execute it there
+ Forwards commands from Bukkit to BungeeCord (Or Velocity) to execute it there
@@ -25,6 +25,7 @@
bukkit
bungee
+ velocity
universal
diff --git a/velocity/pom.xml b/velocity/pom.xml
new file mode 100644
index 0000000..04a5268
--- /dev/null
+++ b/velocity/pom.xml
@@ -0,0 +1,35 @@
+
+ 4.0.0
+
+
+ com.github.games647
+ commandforward
+ 0.4.0
+ ../pom.xml
+
+
+
+ commandforward.velocity
+ jar
+
+
+ CommandForwardVelocity
+
+
+
+
+ velocitypowered-repo
+ https://nexus.velocitypowered.com/repository/maven-public/
+
+
+
+
+
+ com.velocitypowered
+ velocity-api
+ 3.1.0
+ provided
+
+
+
diff --git a/velocity/src/main/java/com/github/games647/commandforward/velocity/CommandForwardVelocity.java b/velocity/src/main/java/com/github/games647/commandforward/velocity/CommandForwardVelocity.java
new file mode 100644
index 0000000..ebe0b33
--- /dev/null
+++ b/velocity/src/main/java/com/github/games647/commandforward/velocity/CommandForwardVelocity.java
@@ -0,0 +1,84 @@
+package com.github.games647.commandforward.velocity;
+
+import com.google.inject.Inject;
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
+import com.velocitypowered.api.plugin.Plugin;
+import com.velocitypowered.api.plugin.annotation.DataDirectory;
+import com.velocitypowered.api.proxy.ProxyServer;
+import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
+import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
+import com.velocitypowered.api.proxy.server.RegisteredServer;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.slf4j.Logger;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ *
+ * Velocity support for CommandForward plugin
+ * Since Velocity supports BungeeCord plugin-
+ * messaging channels now
+ *
+ * @author Alijk
+ * @since 2022-02-13
+ *
+ */
+@Plugin(
+ id = "commandforward",
+ name = "CommandForward",
+ version = "0.4.0",
+ description = "Forwards commands from Bukkit to BungeeCord (Or Velocity) to execute it there",
+ authors = {"games647", "https://github.com/games647/CommandForward/graphs/contributors"}
+)
+public class CommandForwardVelocity {
+
+ private final ChannelIdentifier MESSAGE_CHANNEL = MinecraftChannelIdentifier.from("commandforward:cmd");
+
+ private static Optional instance;
+ private final ProxyServer proxyServer;
+ private final Logger logger;
+
+ private final List lobbies = new ArrayList<>();
+ private final List bedwars = new ArrayList<>();
+
+ @Inject
+ public CommandForwardVelocity(ProxyServer proxyServer, Logger logger, @DataDirectory Path dataDirectory) {
+ instance = Optional.of(this);
+ this.proxyServer = proxyServer;
+ this.logger = logger;
+ }
+
+ @Subscribe
+ public void onProxyInit(ProxyInitializeEvent event) {
+ // Register the custom messaging channel
+ proxyServer.getChannelRegistrar().register(MESSAGE_CHANNEL);
+ // Register an event handler to catch messages for it
+ proxyServer.getEventManager().register(this, new MessageListener(MESSAGE_CHANNEL));
+
+ }
+
+ /**
+ * Print an error message
+ *
+ * @param source Sender that execute the current command
+ * @param message Message to send to command sender
+ */
+ private void sendErrorMessage(CommandSource source, String message) {
+ Component textComponent = Component.text(String.format("[%s] %s", "CommandForward", message), NamedTextColor.RED);
+ source.sendMessage(textComponent);
+ }
+
+ public static CommandForwardVelocity getInstance() {
+ return instance.orElseThrow(IllegalAccessError::new);
+ }
+
+ public ProxyServer getProxyServer() {
+ return proxyServer;
+ }
+}
diff --git a/velocity/src/main/java/com/github/games647/commandforward/velocity/MessageListener.java b/velocity/src/main/java/com/github/games647/commandforward/velocity/MessageListener.java
new file mode 100644
index 0000000..8c1eeda
--- /dev/null
+++ b/velocity/src/main/java/com/github/games647/commandforward/velocity/MessageListener.java
@@ -0,0 +1,57 @@
+package com.github.games647.commandforward.velocity;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.google.common.io.ByteStreams;
+import com.velocitypowered.api.command.CommandManager;
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.connection.PluginMessageEvent;
+import com.velocitypowered.api.plugin.PluginManager;
+import com.velocitypowered.api.proxy.Player;
+import com.velocitypowered.api.proxy.ServerConnection;
+import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
+
+public class MessageListener {
+ private final ChannelIdentifier identifier;
+
+ public MessageListener(ChannelIdentifier identifier){
+ this.identifier = identifier;
+ }
+
+ @Subscribe
+ public void onPluginMessageEvent(PluginMessageEvent event){
+ // Received plugin message, check channel identifier matches
+ if(event.getIdentifier().equals(identifier)){
+ // Since this message was meant for this listener set it to handled
+ // We do this so the message doesn't get routed through.
+ event.setResult(PluginMessageEvent.ForwardResult.handled());
+
+ if(event.getSource() instanceof ServerConnection){
+ // Read the data written to the message
+ Player p = ((ServerConnection) event.getSource()).getPlayer();
+ ByteArrayDataInput in = ByteStreams.newDataInput(event.getData());
+ parseMessage(p, in);
+ }
+ }
+ }
+
+ private void parseMessage(CommandSource source, ByteArrayDataInput dataInput) {
+ final boolean isPlayer = dataInput.readBoolean();
+ final String command = dataInput.readUTF();
+ final String arguments = dataInput.readUTF();
+ final CommandSource invoker = (isPlayer) ? source : CommandForwardVelocity.getInstance().getProxyServer().getConsoleCommandSource();
+
+ invokeCommand(invoker, dataInput.readBoolean(), command, arguments);
+ }
+
+ private void invokeCommand(CommandSource invoker, boolean isOp, String command, String arguments) {
+ PluginManager pluginManager = CommandForwardVelocity.getInstance().getProxyServer().getPluginManager();
+ CommandManager commandManager = CommandForwardVelocity.getInstance().getProxyServer().getCommandManager();
+
+ // TODO implement isOp handle progress
+
+ commandManager.executeAsync(invoker, command + " " + arguments);
+ }
+
+
+}