docs(link): name it the Asset Bridge, and make libgdiplus a stated requirement

The work has a name now — the Asset Bridge — for commits, PR titles, branches
(feat/asset-bridge-p<n>) and conversation. Protocol number stays 8 and the file
stays docs/link/v8.md.

§4.4 closes the last real open question rather than deferring it to phase 0, and
takes all three answers instead of choosing one. ServUO targets net48, so a Linux
host runs it under Mono, and Mono's System.Drawing is a thin layer over
libgdiplus — which §4.2 put in the decode path, not just the encode. So on Linux
it is a hard prerequisite for art. Cliloc and atlas import are unaffected; neither
touches pixels. Windows hosts need nothing at all.

It is now written down as: a SHARD_PREREQS.md entry, a doctor check in the
installer, and a named NO_IMAGING status when it is missing, in the same family
as the cliloc reader's COMPRESSED — never a stack trace, never a 500. Install
routes per distro are in the section, apt-get install libgdiplus being the
normal one.

One fact recorded because depending on something unmaintained should be a
conscious act: github.com/mono/libgdiplus was ARCHIVED in March 2025 and is
read-only. Distributions still package and patch it, so installing it today is
supported and ordinary — but it is the strongest long-term argument for moving
extraction off System.Drawing eventually, and phase 4's UOP reader is written
without it so that door stays open.

§17 restructured: three settled items kept because each changes numbers
elsewhere, and one genuinely open question (the default audience) that does not
block starting.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
2026-09-10 02:01:07 -05:00
parent d39e4163d1
commit 041e1f4069

View File

