Migrate to 1 geyser instance and swap remotes on demand

This commit is contained in:
rtm516 2020-06-15 20:09:41 +01:00
parent 507f1ae26b
commit 872ebdf76d
10 changed files with 132 additions and 30 deletions

View file

@ -5,8 +5,10 @@ import com.nukkitx.protocol.bedrock.BedrockServer;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler; import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.BedrockServerSession;
import lombok.Getter; import lombok.Getter;
import org.geysermc.multi.proxy.GeyserProxyBootstrap;
import org.geysermc.multi.utils.Logger; import org.geysermc.multi.utils.Logger;
import org.geysermc.multi.utils.Player; import org.geysermc.multi.utils.Player;
import org.geysermc.multi.utils.Server;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.HashMap; import java.util.HashMap;
@ -37,6 +39,9 @@ public class MasterServer {
@Getter @Getter
private final Map<InetSocketAddress, Player> players = new HashMap<>(); private final Map<InetSocketAddress, Player> players = new HashMap<>();
@Getter
private GeyserProxyBootstrap geyserProxy;
public MasterServer() { public MasterServer() {
logger = new Logger(); logger = new Logger();
logger.setDebug(true); logger.setDebug(true);
@ -95,5 +100,16 @@ public class MasterServer {
public void shutdown() { public void shutdown() {
shuttingDown = true; shuttingDown = true;
generalThreadPool.shutdown(); generalThreadPool.shutdown();
if (geyserProxy != null) {
geyserProxy.onDisable();
}
}
public void createGeyserProxy() {
if (geyserProxy == null) {
this.geyserProxy = new GeyserProxyBootstrap();
geyserProxy.onEnable();
}
} }
} }

View file

@ -38,9 +38,7 @@ public class PacketHandler implements BedrockPacketHandler {
public void disconnect(DisconnectReason reason) { public void disconnect(DisconnectReason reason) {
if (player != null) { if (player != null) {
player.onDisconnect(); masterServer.getLogger().info(player.getDisplayName() + " has disconnected from the master server (" + reason + ")");
masterServer.getLogger().info(player.getDisplayName() + " has disconnected (" + reason + ")");
masterServer.getPlayers().remove(session.getAddress());
} }
} }
@ -180,4 +178,10 @@ public class PacketHandler implements BedrockPacketHandler {
return true; return true;
} }
@Override
public boolean handle(NetworkStackLatencyPacket packet) {
masterServer.getLogger().debug(packet.toString());
return false;
}
} }

View file

@ -22,14 +22,14 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
private GeyserProxyCommandManager geyserCommandManager; private GeyserProxyCommandManager geyserCommandManager;
private GeyserProxyConfiguration geyserConfig; private GeyserProxyConfiguration geyserConfig;
private Logger geyserLogger; private GeyserProxyLogger geyserLogger;
private IGeyserPingPassthrough geyserPingPassthrough; private IGeyserPingPassthrough geyserPingPassthrough;
private GeyserConnector connector; private GeyserConnector connector;
@Override @Override
public void onEnable() { public void onEnable() {
geyserLogger = MasterServer.getInstance().getLogger(); geyserLogger = new GeyserProxyLogger();
try { try {
InputStream configFile = GeyserProxyBootstrap.class.getClassLoader().getResourceAsStream("proxy_config.yml"); InputStream configFile = GeyserProxyBootstrap.class.getClassLoader().getResourceAsStream("proxy_config.yml");
@ -45,6 +45,8 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
geyserCommandManager = new GeyserProxyCommandManager(connector); geyserCommandManager = new GeyserProxyCommandManager(connector);
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector); geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
connector.getBedrockServer().setHandler(new ProxyConnectorServerEventHandler(connector));
} }
@Override @Override
@ -58,7 +60,7 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
} }
@Override @Override
public Logger getGeyserLogger() { public GeyserProxyLogger getGeyserLogger() {
return geyserLogger; return geyserLogger;
} }
@ -71,11 +73,5 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
public IGeyserPingPassthrough getGeyserPingPassthrough() { public IGeyserPingPassthrough getGeyserPingPassthrough() {
return geyserPingPassthrough; return geyserPingPassthrough;
} }
public void setServer(Server server) {
geyserLogger.debug("Updated remote server info");
connector.getRemoteServer().setAddress(server.getAddress());
connector.getRemoteServer().setPort(server.getPort());
}
} }

View file

@ -0,0 +1,11 @@
package org.geysermc.multi.proxy;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.core.config.Configurator;
import org.geysermc.common.ChatColor;
import org.geysermc.multi.utils.Logger;
@Log4j2
public class GeyserProxyLogger extends Logger {
public void debug(String message) { }
}

View file

@ -0,0 +1,30 @@
package org.geysermc.multi.proxy;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.multi.MasterServer;
import org.geysermc.multi.utils.Player;
public class GeyserProxySession extends GeyserSession {
private final GeyserConnector connector;
private final BedrockServerSession bedrockServerSession;
public GeyserProxySession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
super(connector, bedrockServerSession);
this.connector = connector;
this.bedrockServerSession = bedrockServerSession;
}
public void authenticate(String username, String password) {
Player player = MasterServer.getInstance().getPlayers().get(bedrockServerSession.getAddress());
if (player != null) {
connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress());
connector.getRemoteServer().setPort(player.getCurrentServer().getPort());
super.authenticate(username, password);
}else{
bedrockServerSession.disconnect("Please connect to the master server and pick a server first!");
}
}
}

