docs(link): the Asset Bridge (Protocol 8) — client assets without UOFiddler #234
81
link/v8.md
81
link/v8.md
@@ -169,10 +169,12 @@ application, and a minimal PNG writer over `System.IO.Compression.DeflateStream`
|
|||||||
into a `Bitmap` via `LockBits`, so System.Drawing is in the *decode*, not just the encode — a
|
into a `Bitmap` via `LockBits`, so System.Drawing is in the *decode*, not just the encode — a
|
||||||
Linux/Mono shard needs libgdiplus even to read a sprite. Writing our own pixels and our own PNG
|
Linux/Mono shard needs libgdiplus even to read a sprite. Writing our own pixels and our own PNG
|
||||||
makes the feature portable by construction.
|
makes the feature portable by construction.
|
||||||
3. **It removes the UOP gap.** ServUO's vendored `Animations` reads legacy `anim*.mul` only. This
|
3. **It removes the UOP gap, which lands squarely on the player bodies.** ServUO's vendored
|
||||||
client has a full 195 MB `anim.mul` so most bodies resolve — but **gargoyle bodies 666/667
|
`Animations` reads legacy `anim*.mul` only, never `AnimationFrame*.uop`. This client has a full
|
||||||
returned nothing**, because gargoyles live in `AnimationFrame*.uop`. A player race missing from
|
195 MB `anim.mul` so most creatures resolve — but **six of the twelve stock player-character
|
||||||
an asset store built for "player models and everything" is not a caveat, it is a defect.
|
bodies return nothing**, including every gargoyle and both human ghosts (§5.2). A missing
|
||||||
|
playable race in an asset store built for "player models and everything" is not a caveat, it is
|
||||||
|
a defect, and it is in the highest-attention part of the scope.
|
||||||
4. **We are already in this business.** §9 writes a cliloc decompressor from scratch regardless.
|
4. **We are already in this business.** §9 writes a cliloc decompressor from scratch regardless.
|
||||||
|
|
||||||
A2 also ends the dependency on whatever version of `Ultima` a given ServUO happens to vendor,
|
A2 also ends the dependency on whatever version of `Ultima` a given ServUO happens to vendor,
|
||||||
@@ -210,13 +212,20 @@ Three properties this shape buys:
|
|||||||
### 5.1 There is no direction segment, because only one direction is wanted
|
### 5.1 There is no direction segment, because only one direction is wanted
|
||||||
|
|
||||||
Bodies are stored in **five** directions and the client mirrors three of them to reach eight. Only
|
Bodies are stored in **five** directions and the client mirrors three of them to reach eight. Only
|
||||||
one is needed here — the one facing the viewer — so **direction is fixed by the extractor and is
|
one is needed here, so **direction is fixed by the extractor and is not part of the key**. Leaving
|
||||||
not part of the key**. Leaving it in would advertise a choice nobody is going to make and would
|
it in would advertise a choice nobody is going to vary and would five-fold every count in §11 for
|
||||||
five-fold every count in §11 for nothing.
|
nothing.
|
||||||
|
|
||||||
**The front-facing index is 0.** This was determined by rendering all five for a human, a wolf and
|
**Which one depends on whether the body is a player character:**
|
||||||
a dragon rather than from a table, because the answer is not obvious and the small-thumbnail version
|
|
||||||
of the same test suggested the opposite:
|
| Body | Direction | Why |
|
||||||
|
|---|---|---|
|
||||||
|
| A player character body | **0** — head-on, facing the viewer | A character is a portrait; it should look at you |
|
||||||
|
| Everything else | **1** — front three-quarter | The view that actually reads as a creature (see the caveat below) |
|
||||||
|
|
||||||
|
Which index is which was determined by **rendering all five** for a human, a wolf and a dragon
|
||||||
|
rather than from a table, because the answer is not obvious and the small-thumbnail version of the
|
||||||
|
same test suggested the exact opposite:
|
||||||
|
|
||||||
| Index | View |
|
| Index | View |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -226,12 +235,45 @@ of the same test suggested the opposite:
|
|||||||
| 3 | Rear three-quarter |
|
| 3 | Rear three-quarter |
|
||||||
| 4 | Directly away — back of the head, and a quadruped's tail toward the camera |
|
| 4 | Directly away — back of the head, and a quadruped's tail toward the camera |
|
||||||
|
|
||||||
One caveat the render made obvious, and it is the reason this is written down rather than assumed:
|
The caveat the render made obvious is what produced the split: **index 0 is the least legible view
|
||||||
**index 0 is the least legible view for four-legged and long-bodied creatures.** A wolf seen head-on
|
for four-legged and long-bodied creatures.** A wolf seen head-on is a dark blob; the same wolf at
|
||||||
is a dark blob; the same wolf at index 2 is unmistakably a wolf, and at index 1 is the view
|
index 1 is unmistakably a wolf, which is also why UOFiddler's own thumbnail list picks that view. A
|
||||||
UOFiddler's own thumbnail list picks. For a bestiary tile that matters. The extractor therefore
|
humanoid has no such problem — it reads fine head-on, and head-on is what a character portrait
|
||||||
takes the index as a **configuration value defaulting to 0**, so changing the catalogue's mind later
|
wants.
|
||||||
is a setting and a re-import, not a protocol change.
|
|
||||||
|
Both indices stay **configuration values** (defaulting to 0 and 1), so changing the catalogue's mind
|
||||||
|
later is a setting and a re-import, not a protocol change.
|
||||||
|
|
||||||
|
### 5.2 "Player character body" is asked of the shard, never hardcoded
|
||||||
|
|
||||||
|
`Server.Race.AllRaces` gives every registered race, and each carries `MaleBody`, `FemaleBody`,
|
||||||
|
`MaleGhostBody` and `FemaleGhostBody`. The plugin enumerates those four ids per race and that set —
|
||||||
|
nothing else — takes index 0. On stock ServUO 57.4 that is twelve ids:
|
||||||
|
|
||||||
|
| Race | Male | Female | Male ghost | Female ghost |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| Human | 400 | 401 | 402 | 403 |
|
||||||
|
| Elf | 605 | 606 | 607 | 608 |
|
||||||
|
| Gargoyle | 666 | 667 | **695** | **694** |
|
||||||
|
|
||||||
|
This is the §8 argument again in miniature: only code inside ServUO can answer it, and asking is
|
||||||
|
the only thing that works on a shard with a custom race. Two details make the case that a
|
||||||
|
hardcoded list would have been wrong — `RaceDefinitions.cs` passes the gargoyle's ghost bodies in
|
||||||
|
the **opposite order** to the other two races (695 male, 694 female), and a shard that calls
|
||||||
|
`RegisterRace` adds ids no table of ours would contain.
|
||||||
|
|
||||||
|
**Half of that set does not decode with ServUO's vendored library.** Measured:
|
||||||
|
|
||||||
|
| Decodes | Does not |
|
||||||
|
|---|---|
|
||||||
|
| Human male/female (400, 401) | **Human ghosts (402, 403)** |
|
||||||
|
| Elf male/female (605, 606) | **Every gargoyle body (666, 667, 694, 695)** |
|
||||||
|
| Elf ghosts (607, 608) | |
|
||||||
|
|
||||||
|
Six of twelve, including a whole playable race. So the one part of the asset scope with the most
|
||||||
|
attention on it — the player character, head-on — is precisely the part the vendored `Animations`
|
||||||
|
serves worst, and §4's recommendation to own the decoders is what fixes it. This is the single
|
||||||
|
strongest piece of evidence for that choice.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -505,8 +547,9 @@ prove byte-identical output *before* building six phases on top of it.
|
|||||||
libgdiplus dependency, the UOP gap and the vendor-drift risk all going away at once.
|
libgdiplus dependency, the UOP gap and the vendor-drift risk all going away at once.
|
||||||
2. **§11: gump art deferred.** Confirm that paperdoll and equipment gump art is genuinely
|
2. **§11: gump art deferred.** Confirm that paperdoll and equipment gump art is genuinely
|
||||||
out of scope for 8, given it is the one kind whose existing decoder crashes.
|
out of scope for 8, given it is the one kind whose existing decoder crashes.
|
||||||
3. **§5.1: direction is fixed at index 0** (head-on) and is not in the key — settled 2026-09-10.
|
3. **§5.1/§5.2: direction — settled 2026-09-10.** Player character bodies use index 0, everything
|
||||||
What is *not* settled is whether the catalogue should default to index 1 or 2 instead, since a
|
else index 1, direction is not in the key, and the player-body set is enumerated from
|
||||||
head-on wolf is a dark blob and a side-on wolf is a wolf. It is a setting either way.
|
`Race.AllRaces` rather than hardcoded. Nothing outstanding; recorded here because it changes
|
||||||
|
every count in §11.
|
||||||
4. **§13: the default audience** for asset serving — inheriting the using page's audience is
|
4. **§13: the default audience** for asset serving — inheriting the using page's audience is
|
||||||
proposed; the operator sets the policy either way.
|
proposed; the operator sets the policy either way.
|
||||||
|
|||||||
Reference in New Issue
Block a user