Clean files and add comments

This commit is contained in:
rtm516 2020-06-16 00:53:06 +01:00
parent 872ebdf76d
commit 516057e439
11 changed files with 82 additions and 48 deletions

View file

@ -1,15 +1,7 @@
package org.geysermc.multi;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import com.nukkitx.protocol.bedrock.v390.Bedrock_v390;
public class GeyserMulti {
public static final BedrockPacketCodec CODEC = Bedrock_v390.V390_CODEC;
private static MasterServer masterServer;
public static void main(String[] args) {
new MasterServer();
}

View file

@ -1,9 +1,7 @@
package org.geysermc.multi;
import com.nukkitx.protocol.bedrock.BedrockPong;
import com.nukkitx.protocol.bedrock.BedrockServer;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.*;
import com.nukkitx.protocol.bedrock.v390.Bedrock_v390;
import lombok.Getter;
import org.geysermc.multi.proxy.GeyserProxyBootstrap;
import org.geysermc.multi.utils.Logger;
@ -20,6 +18,8 @@ import java.util.concurrent.ScheduledExecutorService;
public class MasterServer {
public static final BedrockPacketCodec CODEC = Bedrock_v390.V390_CODEC;
private final Timer timer;
private BedrockServer bdServer;
private BedrockPong bdPong;
@ -72,8 +72,8 @@ public class MasterServer {
bdPong.setMaximumPlayerCount(1337);
bdPong.setGameType("Survival");
bdPong.setIpv4Port(port);
bdPong.setProtocolVersion(GeyserMulti.CODEC.getProtocolVersion());
bdPong.setVersion(GeyserMulti.CODEC.getMinecraftVersion());
bdPong.setProtocolVersion(MasterServer.CODEC.getProtocolVersion());
bdPong.setVersion(MasterServer.CODEC.getMinecraftVersion());
bdServer.setHandler(new BedrockServerEventHandler() {
@Override

View file

@ -48,9 +48,9 @@ public class PacketHandler implements BedrockPacketHandler {
// Check the protocol version is correct
int protocol = packet.getProtocolVersion();
if (protocol != GeyserMulti.CODEC.getProtocolVersion()) {
if (protocol != MasterServer.CODEC.getProtocolVersion()) {
PlayStatusPacket status = new PlayStatusPacket();
if (protocol > GeyserMulti.CODEC.getProtocolVersion()) {
if (protocol > MasterServer.CODEC.getProtocolVersion()) {
status.setStatus(PlayStatusPacket.Status.FAILED_SERVER);
} else {
status.setStatus(PlayStatusPacket.Status.FAILED_CLIENT);
@ -59,8 +59,9 @@ public class PacketHandler implements BedrockPacketHandler {
}
// Set the session codec
session.setPacketCodec(GeyserMulti.CODEC);
session.setPacketCodec(MasterServer.CODEC);
// Read the raw chain data
JsonNode rawChainData;
try {
rawChainData = OBJECT_MAPPER.readTree(packet.getChainData().toByteArray());
@ -68,6 +69,7 @@ public class PacketHandler implements BedrockPacketHandler {
throw new AssertionError("Unable to read chain data!");
}
// Get the parsed chain data
JsonNode chainData = rawChainData.get("chain");
if (chainData.getNodeType() != JsonNodeType.ARRAY) {
throw new AssertionError("Invalid chain data!");
@ -78,22 +80,29 @@ public class PacketHandler implements BedrockPacketHandler {
JWSObject jwsObject;
jwsObject = JWSObject.parse(chainData.get(chainData.size() - 1).asText());
// Read the JWS payload
JsonNode payload = OBJECT_MAPPER.readTree(jwsObject.getPayload().toBytes());
// Check the identityPublicKey is there
if (payload.get("identityPublicKey").getNodeType() != JsonNodeType.STRING) {
throw new AssertionError("Missing identity public key!");
}
// Create an ECPublicKey from the identityPublicKey
ECPublicKey identityPublicKey = EncryptionUtils.generateKey(payload.get("identityPublicKey").textValue());
// Get the skin data to validate the JWS token
JWSObject skinData = JWSObject.parse(packet.getSkinData().toString());
if (skinData.verify(new DefaultJWSVerifierFactory().createJWSVerifier(skinData.getHeader(), identityPublicKey))) {
// Make sure the client sent over the username, xuid and other info
if (payload.get("extraData").getNodeType() != JsonNodeType.OBJECT) {
throw new AssertionError("Missing client data");
}
// Fetch the client data
JsonNode extraData = payload.get("extraData");
// Create a new player and add it to the players list
player = new Player(extraData, session);
masterServer.getPlayers().put(session.getAddress(), player);
@ -145,26 +154,25 @@ public class PacketHandler implements BedrockPacketHandler {
player.sendWindow(FormID.MAIN, UIHandler.getServerListFormPacket(player.getServers()));;
/*TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress("81.174.164.211");
transferPacket.setPort(27040);
session.sendPacket(transferPacket);*/
return false;
}
@Override
public boolean handle(ModalFormResponsePacket packet) {
// Make sure the form is valid
FormID id = FormID.fromId(packet.getFormId());
if (id != player.getCurrentWindowId())
return false;
// Fetch the form and parse the response
FormWindow window = player.getCurrentWindow();
window.setResponse(packet.getFormData().trim());
// Resend the form if they closed it
if (window.getResponse() == null) {
player.resendWindow();
} else {
// Send the response to the correct response function
switch (id) {
case MAIN:
UIHandler.handleServerListResponse(player, (SimpleFormResponse) window.getResponse());
@ -178,10 +186,4 @@ public class PacketHandler implements BedrockPacketHandler {
return true;
}
@Override
public boolean handle(NetworkStackLatencyPacket packet) {
masterServer.getLogger().debug(packet.toString());
return false;
}
}

View file

@ -29,8 +29,10 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
@Override
public void onEnable() {
// Setup a logger
geyserLogger = new GeyserProxyLogger();
// Read the static config from resources
try {
InputStream configFile = GeyserProxyBootstrap.class.getClassLoader().getResourceAsStream("proxy_config.yml");
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
@ -39,13 +41,18 @@ public class GeyserProxyBootstrap implements GeyserBootstrap {
geyserLogger.severe("Failed to read proxy_config.yml! Make sure it's up to date and/or readable+writable!", ex);
return;
}
// Not sure there is a point in doing this as its a static config
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
// Create the connector and command manager
connector = GeyserConnector.start(PlatformType.STANDALONE, this);
geyserCommandManager = new GeyserProxyCommandManager(connector);
// Start the ping passthrough thread, again don't think there is a point
geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
// Swap the normal handler to our custom handler so we can change some
connector.getBedrockServer().setHandler(new ProxyConnectorServerEventHandler(connector));
}

View file

@ -13,7 +13,7 @@ import java.nio.file.Paths;
public class GeyserProxyConfiguration extends GeyserJacksonConfiguration {
@JsonProperty("floodgate-key-file")
private String floodgateKeyFile = "";
private String floodgateKeyFile;
@Override
public Path getFloodgateKeyFile() {

View file

@ -1,11 +1,12 @@
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 {
/**
* Disable debug messages
*/
public void debug(String message) { }
}

View file

@ -18,12 +18,15 @@ public class GeyserProxySession extends GeyserSession {
}
public void authenticate(String username, String password) {
// Get the player based on the connection address
Player player = MasterServer.getInstance().getPlayers().get(bedrockServerSession.getAddress());
if (player != null) {
if (player != null && player.getCurrentServer() != null) {
// Set the remote server info for the player
connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress());
connector.getRemoteServer().setPort(player.getCurrentServer().getPort());
super.authenticate(username, password);
}else{
// Disconnect the player if they haven't picked a server on the master server list
bedrockServerSession.disconnect("Please connect to the master server and pick a server first!");
}
}

View file

@ -4,7 +4,6 @@ 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;
@ -27,7 +26,11 @@ public class ProxyConnectorServerEventHandler extends ConnectorServerEventHandle
super.onSessionCreation(bedrockServerSession);
// This doesn't clean up the old packet handler, so may cause a memory leak?
bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserProxySession(connector, bedrockServerSession)));
bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); // Only done here as it sometimes gets cleared
// Add another disconnect handler to remove the player on final disconnect
bedrockServerSession.addDisconnectHandler(disconnectReason -> {
MasterServer.getInstance().getLogger().debug("Player disconnected from geyser proxy: " + player.getDisplayName() + " (" + disconnectReason + ")");
MasterServer.getInstance().getPlayers().remove(bedrockServerSession.getAddress());

View file

@ -1,6 +1,5 @@
package org.geysermc.multi.ui;
import com.nukkitx.protocol.bedrock.packet.TransferPacket;
import org.geysermc.common.window.FormWindow;
import org.geysermc.common.window.SimpleFormWindow;
import org.geysermc.common.window.button.FormButton;
@ -13,34 +12,52 @@ import org.geysermc.multi.utils.Server;
import java.util.List;
public class UIHandler {
/**
* Create a list of servers for the client based on the passed servers list
*
* @param servers A list of {@link Server} objects
* @return A {@link SimpleFormWindow} object
*/
public static FormWindow getServerListFormPacket(List<Server> servers) {
SimpleFormWindow window = new SimpleFormWindow("Servers", "");
// Add a button for each server with the server icon as the image
for (Server server : servers) {
window.getButtons().add(new FormButton(server.getAddress(), new FormImage(FormImage.FormImageType.URL, "https://eu.mc-api.net/v3/server/favicon/" + server.getAddress() + ":" + server.getPort() + ".png")));
window.getButtons().add(new FormButton(server.toString(), new FormImage(FormImage.FormImageType.URL, "https://eu.mc-api.net/v3/server/favicon/" + server.getAddress() + ":" + server.getPort() + ".png")));
}
return window;
}
/**
* Create a simple connecting message form
*
* @param server The server info to display
* @return A {@link SimpleFormWindow} object
*/
public static FormWindow getWaitingScreen(Server server) {
SimpleFormWindow window = new SimpleFormWindow("Servers", "Please wait while we connect you to " + server.toString());
SimpleFormWindow window = new SimpleFormWindow("Connecting", "Please wait while we connect you to " + server.toString());
return window;
}
/**
* Handle the server list response
*
* @param player The player that submitted the response
* @param data The form response data
*/
public static void handleServerListResponse(Player player, SimpleFormResponse data) {
MasterServer.getInstance().getLogger().debug(data.getClickedButton().getText());
// Get the server
Server server = player.getServers().get(data.getClickedButtonId());
// Tell the user we are connecting them
// this wont show up in alot of cases as the client connects quite quickly
player.sendWindow(FormID.CONNECTING, getWaitingScreen(server));
// Create the geyser instance if its not already running
// Create the Geyser instance if its not already running
MasterServer.getInstance().createGeyserProxy();
// Send the user over to the serverty
// Send the user over to the server
player.setCurrentServer(server);
player.connectToProxy();
}

View file

@ -11,10 +11,8 @@ import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.FormWindow;
import org.geysermc.multi.MasterServer;
import org.geysermc.multi.proxy.GeyserProxyBootstrap;
import org.geysermc.multi.ui.FormID;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -48,7 +46,11 @@ public class Player {
servers.add(new Server("81.174.164.211", 25580));
}
/**
* Send a few different packets to get the client to load in
*/
public void sendStartGame() {
// A lot of this likely doesn't need to be changed
StartGamePacket startGamePacket = new StartGamePacket();
startGamePacket.setUniqueEntityId(1);
startGamePacket.setRuntimeEntityId(1);
@ -94,9 +96,7 @@ public class Player {
startGamePacket.setEnchantmentSeed(0);
startGamePacket.setMultiplayerCorrelationId("");
startGamePacket.setBlockPalette(PalleteManger.BLOCK_PALLETE);
//startGamePacket.setItemEntries(ItemRegistry.ITEMS);
startGamePacket.setVanillaVersion("*");
// startGamePacket.setMovementServerAuthoritative(true);
session.sendPacket(startGamePacket);
// Send an empty chunk
@ -125,7 +125,13 @@ public class Player {
session.sendPacket(setEntityMotionPacket);
}
/**
* Send a window with the specified id and content
* Also cache it against the player for later use
*
* @param id The {@link FormID} to use for the form
* @param window The {@link FormWindow} to turn into json and send
*/
public void sendWindow(FormID id, FormWindow window) {
this.currentWindow = window;
this.currentWindowId = id;
@ -133,16 +139,19 @@ public class Player {
ModalFormRequestPacket modalFormRequestPacket = new ModalFormRequestPacket();
modalFormRequestPacket.setFormId(id.ordinal());
modalFormRequestPacket.setFormData(window.getJSONData());
session.sendPacket(modalFormRequestPacket);
session.sendPacketImmediately(modalFormRequestPacket);
}
public void resendWindow() {
sendWindow(currentWindowId, currentWindow);
}
/**
* Send the player to the Geyser proxy server
*/
public void connectToProxy() {
TransferPacket transferPacket = new TransferPacket();
transferPacket.setAddress("127.0.0.1");
transferPacket.setAddress("127.0.0.1"); // Need to find a good way of getting this
transferPacket.setPort(MasterServer.getInstance().getGeyserProxy().getGeyserConfig().getBedrock().getPort());
session.sendPacket(transferPacket);
}

View file

@ -15,6 +15,6 @@ public class Server {
@Override
public String toString() {
return address + ":" + port;
return address + (port != 25565 ? ":" + port : "");
}
}