feat(asset-bridge): item and land art on demand, hued where the files are (Phase 5) #32
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/asset-bridge-p5"
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?
Phase 5 of the Asset Bridge (
docs/link/v8.md§5, §11, §11.1). Protocol stays 8;EXTRACTOR_VERSIONstays 2.The body catalogue is a set. This is not: this client addresses 49,152 static ids and has art for 39,189, plus 4,244 land tiles of 16,384 — and hues multiply the statics by three thousand. So there is no manifest and no scan.
assets.fetchgrows two families and answers the keys the website's own data names.assets.fetchbecomes shared plumbingPhase 3 gave the command to the body catalogue outright, which was right with one family and wrong with three.
BridgeAssetsnow owns it, does thereqId/ consent / key-ceiling checks once, derives the family from the keys themselves and dispatches to the reader that registered it.§5 made the key the address of an asset; a request that also named its family would have two places to be wrong and one of them silent. A batch must be of one family — mixing is refused 400 — because the reply carries a single
catalogid and two families have two fingerprints.assets.sourcesgainsfamilies. Additive, so the protocol stays 8 — and without it a website talking to a phase-4 overlay discovers the gap as a refusal per key, per pass, forever, with no picture ever appearing.Two traps, both §4.5's failure mode: a confident, plausible, wrong picture
The library's cache poisons a hued sprite.
Art.GetStaticandArt.GetLandmemoise into a staticBitmap[0xFFFF]and hand back the same instance;Hue.ApplyTorepaints in place. Measured before the fix: hue item 3922 once, and every later request for the plain 3922 comes back hued, with the next hue stacking on the first. The key is right, the dimensions are right, the hash is stable — nothing downstream can see it.Files.CacheDatais now off for the life of the process. It pays twice: that array is never trimmed, so decoding this client's 39,189 statics would otherwise leave 74 MB ofBitmapin a static field of a game server.TryHuere-checks the flag and refuses rather than risk it, and the same flag decides whether a bitmap is ours to dispose. Copying instead does not solve the retention — andnew Bitmap(src)throws on theFormat16bppArgb1555these decoders produce.PartialHuedecides the picture, and only the shard can read it. A hue is a 32-entry ramp out ofhues.mulindexed by each pixel's red channel; whether it replaces every pixel or only the grey ones is a per-item-id flag intiledata.mul— 13,259 of 65,536 ids on this client. Item 597 is a wooden screen with painted flowers: hued 33 one way the flowers turn red, the other way the whole screen does. Both decode, both are 44×112, both report success.So land takes no hue segment (the mode is an item flag; land has no equivalent, and guessing is how you get a wrong picture) and
h0is not a key (hue 0 means "not hued", so the plain key already names it).The namespace trap that compiled
The first cut wrote
TileData.ItemTableunqualified. ServUO declares its ownServer.TileData/Server.ItemData/Server.TileFlag— with aPartialHuemember — and this file lives inServer.Custom.Bridge, where the enclosing namespace beatsusing Ultima;. It compiled, and at runtime read a file resolved throughCore.DataDirectoriesinstead ofUltima.Files— §4.6's rule broken in a new place. The live rig caught it as aTypeInitializationExceptionrefusing every hued key, from a class the code never meant to name. Every such type is spelledUltima.now.Measured
Through the reader itself, over the whole range on a stock client:
Nothing that carries art is refused, which is the half of the measurement that says the boundary is in the right place (§4.5).
Live walk, real ServUO + real sidecar
assets.sources→families: ["body","land","static"],artDataFile: artlegacymul.uopstatic/597/h33→partialHue: true;static/1/h33→false; rendered and checked by eye (the flowers go red, the wood does not)land/3,land/0,land/16383ok;land/3/h33,static/3922/h0,static/3922/h3001,static/60000→unsupported, each with a reasoncatalog→ 422cursor: k:129, resumes atstatic/130body/400/a0(legacy) andbody/666/a0(uop) unchanged — the catalogue is untouchedScripts compile clean against ServUO 57.4; no shard console warnings across the walk.
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4