6.2 KiB
Code review — NEO-72 client inventory snapshot HUD
Date: 2026-05-24
Scope: Branch NEO-72-client-inventory-snapshot-hud · commits 1273296–e7a61a1 vs origin/main
Base: origin/main
Follow-up: Review feedback addressed in e7a61a1 (header types, tests, docs).
Verdict
Approve with nits — blocking header-type bug fixed; integration tests now exercise handler payloads; remaining nits are deferred (HTTP 500 test, unused inventorySlotKind in HUD).
Summary
The branch adds inventory_client.gd and item_definitions_client.gd, boot wiring and InventoryLabel rendering in main.gd, I → inventory_refresh, GdUnit suites, manual QA, and module/alignment doc updates. The design follows NEO-32/NEO-24 patterns (thin clients, _busy guard, authority config copy, HUD error line + push_warning). Documentation is thorough and matches the adopted kickoff decisions (defs cache, display names, manual refresh). Follow-up commit e7a61a1 corrects request_completed header typing so handlers run under real HTTPRequest and mock transports.
Documentation checked
| Document | Result |
|---|---|
docs/plans/NEO-72-implementation-plan.md |
Matches — acceptance checklist complete; reconciliation section present; kickoff decisions reflected in code. |
docs/plans/E3S5-client-prototype-backlog.md · E3S5-01 |
Matches — acceptance criteria checked; scope/out-of-scope honored. |
docs/decomposition/modules/E3_M3_ItemizationAndInventorySchema.md |
Matches — NEO-72 client HUD landed note added. |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
Matches — E3.M3 row notes NEO-72; Slice 5 remaining stories cited. |
docs/decomposition/modules/module_dependency_register.md |
Matches — E3.M3 note now includes NEO-72 client HUD (e7a61a1). |
docs/manual-qa/NEO-72.md |
Matches — boot empty, seed + refresh, server-down error, I refresh. |
client/README.md inventory HUD section |
Matches — endpoints, bindings, refresh contract for NEO-73; automated test scope updated (e7a61a1). |
| Full-stack epic decomposition | Matches — this is the E3S5-01 client counterpart; Godot manual QA present; does not claim Slice 5 capstone complete. |
Blocking issues
Done.request_completedheader parameter type — Inclient/scripts/inventory_client.gdandclient/scripts/item_definitions_client.gd,_on_request_completeddeclares_headers: PackedByteArray. Every other HTTP client inclient/scripts/uses_headers: PackedStringArray(e.g.cooldown_snapshot_client.gd,hotbar_loadout_client.gd,position_authority_client.gd). GodotHTTPRequest.request_completedemitsPackedStringArrayheaders. GdUnit mock transports match that. Running the new suites logs:ERROR: Error calling from signal 'request_completed' to callable: … Cannot convert argument 3 from PackedStringArray to PackedByteArray.The handler never runs, soinventory_received/definitions_readydo not fire and the HUD stays on Loading… (or never refreshes display names). Fix: change both handlers to_headers: PackedStringArray(body staysPackedByteArray).e7a61a1— both clients usePackedStringArray; GdUnit suites pass with no conversion errors.
Suggestions
-
Re-run integration tests after header fix — Confirm signal assertions still pass and Godot Output has noDone.request_completedconversion errors. Consider asserting payload contents intest_request_sync_emits_inventory_received(e.g.bagSlots.size() == 24) so a silent handler failure cannot pass.e7a61a1— inventory test captures snapshot and asserts 24 bag + 1 equipment slots. -
Done.display_name_forcoverage — Add one GdUnit test that loads defs via mock transport then callsdisplay_name_for("scrap_metal_bulk")on the client instance (plan implied lookup helper coverage; only staticbuild_definitions_mapis exercised today).e7a61a1—test_display_name_for_after_request_sync. -
Done.module_dependency_register.mdE3.M3 note — Append a NEO-72 client HUD landed clause to match the alignment register row (non-blocking doc parity).e7a61a1. -
Done.client/README.mdautomated tests scope — The “Scope” bullet list under Automated tests still omits the new inventory/defs clients; add them when convenient so discoverability matches NEO-72.e7a61a1.
Nits
Nit:Done.item_definitions_client_test.gdhas overlapping parse tests (test_parse_mock_transport_json_body,test_handler_body_bytes_parse_builds_map) that duplicatetest_build_definitions_map_extracts_display_name; consolidate when touching tests for the header fix.e7a61a1— removed duplicate parse tests.- Nit: Plan tests table mentions HTTP 500 for
inventory_sync_failed; only 404 is covered — acceptable for prototype once happy + 404 + malformed JSON paths work. Deferred — 404 + malformed JSON sufficient for merge. - Nit:
inventorySlotKindis cached but unused in HUD formatting (plan listed it as optional row prefix — fine to defer). Deferred.
Verification
After fixing header types:
cd client
godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --ignoreHeadlessMode \
-a res://test/inventory_client_test.gd -a res://test/item_definitions_client_test.gd
Confirm no Cannot convert argument 3 from PackedStringArray to PackedByteArray in output. Verified on e7a61a1.
Manual (required before merge — validates real HTTPRequest path):
cd server/NeonSprawl.Server && dotnet run- Godot F5 — follow
docs/manual-qa/NEO-72.md(boot empty bag, curl seed,Irefresh with display name, server stopped → HUD error).