From 1caa46f846b012f421df0b548afbe0d34dfed922 Mon Sep 17 00:00:00 2001 From: neckfire Date: Tue, 14 Jul 2026 19:21:49 +0200 Subject: [PATCH] fix(game-server): adopt client packet sequences on first packet The Cycle client does not derive its initial packet sequences from the handshake cookie the way stock UE does (its acked server-seq isn't present anywhere in the cookie), so the cookie-based InitSequence disagreed and every post-handshake packet was rejected as out-of-order. On the first packet, adopt the client's announced Seq/AckedSeq instead. Co-Authored-By: Claude Opus 4.8 --- src/Prospect.Unreal/Net/UNetConnection.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Prospect.Unreal/Net/UNetConnection.cs b/src/Prospect.Unreal/Net/UNetConnection.cs index 358070a..36674fc 100644 --- a/src/Prospect.Unreal/Net/UNetConnection.cs +++ b/src/Prospect.Unreal/Net/UNetConnection.cs @@ -267,6 +267,8 @@ public abstract class UNetConnection : UPlayer /// /// Full incoming packet index. /// + private bool _bAdoptedInitialSequence; + public int InPacketId { get; private set; } /// @@ -540,6 +542,25 @@ public abstract class UNetConnection : UPlayer } var packetSequenceDelta = PacketNotify.GetSequenceDelta(header); + + // The Cycle client doesn't derive its initial packet sequences from the handshake + // cookie the way stock UE does, so our cookie-based InitSequence disagrees with it + // and every packet looks out-of-order. On the very first packet, adopt the client's + // announced sequences (Seq + AckedSeq) instead of the cookie-derived ones. + if (packetSequenceDelta <= 0 && !_bAdoptedInitialSequence && Driver != null && Driver.IsServer()) + { + _bAdoptedInitialSequence = true; + var adoptIn = new SequenceNumber((ushort)(header.Seq.Value - 1)); + var adoptOut = new SequenceNumber((ushort)(header.AckedSeq.Value + 1)); + PacketNotify.Init(adoptIn, adoptOut); + InPacketId = header.Seq.Value - 1; + OutPacketId = header.AckedSeq.Value + 1; + OutAckPacketId = header.AckedSeq.Value; + LastNotifiedPacketId = OutAckPacketId; + Logger.Information("[HS-SEQ] Adopted client sequences: inSeq={In} outSeq={Out}", header.Seq.Value, header.AckedSeq.Value + 1); + packetSequenceDelta = PacketNotify.GetSequenceDelta(header); + } + if (packetSequenceDelta > 0) { var bPacketOrderCacheActive = !_bFlushingPacketOrderCache && _packetOrderCache != null;