perf: batch packet-log UI; rename Send/Recv tags to Client/Server#5
perf: batch packet-log UI; rename Send/Recv tags to Client/Server#5erwan-joly merged 2 commits intomasterfrom
Conversation
…rver Drain captured packets on a 50 ms UI-thread Timer into a single BeginUpdate/AddRange/EndUpdate block instead of BeginInvoke-ing the UI thread once per packet. At high packet rates this was saturating the message loop; the batched path keeps the ListBox responsive. Cache the formatted display string on LoggedPacket so repaints don't re-format per item. Select All now runs inside BeginUpdate/EndUpdate so 5000-item selection no longer fires a paint per SetSelected call. Rename the direction tag from [Send]/[Recv] to [Client]/[Server] — it was ambiguous whether "Send" meant sent by client or sent by server. [Client] now unambiguously marks packets that originated on the game client (client→server) and [Server] marks packets that originated on the server (server→client). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR introduces packet validation functionality to the developer tools. A new Changes
Sequence DiagramsequenceDiagram
participant UI as MainForm UI
participant PLS as PacketLogService
participant Val as PacketValidationService
participant Queue as ConcurrentQueue
participant Timer as Update Timer
PLS->>UI: PacketLogged event
activate UI
UI->>Val: Validate(packet)
activate Val
Val->>Val: Reflect on PacketBase types
Val->>Val: Extract header token
Val->>Val: Attempt deserialization
Val-->>UI: PacketValidationIssue or null
deactivate Val
UI->>Queue: Enqueue packet & issue
deactivate UI
Timer->>Queue: Periodic flush
activate Queue
Queue->>UI: Batch add to log listbox
Queue->>UI: Batch add to issues listbox
Queue->>UI: Update failed headers
deactivate Queue
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
#6) * feat: Issues sub-tab detecting Missing / WrongStructure / WrongTag packets Every captured packet is run through NosCore.Packets's deserializer against its expected direction, and anomalies are logged in a new Issues sub-tab under the Packets tab: - Missing — header not defined anywhere in NosCore.Packets. - WrongStructure — header defined for this direction but the deserializer rejects the wire format. - WrongTag — header is defined only in the opposite-direction namespace (client header captured as [Server], or vice versa). Uses two separate Deserializer instances so the "server loses to client on duplicate header" dedup inside Deserializer.Initialize<T> doesn't hide wrong-tag cases. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: filter packet types to PacketBase-derived only NosCore.Packets has classes marked with [PacketHeader] that don't inherit from PacketBase (e.g. ServerPackets.Event.EventPacket). Passing those to Deserializer crashed startup: ArgumentException: GenericArguments[0], 'EventPacket', on 'Void Initialize[T]()' violates the constraint of type 'T'. Add an IsAssignableFrom(PacketBase) filter before constructing the deserializers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: Copy / Copy with tags / Select all on the Issues listbox Same context menu + Ctrl+C / Ctrl+A handling the Log listbox has, now on Issues too. Parameterised so the listbox is passed in rather than hard-coded to _logListBox. Copy picks up Raw text for both item types (LoggedPacket.Raw and PacketValidationIssue.Packet.Raw); Copy with tags uses the full ToString() line — including the [Missing] / [Wrong structure] / [Wrong tag] category and the deserializer detail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: colored stripe on Log rows that have a validation issue Each LoggedPacket carries a nullable ValidationCategory set when the validator flags it. The Log listbox is owner-drawn and paints a 4px left stripe per row: gold for Missing, indian-red for WrongStructure, dark-orange for WrongTag. Selection highlighting still works — the stripe sits over the normal row background. Lets you see problematic packets at a glance while reading the Log, without having to switch to the Issues tab for every packet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat: failed-headers summary on Issues; drop plain Copy on Issues menu - Issues sub-tab gets a read-only TextBox docked at the top listing every packet header that failed validation (unique, sorted). Cleared with the log. - Context menu on Issues drops the raw "Copy" option — only "Copy with tags" makes sense there since the tags carry the category and deserializer detail. Ctrl+C on the Issues listbox now copies with tags; Log listbox behavior is unchanged. - Clear handling consolidated into the PacketLogService.Cleared event so both the Clear button and any future direct clear call empty the log, issues queue, issues listbox, and failed-headers set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: register sub-packet types so 'key not present in dictionary' goes away Deserializer.DeserializeValue looks up sub-packet property types by typeof(T).Name in _packetDeserializerDictionary. Sub-packets don't carry [PacketHeader] — my original type filter excluded them, so every parent packet with a sub-packet field failed with e.g. The given key 'InCharacterSubPacket' was not present in the dictionary. Register all PacketBase-derived types without [PacketHeader] on both client and server deserializer instances (they're direction-neutral). Keep the _clientHeaders / _serverHeaders sets populated from header- bearing types only so the direction-match check still works. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: skip the three pre-auth login-handshake lines in validator Every world-server connection opens with three bare lines from the client before the encrypted packet stream: <sessionId> — single numeric token <account> GF <n> — username / platform / region thisisgfmode — GF-mode marker None of them use the header protocol so NosCore.Packets legitimately doesn't define them. Flagging them as Missing was pure noise on the Issues tab. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
BeginInvoke+ oneListBox.Items.Add+ oneTopIndexupdate per packet. At high packet rates that saturated the message loop — the log got visibly laggy and Select All could stall the UI for seconds. Now the capture path just enqueues onto aConcurrentQueue, and a 50 ms UI-threadTimerdrains the queue into a singleBeginUpdate/AddRange/EndUpdateblock.SetSelectedloop used to repaint per call. Wrapped inBeginUpdate/EndUpdate.LoggedPacket.ToString()is called on every repaint per visible row. Formatted string is now computed once in the record's field initializer.[Send]/[Recv]were ambiguous (send by whom?). Replaced with[Client](originated on the game client, i.e. client→server) and[Server](originated on the server, i.e. server→client).Test plan
[World] [Client]/[World] [Server].Summary by CodeRabbit
Release Notes
New Features
Improvements