Back to Supersonic RC Revive
SOURCE / PINNED RELEASE

Made of little things.

Supersonic RC Revive

Release
1ba42f1ca1d6…
Author-recorded commit
baecad10b1cd…
License
LICENSE
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.napplet.soy%2F/n-143146b0d6f

Archive hash verified: 90d22b206672eba4…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

tools/sim/screenshot.mjs
#!/usr/bin/env node
// Open dist/index.html in headless Chromium, optionally drive, and screenshot.
//   node tools/sim/screenshot.mjs out.png [script] [WxH]
// script: comma list of steps: "<keys>:<seconds>" (keys u d l r s e(Esc), "-" for none),
// "click=<css selector>:<seconds>" or "shot=<file.png>" (extra screenshot).
import { resolve, dirname } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { createRequire } from 'node:module';

const root = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
const require = createRequire(resolve(root, 'node_modules/.pnpm/playwright-core@1.61.0/node_modules/playwright-core/package.json'));
const { chromium } = require('playwright-core');

const [out = 'shot.png', script = '-:2', size = '960x600'] = process.argv.slice(2);
const [width, height] = size.split('x').map(Number);
const KEYS = { u: 'ArrowUp', d: 'ArrowDown', l: 'ArrowLeft', r: 'ArrowRight', s: 'Space', e: 'Escape' };

const browser = await chromium.launch({ args: ['--use-angle=swiftshader', '--enable-unsafe-swiftshader', '--ignore-gpu-blocklist'] });
const page = await browser.newPage({ viewport: { width, height } });
page.on('console', (m) => console.log(`[console.${m.type()}] ${m.text()}`));
page.on('pageerror', (e) => console.log(`[pageerror] ${e.message}`));
await page.goto(pathToFileURL(resolve(root, 'dist/index.html')).href);
await page.waitForFunction(() => document.querySelector('.screen-button, .hud-timer') || document.querySelector('#status')?.dataset.state === 'error', null, { timeout: 90000 });
for (const step of script.split(',')) {
  if (step.startsWith('shot=')) {
    await page.screenshot({ path: step.slice(5) });
    continue;
  }
  if (step.startsWith('click=')) {
    const [sel, secs] = step.slice(6).split(':');
    await page.click(sel);
    await page.waitForTimeout(Number(secs ?? 1) * 1000);
    continue;
  }
  const [keys, secs] = step.split(':');
  const held = keys === '-' ? [] : [...keys].map((k) => KEYS[k]);
  for (const k of held) await page.keyboard.down(k);
  await page.waitForTimeout(Number(secs) * 1000);
  for (const k of held) await page.keyboard.up(k);
}
console.log('status:', await page.textContent('#status'), '| hud:', await page.evaluate(() => document.querySelector('.hud-layer')?.textContent ?? ''));
await page.screenshot({ path: out });
await browser.close();