From 263536414aa19200c3794374b2724be08522913b Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 28 Apr 2023 16:00:09 +0100 Subject: [PATCH] Add messageall and transferall commands --- README.md | 9 ++ .../connect/extension/GeyserConnect.java | 99 +++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/README.md b/README.md index b83b520..bca8295 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,12 @@ GeyserConnect is an easy way for Bedrock Edition clients to connect to any Java GeyserConnect is an extension for Geyser that allows for a list of Minecraft: Java Edition servers to be displayed and accessed through 1 public Geyser instance. It is effectively give the customisability of [BedrockConnect](https://github.com/Pugmatt/BedrockConnect) to [Geyser](https://github.com/GeyserMC/Geyser). If you wish to use DNS redirection please see the [bind9](bind9) folder in this repository. + +## Commands +All commands are prefixed ingame with `/geyserconnect` or in console with `geyserconnect` + +| Command | Description | Example | Console only | +|------------------------------------|----------------------------------------------|--------------------------------------------------------|--------------------| +| `menu` | Reconnect and get back to the menu. | `/geyserconnect menu` | :x: | +| `messageall (chat\|gui) ` | Send a message to all online users. | `/geyserconnect messageall gui This is a test message` | :heavy_check_mark: | +| `transferall [passAsVhost]` | Transfer all online users to another server. | `/geyserconnect transferall gc.example.com true` | :heavy_check_mark: | diff --git a/src/main/java/org/geysermc/connect/extension/GeyserConnect.java b/src/main/java/org/geysermc/connect/extension/GeyserConnect.java index 422c14f..96eb097 100644 --- a/src/main/java/org/geysermc/connect/extension/GeyserConnect.java +++ b/src/main/java/org/geysermc/connect/extension/GeyserConnect.java @@ -31,15 +31,25 @@ import org.geysermc.connect.extension.config.Config; import org.geysermc.connect.extension.config.ConfigLoader; import org.geysermc.connect.extension.storage.AbstractStorageManager; import org.geysermc.connect.extension.storage.DisabledStorageManager; +import org.geysermc.connect.extension.utils.Utils; +import org.geysermc.cumulus.form.CustomForm; import org.geysermc.event.subscribe.Subscribe; +import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.bedrock.SessionInitializeEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.session.GeyserSession; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + public class GeyserConnect implements Extension { private static GeyserConnect instance; private Config config; @@ -116,5 +126,94 @@ public class GeyserConnect implements Extension { session.sendUpstreamPacket(transferPacket); }) .build()); + + event.register(Command.builder(this) + .source(CommandSource.class) + .name("messageall") + .description("Send a message to everyone connected to this GeyserConnect server.") + .executor((source, command, args) -> { + if (!source.isConsole()) { + source.sendMessage("This command can only be ran from the console."); + return; + } + + String type = args[0].toLowerCase(); + String message = Arrays.stream(args).skip(1).collect(Collectors.joining(" ")); + + if (message.isEmpty()) { + source.sendMessage("You must specify a message."); + return; + } + + Collection sessions = GeyserImpl.getInstance().getSessionManager().getSessions().values(); + + switch (type) { + case "chat": + for (GeyserSession session : sessions) { + session.sendMessage(message); + } + break; + case "gui": + for (GeyserSession session : sessions) { + session.sendForm(CustomForm.builder() + .title("Notice") + .label(message) + .build()); + } + break; + default: + source.sendMessage("Invalid message type. Valid types: chat, gui"); + return; + } + }) + .build()); + + + event.register(Command.builder(this) + .source(CommandSource.class) + .name("transferall") + .description("Transfer everyone connected to this GeyserConnect server to another.") + .executor((source, command, args) -> { + if (!source.isConsole()) { + source.sendMessage("This command can only be ran from the console."); + return; + } + + String ip = args[0].toLowerCase(); + int port = 19132; + boolean passAsVhost = args.length > 1 && Boolean.parseBoolean(args[1]); + + // Split the ip and port if needed + String[] parts = ip.split(":"); + ip = parts[0]; + if (parts.length > 1) { + try { + port = Integer.parseInt(parts[1]); + } catch (NumberFormatException ignored) { + } + } + + for (GeyserSession session : GeyserImpl.getInstance().getSessionManager().getSessions().values()) { + String sessionIp = ip; + + // If we are passing with a vhost construct the vhost + if (passAsVhost) { + sessionIp = session.remoteServer().address(); + sessionIp += "._p" + session.remoteServer().port(); + if (session.remoteServer().authType() == AuthType.OFFLINE) { + sessionIp += "._o"; + } + sessionIp += "." + ip; + } + + GeyserConnect.instance().logger().info("Sending " + Utils.displayName(session) + " to " + sessionIp + (port != 19132 ? ":" + port : "")); + + TransferPacket transferPacket = new TransferPacket(); + transferPacket.setAddress(sessionIp); + transferPacket.setPort(port); + session.sendUpstreamPacket(transferPacket); + } + }) + .build()); } } \ No newline at end of file