feat: use nextState on packet write to change states to ensure proper synchronization

This commit is contained in:
mworzala 2023-11-01 22:16:03 -04:00 committed by Matt Worzala
parent 47042abf12
commit d502a4fa62
14 changed files with 64 additions and 14 deletions

View File

@ -128,6 +128,13 @@ public final class PacketListenerManager {
// Packet is likely invalid // Packet is likely invalid
MinecraftServer.getExceptionManager().handleException(e); MinecraftServer.getExceptionManager().handleException(e);
} }
// If the packet intends to switch state, do it now.
var nextState = packet.nextState();
if (nextState != null && state != nextState) {
System.out.println("CHANGE CLIENT STATE TO " + nextState);
connection.setClientState(nextState);
}
} }
/** /**

View File

@ -40,7 +40,7 @@ public final class HandshakeListener {
public static void listener(@NotNull ClientHandshakePacket packet, @NotNull PlayerConnection connection) { public static void listener(@NotNull ClientHandshakePacket packet, @NotNull PlayerConnection connection) {
String address = packet.serverAddress(); String address = packet.serverAddress();
// Bungee support (IP forwarding) // Bungee support (IP forwarding)
if (BungeeCordProxy.isEnabled() && connection instanceof PlayerSocketConnection socketConnection && packet.nextState() == 2) { if (BungeeCordProxy.isEnabled() && connection instanceof PlayerSocketConnection socketConnection && packet.intent() == 2) {
final String[] split = address.split("\00"); final String[] split = address.split("\00");
if (split.length == 3 || split.length == 4) { if (split.length == 3 || split.length == 4) {
@ -110,7 +110,7 @@ public final class HandshakeListener {
((PlayerSocketConnection) connection).refreshServerInformation(address, packet.serverPort(), packet.protocolVersion()); ((PlayerSocketConnection) connection).refreshServerInformation(address, packet.serverPort(), packet.protocolVersion());
} }
switch (packet.nextState()) { switch (packet.intent()) {
case 1 -> { case 1 -> {
connection.setClientState(ConnectionState.STATUS); connection.setClientState(ConnectionState.STATUS);
connection.setServerState(ConnectionState.STATUS); connection.setServerState(ConnectionState.STATUS);

View File

@ -220,9 +220,7 @@ public final class LoginListener {
} }
} }
public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket packet, @NotNull PlayerConnection connection) { public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket ignored, @NotNull PlayerConnection connection) {
connection.setClientState(ConnectionState.CONFIGURATION);
CONNECTION_MANAGER.registerPlayer(connection.getPlayer()); CONNECTION_MANAGER.registerPlayer(connection.getPlayer());
// Registry data // Registry data
@ -262,7 +260,6 @@ public final class LoginListener {
AsyncUtils.runAsync(() -> { AsyncUtils.runAsync(() -> {
//todo event //todo event
connection.setServerState(ConnectionState.PLAY);
connection.sendPacket(new FinishConfigurationPacket()); connection.sendPacket(new FinishConfigurationPacket());
}); });
} }

View File

@ -217,10 +217,10 @@ public final class ConnectionManager {
player.setUuid(eventUuid); player.setUuid(eventUuid);
} }
} }
// Send login success packet
// Send login success packet (and switch to configuration phase)
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(player.getUuid(), player.getUsername(), 0); LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(player.getUuid(), player.getUsername(), 0);
playerConnection.sendPacket(loginSuccessPacket); playerConnection.sendPacket(loginSuccessPacket);
playerConnection.setServerState(ConnectionState.CONFIGURATION);
}); });
} }

View File

@ -240,7 +240,7 @@ final class NetworkBufferTypes {
// Kotlin - https://discord.com/channels/706185253441634317/706186227493109860/1163703658341478462 // Kotlin - https://discord.com/channels/706185253441634317/706186227493109860/1163703658341478462
buffer.write(BYTE, (byte) NBTType.TAG_End.getOrdinal()); buffer.write(BYTE, (byte) NBTType.TAG_End.getOrdinal());
} else { } else {
buffer.write(BYTE, (byte) NBTType.TAG_Compound.getOrdinal()); buffer.write(BYTE, (byte) value.getID().getOrdinal());
nbtWriter.writeRaw(value); nbtWriter.writeRaw(value);
} }
} catch (IOException e) { } catch (IOException e) {
@ -265,7 +265,10 @@ final class NetworkBufferTypes {
buffer.nbtReader = nbtReader; buffer.nbtReader = nbtReader;
} }
try { try {
return nbtReader.read(); byte tagId = buffer.read(BYTE);
if (tagId == NBTType.TAG_End.getOrdinal())
return NBTEnd.INSTANCE;
return nbtReader.readRaw(tagId);
} catch (IOException | NBTException e) { } catch (IOException | NBTException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -1,6 +1,8 @@
package net.minestom.server.network.packet.client; package net.minestom.server.network.packet.client;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import org.jetbrains.annotations.Nullable;
/** /**
* Represents a packet received from a client. * Represents a packet received from a client.
@ -8,4 +10,8 @@ import net.minestom.server.network.NetworkBuffer;
* Packets are value-based, and should therefore not be reliant on identity. * Packets are value-based, and should therefore not be reliant on identity.
*/ */
public interface ClientPacket extends NetworkBuffer.Writer { public interface ClientPacket extends NetworkBuffer.Writer {
default @Nullable ConnectionState nextState() {
return null;
}
} }

View File

