67 lines
2.7 KiB
Markdown
67 lines
2.7 KiB
Markdown
|
|
# Observer Effect — doomsday clock
|
|||
|
|
|
|||
|
|
A period-styled (1964) clock for running Delta Green: *Observer Effect* online.
|
|||
|
|
|
|||
|
|
- **Player screen** — `observer.ellie.town/` (`clock.html`): an Olympian Holobeam
|
|||
|
|
Array master chronometer. Nixie tubes counting toward 22:03:37, warning lamps
|
|||
|
|
that flash on each pulse, a red wash and dissonant flutes/drums as communion
|
|||
|
|
nears. Read-only; safe to share with the players.
|
|||
|
|
- **Handler panel** — `observer.ellie.town/control` (`control.html`): run/hold,
|
|||
|
|
scrub the clock, jump to any scenario beat, set the iteration (which resets
|
|||
|
|
reality to its wake point), and fire pulse / communion / text effects on the
|
|||
|
|
players' screen.
|
|||
|
|
|
|||
|
|
## How it syncs
|
|||
|
|
|
|||
|
|
A tiny Rust WebSocket relay (`relay/`) holds the one authoritative clock. The
|
|||
|
|
panel sends authenticated commands; every connected screen gets the new state
|
|||
|
|
and free-runs the digits locally between actions. Late joiners get the current
|
|||
|
|
state immediately. Served behind nginx with TLS; the relay only listens on
|
|||
|
|
loopback.
|
|||
|
|
|
|||
|
|
## Deploy
|
|||
|
|
|
|||
|
|
1. DNS: point `observer.ellie.town` at the VPS (A/AAAA). ACME does the cert.
|
|||
|
|
2. It's already wired into `flake.nix` (vps modules) as
|
|||
|
|
`./services/observer-effect.nix`. Rebuild the VPS:
|
|||
|
|
`nixos-rebuild switch --flake .#vps` (however you normally deploy).
|
|||
|
|
|
|||
|
|
## The control key
|
|||
|
|
|
|||
|
|
Commands are authenticated with a shared token in `services/secrets/observer_vps.yaml`
|
|||
|
|
(sops). Enter it once in the panel's **CONTROL KEY** field (saved in that
|
|||
|
|
browser). Rotate any time with `sops services/secrets/observer_vps.yaml` then
|
|||
|
|
rebuild.
|
|||
|
|
|
|||
|
|
## Running a session
|
|||
|
|
|
|||
|
|
The clock starts paused at iteration I, 17:00:00 (the Agents' arrival). Drive it
|
|||
|
|
by hand to match table pacing — **JUMP TO BEAT** for the scripted moments, or
|
|||
|
|
**RATE ×N** + **RUN** to let it tick. Fire **PULSE** on the live shudders and
|
|||
|
|
**COMMUNION** at 22:03:37; then hit **ITERATION II/III/IV** to reset reality
|
|||
|
|
nearer the end as the loop tightens. **SHOW** broadcasts a line of text over the
|
|||
|
|
players' screen (e.g. *"I see the throne of God."*).
|
|||
|
|
|
|||
|
|
## Sound effects
|
|||
|
|
|
|||
|
|
The player screen's pulse / communion / broadcast-text sounds are pre-rendered
|
|||
|
|
mp3s in `site/sfx/`, synthesized from pure ffmpeg `lavfi` filtergraphs (no
|
|||
|
|
samples). Regenerate with:
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
cd site/sfx && nix-shell -p ffmpeg --run ./generate.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
If a file fails to load the screen falls back to an equivalent WebAudio synth.
|
|||
|
|
The ambient dread drone is always synth (it's driven by the tension level).
|
|||
|
|
|
|||
|
|
## Local dev (no Nix)
|
|||
|
|
|
|||
|
|
```sh
|
|||
|
|
cd relay
|
|||
|
|
OBSERVER_TOKEN=test cargo run # relay on 127.0.0.1:8770
|
|||
|
|
# serve ./site on :8080 and proxy /ws -> 127.0.0.1:8770, or just open
|
|||
|
|
# site/clock.html and append ?, then point common.js' WS at ws://localhost:8770/ws
|
|||
|
|
```
|
|||
|
|
The pages connect to `wss?://<host>/ws`, so behind nginx everything is same-origin.
|