import { join } from 'node:path'; import { mkdirSync } from 'node:fs'; import { DATA_PATH } from '@@/data-path'; /** * Where the session's state lives, and why none of it is in the plugin's own directory. * * A plugin directory is a git checkout that `plugins:update` will `git pull` over and `plugins:delete` will * remove. The wine prefix is ~600 MB of generated state that takes minutes to rebuild — putting it there * would mean an update fights the working tree and a reinstall costs a fresh download of the VB6 runtime. * * So it goes under `DATA_PATH/minesweeper/`, the same convention music's cache uses. The game executable * DOES ship in the repository: it is 68 KB, it is the thing being run rather than state produced by running * it, and its checksum is in the README. */ export const STATE_DIR = join(DATA_PATH, 'minesweeper'); /** The wine prefix — a `win32` one, because the game is an i386 PE. Generated; never committed. */ export const WINEPREFIX = join(STATE_DIR, 'prefix'); /** * Runtime scratch: pid files, logs, and the VNC socket. * * Created mode 0700 and that is load-bearing rather than tidy — it is the ONLY thing standing between * another local account and an unauthenticated VNC display. x11vnc runs with `-nopw`, which is correct * precisely because this directory refuses everyone but the owner. See `vnc.ts`. */ export const RUN_DIR = join(STATE_DIR, 'run'); /** x11vnc's listening socket. A path, not a port: unreachable without traversing RUN_DIR. */ export const VNC_SOCKET = join(RUN_DIR, 'vnc.sock'); /** Ships with the plugin. `import.meta.dir` is `/sidecar`. */ export const GAME_EXE = join(import.meta.dir, '..', 'game', 'Minesweeper X.exe'); export function ensureDirs(): void { mkdirSync(STATE_DIR, { recursive: true, mode: 0o700 }); mkdirSync(RUN_DIR, { recursive: true, mode: 0o700 }); }