@@ -1,7 +1,13 @@
# Protocol 8 — Client assets over the bridge
# Asset Bridge (Protocol 8)client assets without UOFiddler
**Call it the Asset Bridge.** That is the name for this work everywhere — commits, PR titles,
branches (`feat/asset-bridge-p<n>`), and conversation. The protocol number is **8** and this file is
`docs/link/v8.md`.
**Status:** Design of record. Approved in principle 2026-09-09 (architecture, asset scope,
built-in cliloc decoder, atlas cleanup); §17 lists what is still open.
built-in cliloc decoder, atlas cleanup); refined 2026-09-10 (one direction not five, ServUO's own
decoders, the UOP reader for player bodies, the libgdiplus requirement). §17 lists what is still
open.
**Supersedes the manual half of:** [`../website/UOFIDDLER.md`](../website/UOFIDDLER.md),
[`../website/CLILOCS.md`](../website/CLILOCS.md) §Converting,
[`../website/SPAWN_ATLAS.md`](../website/SPAWN_ATLAS.md) §Artwork and §Configuring the tree.
@@ -181,8 +187,8 @@ Three costs come with it, all known and none of them blocking:
not merely accepted: §4.3 adds a decoder for it**, because it is the player character and the
scope says player models.
2. **`System.Drawing` is a hard dependency, in the decode and not just the encode.** `Frame`
writes ARGB1555 straight through a `LockBits` pointer, so a Linux/Mono shard needs libgdiplus
to read a sprite at all. See §17.
writes ARGB1555 straight through a `LockBits` pointer, so a Linux shard needs **libgdiplus** to
read a sprite at all. That is a stated prerequisite — §4.4.
3. **We inherit whatever `Ultima` a given ServUO vendors**, which can change under a shard upgrade.
`EXTRACTOR_VERSION` (§7) is the mitigation: it already counts as drift, so a shard whose library
changed re-derives on the next import.
@@ -217,6 +223,47 @@ silently puts a spider on the gargoyle page, and no error is raised anywhere. A
correct behaviour; a plausible wrong picture is the failure this protocol most needs to avoid,
because nothing downstream can detect it.
### 4.4 Requirement: a Linux shard host needs libgdiplus
**Stated prerequisite, not a soft recommendation.** ServUO targets `net48`, so on Linux it runs under
Mono, and Mono's `System.Drawing` is a thin layer over **libgdiplus**. §4.2 put `System.Drawing` in
the decode path, so without that library a Linux shard cannot extract art at all — the cliloc table
(§9) and the atlas files (§10) are unaffected, since neither touches pixels.
**Windows shard hosts need nothing.** `System.Drawing` ships with .NET Framework. This is a
Linux-only prerequisite and most shards will never read this section.
| Host | Get it with |
|---|---|
| Debian / Ubuntu | `sudo apt-get install libgdiplus` — in Debian since bullseye (6.0.4) and bookworm/trixie (6.1), and in Ubuntu universe |
| Fedora / RHEL | `sudo dnf install libgdiplus` (EPEL or the Mono repository) |
| Docker | `RUN apt-get update && apt-get install -y libgdiplus` in the shard image |
| Alpine, or a distro with no package | Build from source — see the repository below. This is the awkward case and is worth avoiding by choosing a Debian-based image |
Upstream is <https://github.com/mono/libgdiplus>, with the Mono project's own page at
<https://www.mono-project.com/docs/gui/libgdiplus/>.
**One thing to know before depending on it: that repository was archived in March 2025 and is
read-only.** Distributions still package and patch it, so `apt-get install libgdiplus` is a normal,
supported thing to do today — but upstream is not maintained. It is the strongest long-term argument
for eventually moving extraction off `System.Drawing`, and phase 4's UOP reader (§4.3) is written
without it precisely so that door stays open. It does not change the decision now.
**How its absence must present.** Never a stack trace and never a 500. Missing libgdiplus is a
named, actionable outcome in the same family as the cliloc reader's `COMPRESSED`:
```
status: unavailable
code: NO_IMAGING
reason: This shard host cannot render images — Mono's System.Drawing needs libgdiplus.
Install it (apt-get install libgdiplus) and re-run the import. Cliloc and
atlas import are unaffected.
```
The installer's `doctor` checks for it and reports it alongside its other host checks, so an
operator learns about this while setting the shard up rather than from an empty bestiary weeks
later.
---
## 5. Addressing: one key for every asset
@@ -556,8 +603,8 @@ disagree, so a split bump means the next bundle silently fails to compose.
| `link/` | Six command families forwarded, the REST surface, **the inbound line cap (§3.3)**, `PROTOCOL_VERSION` |
| `module-uo/` | Client calls, asset store, the atlas source backend (§10), cliloc ingest, admin surface |
| `website/` | None expected — `ctx.uploads` already suffices (§12) |
| `docs/` | This file; rewrite `CLILOCS.md` §Converting and `SPAWN_ATLAS.md` §Artwork + §Configuring; **delete `UOFIDDLER.md`** |
| `installer/` | None expected; the bundle pairing already enforces §15 |
| `docs/` | This file; rewrite `CLILOCS.md` §Converting and `SPAWN_ATLAS.md` §Artwork + §Configuring; **delete `UOFIDDLER.md`**; add the libgdiplus prerequisite to `SHARD_PREREQS.md` (§4.4) |
| `installer/` | A `doctor` check for libgdiplus on Linux hosts (§4.4). Bundle pairing already enforces §15 |
| `android-app/` | Consumes images by URL; no parity gate expected until a screen shows one |
| `integration-kit/` | A chapter note only — this is UO-specific and teaches nothing about the module contract |
@@ -592,18 +639,19 @@ because §4.3's whole point is that this failure mode produces confident, wrong
---
## 17. Decisions still open
## 17. Decisions
Items 13 are settled and recorded here because each one changes numbers elsewhere in the document.
**Item 4 is the only thing still open, and it does not block starting.**
1. **§4: settled 2026-09-10 — call ServUO's vendored `Ultima`,** with one exception added the same
day: **§4.3's UOP animation decoder**, scoped to the player bodies the legacy path cannot reach
and to nothing else (phase 4). The crash is confined to the `hasExtra: true` branch that only
`Gumps` reaches, and nothing here calls `Gumps`.
2. **§17.1's consequence: Linux/Mono shards.** §4.2 item 2 leaves `System.Drawing` in the decode
path, so a non-Windows shard needs **libgdiplus** installed or art extraction fails there. Three
ways to answer it, and this is the one real question left: document it as a prerequisite in
`SHARD_PREREQS.md` and let it fail loudly; have the installer's `doctor` detect and report it;
or fall back to no-art on that platform with a status the panel explains. Phase 0 should
establish which failure it actually is before we pick.
2. **§4.4: settled 2026-09-10 — libgdiplus is a stated requirement** on Linux shard hosts, with
all three answers taken rather than one: it goes in `SHARD_PREREQS.md`, the installer's `doctor`
checks it, and its absence degrades to a named `NO_IMAGING` status instead of an error. Windows
hosts are unaffected.
3. **§5.1/§5.2: direction — settled 2026-09-10.** Player character bodies use index 0, everything
else index 1, direction is not in the key, and the player-body set is enumerated from
`Race.AllRaces` rather than hardcoded. Nothing outstanding; recorded here because it changes