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.
/**
* The game thinks in integer save IDs and in usernames; Nostr has addresses
* and public keys. These two maps are the translation.
*
* IDs are derived from the save's address, so the same save has the same ID
* in every browser ("id 1234567" can be shared). Usernames carry a short
* piece of the key, so two players who both call themselves "alice" never
* look like the same person to the game (it uses the name to decide whose
* save it is).
*/
/** 31-bit positive ID from a string (FNV-1a), never 0. */
export function stableId(text) {
let hash = 0x811c9dc5;
for (let i = 0; i < text.length; i++) hash = Math.imul(hash ^ text.charCodeAt(i), 0x01000193) >>> 0;
return (hash & 0x7fffffff) || 1;
}
/** A username the game can show and search: letters, digits, _ and -, plus a key suffix. */
export function usernameFor(pubkey, profile) {
const raw = [profile?.name, profile?.display_name, profile?.displayName]
.find((value) => typeof value === 'string' && value.trim()) ?? '';
const clean = raw.normalize('NFKD').replace(/[^A-Za-z0-9_-]+/g, '').slice(0, 16);
return clean.length >= 2 ? `${clean}_${pubkey.slice(0, 4)}` : `nym_${pubkey.slice(0, 8)}`;
}
