Back to Black Site
SOURCE / PINNED RELEASE

Made of little things.

Black Site

Release
666bc7c74ebd…
Author-recorded commit
05e95af79676…
License
LICENSE
Author’s source reference
nostr://npub12lm3rxsva8kfempyjkxupt09e02n3fezurkyadyqfejdc5e0r2kscqty6r/wss%3A%2F%2Fgit.napplet.soy%2F/n-d2225ddc391

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

src/main.ts
// The game stays framework-light; all account, save and social authority belongs to the shell.
import { bootGame } from 'virtual:black-site-game';
import { runtimeHasDomain } from './domain-availability.js';
import { mountCurrentUser } from './current-user.js';
import { createSaveStore } from './save-store.js';
import { createArmorySync } from './armory-sync.js';
import { createCustomizationSync } from './customization-sync.js';
import { mountArmoryControls } from './armory-ui.js';
import './game/game.css';
import './styles.css';

const store = createSaveStore(() => allSync.forEach(controller => controller.menu()));
(globalThis as { BLACKSITE_STORE?: unknown }).BLACKSITE_STORE = { get: store.get, set: store.set };
let game: ReturnType<typeof bootGame> | undefined;
let desiredOwner = '';
let switching = false;
let suspended = false;
let returnedFromMission = false;
const loading = document.createElement('div');
loading.id = 'accountLoading'; loading.setAttribute('role', 'status'); loading.hidden = true;
loading.textContent = 'Loading player save…'; document.body.append(loading);

mountCurrentUser(pubkey => {
  const owner = /^[a-f0-9]{64}$/i.test(pubkey) ? pubkey.toLowerCase() : '';
  if (owner === desiredOwner) return;
  desiredOwner = owner;
  void activateAccount();
});

const renderSync = mountArmoryControls(() => sync);
const sync = createArmorySync(store, () => game, renderSync);
const renderChoices = mountArmoryControls(() => choicesSync, true);
const choicesSync = createCustomizationSync(store, () => game, renderChoices);
const allSync = [sync, choicesSync];

async function activateAccount() {
  if (!game || switching) return;
  if (!game.isSafe()) {
    returnedFromMission = true;
    if (desiredOwner !== store.owner() && !suspended) { suspended = true; allSync.forEach(controller => controller.suspend()); }
    return;
  }
  if (desiredOwner === store.owner() && !suspended) {
    allSync.forEach(controller => controller.menu());
    if (returnedFromMission) { returnedFromMission = false; allSync.forEach(controller => { void controller.restore(); }); }
    return;
  }
  switching = true; loading.hidden = false;
  allSync.forEach(controller => controller.suspend());
  try {
    let target = desiredOwner;
    let bucket = await store.load(target);
    while (target !== desiredOwner) { target = desiredOwner; bucket = await store.load(target); }
    store.activate(bucket);
    game.reloadSaves();
    suspended = false; returnedFromMission = false;
    allSync.forEach(controller => { void controller.select(target); });
  } finally { switching = false; loading.hidden = true; }
  if (desiredOwner !== store.owner()) void activateAccount();
}
window.addEventListener('blacksite:screen', () => { void activateAccount(); });
window.addEventListener('blacksite:armory', () => sync.changed());
window.addEventListener('blacksite:customization', () => choicesSync.changed());
window.addEventListener('pagehide', () => allSync.forEach(controller => controller.close()));
window.addEventListener('pageshow', event => {
  if (event.persisted) allSync.forEach(controller => { void controller.select(store.owner() === desiredOwner ? desiredOwner : ''); });
});

void (async () => {
  store.activate(await store.load(''));
  game = bootGame();
  // Even a signed-out/missing-domain host receives a usable local save and sync state.
  if (runtimeHasDomain('identity') && desiredOwner) await activateAccount();
  else allSync.forEach(controller => { void controller.select(''); });
})();