@ -1,8 +1,10 @@
package net.minestom.server.network.packet.client.configuration; package net.minestom.server.network.packet.client.configuration;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.network.packet.client.ClientPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ClientFinishConfigurationPacket() implements ClientPacket { public record ClientFinishConfigurationPacket() implements ClientPacket {
@ -14,4 +16,8 @@ public record ClientFinishConfigurationPacket() implements ClientPacket {
public void write(@NotNull NetworkBuffer writer) { public void write(@NotNull NetworkBuffer writer) {
} }
@Override
public @NotNull ConnectionState nextState() {
return ConnectionState.PLAY;
}
} }

View File

@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
import static net.minestom.server.network.NetworkBuffer.*; import static net.minestom.server.network.NetworkBuffer.*;
public record ClientHandshakePacket(int protocolVersion, @NotNull String serverAddress, public record ClientHandshakePacket(int protocolVersion, @NotNull String serverAddress,
int serverPort, int nextState) implements ClientPacket { int serverPort, int intent) implements ClientPacket {
public ClientHandshakePacket { public ClientHandshakePacket {
if (serverAddress.length() > getMaxHandshakeLength()) { if (serverAddress.length() > getMaxHandshakeLength()) {
@ -30,7 +30,7 @@ public record ClientHandshakePacket(int protocolVersion, @NotNull String serverA
} }
writer.write(STRING, serverAddress); writer.write(STRING, serverAddress);
writer.write(UNSIGNED_SHORT, serverPort); writer.write(UNSIGNED_SHORT, serverPort);
writer.write(VAR_INT, nextState); writer.write(VAR_INT, intent);
} }
private static int getMaxHandshakeLength() { private static int getMaxHandshakeLength() {

View File

@ -1,8 +1,10 @@
package net.minestom.server.network.packet.client.login; package net.minestom.server.network.packet.client.login;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.network.packet.client.ClientPacket;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ClientLoginAcknowledgedPacket() implements ClientPacket { public record ClientLoginAcknowledgedPacket() implements ClientPacket {
@ -14,4 +16,8 @@ public record ClientLoginAcknowledgedPacket() implements ClientPacket {
public void write(@NotNull NetworkBuffer writer) { public void write(@NotNull NetworkBuffer writer) {
} }
@Override
public @NotNull ConnectionState nextState() {
return ConnectionState.CONFIGURATION;
}
} }

View File

@ -4,6 +4,7 @@ import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer; import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** /**
* Represents a packet which can be sent to a player using {@link PlayerConnection#sendPacket(SendablePacket)}. * Represents a packet which can be sent to a player using {@link PlayerConnection#sendPacket(SendablePacket)}.
@ -21,4 +22,9 @@ public non-sealed interface ServerPacket extends NetworkBuffer.Writer, SendableP
*/ */
int getId(@NotNull ConnectionState state); int getId(@NotNull ConnectionState state);
// If not null, the server will switch state immediately after sending this packet
default @Nullable ConnectionState nextState() {
return null;
}
} }

View File

@ -5,6 +5,7 @@ import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record FinishConfigurationPacket() implements ServerPacket { public record FinishConfigurationPacket() implements ServerPacket {
@ -20,4 +21,9 @@ public record FinishConfigurationPacket() implements ServerPacket {
public int getId(@NotNull ConnectionState state) { public int getId(@NotNull ConnectionState state) {
return ServerPacketIdentifier.CONFIGURATION_FINISH_CONFIGURATION; return ServerPacketIdentifier.CONFIGURATION_FINISH_CONFIGURATION;
} }
@Override
public @NotNull ConnectionState nextState() {
return ConnectionState.PLAY;
}
} }

View File

@ -5,6 +5,7 @@ import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
@ -27,4 +28,9 @@ public record LoginSuccessPacket(@NotNull UUID uuid, @NotNull String username, i
public int getId(@NotNull ConnectionState state) { public int getId(@NotNull ConnectionState state) {
return ServerPacketIdentifier.LOGIN_SUCCESS; return ServerPacketIdentifier.LOGIN_SUCCESS;
} }
@Override
public @NotNull ConnectionState nextState() {
return ConnectionState.CONFIGURATION;
}
} }

View File

@ -166,7 +166,7 @@ public abstract class PlayerConnection {
* @return the server connection state * @return the server connection state
*/ */
public @NotNull ConnectionState getServerState() { public @NotNull ConnectionState getServerState() {
return clientState; return serverState;
} }
public PlayerPublicKey playerPublicKey() { public PlayerPublicKey playerPublicKey() {

View File

@ -379,9 +379,16 @@ public class PlayerSocketConnection extends PlayerConnection {
} }
} }
try (var hold = ObjectPool.PACKET_POOL.hold()) { try (var hold = ObjectPool.PACKET_POOL.hold()) {
var buffer = PacketUtils.createFramedPacket(getServerState(), hold.get(), serverPacket, compressed); var state = getServerState();
var buffer = PacketUtils.createFramedPacket(state, hold.get(), serverPacket, compressed);
System.out.println("SEND " + getServerState() + " cls=" + serverPacket.getClass().getSimpleName() + " id=" + serverPacket.getId(getServerState())); System.out.println("SEND " + getServerState() + " cls=" + serverPacket.getClass().getSimpleName() + " id=" + serverPacket.getId(getServerState()));
writeBufferSync(buffer, 0, buffer.limit()); writeBufferSync(buffer, 0, buffer.limit());
var nextState = serverPacket.nextState();
if (nextState != null && state != nextState) {
System.out.println("CHANGE SERVER STATE TO " + nextState);
setServerState(nextState);
}
} }
} }