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.
// Strip the parts of Rapier's WASM this game never calls (soft bodies, joints,
// character/vehicle controllers, scene queries, serialization…): ~3.1 MB →
// ~2.1 MB before gzip.
//
// An export survives when any of these hold:
// - it is wasm-bindgen plumbing (not a `raw*` binding), a constructor or a destructor;
// - tools/build/rapier-exports.json lists it (recorded from real runs by
// tools/build/record-rapier-exports.mjs);
// - its method name matches a `.method(` call in src/game/physics/*.ts, so a
// newly used Rapier method is kept even before the list is re-recorded.
// A binding that was stripped anyway fails loudly: "wasm.raw…_… is not a function".
// Set SSRC_RAPIER_FULL=1 to embed the untouched module.
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
import binaryen from 'binaryen';
export function rapierKeepList(root: string): Set<string> {
const keep = new Set<string>(JSON.parse(readFileSync(join(root, 'tools/build/rapier-exports.json'), 'utf8')).exports);
const physics = join(root, 'src/game/physics');
for (const file of readdirSync(physics).filter((f) => f.endsWith('.ts'))) {
for (const m of readFileSync(join(physics, file), 'utf8').matchAll(/\.([A-Za-z]\w*)\(/g)) keep.add(`method:${m[1].toLowerCase()}`);
}
return keep;
}
function kept(name: string, keep: Set<string>): boolean {
if (!name.startsWith('raw') || keep.has(name)) return true;
if (/_new$|_free$/.test(name)) return true;
// rawrigidbodyset_rbSetLinvel → setlinvel; rawcolliderset_coSetFriction → setfriction.
const method = /^raw[a-z0-9]+_(?:rb|co)?([A-Za-z]\w*)$/.exec(name)?.[1];
return method !== undefined && keep.has(`method:${method.toLowerCase()}`);
}
export function slimRapierWasm(wasm: Uint8Array, keep: Set<string>): Uint8Array {
const mod = binaryen.readBinary(wasm);
try {
// Only features every current browser ships: binaryen's `All` would also
// switch on newer binary encodings (e.g. compact imports) that browsers reject.
const F = binaryen.Features;
mod.setFeatures(F.MutableGlobals | F.NontrappingFPToInt | F.BulkMemory | F.BulkMemoryOpt | F.SignExt | F.ReferenceTypes | F.Multivalue);
if (!mod.validate()) throw new Error('rapier-slim: the Rapier module needs WASM features outside the browser baseline');
const drop: string[] = [];
for (let i = 0; i < mod.getNumExports(); i++) {
const info = binaryen.getExportInfo(mod.getExportByIndex(i));
if (info.kind === binaryen.ExternalFunction && !kept(info.name, keep)) drop.push(info.name);
}
for (const name of drop) mod.removeExport(name);
mod.runPasses(['remove-unused-module-elements']);
return mod.emitBinary();
} finally {
mod.dispose();
}
}
