SOURCE / PINNED RELEASE
Made of little things.
Big Rig Rush
- Release
- ec9b6549f752…
- Author-recorded commit
- 74b729258b1a…
- License
- LICENSE
- Author’s source reference
- nostr://npub1sj2vketepqw9v6fmge5fdzuj7atj9sv6qv2jss05n2z6rl64lcfqumdsnt/wss%3A%2F%2Fgit.napplet.soy%2F/n-0a99f0cae40
Archive hash verified: 900e22810340ccb1…. 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';
// The upstream Vite plugin embeds config.schema.json into the signed build.
// Config is optional: without it the game runs on these defaults.
export type TrafficLevel = 'light' | 'normal' | 'rush';
export type TouchControlsMode = 'auto' | 'always' | 'never';
export interface GameSettings {
traffic: TrafficLevel;
rudeness: number;
touchControls: TouchControlsMode;
screenShake: boolean;
soundVolume: number;
}
export const settings: GameSettings = {
traffic: 'normal',
rudeness: 45,
touchControls: 'auto',
screenShake: true,
soundVolume: 80,
};
const listeners = new Set<(value: GameSettings) => void>();
export function onSettingsChange(listener: (value: GameSettings) => void): void {
listeners.add(listener);
}
function applyValues(values: Record<string, unknown>): void {
if (values.traffic === 'light' || values.traffic === 'normal' || values.traffic === 'rush') {
settings.traffic = values.traffic;
}
if (typeof values.rudeness === 'number' && Number.isFinite(values.rudeness)) {
settings.rudeness = Math.max(0, Math.min(100, values.rudeness));
}
if (values.touchControls === 'auto' || values.touchControls === 'always' || values.touchControls === 'never') {
settings.touchControls = values.touchControls;
}
if (typeof values.screenShake === 'boolean') settings.screenShake = values.screenShake;
if (typeof values.soundVolume === 'number' && Number.isFinite(values.soundVolume)) {
settings.soundVolume = Math.max(0, Math.min(100, values.soundVolume));
}
for (const listener of listeners) listener(settings);
}
if (runtimeHasDomain('config')) {
void (async () => {
// Some hosts consume the embedded schema; others need standard registration.
// Do not replace a schema that the host already supplied.
if (!config.schema) {
await config.registerSchema(settingsSchema as Parameters<typeof config.registerSchema>[0]);
}
const subscription = config.subscribe((values) => applyValues(values as Record<string, unknown>));
window.addEventListener('pagehide', () => subscription.close(), { once: true });
})().catch(() => {
// Optional operations may be unavailable even when a host exposes the domain.
});
}
