From 50b868229a4a4358418b7e1106f95b1448df9be6 Mon Sep 17 00:00:00 2001 From: mworzala Date: Tue, 28 Nov 2023 17:30:59 +0200 Subject: [PATCH] feat: player spawning fixes --- .../server/entity/EntitySpawnType.java | 3 +- .../net/minestom/server/entity/Player.java | 11 ++++-- .../fakeplayer/FakePlayerController.java | 3 +- .../manager/PacketListenerManager.java | 6 --- .../server/network/ConnectionManager.java | 4 ++ .../server/network/PacketProcessor.java | 19 +++++++--- .../packet/server/play/SpawnPlayerPacket.java | 37 ------------------- 7 files changed, 28 insertions(+), 55 deletions(-) delete mode 100644 src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java diff --git a/src/main/java/net/minestom/server/entity/EntitySpawnType.java b/src/main/java/net/minestom/server/entity/EntitySpawnType.java index c1d23ebdb..67182a506 100644 --- a/src/main/java/net/minestom/server/entity/EntitySpawnType.java +++ b/src/main/java/net/minestom/server/entity/EntitySpawnType.java @@ -6,7 +6,6 @@ import net.minestom.server.entity.metadata.other.ExperienceOrbMeta; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.play.SpawnEntityPacket; import net.minestom.server.network.packet.server.play.SpawnExperienceOrbPacket; -import net.minestom.server.network.packet.server.play.SpawnPlayerPacket; public enum EntitySpawnType { BASE { @@ -24,7 +23,7 @@ public enum EntitySpawnType { PLAYER { @Override public ServerPacket getSpawnPacket(Entity entity) { - return new SpawnPlayerPacket(entity.getEntityId(), entity.getUuid(), entity.getPosition()); + return EntitySpawnType.basicEntity(entity); } }, EXPERIENCE_ORB { diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index a4352b99a..b04be8b9f 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -57,6 +57,7 @@ import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.ConnectionState; import net.minestom.server.network.PlayerProvider; import net.minestom.server.network.packet.client.ClientPacket; +import net.minestom.server.network.packet.server.CachedPacket; import net.minestom.server.network.packet.server.SendablePacket; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; @@ -163,7 +164,9 @@ public class Player extends LivingEntity implements CommandSender, Localizable, private final AtomicInteger teleportId = new AtomicInteger(); private int receivedTeleportId; - private final MessagePassingQueue packets = new MpscUnboundedXaddArrayQueue<>(32); + private record PacketInState(ConnectionState state, ClientPacket packet) {} + + private final MessagePassingQueue packets = new MpscUnboundedXaddArrayQueue<>(32); private final boolean levelFlat; private final PlayerSettings settings; private float exp; @@ -1977,8 +1980,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable, * * @param packet the packet to add in the queue */ - public void addPacketToQueue(@NotNull ClientPacket packet) { - this.packets.offer(packet); + public void addPacketToQueue(@NotNull ConnectionState state, @NotNull ClientPacket packet) { + this.packets.offer(new PacketInState(state, packet)); } @ApiStatus.Internal @@ -1990,7 +1993,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.getClientState(), packet, playerConnection), PACKET_PER_TICK); + this.packets.drain(packet -> manager.processClientPacket(packet.state, packet.packet, playerConnection), PACKET_PER_TICK); } /** diff --git a/src/main/java/net/minestom/server/entity/fakeplayer/FakePlayerController.java b/src/main/java/net/minestom/server/entity/fakeplayer/FakePlayerController.java index 0d779bfc9..5022e7833 100644 --- a/src/main/java/net/minestom/server/entity/fakeplayer/FakePlayerController.java +++ b/src/main/java/net/minestom/server/entity/fakeplayer/FakePlayerController.java @@ -206,6 +206,7 @@ public class FakePlayerController { * @param clientPlayPacket The packet to add in the queue. */ private void addToQueue(ClientPacket clientPlayPacket) { - this.fakePlayer.addPacketToQueue(clientPlayPacket); + //todo fix me +// this.fakePlayer.addPacketToQueue(clientPlayPacket); } } diff --git a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java index 97bd8024b..b0fa9959c 100644 --- a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java +++ b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java @@ -130,12 +130,6 @@ 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) { - connection.setClientState(nextState); - } } /** diff --git a/src/main/java/net/minestom/server/network/ConnectionManager.java b/src/main/java/net/minestom/server/network/ConnectionManager.java index bd8ac6571..0b7929da6 100644 --- a/src/main/java/net/minestom/server/network/ConnectionManager.java +++ b/src/main/java/net/minestom/server/network/ConnectionManager.java @@ -292,6 +292,10 @@ public final class ConnectionManager { // Interpret packets for configuration players for (var player : configurationPlayers) { // System.out.println("CONFIG INTERPRET: " + player.getUsername()); + + //todo we are required to do this because when we wait for the config ack packet we are not in an instance so not ticking. + // but then once we switch to config the packets must be eval-ed immediately because we are in an instance. What if we change + // the protocol state swap to happen immediately when the packet is read, not when its processed? player.interpretPacketQueue(); } } diff --git a/src/main/java/net/minestom/server/network/PacketProcessor.java b/src/main/java/net/minestom/server/network/PacketProcessor.java index f37c0e7f4..595ace1f1 100644 --- a/src/main/java/net/minestom/server/network/PacketProcessor.java +++ b/src/main/java/net/minestom/server/network/PacketProcessor.java @@ -53,16 +53,25 @@ public class PacketProcessor { } public ClientPacket process(@NotNull PlayerConnection connection, int packetId, ByteBuffer body) { - System.out.println("READ: " + connection.getClientState() + " " + packetId); +// System.out.println("READ: " + connection.getClientState() + " " + packetId); final ClientPacket packet = create(connection.getClientState(), packetId, body); final ConnectionState state = connection.getClientState(); - System.out.println("READ2: " + state + " " + packet.getClass().getSimpleName()); +// System.out.println("READ2: " + state + " " + packet.getClass().getSimpleName()); + + // If the packet intends to switch state, do it now. + // Since packets are processed next tick for players, we have to switch immediately. + // TODO HOWEVER THIS WILL NOT ACTUALLY WORK BECAUSE WHEN WE QUEUE THE PACKET IT HAS THE WRONG LISTENER. + var nextState = packet.nextState(); + if (nextState != null && state != nextState) { + connection.setClientState(nextState); + } + switch (state) { - case HANDSHAKE, STATUS, LOGIN, CONFIGURATION -> packetListenerManager.processClientPacket(connection.getClientState(), packet, connection); - case PLAY -> { + case HANDSHAKE, STATUS, LOGIN -> packetListenerManager.processClientPacket(state, packet, connection); + case CONFIGURATION, PLAY -> { final Player player = connection.getPlayer(); assert player != null; - player.addPacketToQueue(packet); + player.addPacketToQueue(state, packet); } } return packet; diff --git a/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java deleted file mode 100644 index 06e60d21f..000000000 --- a/src/main/java/net/minestom/server/network/packet/server/play/SpawnPlayerPacket.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.minestom.server.network.packet.server.play; - -import net.minestom.server.coordinate.Pos; -import net.minestom.server.network.ConnectionState; -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 java.util.UUID; - -import static net.minestom.server.network.NetworkBuffer.*; - -public record SpawnPlayerPacket(int entityId, @NotNull UUID playerUuid, - @NotNull Pos position) implements ServerPacket { - public SpawnPlayerPacket(@NotNull NetworkBuffer reader) { - this(reader.read(VAR_INT), reader.read(UUID), - new Pos(reader.read(DOUBLE), reader.read(DOUBLE), reader.read(DOUBLE), - (reader.read(BYTE) * 360f) / 256f, (reader.read(BYTE) * 360f) / 256f)); - } - - @Override - public void write(@NotNull NetworkBuffer writer) { - writer.write(VAR_INT, entityId); - writer.write(UUID, playerUuid); - writer.write(DOUBLE, position.x()); - writer.write(DOUBLE, position.y()); - writer.write(DOUBLE, position.z()); - writer.write(BYTE, (byte) (position.yaw() * 256f / 360f)); - writer.write(BYTE, (byte) (position.pitch() * 256f / 360f)); - } - - @Override - public int getId(@NotNull ConnectionState state) { - throw new UnsupportedOperationException("SpawnPlayerPacket is not supported in " + state); - } -}