Skip to content

EN Play Speedrun

wanoo edited this page Oct 23, 2026 · 2 revisions

Speedrun for players: LiveSplit and OBS

Français · Type: how-to · Audience: player · Context: player's browser · Status: ready · Applies from: 4.1.14

Speedrun and Remix · contract: stable · verified by CI (support matrix of 4.4.0, 2026-10-23): Replays in four runtimes (cross-runtime) · automated checks: jobs cross-runtime, e2e; CI plan e2e; 2 test files · people's passes: runs-real-players not run (#85), run-resume-power-cycle not run (#84), mystery-deployed not run (#82), livesplit-obs not run (#81), code-wheel-human not run (#78) · known limits: integrity-not-authenticity, livesplit-obs-not-tried

How to run a quest'n'click game against the clock, export the proof of your run, and show your timer in OBS or drive LiveSplit. For authors who want to declare categories: Speedrun for authors.

What you get

A timed attempt in a category the game declares (Any%, for instance), split on what happens in the game, never on pixels; at the finish, a sealed .wsrun file that anyone can replay and verify; your records on your device; and, if you stream, a timer in OBS or LiveSplit driven by the game.

A replay proves that a run is possible and that its in-game time is exact. It does not promise to detect every cheat: only a server's or a person's observation raises the trust further (see the limits).

Context and versions

The player of a game that declares speedrun categories (speedrun in its content). The engine has had speedruns since 4.1.14 "Time Attack"; this page holds from that version. The sample game at wanoo.github.io/quest-n-click declares no category, so its pause menu has no Speedrun row; the reference game in the engine repository (games/reference) declares several.

Prerequisites

  • A game whose pause menu shows Speedrun.
  • For OBS or LiveSplit only: Node 22.12 or newer on the machine you stream from, and a copy of the engine (a created project, or the engine repository); OBS or LiveSplit.

Where to run the commands

The run itself needs no command: it happens in the game. The streaming tools are small Node processes on your own machine, never on a server and never in the game: in the engine repository through npm run, or in a created project from the engine package it installed (node_modules/quest-n-click/tools/speedrun/).

Steps

  1. Start: pause menu › Speedrun › a category. The game restarts with the category's seed; a small timer shows the category, the time it is ranked on (real time, in-game time, or in-game time without pauses) and the last split.
  1. During the run: the pause menu shows Abandon run. Opening the menu is recorded as a pause, and the tab going to the background is recorded too; neither stops the in-game time (the game does not run while it waits).
  1. At the finish: the run is sealed, and the pause menu shows Export run: a .wsrun file, the proof to send to a leaderboard or a friend. The dev panel (?dev) has the same export.
  1. Your records stay on the device, offline (IndexedDB web-scumm-runs): the personal best and its splits, the best segment of every split, the sum of best, attempts, finishes, abandons, notes. A run resumes after a crash or a closed tab from its last stored chunk (every 500 inputs); what was played after it is played again.

The ghost is your personal best played beside you, on semantic targets: the room it is in, the action it does and what it holds, ahead or behind at each split, never a pixel trail. It is off the first time you play a category on this device, because it would show the answers of the puzzles.

Streaming: OBS and LiveSplit

The tools run on the player's machine (decision D23), never on the Bridge, never in the game. Open the game with ?speedrunTool=<port> in its address: the page then posts its run's events (the category, the split ids and names, the times; nothing else: no save, no player id, no token) to 127.0.0.1:<port>. A page carries one port, so it feeds one tool at a time. The tools accept events from the game's origin only: the dev server and the preview by default (localhost and 127.0.0.1, ports 5173 and 4173), --origin=<url> for a deployed game. Another page open in the browser cannot post fake splits.

  1. OBS: start the overlay, then add an OBS Browser Source at http://127.0.0.1:7777/?mode=full (or compact: the timer and the last split; transparent: the same on no background). It updates by Server-Sent Events.

    # in the engine repository, on your machine
    npm run speedrun:overlay -- --port=7777 --origin=https://wanoo.github.io
    # in a created project, on your machine
    node node_modules/quest-n-click/tools/speedrun/overlay.mjs --port=7777 --origin=https://wanoo.github.io

    Then open the game at https://…/?speedrunTool=7777. Use your game's own address in --origin.

  1. LiveSplit: in LiveSplit, Control › Start WebSocket Server (it listens on ws://127.0.0.1:16834/livesplit), then start the bridge and open the game with ?speedrunTool=7778. The game drives LiveSplit: start, in-game time, split, skip, pause, reset.

    # in the engine repository, on your machine
    npm run speedrun:livesplit -- serve --port=7778 --origin=https://wanoo.github.io

    --livesplit=ws://… points to another LiveSplit address.

  1. LiveSplit splits from a run: write a LiveSplit .lss file with a run's splits as the personal best.

    # in the engine repository, on your machine
    npm run speedrun:livesplit -- export run.wsrun --names=Pantry,Garden,Market --out=run.lss

    Without --names, the segments are named by the split ids; without --out, the file is written beside the run.

Expected result, and how to check it

  • In the game: the timer, then Export run at the finish.
  • In OBS: the Browser Source shows the category's name instead of "waiting for a run…", and the splits as you reach them.
  • In LiveSplit: the timer starts when the run starts and splits with the game.

Common errors

Symptom Cause Fix
No Speedrun row in the pause menu The game declares no category Nothing to do: that game has no speedrun
The overlay stays on "waiting for a run…" The page was opened without ?speedrunTool=<port>, or with another port Reload the game with the overlay's port in the address
The overlay gets nothing from a deployed game The tool accepts the dev server's origins only by default Restart it with --origin=<the game's address>
LiveSplit does not move Its WebSocket server is not started LiveSplit › Control › Start WebSocket Server
The run does not start The category could not start (the message says why) Read the message; report it to the game's author

Files or data changed

In the browser: the run's chunks and your records in IndexedDB (web-scumm-runs). On disk: the .wsrun you export, the .lss that export writes. The tools keep nothing.

Recovery or going back

Abandon run ends an attempt (counted as an abandon). A run resumed after a crash continues from its last chunk; a run cannot be resumed in another world or with another proof. A run submitted to a leaderboard on a Bridge can be deleted with the token the Bridge gave at submission (Privacy).

Limits

Limit · integrity-not-authenticity The chain proves a file was not altered after it was sealed, not that the player was honest: pauses, menus, saves, the real time and the inputs used are the player's word. A run whose inputs a script chose replays as valid; only a witness or a moderator rules it out.

Limit · livesplit-obs-not-tried OBS and LiveSplit are tested by machines only. A real session by a person is the pass livesplit-obs, open (#81) as of 4.4.0.

References


Edit the source of this page · Report an error

Home

Index (6)
Start (6)
Play (9)
Install (17)
Create a game (55)
Engine (4)
Local Studio (24)
Team Studio (21)
Clever Cloud (23)
Reality Bridge and connectors (16)
Contribute (25)
Reference (7)

Clone this wiki locally