feat(asset-bridge): the 73 bodies action 0 could not see, and the ceiling that makes looking safe (Phase 6) #33
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/asset-bridge-p6"
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
Phase 6 of the Asset Bridge (
docs/link/v8.md§4.10, §11.2 — protocol 8). Not the phase §16 planned: the measurement came first and the org lead's scope answer (2026-09-11) removed most of it — the site displays still pictures, so deep frame keys and the bulk-fill switch were not built. Docs PR has the numbers.What shipped is what the still-picture site was missing.
The catalogue looks past action 0. 73 of this client's bodies have no art there and real art deeper — body 820's first drawn action is 23, and it is a horse. They were absent from the catalogue and rendered as text on the bestiary. The catalogue now takes the first action that has art and the key names that action (
body/820/a23), so it is still exactly one row per body and the row says which picture it is. 1,022 → 1,095.The action ceiling (§4.10), without which the fallback walk is the bug. A body's actions are a contiguous band and the next body's slots begin immediately after, so one action past the ceiling is a real record of a different creature. Measured over the 795 legacy bodies:
Body 1 action 22 is an ettin, body 3's is an imp — confirmed by rendering them beside the body they belong to. Nothing about those records is defective, so the only defence is to refuse the address: the ceiling lives in
BridgeAssetValidator.ResolveAnimation, where every caller already goes.The ceiling is the banding, never
Animations.GetAnimLength. That function disagrees with the index arithmetic on exactly one body of this client — a body reaching file type 5 as id 34 owns 13 actions while it answers 22 — and the gap is nine actions of somebody else's art.A fetch serves only the key the catalogue chose.
body/820/a0andbody/400/a2come backunsupportedwith the chosen action alongside, never by decoding what was asked for.EXTRACTOR_VERSION2 → 3 (unchanged input, a different answer). Protocol stays 8 —actionon a row is additive.linkneeds nothing.How it was tested
Compiled (
dotnet build Scripts.csproj -c Release— 0 warnings, 0 errors), then the real rig: sidecar, then ServUO, then REST.GET /assets/sources→extractorVersion 3, familiesbody/land/staticGET /assets/manifest?family=body→ 1,095 rows in one page, 1,991 ms (cold scan of all 2,047 bodies was 1,409 ms before this phase), every row carryingaction, 73 of them non-zeroPOST /assets/fetch→body/820/a23body/820/a0unsupported,action: 23body/400/a2unsupported,action: 0body/1/a22unsupported,action: 0body/400/a0/f3unsupportedThe ceiling directly: body 1 a21 resolves, a22 refused; body 400 a34 resolves, a35 refused; body 276 (→ 34 in anim5) a12 resolves, a13 refused.
All 73 fallback sprites rendered and inspected. The 7 legacy ones and ~12 UOP ones are recognisable creatures (horse, spider, dragon, phoenix, turkey); most of the remaining UOP ones are thin flat object/equipment sprites — correct by construction (a UOP entry is addressed by a name carrying body and action, and the payload re-declares the body) and never surfaced unless a spawn file names them.
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-Bytrailer.🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4