mirror of
https://github.com/Minestom/Minestom.git
synced 2024-10-01 07:57:41 +02:00
feat: use nextState on packet write to change states to ensure proper synchronization
This commit is contained in:
parent
47042abf12
commit
d502a4fa62
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user