first join

(cherry picked from commit 47042abf12)
This commit is contained in:
mworzala 2023-10-07 09:00:15 -04:00 committed by Matt Worzala
parent 183159c85d
commit 89f9b0d513
17 changed files with 100 additions and 52 deletions

View File

@ -453,7 +453,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
if (this instanceof Player player) {
PlayerConnection playerConnection = player.playerConnection;
// connection null during Player initialization (due to #super call)
self = playerConnection != null && playerConnection.getConnectionState() == ConnectionState.PLAY;
self = playerConnection != null && playerConnection.getServerState() == ConnectionState.PLAY;
}
EntityPropertiesPacket propertiesPacket = new EntityPropertiesPacket(getEntityId(), List.of(attributeInstance));
if (self) {

View File

@ -266,7 +266,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
final JoinGamePacket joinGamePacket = new JoinGamePacket(
getEntityId(), false, List.of(), 0,
MinecraftServer.getChunkViewDistance(), MinecraftServer.getChunkViewDistance(),
false, true, dimensionType.toString(), spawnInstance.getDimensionName(),
false, true, false, dimensionType.toString(), spawnInstance.getDimensionName(),
0, gameMode, null, false, levelFlat, deathLocation, portalCooldown);
sendPacket(joinGamePacket);
@ -1501,7 +1501,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @param component the reason
*/
public void kick(@NotNull Component component) {
final ConnectionState connectionState = playerConnection.getConnectionState();
final ConnectionState connectionState = playerConnection.getServerState();
// Packet type depends on the current player connection state
final ServerPacket disconnectPacket;
if (connectionState == ConnectionState.LOGIN) {
@ -1925,7 +1925,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
final PacketListenerManager manager = MinecraftServer.getPacketListenerManager();
// This method is NOT thread-safe
this.packets.drain(packet -> manager.processClientPacket(playerConnection.getConnectionState(), packet, playerConnection), ServerFlag.PACKET_PER_TICK);
this.packets.drain(packet -> manager.processClientPacket(playerConnection.getClientState(), packet, playerConnection), ServerFlag.PACKET_PER_TICK);
}
/**
@ -1935,7 +1935,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*/
public void refreshLatency(int latency) {
this.latency = latency;
if (getPlayerConnection().getConnectionState() == ConnectionState.PLAY) {
if (getPlayerConnection().getServerState() == ConnectionState.PLAY) {
PacketUtils.broadcastPacket(new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.UPDATE_LATENCY, infoEntry()));
}
}
@ -2348,7 +2348,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
this.allowServerListings = allowServerListings;
// TODO: Use the metadata object here
boolean isInPlayState = getPlayerConnection().getConnectionState() == ConnectionState.PLAY;
boolean isInPlayState = getPlayerConnection().getServerState() == ConnectionState.PLAY;
if (isInPlayState) metadata.setNotifyAboutChanges(false);
metadata.setIndex((byte) 17, Metadata.Byte(displayedSkinParts));
metadata.setIndex((byte) 18, Metadata.Byte((byte) (this.mainHand == MainHand.RIGHT ? 1 : 0)));

View File

@ -163,9 +163,9 @@ public class BlockPlacementListener {
// Place the block
Block resultBlock = playerBlockPlaceEvent.getBlock();
player.sendPacket(new AcknowledgeBlockChangePacket(packet.sequence()));
instance.placeBlock(new BlockHandler.PlayerPlacement(resultBlock, instance, placementPosition, player, hand, blockFace,
packet.cursorPositionX(), packet.cursorPositionY(), packet.cursorPositionZ()), playerBlockPlaceEvent.shouldDoBlockUpdates());
player.sendPacket(new AcknowledgeBlockChangePacket(packet.sequence()));
// Block consuming
if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand

View File

@ -1,13 +1,23 @@
package net.minestom.server.listener.preplay;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.packet.client.configuration.ClientFinishConfigurationPacket;
import org.jetbrains.annotations.NotNull;
public final class ConfigurationListener {
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static void finishListener(@NotNull ClientFinishConfigurationPacket packet, @NotNull Player player) {
//todo move to play state
player.getPlayerConnection().setClientState(ConnectionState.PLAY);
System.out.println("Finished configuration for " + player.getUsername() );
CONNECTION_MANAGER.startPlayState(player);
//todo move to play state
}
}

View File

@ -111,10 +111,14 @@ public final class HandshakeListener {
}
switch (packet.nextState()) {
case 1 -> connection.setConnectionState(ConnectionState.STATUS);
case 1 -> {
connection.setClientState(ConnectionState.STATUS);
connection.setServerState(ConnectionState.STATUS);
}
case 2 -> {
if (packet.protocolVersion() == MinecraftServer.PROTOCOL_VERSION) {
connection.setConnectionState(ConnectionState.LOGIN);
connection.setClientState(ConnectionState.LOGIN);
connection.setServerState(ConnectionState.LOGIN);
} else {
// Incorrect client version
disconnect(connection, INVALID_VERSION_TEXT);

View File

@ -18,6 +18,7 @@ import net.minestom.server.network.packet.client.login.ClientEncryptionResponseP
import net.minestom.server.network.packet.client.login.ClientLoginAcknowledgedPacket;
import net.minestom.server.network.packet.client.login.ClientLoginPluginResponsePacket;
import net.minestom.server.network.packet.client.login.ClientLoginStartPacket;
import net.minestom.server.network.packet.server.common.ResourcePackSendPacket;
import net.minestom.server.network.packet.server.common.TagsPacket;
import net.minestom.server.network.packet.server.configuration.FinishConfigurationPacket;
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
@ -79,7 +80,6 @@ public final class LoginListener {
return;
}
final PlayerSocketConnection socketConnection = (PlayerSocketConnection) connection;
socketConnection.setConnectionState(ConnectionState.LOGIN);
final byte[] publicKey = MojangAuth.getKeyPair().getPublic().getEncoded();
byte[] nonce = new byte[4];
@ -221,7 +221,7 @@ public final class LoginListener {
}
public static void loginAckListener(@NotNull ClientLoginAcknowledgedPacket packet, @NotNull PlayerConnection connection) {
connection.setConnectionState(ConnectionState.CONFIGURATION);
connection.setClientState(ConnectionState.CONFIGURATION);
CONNECTION_MANAGER.registerPlayer(connection.getPlayer());
@ -262,6 +262,7 @@ public final class LoginListener {
AsyncUtils.runAsync(() -> {
//todo event
connection.setServerState(ConnectionState.PLAY);
connection.sendPacket(new FinishConfigurationPacket());
});
}

View File

@ -220,12 +220,14 @@ public final class ConnectionManager {
// Send login success packet
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(player.getUuid(), player.getUsername(), 0);
playerConnection.sendPacket(loginSuccessPacket);
// playerConnection.setConnectionState(ConnectionState.CONFIGURATION);
// if (register) registerPlayer(player); // WHEN ENTERING CONFIGURATION THIS SHOULD BE SET
// this.waitingPlayers.relaxedOffer(player);
playerConnection.setServerState(ConnectionState.CONFIGURATION);
});
}
public void startPlayState(@NotNull Player player) {
this.waitingPlayers.relaxedOffer(player);
}
/**
* Calls the player initialization callbacks and the event {@link AsyncPlayerPreLoginEvent}.
* <p>
@ -262,7 +264,7 @@ public final class ConnectionManager {
// Send login success packet
LoginSuccessPacket loginSuccessPacket = new LoginSuccessPacket(player.getUuid(), player.getUsername(), 0);
playerConnection.sendPacket(loginSuccessPacket);
playerConnection.setConnectionState(ConnectionState.PLAY);
// playerConnection.setConnectionState(ConnectionState.PLAY);
if (register) registerPlayer(player);
this.waitingPlayers.relaxedOffer(player);
});
@ -300,13 +302,12 @@ public final class ConnectionManager {
EventDispatcher.call(loginEvent);
final Instance spawningInstance = loginEvent.getSpawningInstance();
Check.notNull(spawningInstance, "You need to specify a spawning instance in the PlayerLoginEvent");
// Spawn the player at Player#getRespawnPoint
if (DebugUtils.INSIDE_TEST) {
// Required to get the exact moment the player spawns
waitingPlayer.UNSAFE_init(spawningInstance).join();
} else {
waitingPlayer.UNSAFE_init(spawningInstance);
}
CompletableFuture<Void> spawnFuture = waitingPlayer.UNSAFE_init(spawningInstance);
// Required to get the exact moment the player spawns
if (DebugUtils.INSIDE_TEST) spawnFuture.join();
});
}

View File

@ -5,6 +5,9 @@ import net.minestom.server.listener.manager.PacketListenerManager;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.ClientPacketsHandler;
import net.minestom.server.network.packet.client.handshake.ClientHandshakePacket;
import net.minestom.server.network.packet.client.play.ClientPlayerPositionAndRotationPacket;
import net.minestom.server.network.packet.client.play.ClientPlayerPositionPacket;
import net.minestom.server.network.packet.client.play.ClientPlayerRotationPacket;
import net.minestom.server.network.player.PlayerConnection;
import org.jetbrains.annotations.NotNull;
@ -50,12 +53,14 @@ public class PacketProcessor {
}
public ClientPacket process(@NotNull PlayerConnection connection, int packetId, ByteBuffer body) {
final ClientPacket packet = create(connection.getConnectionState(), packetId, body);
System.out.println("PROCESS " + connection.getConnectionState() + " " + packet.getClass().getSimpleName());
final ClientPacket packet = create(connection.getClientState(), packetId, body);
var packetClass = packet.getClass();
if (packetClass != ClientPlayerPositionPacket.class && packetClass != ClientPlayerPositionAndRotationPacket.class && packetClass != ClientPlayerRotationPacket.class)
System.out.println("PROCESS " + connection.getClientState() + " " + packet.getClass().getSimpleName());
final ConnectionState state = connection.getConnectionState();
final ConnectionState state = connection.getClientState();
switch (state) {
case HANDSHAKE, STATUS, LOGIN, CONFIGURATION -> packetListenerManager.processClientPacket(connection.getConnectionState(), packet, connection);
case HANDSHAKE, STATUS, LOGIN, CONFIGURATION -> packetListenerManager.processClientPacket(connection.getClientState(), packet, connection);
case PLAY -> {
final Player player = connection.getPlayer();
assert player != null;

View File

@ -118,6 +118,7 @@ public sealed class ClientPacketsHandler permits ClientPacketsHandler.Status, Cl
register(nextId(), ClientVehicleMovePacket::new);
register(nextId(), ClientSteerBoatPacket::new);
register(nextId(), ClientPickItemPacket::new);
nextId(); // Ping request
register(nextId(), ClientCraftRecipeRequest::new);
register(nextId(), ClientPlayerAbilitiesPacket::new);
register(nextId(), ClientPlayerDiggingPacket::new);

View File

@ -24,7 +24,6 @@ public final class ServerPacketIdentifier {
public static final int BUNDLE = nextPlayId();
public static final int SPAWN_ENTITY = nextPlayId();
public static final int SPAWN_EXPERIENCE_ORB = nextPlayId();
public static final int SPAWN_PLAYER = nextPlayId();
public static final int ENTITY_ANIMATION = nextPlayId();
public static final int STATISTICS = nextPlayId();
public static final int ACKNOWLEDGE_BLOCK_CHANGE = nextPlayId();

View File

@ -17,6 +17,7 @@ import static net.minestom.server.network.NetworkBuffer.*;
public record JoinGamePacket(
int entityId, boolean isHardcore, List<String> worlds, int maxPlayers,
int viewDistance, int simulationDistance, boolean reducedDebugInfo, boolean enableRespawnScreen,
boolean doLimitedCrafting,
String dimensionType, String world, long hashedSeed, GameMode gameMode, GameMode previousGameMode,
boolean isDebug, boolean isFlat, DeathLocation deathLocation, int portalCooldown
) implements ServerPacket {
@ -34,6 +35,7 @@ public record JoinGamePacket(
reader.read(VAR_INT),
reader.read(BOOLEAN),
reader.read(BOOLEAN),
reader.read(BOOLEAN),
reader.read(STRING),
reader.read(STRING),
@ -57,6 +59,7 @@ public record JoinGamePacket(
writer.write(VAR_INT, simulationDistance);
writer.write(BOOLEAN, reducedDebugInfo);
writer.write(BOOLEAN, enableRespawnScreen);
writer.write(BOOLEAN, doLimitedCrafting);
writer.write(STRING, dimensionType);
writer.write(STRING, world);

View File

@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull;
import static net.minestom.server.network.NetworkBuffer.BYTE;
import static net.minestom.server.network.NetworkBuffer.FLOAT;
public record PlayerAbilitiesPacket(byte flags, float flyingSpeed, float fieldViewModifier) implements ServerPacket {
public record PlayerAbilitiesPacket(byte flags, float flyingSpeed, float walkingSpeed) implements ServerPacket {
public static final byte FLAG_INVULNERABLE = 0x01;
public static final byte FLAG_FLYING = 0x02;
public static final byte FLAG_ALLOW_FLYING = 0x04;
@ -23,7 +23,7 @@ public record PlayerAbilitiesPacket(byte flags, float flyingSpeed, float fieldVi
public void write(@NotNull NetworkBuffer writer) {
writer.write(BYTE, flags);
writer.write(FLOAT, flyingSpeed);
writer.write(FLOAT, fieldViewModifier);
writer.write(FLOAT, walkingSpeed);
}
@Override

View File

@ -32,6 +32,6 @@ public record SpawnPlayerPacket(int entityId, @NotNull UUID playerUuid,
@Override
public int getId(@NotNull ConnectionState state) {
return ServerPacketIdentifier.SPAWN_PLAYER;
throw new UnsupportedOperationException("SpawnPlayerPacket is not supported in " + state);
}
}

View File

@ -16,7 +16,7 @@ public class FakePlayerConnection extends PlayerConnection {
@Override
public void sendPacket(@NotNull SendablePacket packet) {
FakePlayerController controller = getFakePlayer().getController();
final ServerPacket serverPacket = SendablePacket.extractServerPacket(getConnectionState(), packet);
final ServerPacket serverPacket = SendablePacket.extractServerPacket(getServerState(), packet);
controller.consumePacket(serverPacket);
}

View File

@ -20,13 +20,15 @@ import java.util.List;
*/
public abstract class PlayerConnection {
private Player player;
private volatile ConnectionState connectionState;
private volatile ConnectionState clientState;
private volatile ConnectionState serverState;
private PlayerPublicKey playerPublicKey;
volatile boolean online;
public PlayerConnection() {
this.online = true;
this.connectionState = ConnectionState.HANDSHAKE;
this.clientState = ConnectionState.HANDSHAKE;
this.serverState = ConnectionState.HANDSHAKE;
}
/**
@ -139,8 +141,14 @@ public abstract class PlayerConnection {
return online;
}
public void setConnectionState(@NotNull ConnectionState connectionState) {
this.connectionState = connectionState;
@ApiStatus.Internal
public void setClientState(@NotNull ConnectionState state) {
this.clientState = state;
}
@ApiStatus.Internal
public void setServerState(@NotNull ConnectionState state) {
this.serverState = state;
}
/**
@ -148,8 +156,17 @@ public abstract class PlayerConnection {
*
* @return the client connection state
*/
public @NotNull ConnectionState getConnectionState() {
return connectionState;
public @NotNull ConnectionState getClientState() {
return clientState;
}
/**
* Gets the server connection state.
*
* @return the server connection state
*/
public @NotNull ConnectionState getServerState() {
return clientState;
}
public PlayerPublicKey playerPublicKey() {
@ -163,7 +180,8 @@ public abstract class PlayerConnection {
@Override
public String toString() {
return "PlayerConnection{" +
"connectionState=" + connectionState +
"clientState=" + clientState +
", serverState=" + serverState +
", identifier=" + getIdentifier() +
'}';
}

View File

@ -13,6 +13,9 @@ import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.handshake.ClientHandshakePacket;
import net.minestom.server.network.packet.server.*;
import net.minestom.server.network.packet.server.login.SetCompressionPacket;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.network.packet.server.play.TimeUpdatePacket;
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
import net.minestom.server.network.socket.Worker;
import net.minestom.server.utils.ObjectPool;
import net.minestom.server.utils.PacketUtils;
@ -112,7 +115,7 @@ public class PlayerSocketConnection extends PlayerConnection {
MinecraftServer.getExceptionManager().handleException(e);
} finally {
if (payload.position() != payload.limit()) {
LOGGER.warn("WARNING: Packet ({}) 0x{} not fully read ({}) {}", getConnectionState(), Integer.toHexString(id), payload, packet);
LOGGER.warn("WARNING: Packet ({}) 0x{} not fully read ({}) {}", getClientState(), Integer.toHexString(id), payload, packet);
}
}
});
@ -290,14 +293,14 @@ public class PlayerSocketConnection extends PlayerConnection {
/**
* Adds an entry to the plugin request map.
* <p>
* Only working if {@link #getConnectionState()} is {@link net.minestom.server.network.ConnectionState#LOGIN}.
* Only working if {@link #getServerState()} ()} is {@link net.minestom.server.network.ConnectionState#LOGIN}.
*
* @param messageId the message id
* @param channel the packet channel
* @throws IllegalStateException if a messageId with the value {@code messageId} already exists for this connection
*/
public void addPluginRequestEntry(int messageId, @NotNull String channel) {
if (!getConnectionState().equals(ConnectionState.LOGIN)) {
if (getServerState() != ConnectionState.LOGIN) {
return;
}
Check.stateCondition(pluginRequestMap.containsKey(messageId), "You cannot have two messageId with the same value");
@ -317,10 +320,10 @@ public class PlayerSocketConnection extends PlayerConnection {
}
@Override
public void setConnectionState(@NotNull ConnectionState connectionState) {
super.setConnectionState(connectionState);
public void setClientState(@NotNull ConnectionState state) {
super.setClientState(state);
// Clear the plugin request map (since it is not used anymore)
if (connectionState.equals(ConnectionState.PLAY)) {
if (state == ConnectionState.PLAY) {
this.pluginRequestMap.clear();
}
}
@ -338,7 +341,7 @@ public class PlayerSocketConnection extends PlayerConnection {
final Player player = getPlayer();
// Outgoing event
if (player != null && outgoing.hasListener()) {
final ServerPacket serverPacket = SendablePacket.extractServerPacket(getConnectionState(), packet);
final ServerPacket serverPacket = SendablePacket.extractServerPacket(getServerState(), packet);
PlayerPacketOutEvent event = new PlayerPacketOutEvent(player, serverPacket);
outgoing.call(event);
if (event.isCancelled()) return;
@ -348,15 +351,18 @@ public class PlayerSocketConnection extends PlayerConnection {
writeServerPacketSync(serverPacket, compressed);
} else if (packet instanceof FramedPacket framedPacket) {
var buffer = framedPacket.body();
System.out.println("SEND " + getConnectionState() + " " + "UNKNOWN FRAMED");
System.out.println("SEND " + getServerState() + " " + "UNKNOWN FRAMED");
writeBufferSync(buffer, 0, buffer.limit());
} else if (packet instanceof CachedPacket cachedPacket) {
var buffer = cachedPacket.body(getConnectionState());
var buffer = cachedPacket.body(getServerState());
if (buffer != null) {
System.out.println("SEND " + getConnectionState() + " " + cachedPacket.packet(getConnectionState()).getClass().getSimpleName());
var packetClass = cachedPacket.packet(getServerState()).getClass();
if (packetClass != TimeUpdatePacket.class && packetClass != UpdateLightPacket.class && packetClass != ChunkDataPacket.class) {
System.out.println("SEND " + getServerState() + " " + cachedPacket.packet(getServerState()).getClass().getSimpleName());
}
writeBufferSync(buffer, buffer.position(), buffer.remaining());
}
else writeServerPacketSync(cachedPacket.packet(getConnectionState()), compressed);
else writeServerPacketSync(cachedPacket.packet(getServerState()), compressed);
} else if (packet instanceof LazyPacket lazyPacket) {
writeServerPacketSync(lazyPacket.packet(), compressed);
} else {
@ -373,8 +379,8 @@ public class PlayerSocketConnection extends PlayerConnection {
}
}
try (var hold = ObjectPool.PACKET_POOL.hold()) {
var buffer = PacketUtils.createFramedPacket(getConnectionState(), hold.get(), serverPacket, compressed);
System.out.println("SEND " + getConnectionState() + " " + serverPacket.getClass().getSimpleName() + " " + buffer.limit());
var buffer = PacketUtils.createFramedPacket(getServerState(), hold.get(), serverPacket, compressed);
System.out.println("SEND " + getServerState() + " cls=" + serverPacket.getClass().getSimpleName() + " id=" + serverPacket.getId(getServerState()));
writeBufferSync(buffer, 0, buffer.limit());
}
}

View File

@ -320,7 +320,7 @@ public final class PacketUtils {
private synchronized void append(Viewable viewable, ServerPacket serverPacket, Player player) {
try (var hold = ObjectPool.PACKET_POOL.hold()) {
final ByteBuffer framedPacket = createFramedPacket(player.getPlayerConnection().getConnectionState(), hold.get(), serverPacket);
final ByteBuffer framedPacket = createFramedPacket(player.getPlayerConnection().getServerState(), hold.get(), serverPacket);
final int packetSize = framedPacket.limit();
if (packetSize >= buffer.capacity()) {
process(viewable);