Files
runicgateway.com/src/data/games/uo.mjs
wtclaude 769d213c80
Some checks failed
PR checks / checks (pull_request) Failing after 2m16s
feat(demo): list the demo's sign-ins on /beta and link into it per game
The public demo (demo.runicgateway.com) is live, so the site's demo slot
can be switched on. Two decisions of record, PLAN.md §15:

- D82: /beta reads the demo's GET /api/v1/public/settings demo.logins on
  the server, caches it for a minute, and lists the published sign-ins
  with the next wipe. If the demo does not answer, /beta links to its
  sign-in page instead. Gate two reads as in place.
- D83: a deep link into a game module's pages carries data-demo-game, and
  applyBrand.mjs fills it only for games in the new mounted demoGames
  list. The Rust features gain links into /rust and /rust/servers/demo.
  UO's stay hidden on a Rust demo.

The public-demo not-built entry is removed, because its resolvedBy was met.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-28 15:32:34 -05:00

119 lines
4.8 KiB
JavaScript

/**
* games/uo.mjs — what the Ultima Online module adds, in Ultima Online's own words.
*
* PLAN.md §16, phase 17. Until this phase these items were the "Game intelligence" group of
* `capabilities.mjs`, which the homepage and `/features/` render — core pages, which D63
* says may name the games but not use their vocabulary. They moved here, to a file that
* belongs to one game, and `/modules/uo/` renders them. The core pages now describe what a
* game module adds in core's words and link here (D75).
*
* `caps` is the contract with `platform.json`'s `games.uo.module.capabilities`, which
* `checkFacts.mjs` re-reads from the module's own `module.json`. `assertGameCoverage()` in
* `index.mjs` fails the build when the two drift apart, in either direction — so the day the
* module gains a capability, the JSON goes red, and the day the JSON moves, this page does.
*
* Slugs are NOT one-per-item: `shard` is the source of four separate user-facing features,
* and the marketplace draws on `market` and `cliloc` together (item names arrive as cliloc
* ids and are resolved against the shard's own string table). Coverage, not a bijection.
*
* `demoPath` is a stable public route on the module's own pages, deep-linked into a demo
* when one is mounted (D25) and the mounted `demoGames` lists `uo` (D83) — which the public
* demo, a Rust deployment, does not. Paths are read from `module-uo`'s `client/src/entry.jsx`.
*/
/** @typedef {import('../capabilities.mjs').Capability} Capability */
/** @type {Capability[]} */
export const features = [
{
label: 'Live shard status',
caps: ['shard'],
demoPath: '/uo/shard',
detail:
'Whether the shard is up, who is on it, and how long ago the site last heard from it. ' +
'When the game is down this page is the thing that says so — the site does not go ' +
'down with it.',
},
{
label: 'Economy and activity',
caps: ['shard'],
demoPath: '/uo/shard/activity',
detail:
'A live feed of what is happening in the world, and the economy underneath it. Every ' +
'event passes an allowlist before it can reach a public page; staff read a second ' +
'stream carrying the rest.',
},
{
label: 'Character sheets',
caps: ['shard'],
detail:
'Skills, stats and equipment, drawn from the live world rather than from a form ' +
'somebody filled in. Reachable by the account the character is linked to, and by ' +
'staff — not by the public.',
},
{
label: 'Points and loyalty boards',
caps: ['shard'],
demoPath: '/uo/leaderboards',
detail:
'The leaderboards the shard already keeps, published without anyone exporting a ' +
'spreadsheet on a Sunday.',
},
{
label: 'Player-vendor marketplace',
caps: ['market', 'cliloc'],
demoPath: '/uo/market',
detail:
'Every player vendor on the shard and what is on it, searchable without logging in to ' +
'the game. Item names arrive from the world as cliloc ids and are resolved against the ' +
"shard's own string table, so they read as names rather than numbers — beside the " +
"item's own picture, in the colour it was dyed.",
},
{
label: 'Houses and IDOC decay',
caps: ['houses'],
demoPath: '/uo/houses',
detail:
'Who owns what and where it stands, including which houses are decaying — published ' +
'while it is still information rather than after it has become a rumour.',
},
{
label: 'Spawn atlas',
caps: ['atlas'],
demoPath: '/uo/atlas',
detail:
"A bestiary and spawn map built by reading your shard's own spawn tables, so it " +
"describes your server rather than someone else's idea of the game. Regions, " +
'landmarks and champion altars come with it, and each creature is shown as the ' +
'artwork your own client draws it with.',
},
{
label: 'Champion boards',
caps: ['champs'],
demoPath: '/uo/champs',
detail: 'Which altars are running, how far along they are, and what turned up.',
},
{
label: 'Guilds',
caps: ['guilds'],
demoPath: '/uo/guilds',
detail:
'Guild rosters and standings, kept in step with the shard. Each guild is also a Team ' +
'on the site, with the forum, the notifications and the voice channel that core ' +
'attaches to one.',
},
{
label: 'City governors',
caps: ['governors'],
demoPath: '/uo/governors',
detail: 'Who holds which city, and what they did with it.',
},
];
/**
* The screenshots `/modules/uo/` shows beside the list, by id from `screens.mjs`. Every one
* is tagged `game: 'uo'` there, so it prints the game's name beside it (D67) wherever it is
* shown. They lived on `/features/` until phase 17.
*/
export const screens = ['shard-status', 'marketplace', 'spawn-atlas', 'guilds', 'houses'];