chore(tools): dress a seeded world so it can be screenshotted #16

Merged
whitlocktech merged 1 commits from chore/demo-world-dressing into main 2026-08-25 00:34:57 +00:00
Member

Why

BridgeSeeder builds a world at realistic scale — 50 accounts, 150 characters, 30 houses, 30 vendors, 1,200 listings — which is exactly what the bridge needed. It never needed the world to look like anything, so a vendor is seed vendor trading as Seed Shop 810, a character is Seed004A, a house sign reads Seed House 12.

Every one of those strings travels the whole bridge — plugin → sidecar → website — and lands on the marketplace, the guild roster and the housing pages. Fine for a protocol test; wrong for the marketing site's screenshots, which are meant to be real captures of a real deployment (runicgateway.com PLAN.md §13 phase 9, D42/D46).

What it does

BridgeDemoDress.cs renames what is already there and seeds nothing. Prices, listing counts, decay stages, fame and skill sheets stay exactly as the seeder produced them and as the shard has moved them since — only the strings a human reads change, so the data keeps its provenance.

Names are drawn from fixed tables by a hash of each object's serial, so a run reproduces the same world and screenshots retaken later still match. Shop and house names are re-dressed when they are names the pass itself produced, so a change to the tables can be applied to a world that has already been through here; character names are not, because a person's name has no closed set to recognise it by.

Two other things, each because nothing else provides them:

  • Stages a few condemned houses back into the last decay levels. Decay is a live process, so "Houses in danger" is empty by the time anybody looks. Only houses that CanDecay are touched — forcing an active owner's AutoRefresh house into IDOC would invent a state the game never produces, and the next refresh would undo it.
  • Sets a known password on seed_000. Logging a character in is the only way to make the website's online roster non-empty, that needs a client, and a client needs a password the seeder never kept (it assigns a random GUID). Read from Bridge.cfg, never compiled in.

Scope

tools/scaffolding/, which deploy.ps1 does not copy — overlay/ is the only thing deployed. Guarded the same way as every other probe here: Config.Get returns false for a missing key, so a shard whose Bridge.cfg lacks DemoDressOnStart never runs it even with the file present.

Verified

Ran against the local ServUO world behind a protocol-4 sidecar and a website with module-uo installed. 27 vendors, 150 characters and 30 house signs dressed; the names reach the site's marketplace on the next market sweep.

One note now in the README, because it cost a debugging detour: the sidecar caches its boards, and a market sweep advances MarketSweepBatch vendors per tick, so the website lags a rename by a couple of minutes. The shard had the new names the whole time.


  • AI-assisted: written with Claude Code (Claude Opus).

Co-Authored-By: Claude <noreply@anthropic.com>

## Why `BridgeSeeder` builds a world at realistic **scale** — 50 accounts, 150 characters, 30 houses, 30 vendors, 1,200 listings — which is exactly what the bridge needed. It never needed the world to *look* like anything, so a vendor is `seed vendor` trading as `Seed Shop 810`, a character is `Seed004A`, a house sign reads `Seed House 12`. Every one of those strings travels the whole bridge — plugin → sidecar → website — and lands on the marketplace, the guild roster and the housing pages. Fine for a protocol test; wrong for the marketing site's screenshots, which are meant to be real captures of a real deployment (runicgateway.com `PLAN.md` §13 phase 9, D42/D46). ## What it does `BridgeDemoDress.cs` renames what is already there and **seeds nothing**. Prices, listing counts, decay stages, fame and skill sheets stay exactly as the seeder produced them and as the shard has moved them since — only the strings a human reads change, so the data keeps its provenance. Names are drawn from fixed tables by a hash of each object's serial, so a run reproduces the same world and screenshots retaken later still match. Shop and house names are re-dressed when they are names the pass itself produced, so a change to the tables can be applied to a world that has already been through here; character names are not, because a person's name has no closed set to recognise it by. Two other things, each because nothing else provides them: - **Stages a few condemned houses back into the last decay levels.** Decay is a live process, so "Houses in danger" is empty by the time anybody looks. Only houses that `CanDecay` are touched — forcing an active owner's `AutoRefresh` house into IDOC would invent a state the game never produces, and the next refresh would undo it. - **Sets a known password on `seed_000`.** Logging a character in is the only way to make the website's online roster non-empty, that needs a client, and a client needs a password the seeder never kept (it assigns a random GUID). Read from `Bridge.cfg`, never compiled in. ## Scope `tools/scaffolding/`, which `deploy.ps1` does not copy — `overlay/` is the only thing deployed. Guarded the same way as every other probe here: `Config.Get` returns false for a missing key, so a shard whose `Bridge.cfg` lacks `DemoDressOnStart` never runs it even with the file present. ## Verified Ran against the local ServUO world behind a protocol-4 sidecar and a website with `module-uo` installed. 27 vendors, 150 characters and 30 house signs dressed; the names reach the site's marketplace on the next market sweep. One note now in the README, because it cost a debugging detour: **the sidecar caches its boards**, and a market sweep advances `MarketSweepBatch` vendors per tick, so the website lags a rename by a couple of minutes. The shard had the new names the whole time. --- - [x] AI-assisted: written with Claude Code (Claude Opus). Co-Authored-By: Claude &lt;noreply@anthropic.com&gt;
wtclaude added 1 commit 2026-08-25 00:24:59 +00:00
BridgeSeeder builds a world at realistic scale, which is what the bridge needed;
it never needed the world to look like anything. So a vendor is `seed vendor`
trading as `Seed Shop 810`, a character is `Seed004A` and a house sign reads
`Seed House 12` — and every one of those strings travels the whole bridge and
lands on the marketplace, the guild roster and the housing pages of the website.
That is fine for a protocol test and wrong for the marketing site's screenshots
(runicgateway.com PLAN.md §13 phase 9, D42/D46).

BridgeDemoDress renames them in place and seeds nothing: prices, listing counts,
decay stages, fame and skills stay exactly as the seeder left them, so the data
keeps its provenance and only the strings a human reads change. Names come from
fixed tables hashed off each object's serial, so a re-run reproduces the same
world and screenshots can be retaken later and still match.

It also does two things the screenshots needed and nothing else provides:

- stages a few condemned houses back into the last decay levels, because decay
  is a live process and "Houses in danger" is empty by the time anyone looks
- sets a known password on seed_000, because logging a character in is the only
  way to make the online roster non-empty and the seeder assigns a random GUID.
  The password is read from Bridge.cfg, never compiled in.

Test scaffolding, in tools/, never deployed — deploy.ps1 copies overlay/ only.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech approved these changes 2026-08-25 00:34:51 +00:00
whitlocktech merged commit 8cf995f27f into main 2026-08-25 00:34:57 +00:00
whitlocktech deleted branch chore/demo-world-dressing 2026-08-25 00:34:58 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/servuo-plugins#16
No description provided.