Allow Bedrock to manage entering server and not us

This commit is contained in:
Camotoy 2021-02-20 16:07:07 -05:00
parent ccfea684c4
commit bcb4d0c8d6
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
6 changed files with 46 additions and 40 deletions

View file

@ -72,7 +72,7 @@
<dependency> <dependency>
<groupId>com.github.CloudburstMC.Protocol</groupId> <groupId>com.github.CloudburstMC.Protocol</groupId>
<artifactId>bedrock-v422</artifactId> <artifactId>bedrock-v422</artifactId>
<version>d41b84e86c</version> <version>294e7e53b6</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<!-- Stay on the older version of Network while it's rewritten --> <!-- Stay on the older version of Network while it's rewritten -->

View file

@ -25,12 +25,15 @@
package org.geysermc.connect; package org.geysermc.connect;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.nukkitx.protocol.bedrock.*; import com.nukkitx.protocol.bedrock.*;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.connect.storage.DisabledStorageManager; import org.geysermc.connect.storage.DisabledStorageManager;
import org.geysermc.connect.utils.Server; import org.geysermc.connect.utils.Server;
import org.geysermc.connect.utils.ServerCategory; import org.geysermc.connect.utils.ServerCategory;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.BedrockProtocol; import org.geysermc.connector.network.BedrockProtocol;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
import org.geysermc.connect.proxy.GeyserProxyBootstrap; import org.geysermc.connect.proxy.GeyserProxyBootstrap;
@ -44,12 +47,12 @@ import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MasterServer { public class MasterServer {
private BedrockServer bdServer; private BedrockServer bdServer;
private BedrockPong bdPong;
@Getter @Getter
private boolean shuttingDown = false; private boolean shuttingDown = false;
@ -66,6 +69,14 @@ public class MasterServer {
@Getter @Getter
private final Map<String, Player> players = new HashMap<>(); private final Map<String, Player> players = new HashMap<>();
/**
* Players that are transferring and are expected to rejoin on the Geyser side.
*/
@Getter
private final Cache<String, Player> transferringPlayers = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build();
@Getter @Getter
private GeyserProxyBootstrap geyserProxy; private GeyserProxyBootstrap geyserProxy;
@ -134,16 +145,6 @@ public class MasterServer {
InetSocketAddress bindAddress = new InetSocketAddress(geyserConnectConfig.getAddress(), port); InetSocketAddress bindAddress = new InetSocketAddress(geyserConnectConfig.getAddress(), port);
bdServer = new BedrockServer(bindAddress); bdServer = new BedrockServer(bindAddress);
bdPong = new BedrockPong();
bdPong.setEdition("MCPE");
bdPong.setMotd(geyserConnectConfig.getMotd());
bdPong.setPlayerCount(0);
bdPong.setMaximumPlayerCount(geyserConnectConfig.getMaxPlayers());
bdPong.setGameType("Survival");
bdPong.setIpv4Port(port);
bdPong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion());
bdPong.setVersion(null); // Server tries to connect either way and it looks better
bdServer.setHandler(new BedrockServerEventHandler() { bdServer.setHandler(new BedrockServerEventHandler() {
@Override @Override
public boolean onConnectionRequest(InetSocketAddress address) { public boolean onConnectionRequest(InetSocketAddress address) {
@ -152,6 +153,19 @@ public class MasterServer {
@Override @Override
public BedrockPong onQuery(InetSocketAddress address) { public BedrockPong onQuery(InetSocketAddress address) {
int playerCount = players.size();
if (GeyserConnector.getInstance() != null) {
playerCount += GeyserConnector.getInstance().getPlayers().size();
}
BedrockPong bdPong = new BedrockPong();
bdPong.setEdition("MCPE");
bdPong.setMotd(geyserConnectConfig.getMotd());
bdPong.setPlayerCount(playerCount);
bdPong.setMaximumPlayerCount(geyserConnectConfig.getMaxPlayers());
bdPong.setGameType("Survival");
bdPong.setIpv4Port(port);
bdPong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion());
bdPong.setVersion(null); // Server tries to connect either way and it looks better
return bdPong; return bdPong;
} }

View file

@ -79,9 +79,10 @@ public class PacketHandler implements BedrockPacketHandler {
masterServer.getLogger().info(player.getDisplayName() + " has disconnected from the master server (" + reason + ")"); masterServer.getLogger().info(player.getDisplayName() + " has disconnected from the master server (" + reason + ")");
masterServer.getStorageManager().saveServers(player); masterServer.getStorageManager().saveServers(player);
if (player.getCurrentServer() == null || player.getCurrentServer().isBedrock()) { if (player.getCurrentServer() != null && !player.getCurrentServer().isBedrock()) {
masterServer.getPlayers().remove(player.getXuid(), player); masterServer.getTransferringPlayers().put(player.getXuid(), player);
} }
masterServer.getPlayers().remove(player.getXuid(), player);
} }
} }
@ -203,12 +204,6 @@ public class PacketHandler implements BedrockPacketHandler {
@Override @Override
public boolean handle(SetLocalPlayerAsInitializedPacket packet) { public boolean handle(SetLocalPlayerAsInitializedPacket packet) {
// Disconnect the player if the server is full
if (MasterServer.getInstance().getPlayers().size() > MasterServer.getInstance().getGeyserConnectConfig().getMaxPlayers()) {
session.disconnect("disconnectionScreen.serverFull");
return false;
}
masterServer.getLogger().debug("Player initialized: " + player.getDisplayName()); masterServer.getLogger().debug("Player initialized: " + player.getDisplayName());
// Handle the virtual host if specified // Handle the virtual host if specified

View file

@ -26,6 +26,7 @@
package org.geysermc.connect.proxy; package org.geysermc.connect.proxy;
import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.BedrockServerSession;
import lombok.Getter;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.common.AuthType; import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -37,6 +38,8 @@ public class GeyserProxySession extends GeyserSession {
private final GeyserConnector connector; private final GeyserConnector connector;
private final BedrockServerSession bedrockServerSession; private final BedrockServerSession bedrockServerSession;
@Getter
private Player player;
public GeyserProxySession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { public GeyserProxySession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
super(connector, bedrockServerSession); super(connector, bedrockServerSession);
@ -44,10 +47,20 @@ public class GeyserProxySession extends GeyserSession {
this.bedrockServerSession = bedrockServerSession; this.bedrockServerSession = bedrockServerSession;
} }
@Override
public void setAuthenticationData(AuthData authData) {
super.setAuthenticationData(authData);
player = MasterServer.getInstance().getTransferringPlayers().getIfPresent(authData.getXboxUUID());
if (player == null) {
bedrockServerSession.disconnect("Please connect to the master server and pick a server first!");
} else {
MasterServer.getInstance().getTransferringPlayers().invalidate(authData.getXboxUUID());
}
}
@Override @Override
public void authenticate(String username, String password) { public void authenticate(String username, String password) {
// Get the player based on the connection address
Player player = MasterServer.getInstance().getPlayers().get(getAuthData().getXboxUUID());
if (player != null && player.getCurrentServer() != null) { if (player != null && player.getCurrentServer() != null) {
// Set the remote server info for the player // Set the remote server info for the player
connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress()); connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress());
@ -64,8 +77,6 @@ public class GeyserProxySession extends GeyserSession {
@Override @Override
public void authenticateWithMicrosoftCode() { public void authenticateWithMicrosoftCode() {
// Get the player based on the connection address
Player player = MasterServer.getInstance().getPlayers().get(getAuthData().getXboxUUID());
if (player != null && player.getCurrentServer() != null) { if (player != null && player.getCurrentServer() != null) {
// Set the remote server info for the player // Set the remote server info for the player
connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress()); connector.getRemoteServer().setAddress(player.getCurrentServer().getAddress());
@ -82,19 +93,8 @@ public class GeyserProxySession extends GeyserSession {
@Override @Override
public void login() { public void login() {
Player player = MasterServer.getInstance().getPlayers().get(getAuthData().getXboxUUID());
connector.setAuthType(player.getCurrentServer().isOnline() ? AuthType.ONLINE : AuthType.OFFLINE); connector.setAuthType(player.getCurrentServer().isOnline() ? AuthType.ONLINE : AuthType.OFFLINE);
super.login(); super.login();
} }
@Override
public void setAuthenticationData(AuthData authData) {
super.setAuthenticationData(authData);
Player player = MasterServer.getInstance().getPlayers().get(authData.getXboxUUID());
if (player == null) {
bedrockServerSession.disconnect("Please connect to the master server and pick a server first!");
}
}
} }

View file

@ -40,8 +40,7 @@ public class GeyserProxyUpstreamPacketHandler extends UpstreamPacketHandler {
@Override @Override
public boolean handle(SetLocalPlayerAsInitializedPacket packet) { public boolean handle(SetLocalPlayerAsInitializedPacket packet) {
Player player = MasterServer.getInstance().getPlayers().get(session.getAuthData().getXboxUUID()); connector.setAuthType(((GeyserProxySession) session).getPlayer().getCurrentServer().isOnline() ? AuthType.ONLINE : AuthType.OFFLINE);
connector.setAuthType(player.getCurrentServer().isOnline() ? AuthType.ONLINE : AuthType.OFFLINE);
return super.handle(packet); return super.handle(packet);
} }

View file

@ -55,16 +55,14 @@ public class ProxyConnectorServerEventHandler extends ConnectorServerEventHandle
bedrockServerSession.addDisconnectHandler(disconnectReason -> { bedrockServerSession.addDisconnectHandler(disconnectReason -> {
// Make sure nothing is null before locating the player // Make sure nothing is null before locating the player
if (MasterServer.getInstance() == null if (MasterServer.getInstance() == null
|| MasterServer.getInstance().getPlayers().size() == 0
|| session.getAuthData() == null || session.getAuthData() == null
|| session.getAuthData().getXboxUUID() == null) { || session.getAuthData().getXboxUUID() == null) {
return; return;
} }
Player player = MasterServer.getInstance().getPlayers().get(session.getAuthData().getXboxUUID()); Player player = session.getPlayer();
if (player != null) { if (player != null) {
MasterServer.getInstance().getLogger().debug("Player disconnected from Geyser proxy: " + player.getDisplayName() + " (" + disconnectReason + ")"); MasterServer.getInstance().getLogger().debug("Player disconnected from Geyser proxy: " + player.getDisplayName() + " (" + disconnectReason + ")");
MasterServer.getInstance().getPlayers().remove(session.getAuthData().getXboxUUID());
// Set the last disconnect time // Set the last disconnect time
MasterServer.getInstance().setLastDisconnectTime(System.currentTimeMillis()); MasterServer.getInstance().setLastDisconnectTime(System.currentTimeMillis());