Back to Napplet Machines V8
SOURCE / PINNED RELEASE

Made of little things.

Napplet Machines V8

Release
f041ff5dc40c…
Author-recorded commit
71c68951e1dd…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-b5572362d4a

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

tests/network-state.test.mjs
import assert from 'node:assert/strict';
import test from 'node:test';
import { makeLoader } from './load.mjs';
const race = '12345678-1234-1234-1234-123456789abc',
  host = 'a'.repeat(64),
  guest = 'b'.repeat(64);
function fixture(bytes = async () => {}) {
  const json = [],
    binary = [],
    errors = [];
  const window = {
    setTimeout,
    clearTimeout,
    setInterval,
    clearInterval,
    napplet: {
      webrtc: {
        sendBytes: async (id, value) => {
          binary.push(value);
          return bytes(id, value);
        },
      },
    },
  };
  const sdk = {
    webrtc: {
      send: async (id, payload) => {
        json.push({ id, payload });
      },
    },
    cvm: {},
  };
  const load = makeLoader({ window, Error, crypto, clearTimeout, clearInterval }, sdk);
  const { Multiplayer } = load('src/network.ts'),
    { createWorld } = load('src/physics.ts'),
    { Road, presets } = load('src/track.ts');
  const world = createWorld(
    [{ id: guest, name: 'Guest', car: 0, ai: false }],
    new Road(presets[0]),
  );
  const m = new Multiplayer();
  Object.assign(m, {
    actor: guest,
    authority: host,
    room: { room: 'test', peers: [host, guest] },
    session: 'control',
    stateSession: 'state',
    transient: true,
    start: { type: 'start', race, world, track: presets[0] },
  });
  m.connected.add(host);
  m.statePeers.add(host);
  m.binaryPeers.add(host);
  m.onError = (e) => errors.push(e);
  return { m, json, binary, errors, world };
}
const command = (seq) => ({
  seq,
  input: { throttle: 1, steer: 0, boost: false, brake: false, reset: false },
});
test('reordered/duplicate snapshots never move backwards; inputs and reliable one-shot resets deduplicate', () => {
  const { m, world } = fixture(),
    ticks = [],
    inputs = [],
    resets = [];
  m.onSnapshot = (w) => ticks.push(w.tick);
  for (const tick of [8, 6, 8, 9])
    m.receive(host, { type: 'world', race, world: { ...world, tick } });
  assert.deepEqual(ticks, [8, 9]);
  m.receive(guest, { type: 'world', race, world: { ...world, tick: 100 } });
  assert.deepEqual(ticks, [8, 9]);
  m.actor = host;
  m.onInput = (_, c) => inputs.push(c.at(-1).seq);
  m.onReset = (_, seq) => resets.push(seq);
  for (const seq of [4, 3, 4, 5])
    m.receive(guest, { type: 'input', race, commands: [command(seq)] });
  m.receive(guest, { type: 'input', race, commands: [command(9), command(8)] });
  m.receive(guest, {
    type: 'input',
    race,
    commands: [{ ...command(10), input: { ...command(10).input, steer: NaN } }],
  });
  for (const seq of [3, 3, 2, 4]) m.receive(guest, { type: 'reset', race, seq });
  assert.deepEqual(inputs, [4, 5]);
  assert.deepEqual(resets, [3, 4]);
});
test('backpressure keeps only newest state and preserves the in-flight snapshot', async () => {
  let complete;
  const f = fixture(() => new Promise((r) => (complete = r)));
  const packet = (tick) => ({ type: 'world', race, world: { ...f.world, tick } });
  const sending = f.m.sendLatest(packet(1));
  await f.m.sendLatest(packet(2));
  await f.m.sendLatest(packet(3));
  assert.equal(f.binary.length, 1);
  assert.equal(f.m.queued.world.tick, 3);
  complete();
  await new Promise((r) => setTimeout(r, 0));
  assert.equal(f.binary.length, 2);
  complete();
  await sending;
  assert.equal(f.m.queued, null);
});
test('unsupported is an explicit safe JSON fallback, timeout never retries the same payload', async () => {
  const packet = { type: 'world', race, world: fixture().world };
  const unsupported = fixture(async () => {
    throw new Error('unsupported');
  });
  await unsupported.m.sendLatest(packet);
  assert.equal(unsupported.json.length, 1);
  assert.equal(unsupported.binary.length, 1);
  const timeout = fixture(async () => {
    throw new Error('Request timed out');
  });
  await timeout.m.sendLatest(packet);
  assert.equal(timeout.json.length, 0);
  assert.equal(timeout.errors.length, 1);
  await timeout.m.sendLatest({ ...packet, world: { ...packet.world, tick: 2 } });
  assert.equal(timeout.json.length, 1);
  assert.equal(timeout.binary.length, 1);
  const full = fixture(async () => {
    throw new Error('QUEUE_FULL');
  });
  await full.m.sendLatest(packet);
  assert.equal(full.json.length, 0);
  assert.ok(full.m.queued);
  clearTimeout(full.m.retrySend);
});
test('missing peer capabilities use reliable JSON without probing with bytes', async () => {
  const f = fixture();
  f.m.statePeers.clear();
  f.m.binaryPeers.clear();
  await f.m.sendLatest({ type: 'input', race, commands: [command(1)] });
  assert.equal(f.binary.length, 0);
  assert.equal(f.json[0].id, 'control');
});