Paperdoll on the character sheet, and a themed Export PNG character card #45
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
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?
Future plan — not scheduled, nothing to implement yet. Filed so the investigation behind it survives.
What we want
On the character sheet (
client/src/components/CharacterSheet.jsx): a real UO paperdoll showing the character as they actually appear in game — their own body, hair and worn gear, correctly hued and layered — plus an Export PNG button producing a shareable character card (paperdoll, name, standing, skills, stats) styled from the site's own CSS theme variables, so a themed install exports in its own palette.Why it is not a small change
A paperdoll is composed from gump art: a body gump per race/gender, and one gump per worn item at
ItemData.AnimID + 50000(male) /+ 60000(female). Protocol 8 consumed no gump art, and that is a safety rule rather than a scoping preference.docs/link/v8.md§4.7 / §17.15:Ultima.Gumps.GetGump(2)does not fail, it corrupts the process —AccessViolationException, exit0xC0000005. Phase 0 called it once from inside a running shard and killed the shard. The fault is on thehasExtra: trueFileIndexbranch that onlyGumpsreaches;servuo-plugins/tools/scaffolding/BridgeAssetProbe.cskeeps agumpsection whose documented purpose is to reproduce the crash.What the Asset Bridge did consume cannot substitute:
bodybody/400/a0static/landstatic/3922/h33Item icons are inventory sprites of assorted sizes. Stacked, they make a pile, not a figure.
Two further gaps, independent of the decoder:
BridgeProfile.IsGearLayerexcludesLayer.HairandLayer.FacialHair, so any figure we draw today is bald. Fixing it is achar.profileshape change.BridgeCatalogdecodes withpreserveHue: false, and body keys have no hue segment, so a character's skin colour is not representable. A hued body key (body/<id>/a<n>/h<hue>) is well-formed under §5 and simply not served.Scope when it is picked up
Ultima.Gumps). Phase 4'sBridgeUop.csblock-chain reader is reusable for the UOP container; the gump record format and theextrawidth/height field are new. Then: thegumpkey family, the AnimID→gump-id mapping with the female-gump-absent fallback, gumpPartialHue, and Hair/FacialHair onchar.profile.assets_callforwards a request body verbatim andrespond_assetsreturns the reply verbatim, so a new key family has passed through untouched for three phases running.link/v9.md(or a v8 amendment), the protocol bump,modules/uo/SCHEMA.md.PROTOCOL_VERSIONbumped in the same PR as the emitters, or the next bundle silently fails to compose.The cheaper alternative, if the real thing stays parked
A character card with no protocol change at all, which is a strict subset of the above rather than throwaway work: the figure is the character's own body sprite (
body/<bodyId>/a<n>— the catalogue already imports all six player bodies, §5.2), with the correctly hued item icons laid out in paperdoll-shaped slots around it, plus the Export PNG card. Server side is onefileForBody(bodyId)lookup inshardAssets.db(pinned to the catalogue key the way the atlas join is) and onebodyArtfield fromenrichCharProfile; client side is a pure composition model shared by the on-page canvas and the export canvas so the two cannot drift. Caveats are honest and visible: no worn gear on the figure, no hair, and the wrong skin colour.The slot model, card layout, theme-token reader and export renderer all survive unchanged when gumps land — only the figure layer is swapped.
Design notes worth keeping
toBlob+ a blob-URL anchor — no library, and no server-side image generation./uploadsis same-origin, so the canvas stays untainted. Precedent:website/client/src/components/security/RecoveryCodesDisplay.jsx.getComputedStyle(document.documentElement), which picks up the admin-configured tokensthemeVars.jswrites onto<html>. Use the flat tokens and rebuild--panel-gradfrom its endpoints — canvas cannot consume a CSS gradient string.--displayis Cinzel, a webfont:await document.fonts.load(...)before drawing or the card silently exports in Georgia on a cold load.PartialHuelives intiledata.mul, which the browser will never have.Open questions
/shard/char/:serialis owner-or-admin only, and a client-side export adds no exposure — a public card would mean server-side rendering, which this plan deliberately avoids.Investigation and write-up AI-assisted (Claude Code); no code changed.
🤖 Generated with Claude Code
https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4