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
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) {
String address = packet.serverAddress();
// 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");
if (split.length == 3 || split.length == 4) {
@ -110,7 +110,7 @@ public final class HandshakeListener {
((PlayerSocketConnection) connection).refreshServerInformation(address, packet.serverPort(), packet.protocolVersion());
}
switch (packet.nextState()) {
switch (packet.intent()) {
case 1 -> {
connection.setClientState(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) {
connection.setClientState(ConnectionState.CONFIGURATION);
public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket ignored, @NotNull PlayerConnection connection) {
CONNECTION_MANAGER.registerPlayer(connection.getPlayer());
// Registry data
@ -262,7 +260,6 @@ public final class LoginListener {
AsyncUtils.runAsync(() -> {
//todo event
connection.setServerState(ConnectionState.PLAY);
connection.sendPacket(new FinishConfigurationPacket());
});
}

View File

@ -217,10 +217,10 @@ public final class ConnectionManager {
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);
playerConnection.sendPacket(loginSuccessPacket);
playerConnection.setServerState(ConnectionState.CONFIGURATION);
});
}

View File

@ -240,7 +240,7 @@ final class NetworkBufferTypes {
// Kotlin - https://discord.com/channels/706185253441634317/706186227493109860/1163703658341478462
buffer.write(BYTE, (byte) NBTType.TAG_End.getOrdinal());
} else {
buffer.write(BYTE, (byte) NBTType.TAG_Compound.getOrdinal());
buffer.write(BYTE, (byte) value.getID().getOrdinal());
nbtWriter.writeRaw(value);
}
} catch (IOException e) {
@ -265,7 +265,10 @@ final class NetworkBufferTypes {
buffer.nbtReader = nbtReader;
}
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) {
throw new RuntimeException(e);
}

View File

@ -1,6 +1,8 @@
package net.minestom.server.network.packet.client;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer;
import org.jetbrains.annotations.Nullable;
/**
* 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.
*/
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;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.client.ClientPacket;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ClientFinishConfigurationPacket() implements ClientPacket {
@ -14,4 +16,8 @@ public record ClientFinishConfigurationPacket() implements ClientPacket {
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.*;
public record ClientHandshakePacket(int protocolVersion, @NotNull String serverAddress,
int serverPort, int nextState) implements ClientPacket {
int serverPort, int intent) implements ClientPacket {
public ClientHandshakePacket {
if (serverAddress.length() > getMaxHandshakeLength()) {
@ -30,7 +30,7 @@ public record ClientHandshakePacket(int protocolVersion, @NotNull String serverA
}
writer.write(STRING, serverAddress);
writer.write(UNSIGNED_SHORT, serverPort);
writer.write(VAR_INT, nextState);
writer.write(VAR_INT, intent);
}
private static int getMaxHandshakeLength() {

View File

@ -1,8 +1,10 @@
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.packet.client.ClientPacket;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record ClientLoginAcknowledgedPacket() implements ClientPacket {
@ -14,4 +16,8 @@ public record ClientLoginAcknowledgedPacket() implements ClientPacket {
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.player.PlayerConnection;
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)}.
@ -21,4 +22,9 @@ public non-sealed interface ServerPacket extends NetworkBuffer.Writer, SendableP
*/
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.ServerPacketIdentifier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public record FinishConfigurationPacket() implements ServerPacket {
@ -20,4 +21,9 @@ public record FinishConfigurationPacket() implements ServerPacket {
public int getId(@NotNull ConnectionState state) {
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.ServerPacketIdentifier;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
@ -27,4 +28,9 @@ public record LoginSuccessPacket(@NotNull UUID uuid, @NotNull String username, i
public int getId(@NotNull ConnectionState state) {
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
*/
public @NotNull ConnectionState getServerState() {
return clientState;
return serverState;
}
public PlayerPublicKey playerPublicKey() {

View File

@ -379,9 +379,16 @@ public class PlayerSocketConnection extends PlayerConnection {
}
}
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()));
writeBufferSync(buffer, 0, buffer.limit());
var nextState = serverPacket.nextState();
if (nextState != null && state != nextState) {
System.out.println("CHANGE SERVER STATE TO " + nextState);
setServerState(nextState);
}
}
}