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:
74
link/v8.md
74
link/v8.md
@@ -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,
|
**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),
|
**Supersedes the manual half of:** [`../website/UOFIDDLER.md`](../website/UOFIDDLER.md),
|
||||||
[`../website/CLILOCS.md`](../website/CLILOCS.md) §Converting,
|
[`../website/CLILOCS.md`](../website/CLILOCS.md) §Converting,
|
||||||
[`../website/SPAWN_ATLAS.md`](../website/SPAWN_ATLAS.md) §Artwork and §Configuring the tree.
|
[`../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
|
not merely accepted: §4.3 adds a decoder for it**, because it is the player character and the
|
||||||
scope says player models.
|
scope says player models.
|
||||||
2. **`System.Drawing` is a hard dependency, in the decode and not just the encode.** `Frame`
|
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
|
writes ARGB1555 straight through a `LockBits` pointer, so a Linux shard needs **libgdiplus** to
|
||||||
to read a sprite at all. See §17.
|
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.
|
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
|
`EXTRACTOR_VERSION` (§7) is the mitigation: it already counts as drift, so a shard whose library
|
||||||
changed re-derives on the next import.
|
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,
|
correct behaviour; a plausible wrong picture is the failure this protocol most needs to avoid,
|
||||||
because nothing downstream can detect it.
|
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
|
## 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` |
|
| `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 |
|
| `module-uo/` | Client calls, asset store, the atlas source backend (§10), cliloc ingest, admin surface |
|
||||||
| `website/` | None expected — `ctx.uploads` already suffices (§12) |
|
| `website/` | None expected — `ctx.uploads` already suffices (§12) |
|
||||||
| `docs/` | This file; rewrite `CLILOCS.md` §Converting and `SPAWN_ATLAS.md` §Artwork + §Configuring; **delete `UOFIDDLER.md`** |
|
| `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/` | None expected; the bundle pairing already enforces §15 |
|
| `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 |
|
| `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 |
|
| `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 1–3 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
|
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
|
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
|
and to nothing else (phase 4). The crash is confined to the `hasExtra: true` branch that only
|
||||||
`Gumps` reaches, and nothing here calls `Gumps`.
|
`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
|
2. **§4.4: settled 2026-09-10 — libgdiplus is a stated requirement** on Linux shard hosts, with
|
||||||
path, so a non-Windows shard needs **libgdiplus** installed or art extraction fails there. Three
|
all three answers taken rather than one: it goes in `SHARD_PREREQS.md`, the installer's `doctor`
|
||||||
ways to answer it, and this is the one real question left: document it as a prerequisite in
|
checks it, and its absence degrades to a named `NO_IMAGING` status instead of an error. Windows
|
||||||
`SHARD_PREREQS.md` and let it fail loudly; have the installer's `doctor` detect and report it;
|
hosts are unaffected.
|
||||||
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.
|
|
||||||
3. **§5.1/§5.2: direction — settled 2026-09-10.** Player character bodies use index 0, everything
|
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
|
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
|
`Race.AllRaces` rather than hardcoded. Nothing outstanding; recorded here because it changes
|
||||||
|
|||||||
Reference in New Issue
Block a user