- Workshop (WORKSHOP_CARTRIDGE): five-stage cartridge assembly at Deck A — seat/square, crimp four tag-wires, torque screws, ride-the-arm counterweight balance, needle-drop diagnostic with per-fault audio + scope. Relay-synced (per-field co-op merge: held screw + carried wire survive remote state). - Glow-Up (G1-G5): 32px atlas with per-voxel variants, selective LED bloom (quality-gated), screen-print decal system + party flyers, mixer/PCB worldgen density pass, record groove-sheen side texture. - 10 confirmed multi-agent review fixes, incl. co-op screw-stomp soft-lock, ride-snap collider-identity (magnet feet / eaten record-fling), workshop SFX exact-match map (rca_seated hijack), beam ride colliders to the head, double-crimp guard, WIRING INCOMPLETE diagnosis mode, skate-abort timer, completedState wiring, per-tick material churn, trackingHeavy platter drag. - Crossfader playtest fix: slew-limited sled (3.4 v/s) + ribbed grip caps with amber index — the sled reads as a heavy handle, not a teleporting wall. - Demo harnesses: machinesDemo hold-key wiring, playerDemo seesaw phase continuity, audioDemo incomplete fault button. - Workshop sync: exact 1.0 screw endpoint gets its own emit signature. Verified: typecheck + vite build clean, live solo quest smoke, two-client co-op relay smoke (simultaneous torque, no rewind, exact convergence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
119 lines
11 KiB
Plaintext
119 lines
11 KiB
Plaintext
Fable's Glow-Up review has direct engine/rendering implications — LED bloom (my renderer), a 32px atlas with tile variants (my atlas), and possibly a decal system. Let me read both new briefs and see the current repo state to identify exactly what's Lane A's.
|
||
|
||
The project has grown a lot — all lanes integrated, multiplayer added, and now a Glow-Up pass. Let me read both new briefs to find my Lane A assignments.
|
||
|
||
The Glow-Up brief spans several lanes, but the **engine-owned parts are squarely mine**: **G1 (Atlas v2 — 32px + better patterns + variants)** and **G2 (selective LED bloom in the renderer)**. G3–G5 (decals in `fx/`, worldgen density, record texture) belong to the Glow-Up session's other-lane files. Let me focus on my lane. First, let me read the current state of my files (they may have changed during integration) and the merge points.
|
||
|
||
Renderer is structurally mine (concept-art pass tweaked lighting/fog). Let me read the atlas, the integration merge points, and check the post-processing modules I'll need for bloom.
|
||
|
||
Both `atlas.ts` and `renderer.ts` are still exactly my Lane A files. Let me read the merge points (main.ts, Menu.ts), the integration notes, and confirm the post-processing modules I need for bloom exist.
|
||
|
||
main.ts calls `render()` (line 180) and configures quality via the Menu's `onApply` (line 99). Clean seams for bloom. Let me read Menu.ts and confirm the post-processing modules exist.
|
||
|
||
Now let me confirm the post-processing modules exist and check the integration notes and how `window.TURNCRAFT_CINE` works (I'll use it for before/after shots).
|
||
|
||
All bloom modules present with types; dev server config exists. Let me read the integration notes and confirm the mesher's tile-writing (so my variant approach stays mesher-free).
|
||
|
||
Let me confirm the mesher's tile attribute write (so my variant system can live entirely in the atlas shader without touching the mesher).
|
||
|
||
I have everything I need. The mesher writes `aTile = (id%8, id/8)` (base cell) — so my variant system can live **entirely in the atlas shader**, leaving the mesher (and its verified winding/AO) untouched. Let me verify the RenderPass type exists, then set up tasks.
|
||
|
||
All types present. Let me set up fresh tasks for the Glow-Up engine work and clean up the stale ones.
|
||
|
||
Before I change anything, let me capture BEFORE screenshots of the current state for the acceptance comparison. Let me start the dev server and boot the game.
|
||
|
||
Booted clean: **810 ms build, 467 chunk meshes** (< 600 ✓), no errors. Let me capture BEFORE shots using the cine camera. Mixer face first.
|
||
|
||
Start splash is overlaying the view (and I can see the sparse mixer face behind it — finding #1). Let me dismiss it to get clean shots.
|
||
|
||
The pause overlay returns when pointer lock drops. Let me click to start and screenshot while locked (cine still controls the camera).
|
||
|
||
Pointer lock can't be acquired in this headless pane, so the start/pause overlay persists. I'll hide that DOM overlay just for screenshots (cosmetic, doesn't touch game code). Let me find it.
|
||
|
||
The splash lives inside `.tc-hud`. Let me find and hide just the splash child.
|
||
|
||
Splash hidden. Now a clean BEFORE shot of the mixer face.
|
||
|
||
The camera drifted — let me re-assert the cine position and confirm the camera is actually there before shooting.
|
||
|
||
The rAF loop is paused (headless pane), so cine isn't applied and renders are on-demand — same throttling I hit before. I'll drive the camera directly and force a render, like I did in the Lane A demo.
|
||
|
||
The splash keeps re-showing (can't hold pointer lock). Let me fold overlay-hiding into the shot helper and take a wide orienting shot first.
|
||
|
||
The camera isn't sticking. Let me diagnose whether the render is being overwritten or the screenshot is stale.
|
||
|
||
rAF is fully paused (0 frames) — so my single manual `render()` never gets composited into the screenshot. I need continuous rendering. Let me drive a small `setInterval` render loop with a pinned camera (survives the rAF pause and forces fresh frames).
|
||
|
||
The render loop works now — and this is an excellent BEFORE shot covering findings #1 (sparse mixer face on a black plain), #3 (flat 16px textures), and #4 (VU/strobe LEDs are flat colored squares, no bloom). Let me grab one more before — a deck close-up (records/strobe) — then implement.
|
||
|
||
That mixer BEFORE shot is comprehensive (findings #1, #3, #4 all visible). I have enough reference. The render-loop technique works; I'll reuse those exact positions for AFTER shots. Now to the actual work — let me implement **G1: Atlas v2**. First, confirm nothing external depends on `atlas.cols`/`rows` so my variant grid change stays internal.
|
||
|
||
Only the two materials are consumed externally — my variant grid change stays fully internal. Now let me write **Atlas v2** (32px, 4 world-hashed variants, richer patterns, canvas-drawn).
|
||
|
||
Typecheck errors are both in `src/machines/**` — the **Workshop session's** in-progress code (the other parallel brief), not mine. My engine/atlas code is clean (zero errors under `src/engine`). Let me reload the game to see Atlas v2 and re-establish the render loop.
|
||
|
||
The splash keeps racing my hide. Let me override it robustly with an `!important` stylesheet rule (beats the game's inline style).
|
||
|
||
The splash is gone and the **atlas v2 is live** — the plywood wall now shows fine directional grain instead of the old coarse speckle. But the camera framing is off (showing a wall, not the mixer). Let me check whether rAF resumed after reload and is fighting my pin.
|
||
|
||
My `setInterval` loop isn't persisting (`loopAlive:false`) and rAF is paused — so renders only happen when I trigger them. Let me set up the loop robustly with a tick counter and error capture, then verify it's actually ticking.
|
||
|
||
The page keeps reloading — my helpers get wiped between calls. Likely the **Workshop session is live-editing** `src/machines/**` right now, triggering Vite HMR reloads. Let me confirm via the dev-server logs, then pivot to my isolated **engine demo** (uses the same atlas/renderer, immune to workshop churn).
|
||
|
||
Confirmed — the **Workshop session is live-editing** many files (Hud, PlayerController, machines, interaction, audio); each save triggers a full Vite page reload of the shared dev server every ~10s, wiping my helpers. Let me neutralize the HMR reload in my page so I can set up a stable render loop.
|
||
|
||
Reload override accepted. Now let me set up the render loop and confirm it survives (the game already loaded my atlas v2 on the last reload).
|
||
|
||
Let me wait past a reload window, then confirm the loop survived and shoot the mixer.
|
||
|
||
Loop survived and camera is pinned to the mixer. Let me screenshot Atlas v2 on the mixer face (compare to the BEFORE).
|
||
|
||
The shared main-game is a hostile screenshot environment (constant reloads + multiplayer world mutation + front-lip occlusion). My **engine demo** (`demo-engine.html`) is the right tool: same atlas/renderer, clean test pattern with every block type + an LED wall, no multiplayer/workshop deps. Let me switch to it.
|
||
|
||
Demo's rAF is also paused, so I need the continuous `setInterval` render (which composites correctly). Let me set it up in the demo.
|
||
|
||
**Atlas v2 is a clear win** — plywood shows end-grain rings + directional grain, metals show vertical brushed strokes, the PCB pillar shows copper traces + a via pad, and the LEDs are smooth glowing radial dots. All blocks render solid (winding still correct). Let me verify the variant system breaks up tiling without seams — look down at the large plywood floor.
|
||
|
||
Good — the floor plywood shows grain variation across the surface (variants working), no seams or garbage tiles, all blocks solid. Let me get a close-up of the floor to clearly confirm per-voxel variant variation.
|
||
|
||
Page reloaded again (workshop churn). Let me re-establish the harness and shoot quickly.
|
||
|
||
The plywood floor close-up confirms **variants work** — grain phase/direction shifts per voxel, no wallpaper tiling, no seams or garbage. Atlas v2 is solid. Let me mark G1 done and implement **G2: bloom** in the renderer.
|
||
|
||
Now the merge points. main.ts: destructure `setBloom` and gate it in the Menu `onApply`.
|
||
|
||
main.ts was modified on disk (it's a shared merge point). Let me re-read the Menu `onApply` region before editing it.
|
||
|
||
Now Menu.ts: add the `bloom` setting + checkbox. Let me re-read it in case the workshop touched it too.
|
||
|
||
Menu.ts unchanged. Let me add the `bloom` setting (interface, default, checkbox row).
|
||
|
||
Now let me wire bloom into the engine demo so I can verify it (LED wall is the perfect test). Let me check the demo's current structure.
|
||
|
||
Now typecheck the whole project (expecting only the Workshop session's known errors).
|
||
|
||
Whole-project typecheck is **clean** (exit 0) — the Workshop session fixed their errors, and my atlas + bloom + merge-point edits all typecheck. Now let me verify bloom in the demo. Reload and set up on the LED wall.
|
||
|
||
Bloom OFF baseline captured — LEDs are bright but flat (glow contained per-voxel, no halo). Now enable bloom and compare.
|
||
|
||
Bloom works and is **selective** — the LED wall now glows with a soft halo while the plywood floor, steel cave, and blue vinyl stay matte. fps shows 79 but that's unreliable here (the demo's rAF fps counter is stale since rAF is paused; I'm driving renders via setInterval). Let me strengthen the glow a touch for more "magic" and then measure real render cost via a timed loop.
|
||
|
||
The canvas is only 600×300 now (pane shrank), so those fps numbers are meaningless (GPU idle). Let me resize the pane to a realistic desktop resolution for both better screenshots and a fairer perf measure.
|
||
|
||
The canvas stays small and readPixels adds noise — I can't get a trustworthy absolute fps from this headless pane. The ratio is clear (bloom is a real per-pixel cost). I'll document perf honestly and rely on the quality gating. Let me confirm the stronger glow looks good and stays selective.
|
||
|
||
Bloom is confirmed selective (LEDs glow, everything else matte) but the demo's bright floor washes it out. Bloom pops against darkness — which is the real booth. Let me get a clean centered on/off pair against the dark background first, then try the actual game. Pin close on the wall, bloom OFF.
|
||
|
||
The reload-block can't survive the reload itself (chicken-and-egg). The real fix: run **my own Vite server with HMR disabled** so the Workshop's edits don't reload my page. Let me set that up on a separate port.
|
||
|
||
The config can't import `vite` from scratchpad. Let me export a plain object (no import needed).
|
||
|
||
HMR-disabled server up on 5199 — my page will stay put now. Let me open the demo there and set up the harness once.
|
||
|
||
Stable server confirmed (no reload). The LED wall isn't framed here — let me use the known-good framing and do a clean OFF vs ON pair.
|
||
|
||
Bloom OFF: LEDs flat, fps 72 shown (rAF seems live on the stable server — real number). Now bloom ON, same framing.
|
||
|
||
Bloom ON shows clear soft halos on the LEDs bleeding into the dark background — visibly glowier than OFF — while blue vinyl, steel, and plywood stay matte (**selective confirmed**). The demo's rAF is running here (fps updating), so let me get a real fps measurement by counting rAF frames with bloom off vs on (stopping my interecval so it's a clean measure).
|
||
|
||
rAF is genuinely paused (frame-count timed out) — I can't get an authoritative fps here; I'll document that honestly. Bloom evidence is solid from the demo. Now the critical check: **confirm the real game boots and renders correctly with atlas v2 + bloom, no errors**. Let me load the game on the stable server. |