Repository navigation
v4.1.11
"Viewport": the programme's fourth release, the second with a release candidate. The rendering is no
longer a source of state: the room view makes an immutable scene frame with a pure function and paints it, the DOM
and the Canvas painters send the engine nothing but intentions, and the semantic journal of what happened in the
game (rooms, items, flags, endings, loads) belongs to the core, replayed identically by a session. The Studio edits
a room's layers, masks, zones and portals; the validator refuses a degenerate mask. Measured against 4.1.10 in
docs/dev/baselines/4.1.11.md; what this release does not do (every browser measure, the WebGL spike) is in the
LOG and the passes sheet (docs/dev/passes/4.1.11.md).
Changes
- The semantic journal (4.1.11).
Engine.journalnumbers what happened in the game, in ids: a session started, a
room entered (and from where), an item acquired or lost (an item handed to another player is both, each with its
player), a flag changed (only when its value changes;nullwhen it is removed), the player switching character,
an ending reached, a load, and the autosave that follows something semantic. The command handlers, a room's entry and the
engine's lifecycle emit it, nothing in the DOM does, and a kind it does not know is refused. Replaying a session yields
the same journal (the sample game, the reference chapter, 200 generated games). A session file carries it;
npm run replayprints it and exits 1 when the replay's differs; a session longer than the journal's window
(10 000 events) is exported withjournalTruncated: trueand no journal, andnpm run replaythen says "no journal
comparison: the window was exceeded" instead of "matches". The dev panel lists the latest events. - The scene frame (4.1.11, ADR 0011). The room view makes an immutable
SceneFrame(camera, layers, characters,
targets with their hit polygons precomputed, effects, a hash) with a pure function, then paints it. Taps are tested
against the frame and the accessible buttons follow its targets, whatever paints the room. Every room of the sample
game and of the reference chapter, in three states, paints the same DOM and answers the same taps as before. - The player's input is an intention (4.1.11, D21).
Appcomposes the engine, aPresenter(dom/presenter.ts:
the scene's calls, lines, overlays, minigames, the ending) and the room view'sRenderer; a verb on a target, a
walk, a choice, a skip or a screen opened goes through the presenter'sintent(). The same clicks on the DOM and on
the Canvas painter record the same session and journal, at device pixel ratios 1, 2 and 3, on a phone and a desktop
screen, with and without reduced motion. The busy state (runs, the tutorial step, a skip) iscore/busy.ts; a skip
left pending no longer outlives a new game or a load. The page's test hook moved with it:
window.__game.presenter.inventory(…)where e2e scripts calledwindow.__game.inventory(…). - The Canvas painter survives a lost context (4.1.11). Nothing is painted while the browser has reclaimed the
canvas; once restored, the background, the masks and the occluders are rebuilt from their images and the room is
painted again. A tap or a hover reuses the room's frame until something changes (a version counter), instead of
building and hashing it again. The route between walk zones is the core's (core/motion.tszoneRoute), the walker walks it. - The Studio edits a room's layers, masks, zones and portals (4.1.11). Under the room sheet of the Rooms tab: each
layer's depth, parallax, opacity and blend; occlusion masks and walk zones drawn as polygons on the backdrop; links
between zones placed by two clicks; Save stage writes the geometry over the room's layout. - The validator refuses a mask polygon that closes no surface and, in a room of several walk zones, a zone no link
joins (4.1.11). A layout that validated in 4.1.10 with a degenerate mask polygon (collinear points, crossing edges)
now failsnpm run validate; the bundled games pass. - API (4.1.11), additive.
web-scumm/player:SceneFrame,Renderer,Intent(@extension).
web-scumm/testing:SemanticEvent,SemanticJournal(@public).Engine.journalandEngine.sessionSeqare new
members ofEngine. - The first visit's JavaScript goes from 120 to 122 KB gzipped (4.1.11): the scene frame, the presenter, the
intents and the journal are in the player's main chunk; the budget (initialJsKB140) is untouched and the
baseline moved on purpose.
Manual passes (D12: reported, not blocking)
0 of 12 done.
| Pass | Status | Who, when | Device, OS, browser, versions | What failed |
|---|---|---|---|---|
| Real phone, frame rate of the heaviest scene on the DOM and the Canvas painter (≥ 30 FPS) | not done | |||
Screen reader on both painters (docs/dev/SCREEN-READER.md) |
not done | |||
| A room's layers, masks, zones and portals edited by a person in the Studio, then played | not done | |||
| A real multi-instance deployment behind HTTPS (Postgres), a connector delivering | not done | |||
| A real email provider (webhook mode) delivering to a game | not done | |||
| A real Open Badge (OB2 hosted, OB3 VC-JWT) from a real issuer verified | not done | |||
| SSH and Telnet exposed in a controlled environment, attacked by a person | not done | |||
Safari offline (docs/dev/SAFARI-OFFLINE.md), iPhone install and update |
not done | |||
| Firefox offline on a real machine | not done | |||
Windows: npm run doctor, npm run dev, npm run build by hand |
not done | |||
Playtesters who do not know the puzzles (npm run verify:field) |
not done | |||
Recorded voices; listening; a signed tag (git tag -s) |
not done |