fix(shard): decode the atlas places objects and render them
#32
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/atlas-places-decode"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
Found by running the M11 on-device five-rung walk against a live shard (ServUO + sidecar + website + AVD) — the gate the
edge→maincutover is waiting on.The blocker:
AtlasCreatureDto.placeswas typedList<String>, but the server sends{facet, label, spawners, maxAlive}objects. The detail route answers200with ~49 KB, kotlinx throws on decode, and the screen renders "Something went wrong on the server" — so the whole Atlas creature page was dead, and the message blamed a server that was fine. Nullable-with-defaults protects against a missing field, never a wrong element type.Because this PR targets
feat/protocol-3-visibility, the fix lands in #30 rather than letting a broken screen reachmainfirst.Changes
AtlasPlaceDtoadded andplacesretyped — the actual fix.artfield added so a decode can't depend on the server not sending it. Neither client renders creature art today; not changing that here, since doing so app-only would break parity the other way.placeswas never rendered at all, so the aggregate the atlas exists to give — "Shrines, Isamu-Jima, Yew", resolved server-side by point-in-rect — was missing from the app while the web page leads with it. Placed above the individual spawners, matching web's ordering.top.The root cause worth fixing, not just the symptom
ShardContentDtoTestis the first decode test any of the four Protocol 3.0 DTOs has had. The fakes indata/api/fake/construct DTOs directly in Kotlin, so no test in the suite could ever see a wire mismatch —PLAN.md§9 already required "DTO decode for each new shape" and it hadn't been done. The new tests feed payloads captured from a live server, and cover the projected/empty shapes the visibility framework produces as well.How it was tested
./gradlew testDebugUnitTest lintDebug assembleDebug -Pksp.incremental=false— 344 tests, 0 failures, lint clean (was 336).playerrung withmarket.ownerNamegated tostaff: the "Kept by …" line correctly disappears while the location stays.Docs for the
placesshape and the decode-test rule: RunicGateway/docs#76.Checklist
AI-assisted contributions (required)
Claude Code (Opus 5). I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with aCo-Authored-By/Assisted-Bytrailer.License
🤖 Generated with Claude Code
https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP
placesobjects and render them 4f85021be2`AtlasCreatureDto.places` was typed `List<String>` while the server sends `{facet, label, spawners, maxAlive}` objects. The detail route answers 200 with ~49 KB, kotlinx throws on decode, and the screen renders "Something went wrong on the server" — so the whole Atlas creature page was dead, and the error blamed a server that was fine. Nullable-with-defaults protects against a missing field, never a wrong element type. Adds AtlasPlaceDto, plus the `art` field the server also sends, so a decode cannot depend on that staying absent (neither client renders art yet). `places` was never rendered either, so the aggregate the atlas exists to give — "Shrines, Isamu-Jima, Yew", resolved server-side by point-in-rect — was missing from the app while the web page led with it. Adds a "Where it spawns" section above the individual spawners, matching web's ordering, and a plural for the spawner count now that single-spawner places are on screen in bulk. Adds ShardContentDtoTest — the first decode test any of the four Protocol 3.0 DTOs has had, fed payloads captured from a live server. That absence is the root cause: the fakes in data/api/fake/ construct DTOs in Kotlin, so no test in the suite could see a wire mismatch, even though PLAN.md §9 already required "DTO decode for each new shape". Also renders a placeholder row on an unscored leaderboard (the instance name, em dash where a score goes) rather than a blank card — deliberately not shaped like a real entry, since a placeholder that looked like a standing would be a fabricated one. Found by the on-device five-rung walk against a live shard; all four screens re-verified on the emulator afterwards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U7CBg11prhLimL9iHSX1bP