Back to Powder Tool V600Billion
SOURCE / PINNED RELEASE

Made of little things.

Powder Tool V600Billion

Release
142767edcab8…
Author-recorded commit
6d92971effd0…
License
LICENSE
Author’s source reference
nostr://npub1fllw8kw0thjj55wds0uugcnp5kej2nfxd36eruq39d56wwz8r44q5q78wj/wss%3A%2F%2Fgit.napplet.soy%2F/powder-toy

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

source/scripts/gen-elements.mjs
/**
 * Generate src/save/elements.js: element and wall colours for the thumbnail
 * renderer, read from upstream's source at the pinned tag.
 *
 *   git clone --depth 1 --branch v100.1.400 https://github.com/The-Powder-Toy/The-Powder-Toy /tmp/tpt
 *   node scripts/gen-elements.mjs /tmp/tpt
 *
 * Element ids are the positions in src/simulation/elements/meson.build
 * (upstream generates ElementNumbers.h from that list); each element's
 * colour is the `Colour = 0x..._rgb` line in its .cpp. Wall ids are the
 * positions in LoadWalls() in src/simulation/SimulationData.cpp.
 */
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { upstream } from './upstream.mjs';

const source = process.argv[2] ?? process.env.UPSTREAM_SRC;
if (!source || !existsSync(join(source, 'src/simulation/elements/meson.build'))) {
  console.error('usage: node scripts/gen-elements.mjs <upstream checkout at the pinned tag>');
  process.exit(1);
}

const list = readFileSync(join(source, 'src/simulation/elements/meson.build'), 'utf8');
const block = /simulation_elem_names\s*=\s*\[([\s\S]*?)\]/.exec(list);
if (!block) throw new Error('simulation_elem_names not found');
const names = [...block[1].matchAll(/'([A-Z0-9_]+)'/g)].map((match) => match[1]);

const elements = names.map((name, id) => {
  const file = join(source, 'src/simulation/elements', `${name}.cpp`);
  if (!existsSync(file)) return [id, name, null];
  const colour = /\bColour\s*=\s*0x([0-9A-Fa-f]{6})_rgb/.exec(readFileSync(file, 'utf8'));
  return [id, name, colour ? parseInt(colour[1], 16) : null];
});

const data = readFileSync(join(source, 'src/simulation/SimulationData.cpp'), 'utf8');
const wallsBlock = /LoadWalls\(\)\s*\{[\s\S]*?std::vector<wall_type>\s*\{([\s\S]*?)\n\t\};/.exec(data);
if (!wallsBlock) throw new Error('LoadWalls() not found');
const walls = [...wallsBlock[1].matchAll(/\{0x([0-9A-Fa-f]{6})_rgb,[^}]*?"DEFAULT_WL_([A-Z]+)"/g)]
  .map((match, id) => [id, match[2], parseInt(match[1], 16)]);

const output = fileURLToPath(new URL('../src/save/elements.js', import.meta.url));
writeFileSync(output, `// Generated by scripts/gen-elements.mjs from The Powder Toy ${upstream.tag} (${upstream.commit}). GPL-3.0.\n`
  + `// [id, name, 0xRRGGBB]\nexport default ${JSON.stringify({ version: upstream.version, elements, walls })};\n`);
console.log(`${elements.length} elements (${elements.filter((row) => row[2] === null).length} without a colour), ${walls.length} walls -> ${output}`);