# vpinball Play real `.vpx` pinball tables in your browser. Drop in your own table or try the bundled demo — no plugins, no native install. Powered by [`@valknar/vpinball-wasm`](https://dev.pivoine.art/valknar/vpinball-wasm), a WebAssembly build of the real [Visual Pinball](https://github.com/vpinball/vpinball) engine (real physics, real VBScript table scripting, real WebGL2 rendering). ## Features - **Play any self-contained `.vpx` table** — drag a file onto the landing page, or click to browse. - **Demo mode** — a bundled table plays instantly with no upload required. - **Fullscreen**, a live **FPS/stats** readout, and a **game info** panel (table name, size, load time) in an in-game HUD styled after a pinball cabinet's coin door. - **Installable as a PWA** — add it to your home screen or desktop; the engine is cached after your first game so it's available offline afterward. - **Deployable as a static site** via Docker Compose — no Node server at runtime, just nginx serving prebuilt files. ## Prerequisites - Node.js ≥ 20, [pnpm](https://pnpm.io) ≥ 11 - Docker + Docker Compose, for the containerized deploy ## Install ```bash pnpm install --frozen-lockfile --trust-lockfile ``` `vpinball-wasm` is published to a private Gitea npm registry (`https://dev.pivoine.art/api/packages/valknar/npm/`) under the `@valknar` scope. `.npmrc` maps that scope to the registry; the package is publicly readable, so no auth token is needed to install it. To bump the engine to a newer published version: ```bash pnpm add @valknar/vpinball-wasm@ ``` ## Development ```bash pnpm dev ``` `pnpm dev` copies the engine's build output into `public/vendor/vpinball-wasm/` first (via the `predev` script) — it's gitignored and regenerated from `node_modules`, so this only needs `pnpm install` to have completed. Re-run `pnpm run copy-engine-assets` by hand if you update the dependency without restarting the dev server. The dev server runs at `http://localhost:3000`. ## Build ```bash pnpm build ``` Produces a fully static export in `out/` (`next.config.ts` sets `output: "export"`) — no Node server needed to serve it. ## Docker deploy ```bash docker compose build docker compose up -d ``` Serves the static build via nginx on `http://localhost:8080`. No secrets or registry authentication are required to build the image. ## PWA The app can be installed from the browser's install prompt. A hand-rolled service worker (`public/sw.js`) precaches the app shell; the engine's `.wasm`/`.data` files (~34 MB) are cached on first visit to `/play`, not upfront, so installing the app doesn't force a large download before anyone has actually played. After that first visit, offline reloads work. When you ship a release that changes the app shell or updates the vendored engine build, bump the cache version so returning visitors actually get the update: ```bash pnpm run sw:bump ``` ## Controls | Key | Action | | -------------- | ------------- | | Left Shift | Left flipper | | Right Shift | Right flipper | | Enter | Plunger | | 1 | Start game | On touch devices, an on-screen control overlay appears automatically once a table is running. ## Limitations Inherited from the underlying engine: - Only self-contained `.vpx` tables are supported — tables that reference an external `.vbs` script override or a `Music/` folder won't load correctly. - No PinMAME, DOF, or FlexDMD plugin support. - Single-threaded (no `SharedArrayBuffer`) — performance depends on your device's single-core WebGL2 throughput. - Initial engine download is ~34 MB (cached after the first visit). - Gamepad input and DMD rendering are implemented but not yet confirmed on real hardware/tables. - Raw cabinet hardware input (real nudge/plunger boards) has no browser equivalent. ## License This app's own source has no license file yet — add one before distributing it. Separately, the built output bundles the `@valknar/vpinball-wasm` engine and its default table, which redistribute Visual Pinball source under a **mixed legacy/GPLv3+ license** (migrating file-by-file to GPLv3+ since October 2020) — see that package's own `LICENSE` for the authoritative terms before distributing a build.