diff --git a/pom.xml b/pom.xml index 1d5c02f..b675bcd 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ <url>https://www.spigotmc.org/resources/</url> <description> - Forwards commands from Bukkit to BungeeCord to execute it there + Forwards commands from Bukkit to BungeeCord (Or Velocity) to execute it there </description> <properties> @@ -25,6 +25,7 @@ <modules> <module>bukkit</module> <module>bungee</module> + <module>velocity</module> <module>universal</module> </modules> 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 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>com.github.games647</groupId> + <artifactId>commandforward</artifactId> + <version>0.4.0</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <!--This have to be in lowercase because it's used by plugin.yml--> + <artifactId>commandforward.velocity</artifactId> + <packaging>jar</packaging> + + <!--Represents the main plugin--> + <name>CommandForwardVelocity</name> + + <repositories> + <!--Velocity-API --> + <repository> + <id>velocitypowered-repo</id> + <url>https://nexus.velocitypowered.com/repository/maven-public/</url> + </repository> + </repositories> + + <dependencies> + <dependency> + <groupId>com.velocitypowered</groupId> + <artifactId>velocity-api</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> 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<CommandForwardVelocity> instance; + private final ProxyServer proxyServer; + private final Logger logger; + + private final List<RegisteredServer> lobbies = new ArrayList<>(); + private final List<RegisteredServer> 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); + } + + +}