From 507f1ae26b4112a41f4c55805ab58ffd5f09260c Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 15 Jun 2020 01:08:01 +0100 Subject: [PATCH] Add auto start of Geyser and transfer of user --- .../network/remote/RemoteServer.java | 17 +++ .../org/geysermc/multi/PacketHandler.java | 1 + .../multi/proxy/GeyserProxyBootstrap.java | 81 +++++++++++++ .../proxy/GeyserProxyCommandManager.java | 41 +++++++ .../multi/proxy/GeyserProxyConfiguration.java | 22 ++++ .../java/org/geysermc/multi/ui/UIHandler.java | 7 +- .../java/org/geysermc/multi/utils/Logger.java | 3 +- .../java/org/geysermc/multi/utils/Player.java | 26 +++++ .../java/org/geysermc/multi/utils/Server.java | 1 - src/main/resources/proxy_config.yml | 106 ++++++++++++++++++ 10 files changed, 298 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/geysermc/connector/network/remote/RemoteServer.java create mode 100644 src/main/java/org/geysermc/multi/proxy/GeyserProxyBootstrap.java create mode 100644 src/main/java/org/geysermc/multi/proxy/GeyserProxyCommandManager.java create mode 100644 src/main/java/org/geysermc/multi/proxy/GeyserProxyConfiguration.java create mode 100644 src/main/resources/proxy_config.yml diff --git a/src/main/java/org/geysermc/connector/network/remote/RemoteServer.java b/src/main/java/org/geysermc/connector/network/remote/RemoteServer.java new file mode 100644 index 0000000..3358ddf --- /dev/null +++ b/src/main/java/org/geysermc/connector/network/remote/RemoteServer.java @@ -0,0 +1,17 @@ +package org.geysermc.connector.network.remote; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * This is super hacky but I guess it works + */ +@Getter +@Setter +@AllArgsConstructor +public class RemoteServer { + + private String address; + private int port; +} \ No newline at end of file diff --git a/src/main/java/org/geysermc/multi/PacketHandler.java b/src/main/java/org/geysermc/multi/PacketHandler.java index dc98640..736ef9b 100644 --- a/src/main/java/org/geysermc/multi/PacketHandler.java +++ b/src/main/java/org/geysermc/multi/PacketHandler.java @@ -38,6 +38,7 @@ public class PacketHandler implements BedrockPacketHandler { public void disconnect(DisconnectReason reason) { if (player != null) { + player.onDisconnect(); masterServer.getLogger().info(player.getDisplayName() + " has disconnected (" + reason + ")"); masterServer.getPlayers().remove(session.getAddress()); } diff --git a/src/main/java/org/geysermc/multi/proxy/GeyserProxyBootstrap.java b/src/main/java/org/geysermc/multi/proxy/GeyserProxyBootstrap.java new file mode 100644 index 0000000..ba21c66 --- /dev/null +++ b/src/main/java/org/geysermc/multi/proxy/GeyserProxyBootstrap.java @@ -0,0 +1,81 @@ +package org.geysermc.multi.proxy; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.bootstrap.GeyserBootstrap; +import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.ping.IGeyserPingPassthrough; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.utils.FileUtils; +import org.geysermc.multi.MasterServer; +import org.geysermc.multi.utils.Logger; +import org.geysermc.multi.utils.Server; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +public class GeyserProxyBootstrap implements GeyserBootstrap { + + private GeyserProxyCommandManager geyserCommandManager; + private GeyserProxyConfiguration geyserConfig; + private Logger geyserLogger; + private IGeyserPingPassthrough geyserPingPassthrough; + + private GeyserConnector connector; + + @Override + public void onEnable() { + geyserLogger = MasterServer.getInstance().getLogger(); + + try { + InputStream configFile = GeyserProxyBootstrap.class.getClassLoader().getResourceAsStream("proxy_config.yml"); + ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); + geyserConfig = objectMapper.readValue(configFile, GeyserProxyConfiguration.class); + } catch (IOException ex) { + geyserLogger.severe("Failed to read proxy_config.yml! Make sure it's up to date and/or readable+writable!", ex); + return; + } + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); + + connector = GeyserConnector.start(PlatformType.STANDALONE, this); + geyserCommandManager = new GeyserProxyCommandManager(connector); + + geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector); + } + + @Override + public void onDisable() { + connector.shutdown(); + } + + @Override + public GeyserConfiguration getGeyserConfig() { + return geyserConfig; + } + + @Override + public Logger getGeyserLogger() { + return geyserLogger; + } + + @Override + public CommandManager getGeyserCommandManager() { + return geyserCommandManager; + } + + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserPingPassthrough; + } + + public void setServer(Server server) { + geyserLogger.debug("Updated remote server info"); + connector.getRemoteServer().setAddress(server.getAddress()); + connector.getRemoteServer().setPort(server.getPort()); + } +} + diff --git a/src/main/java/org/geysermc/multi/proxy/GeyserProxyCommandManager.java b/src/main/java/org/geysermc/multi/proxy/GeyserProxyCommandManager.java new file mode 100644 index 0000000..9e93bbd --- /dev/null +++ b/src/main/java/org/geysermc/multi/proxy/GeyserProxyCommandManager.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.multi.proxy; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandManager; + +public class GeyserProxyCommandManager extends CommandManager { + + public GeyserProxyCommandManager(GeyserConnector connector) { + super(connector); + } + + @Override + public String getDescription(String command) { + return ""; // this is not sent over the protocol, so we return none + } +} diff --git a/src/main/java/org/geysermc/multi/proxy/GeyserProxyConfiguration.java b/src/main/java/org/geysermc/multi/proxy/GeyserProxyConfiguration.java new file mode 100644 index 0000000..527200d --- /dev/null +++ b/src/main/java/org/geysermc/multi/proxy/GeyserProxyConfiguration.java @@ -0,0 +1,22 @@ +package org.geysermc.multi.proxy; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import org.geysermc.connector.configuration.GeyserJacksonConfiguration; + +import java.nio.file.Path; +import java.nio.file.Paths; + +@Getter +@JsonIgnoreProperties(ignoreUnknown = true) +public class GeyserProxyConfiguration extends GeyserJacksonConfiguration { + + @JsonProperty("floodgate-key-file") + private String floodgateKeyFile = ""; + + @Override + public Path getFloodgateKeyFile() { + return Paths.get(floodgateKeyFile); + } +} diff --git a/src/main/java/org/geysermc/multi/ui/UIHandler.java b/src/main/java/org/geysermc/multi/ui/UIHandler.java index 28e1c66..3755c35 100644 --- a/src/main/java/org/geysermc/multi/ui/UIHandler.java +++ b/src/main/java/org/geysermc/multi/ui/UIHandler.java @@ -27,10 +27,7 @@ public class UIHandler { MasterServer.getInstance().getLogger().debug(data.getClickedButton().getText()); Server server = player.getServers().get(data.getClickedButtonId()); - - TransferPacket transferPacket = new TransferPacket(); - transferPacket.setAddress(server.getAddress()); - transferPacket.setPort(server.getPort()); - player.getSession().sendPacket(transferPacket); + player.createGeyserProxy(server); + player.connectToProxy(); } } diff --git a/src/main/java/org/geysermc/multi/utils/Logger.java b/src/main/java/org/geysermc/multi/utils/Logger.java index c585f5e..d2397cf 100644 --- a/src/main/java/org/geysermc/multi/utils/Logger.java +++ b/src/main/java/org/geysermc/multi/utils/Logger.java @@ -4,10 +4,11 @@ import lombok.extern.log4j.Log4j2; import net.minecrell.terminalconsole.SimpleTerminalConsole; import org.apache.logging.log4j.core.config.Configurator; import org.geysermc.common.ChatColor; +import org.geysermc.connector.GeyserLogger; import org.geysermc.multi.MasterServer; @Log4j2 -public class Logger extends SimpleTerminalConsole { +public class Logger extends SimpleTerminalConsole implements GeyserLogger { private boolean colored = true; diff --git a/src/main/java/org/geysermc/multi/utils/Player.java b/src/main/java/org/geysermc/multi/utils/Player.java index ce11c2b..747776e 100644 --- a/src/main/java/org/geysermc/multi/utils/Player.java +++ b/src/main/java/org/geysermc/multi/utils/Player.java @@ -9,6 +9,7 @@ import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import org.geysermc.common.window.FormWindow; +import org.geysermc.multi.proxy.GeyserProxyBootstrap; import org.geysermc.multi.ui.FormID; import java.util.ArrayList; @@ -29,6 +30,8 @@ public class Player { private FormWindow currentWindow; private FormID currentWindowId; + private GeyserProxyBootstrap geyserProxy; + public Player(JsonNode extraData, BedrockServerSession session) { this.xuid = extraData.get("XUID").asText(); this.identity = UUID.fromString(extraData.get("identity").asText()); @@ -118,6 +121,13 @@ public class Player { session.sendPacket(setEntityMotionPacket); } + public void onDisconnect() { + if (geyserProxy != null) { + //geyserProxy.onDisable(); + } + } + + public void sendWindow(FormID id, FormWindow window) { this.currentWindow = window; this.currentWindowId = id; @@ -131,4 +141,20 @@ public class Player { public void resendWindow() { sendWindow(currentWindowId, currentWindow); } + + public void createGeyserProxy(Server server) { + if (this.geyserProxy == null) { + this.geyserProxy = new GeyserProxyBootstrap(); + geyserProxy.onEnable(); + } + + geyserProxy.setServer(server); + } + + public void connectToProxy() { + TransferPacket transferPacket = new TransferPacket(); + transferPacket.setAddress("127.0.0.1"); + transferPacket.setPort(geyserProxy.getGeyserConfig().getBedrock().getPort()); + session.sendPacket(transferPacket); + } } diff --git a/src/main/java/org/geysermc/multi/utils/Server.java b/src/main/java/org/geysermc/multi/utils/Server.java index 7995ef4..1e6b223 100644 --- a/src/main/java/org/geysermc/multi/utils/Server.java +++ b/src/main/java/org/geysermc/multi/utils/Server.java @@ -2,7 +2,6 @@ package org.geysermc.multi.utils; import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter @AllArgsConstructor diff --git a/src/main/resources/proxy_config.yml b/src/main/resources/proxy_config.yml new file mode 100644 index 0000000..b27b59f --- /dev/null +++ b/src/main/resources/proxy_config.yml @@ -0,0 +1,106 @@ +# -------------------------------- +# Geyser Configuration File +# +# A bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition. +# +# GitHub: https://github.com/GeyserMC/Geyser +# Discord: https://discord.geysermc.org/ +# -------------------------------- + +bedrock: + # The IP address that will listen for connections + address: 0.0.0.0 + # The port that will listen for connections + port: 19133 + # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. Irrelevant if "passthrough-motd" is set to true + motd1: "GeyserMC" + motd2: "Another GeyserMC forced host." +remote: + # The IP address of the remote (Java Edition) server + address: 127.0.0.1 + # The port of the remote (Java Edition) server + port: 25565 + # Authentication type. Can be offline, online, or floodgate (see https://github.com/GeyserMC/Geyser/wiki/Floodgate). + auth-type: online + +# Floodgate uses encryption to ensure use from authorised sources. +# This should point to the public key generated by Floodgate (Bungee or CraftBukkit) +# You can ignore this when not using Floodgate. +floodgate-key-file: public-key.pem + +## the Xbox/MCPE username is the key for the Java server auth-info +## this allows automatic configuration/login to the remote Java server +## if you are brave/stupid enough to put your Mojang account info into +## a config file +#userAuths: +# bluerkelp2: # MCPE/Xbox username +# email: not_really_my_email_address_mr_minecrafter53267@gmail.com # Mojang account email address +# password: "this isn't really my password" +# +# herpderp40300499303040503030300500293858393589: +# email: herpderp@derpherp.com +# password: dooooo + +# Bedrock clients can freeze when opening up the command prompt for the first time if given a lot of commands. +# Disabling this will prevent command suggestions from being sent and solve freezing for Bedrock clients. +command-suggestions: false + +# The following two options enable "ping passthrough" - the MOTD and/or player count gets retrieved from the Java server. +# Relay the MOTD from the remote server to Bedrock players. +passthrough-motd: false +# Relay the player count and max players from the remote server to Bedrock players. +passthrough-player-counts: false +# Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly. +# This option does nothing on standalone. +legacy-ping-passthrough: false +# How often to ping the remote server, in seconds. Only relevant for standalone or legacy ping passthrough. +# Increase if you are getting BrokenPipe errors. +ping-passthrough-interval: 3 + +# Maximum amount of players that can connect +max-players: 100 + +# If debug messages should be sent through console +debug-mode: false + +# Thread pool size +general-thread-pool: 32 + +# Allow third party capes to be visible. Currently allowing: +# OptiFine capes, LabyMod capes, 5Zig capes and MinecraftCapes +allow-third-party-capes: true + +# Allow third party deadmau5 ears to be visible. Currently allowing: +# MinecraftCapes +allow-third-party-ears: false + +# The default locale if we dont have the one the client requested +default-locale: en_us + +# Configures if chunk caching should be enabled or not. This keeps an individual +# record of each block the client loads in. While this feature does allow for a few +# things such as block break animations to show up in creative mode and among others, +# it is HIGHLY recommended you disable this on a production environment as it can eat +# up a lot of RAM. However, when using the Bukkit version of Geyser, support for features +# or implementations this allows is automatically enabled without the additional caching as +# Geyser has direct access to the server itself. +cache-chunks: false + +# Bedrock prevents building and displaying blocks above Y127 in the Nether - +# enabling this config option works around that by changing the Nether dimension ID +# to the End ID. The main downside to this is that the sky will resemble that of +# the end sky in the nether, but ultimately it's the only way for this feature to work. +above-bedrock-nether-building: false + +# bStats is a stat tracker that is entirely anonymous and tracks only basic information +# about Geyser, such as how many people are online, how many servers are using Geyser, +# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/. +# https://bstats.org/plugin/server-implementation/GeyserMC +metrics: + # If metrics should be enabled + enabled: false + # UUID of server, don't change! + uuid: generateduuid + +# DO NOT TOUCH! +config-version: 3