View file

@ -0,0 +1,36 @@
package org.geysermc.multi.proxy;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.ConnectorServerEventHandler;
import org.geysermc.connector.network.UpstreamPacketHandler;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.multi.MasterServer;
import org.geysermc.multi.utils.Player;
public class ProxyConnectorServerEventHandler extends ConnectorServerEventHandler {
private final GeyserConnector connector;
public ProxyConnectorServerEventHandler(GeyserConnector connector) {
super(connector);
this.connector = connector;
MasterServer.getInstance().getLogger().debug("Registered custom ConnectorServerEventHandler");
}
@Override
public void onSessionCreation(BedrockServerSession bedrockServerSession) {
Player player = MasterServer.getInstance().getPlayers().get(bedrockServerSession.getAddress());
if (player == null) {
bedrockServerSession.disconnect("Please connect to the master server and pick a server first!");
return;
}
super.onSessionCreation(bedrockServerSession);
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserProxySession(connector, bedrockServerSession)));
bedrockServerSession.addDisconnectHandler(disconnectReason -> {
MasterServer.getInstance().getLogger().debug("Player disconnected from geyser proxy: " + player.getDisplayName() + " (" + disconnectReason + ")");
MasterServer.getInstance().getPlayers().remove(bedrockServerSession.getAddress());
});
}
}

View file

@ -5,6 +5,7 @@ public enum FormID {
DIRECT_CONNECT, DIRECT_CONNECT,
ADD_SERVER, ADD_SERVER,
REMOVE_SERVER, REMOVE_SERVER,
CONNECTING,
ERROR; ERROR;
private static final FormID[] VALUES = values(); private static final FormID[] VALUES = values();

View file

@ -23,11 +23,25 @@ public class UIHandler {
return window; return window;
} }
public static FormWindow getWaitingScreen(Server server) {
SimpleFormWindow window = new SimpleFormWindow("Servers", "Please wait while we connect you to " + server.toString());
return window;
}
public static void handleServerListResponse(Player player, SimpleFormResponse data) { public static void handleServerListResponse(Player player, SimpleFormResponse data) {
MasterServer.getInstance().getLogger().debug(data.getClickedButton().getText()); MasterServer.getInstance().getLogger().debug(data.getClickedButton().getText());
// Get the server
Server server = player.getServers().get(data.getClickedButtonId()); Server server = player.getServers().get(data.getClickedButtonId());
player.createGeyserProxy(server);
// Tell the user we are connecting them
player.sendWindow(FormID.CONNECTING, getWaitingScreen(server));
// Create the geyser instance if its not already running
MasterServer.getInstance().createGeyserProxy();
// Send the user over to the serverty
player.setCurrentServer(server);
player.connectToProxy(); player.connectToProxy();
} }
} }

View file

@ -8,10 +8,13 @@ import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.packet.*; import com.nukkitx.protocol.bedrock.packet.*;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.FormWindow; import org.geysermc.common.window.FormWindow;
import org.geysermc.multi.MasterServer;
import org.geysermc.multi.proxy.GeyserProxyBootstrap; import org.geysermc.multi.proxy.GeyserProxyBootstrap;
import org.geysermc.multi.ui.FormID; import org.geysermc.multi.ui.FormID;
import java.lang.management.ManagementFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -30,7 +33,8 @@ public class Player {
private FormWindow currentWindow; private FormWindow currentWindow;
private FormID currentWindowId; private FormID currentWindowId;
private GeyserProxyBootstrap geyserProxy; @Setter
private Server currentServer;
public Player(JsonNode extraData, BedrockServerSession session) { public Player(JsonNode extraData, BedrockServerSession session) {
this.xuid = extraData.get("XUID").asText(); this.xuid = extraData.get("XUID").asText();
@ -121,12 +125,6 @@ public class Player {
session.sendPacket(setEntityMotionPacket); session.sendPacket(setEntityMotionPacket);
} }
public void onDisconnect() {
if (geyserProxy != null) {
//geyserProxy.onDisable();
}
}
public void sendWindow(FormID id, FormWindow window) { public void sendWindow(FormID id, FormWindow window) {
this.currentWindow = window; this.currentWindow = window;
@ -142,19 +140,10 @@ public class Player {
sendWindow(currentWindowId, currentWindow); sendWindow(currentWindowId, currentWindow);
} }
public void createGeyserProxy(Server server) {
if (this.geyserProxy == null) {
this.geyserProxy = new GeyserProxyBootstrap();
geyserProxy.onEnable();
}
geyserProxy.setServer(server);
}
public void connectToProxy() { public void connectToProxy() {
TransferPacket transferPacket = new TransferPacket(); TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress("127.0.0.1"); transferPacket.setAddress("127.0.0.1");
transferPacket.setPort(geyserProxy.getGeyserConfig().getBedrock().getPort()); transferPacket.setPort(MasterServer.getInstance().getGeyserProxy().getGeyserConfig().getBedrock().getPort());
session.sendPacket(transferPacket); session.sendPacket(transferPacket);
} }
} }

View file

@ -12,4 +12,9 @@ public class Server {
public Server(String address) { public Server(String address) {
this(address, 25565); this(address, 25565);
} }
@Override
public String toString() {
return address + ":" + port;
}
} }