SOURCE / PINNED RELEASE
Made of little things.
blockfall
- Release
- a6bb863994d9…
- Author-recorded commit
- e6ab5899ddac…
- License
- LICENSE
- Author’s source reference
- nostr://npub1dmmh0futyszl4445mv4xrygkgsgj8vpu79yx3qyy9qxmz4pemtzqlqmc87/wss%3A%2F%2Fgit.napplet.soy%2F/n-afafae55ef1
Archive hash verified: ba8de5cbee33e11e…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import { config } from '@napplet/sdk';
import { runtimeHasDomain } from './domain-availability.js';
import settingsSchema from '../config.schema.json';
export interface GameSettings {
effects: boolean;
trajectoryGuide: boolean;
}
export const gameSettings: GameSettings = {
effects: true,
trajectoryGuide: true,
};
type SettingsListener = (settings: GameSettings) => void;
const listeners = new Set<SettingsListener>();
export function onGameSettings(listener: SettingsListener): () => void {
listeners.add(listener);
listener({ ...gameSettings });
return () => {
listeners.delete(listener);
};
}
function notify(): void {
const snapshot = { ...gameSettings };
for (const listener of listeners) listener(snapshot);
}
// The upstream Vite plugin embeds config.schema.json into the signed build.
// Config stays optional: the game supplies sensible defaults above.
if (runtimeHasDomain('config')) {
void (async () => {
if (!config.schema) {
await config.registerSchema(
settingsSchema as Parameters<typeof config.registerSchema>[0],
);
}
const subscription = config.subscribe((values) => {
if (typeof values.effects === 'boolean') gameSettings.effects = values.effects;
if (typeof values.trajectoryGuide === 'boolean') {
gameSettings.trajectoryGuide = values.trajectoryGuide;
}
notify();
});
window.addEventListener('pagehide', () => subscription.close(), { once: true });
})().catch(() => {
// Optional settings: keep local defaults when the host does not support them.
});
}
