Back to Supersonic RC Revive
SOURCE / PINNED RELEASE

Made of little things.

Supersonic RC Revive

Release
bb8b570f3600…
Author-recorded commit
073e2d2c0e63…
License
LICENSE
Author’s source reference
nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.shakespeare.diy%2F/SuperSonicRCRevive

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

tests/online-scenario-shared.mjs
// Trusted local scenario helpers: real soyLI services and WebRTC between guest contexts.
import { readFileSync } from 'node:fs';
import { createHash } from 'node:crypto';

export async function runOnlineScenario({players,check,measure,diagnostics}, enter) {
  const waitFor = (player, fn, arg, timeout=30000) => player.frame.waitForFunction(fn,arg,{timeout});
  const ready = p => waitFor(p,()=>!!document.querySelector('canvas')?.dataset.localPosition);
  // Seed one guest with a different valid pack through the real pack-loading UI.
  // Only this fixture download is supplied by the test. The later host-pack
  // download uses the actual soyLI RESOURCE bridge and registered asset bytes.
  const inventory = JSON.parse(readFileSync('napplet.assets.json', 'utf8'));
  const original = readFileSync(inventory.assets.find(a => a.id === 'game-pack').path);
  const different = Buffer.from(original);
  const indexLength = original.readUInt32LE(12);
  const index = JSON.parse(original.subarray(16, 16 + indexLength).toString());
  index.meta.title = 'Guest fixture'.padEnd(index.meta.title.length, '.').slice(0, index.meta.title.length);
  const encoded = Buffer.from(JSON.stringify(index));
  if (encoded.length !== indexLength) throw new Error('Fixture metadata must preserve pack index length');
  encoded.copy(different, 16);
  const hash = createHash('sha256').update(different).digest('hex');
  await players[1].frame.evaluate(({hash,base64}) => {
    const resource = window.napplet.resource;
    const bytes = resource.bytes.bind(resource);
    window.__onlineResourceDownloads = [];
    resource.bytes = async (url, options) => {
      window.__onlineResourceDownloads.push(url);
      if (url === `blossom:sha256:${hash}`) return new Blob([Uint8Array.from(atob(base64), c => c.charCodeAt(0))]);
      return bytes(url, options);
    };
  }, {hash,base64:different.toString('base64')});
  await players[1].frame.getByRole('button',{name:'Asset pack…',exact:true}).click();
  await players[1].frame.locator('#packLink').fill(hash);
  await players[1].frame.getByRole('button',{name:'Load',exact:true}).click();
  await players[1].frame.locator('#packPanel').waitFor({state:'hidden'});
  check('guest starts with a different asset pack', true);
  await enter(players, ready, check);
  check('guest downloaded the room pack through RESOURCE before spawning',
    await players[1].frame.evaluate(hash => window.__onlineResourceDownloads.includes(`blossom:sha256:${hash}`),
      createHash('sha256').update(original).digest('hex')));
  await Promise.all(players.map(p=>waitFor(p,n=>Number(document.querySelector('canvas')?.dataset.onlinePlayers)===n,players.length)));
  check('all players render every remote car',true);
  check('real peer transport connected',(await diagnostics()).every(rows=>rows.some(p=>p.state==='connected')));
  const guest=players[1];
  const feedback=await guest.frame.evaluate(async()=>{
    const canvas=document.querySelector('canvas');
    const before=canvas.dataset.localPosition.split(',').map(Number),start=performance.now();
    window.dispatchEvent(new KeyboardEvent('keydown',{code:'ArrowUp',bubbles:true}));
    try {
      await new Promise((resolve,reject)=>{
        const poll=()=>{
          const p=canvas.dataset.localPosition.split(',').map(Number);
          if(Math.hypot(p[0]-before[0],p[1]-before[1])>.01) resolve();
          else if(performance.now()-start>2000) reject(new Error('Guest car did not move'));
          else requestAnimationFrame(poll);
        };
        requestAnimationFrame(poll);
      });
      return performance.now()-start;
    } finally {window.dispatchEvent(new KeyboardEvent('keyup',{code:'ArrowUp',bubbles:true}));}
  });
  measure('guest local rendered driving feedback',feedback,250);
  // Remote cars are ordered by player key, not join order: watch for any one of them to move.
  const before=JSON.parse(await players[0].frame.locator('canvas').getAttribute('data-remote-positions'));
  await guest.frame.evaluate(()=>window.dispatchEvent(new KeyboardEvent('keydown',{code:'ArrowUp',bubbles:true})));
  await waitFor(players[0],previous=>{
    const current=JSON.parse(document.querySelector('canvas')?.dataset.remotePositions??'[]');
    return current.length===previous.length && current.some((p,i)=>Math.hypot(p[0]-previous[i][0],p[1]-previous[i][1])>2);
  },before);
  await guest.frame.evaluate(()=>window.dispatchEvent(new KeyboardEvent('keyup',{code:'ArrowUp',bubbles:true})));
  check('guest movement reaches another player\'s rendered cars',true);
  await guest.frame.getByRole('button',{name:'Leave online',exact:true}).click();
  await waitFor(players[0],n=>Number(document.querySelector('canvas')?.dataset.onlinePlayers)===n,players.length-1);
  check('leaving removes the remote car',true);
  // No host: the room continues for everyone else when its first player leaves.
  await players[0].frame.getByRole('button',{name:'Leave online',exact:true}).click();
  const remaining=players.slice(2);
  if(remaining.length>1) {
    await Promise.all(remaining.map(p=>waitFor(p,n=>Number(document.querySelector('canvas')?.dataset.onlinePlayers)===n,remaining.length)));
    check('the room continues after its first player leaves',true);
  }
}