docs(link): the hue belongs where the files are, and the cache poisons it (Phase 5) #240

Merged
whitlocktech merged 1 commits from docs/asset-bridge-p5 into main 2026-09-11 11:26:25 +00:00
Member

Documents Phase 5. Pairs with servuo-plugins#32 and Module-uo#38.

§11.1 is new — what phase 5 measured

Measured
Static ids addressable 49,152
...with real art 39,189
...empty index slots (§4.5's shape) 9,963
Land tiles addressable / with art 16,384 / 4,244
Whole static + land set, as PNG 43,433 files, 81 MB, mean 1.9 KB
Time to decode and encode all of it 34 s
Item ids flagged PartialHue 13,259 of 65,536

Two of those needed saying out loud.

49,152, not the 81,884 entries artidx.mul declares. FileIndex sizes its index table from the length argument it is constructed with (0x10000), not from the idx file. A ceiling read off the file would invent 16,348 ids and answer every one out of an array nobody bounded. The first probe of this phase made exactly that mistake and reported 65,500 — PowerShell returns $null for an out-of-range array index rather than throwing, so the over-run counted silently as "empty slots".

81 MB reopens the bulk question and the answer is still no. Not on size — on what the transfer buys: 108 MB of base64 through a 512 KB single-slot channel, ~210 round trips, to store 43,433 pictures of which a live shard displays a few hundred.

The two traps

The library's cache poisons a hued sprite. Art.GetStatic hands back the same cached Bitmap and Hue.ApplyTo repaints in place, so hueing edits the library's own copy — the plain key comes back hued from then on, and the next hue stacks. §4.5's failure mode reached through a door §4.5 never looked at: phase 0 was auditing records, and this is the library's cache. Files.CacheData = false fixes it and also stops a game server retaining 74 MB of Bitmap. Copying instead does not solve the retention, and new Bitmap(src) throws on ARGB1555 anyway.

PartialHue decides the picture, from a file only the shard has. Item 597 is a wooden screen with painted flowers: one mode reddens the flowers, the other the whole screen, and both decode. Hence land takes no hue segment, and h0 is not a key.

Plus the namespace trap that compiled: unqualified TileData binds to ServUO's own Server.TileData, because the enclosing namespace beats using Ultima;.

The rest

  • §14 — the static and land families, families on assets.sources, and assets.fetch becoming shared plumbing whose family is derived from the keys (§5 made the key the address; a request naming its family too would have two places to be wrong and one of them silent). Additive, so the protocol stays 8 and EXTRACTOR_VERSION stays 2.
  • §15link needed nothing in phases 4 or 5: assets_call forwards a request body verbatim and respond_assets returns the reply verbatim.
  • §17.10 — the four org-lead decisions.
  • §12 and modules/uo/SCHEMA.mduploads/items/, per-row catalog staleness, why shard_asset_meta stays the body catalogue's alone, and why a key with no art writes no row at all.
  • modules/uo/API.mdPOST /shard/assets/warm, and the art field on listings and equipment.

🤖 Generated with Claude Code

https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4

Documents Phase 5. Pairs with servuo-plugins#32 and Module-uo#38. ## §11.1 is new — what phase 5 measured | | Measured | |---|---| | Static ids addressable | **49,152** | | ...with real art | **39,189** | | ...empty index slots (§4.5's shape) | **9,963** | | Land tiles addressable / with art | 16,384 / **4,244** | | Whole static + land set, as PNG | 43,433 files, **81 MB**, mean 1.9 KB | | Time to decode and encode all of it | **34 s** | | Item ids flagged `PartialHue` | **13,259** of 65,536 | Two of those needed saying out loud. **49,152, not the 81,884 entries `artidx.mul` declares.** `FileIndex` sizes its index table from the *length argument it is constructed with* (`0x10000`), not from the idx file. A ceiling read off the file would invent 16,348 ids and answer every one out of an array nobody bounded. The first probe of this phase made exactly that mistake and reported 65,500 — PowerShell returns `$null` for an out-of-range array index rather than throwing, so the over-run counted silently as "empty slots". **81 MB reopens the bulk question and the answer is still no.** Not on size — on what the transfer buys: 108 MB of base64 through a 512 KB single-slot channel, ~210 round trips, to store 43,433 pictures of which a live shard displays a few hundred. ## The two traps **The library's cache poisons a hued sprite.** `Art.GetStatic` hands back the *same* cached `Bitmap` and `Hue.ApplyTo` repaints in place, so hueing edits the library's own copy — the plain key comes back hued from then on, and the next hue stacks. §4.5's failure mode reached through a door §4.5 never looked at: phase 0 was auditing *records*, and this is the library's *cache*. `Files.CacheData = false` fixes it and also stops a game server retaining 74 MB of `Bitmap`. Copying instead does not solve the retention, and `new Bitmap(src)` throws on ARGB1555 anyway. **`PartialHue` decides the picture, from a file only the shard has.** Item 597 is a wooden screen with painted flowers: one mode reddens the flowers, the other the whole screen, and both decode. Hence land takes no hue segment, and `h0` is not a key. **Plus the namespace trap that compiled:** unqualified `TileData` binds to ServUO's own `Server.TileData`, because the enclosing namespace beats `using Ultima;`. ## The rest - **§14** — the `static` and `land` families, `families` on `assets.sources`, and `assets.fetch` becoming shared plumbing whose family is *derived from the keys* (§5 made the key the address; a request naming its family too would have two places to be wrong and one of them silent). Additive, so the protocol stays **8** and `EXTRACTOR_VERSION` stays **2**. - **§15** — `link` needed nothing in phases 4 *or* 5: `assets_call` forwards a request body verbatim and `respond_assets` returns the reply verbatim. - **§17.10** — the four org-lead decisions. - **§12** and **`modules/uo/SCHEMA.md`** — `uploads/items/`, per-row `catalog` staleness, why `shard_asset_meta` stays the body catalogue's alone, and why a key with no art writes no row at all. - **`modules/uo/API.md`** — `POST /shard/assets/warm`, and the `art` field on listings and equipment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude added 1 commit 2026-09-11 11:18:01 +00:00
§11.1 is new and carries what phase 5 measured: 49,152 addressable static ids
(not the 81,884 `artidx.mul` declares -- `FileIndex` sizes its table from its
length ARGUMENT), 39,189 with art, 4,244 land tiles, 9,963 + 12,140 empty index
slots, and the whole set at 81 MB decoding in 34 s. That last number reopens the
bulk question and the answer is still no: 108 MB of base64 through a 512 KB
single-slot channel to store 43,433 pictures a shard displays a few hundred of.

Two traps, both §4.5's failure mode -- a confident, plausible, wrong picture:

- `Art.GetStatic` hands back the SAME cached Bitmap and `Hue.ApplyTo` repaints in
  place, so hueing edits the library's own copy: the plain key comes back hued
  from then on, and the next hue stacks. `Files.CacheData` off process-wide fixes
  it and also stops a game server retaining 74 MB of Bitmap. Copying instead does
  not solve the retention, and `new Bitmap(src)` throws on ARGB1555 anyway.

- `PartialHue` (13,259 of 65,536 ids) decides whether a hue repaints every pixel
  or only the grey ones, from a file only the shard has. Item 597 is a wooden
  screen with painted flowers; one mode reddens the flowers, the other the whole
  screen, and both decode. Hence land takes no hue segment and `h0` is not a key.

Plus the namespace trap that compiled: unqualified `TileData` binds to ServUO's
own `Server.TileData`, because the enclosing namespace beats `using Ultima;`.

§14 records what the wire gained -- the `static` and `land` families, `families`
on `assets.sources`, and `assets.fetch` becoming shared plumbing whose family is
DERIVED from the keys (§5 made the key the address; a request naming its family
too would have two places to be wrong and one of them silent). Additive, so the
protocol stays 8 and EXTRACTOR_VERSION stays 2. §15 records that `link` needed
nothing in phases 4 or 5: it forwards verbatim in both directions.

§17.10 is the four org-lead decisions. §12 and modules/uo/SCHEMA.md carry the
website side: `uploads/items/`, per-row `catalog` staleness, and why a key with
no art writes no row at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
whitlocktech merged commit e1cefa5be2 into main 2026-09-11 11:26:25 +00:00
whitlocktech deleted branch docs/asset-bridge-p5 2026-09-11 11:26:26 +00:00
Sign in to join this conversation.
No description provided.