(function (root, factory) { "use strict"; const api = factory(); if (typeof module === "object" && module.exports) module.exports = api; root.ArchiveWorldState = api; }(typeof globalThis !== "undefined" ? globalThis : this, function () { "use strict"; const VERSION = 1; const STORAGE_KEY = "zxh_archive_world_v1"; const PALETTES = Object.freeze(["brass", "moss", "berry"]); const LANDMARK_IDS = Object.freeze([ "gate", "library", "study", "inn", "workshop", "playroom", "museum", "garden" ]); const SPAWN = Object.freeze({ x: 640, y: 830 }); function validateName(value) { const name = String(value || "").trim().replace(/\s+/g, " "); return name.length >= 1 && name.length <= 20 ? name : null; } function validatePalette(value) { return PALETTES.includes(value) ? value : null; } function fresh(name, palette) { return { version: VERSION, name: validateName(name) || "", palette: validatePalette(palette) || "brass", discovered: [], complete: false, position: { x: SPAWN.x, y: SPAWN.y }, soundEnabled: false }; } function clamp(value, min, max, fallback) { const number = Number(value); return Number.isFinite(number) ? Math.min(max, Math.max(min, number)) : fallback; } function normalize(candidate) { if (!candidate || candidate.version !== VERSION) return null; const name = validateName(candidate.name); const palette = validatePalette(candidate.palette); if (!name || !palette) return null; const discovered = Array.isArray(candidate.discovered) ? Array.from(new Set(candidate.discovered.filter((id) => LANDMARK_IDS.includes(id)))) : []; return { version: VERSION, name, palette, discovered, complete: LANDMARK_IDS.every((id) => discovered.includes(id)), position: { x: clamp(candidate.position && candidate.position.x, 36, 1244, SPAWN.x), y: clamp(candidate.position && candidate.position.y, 36, 924, SPAWN.y) }, soundEnabled: candidate.soundEnabled === true }; } function parse(raw) { if (!raw) return null; try { return normalize(JSON.parse(raw)); } catch (_error) { return null; } } function discover(state, landmarkId) { const current = normalize(state); if (!current || !LANDMARK_IDS.includes(landmarkId)) return current; if (!current.discovered.includes(landmarkId)) current.discovered.push(landmarkId); current.complete = LANDMARK_IDS.every((id) => current.discovered.includes(id)); return current; } function withPosition(state, x, y) { const current = normalize(state); if (!current) return null; current.position.x = clamp(x, 36, 1244, SPAWN.x); current.position.y = clamp(y, 36, 924, SPAWN.y); return current; } return Object.freeze({ VERSION, STORAGE_KEY, PALETTES, LANDMARK_IDS, SPAWN, validateName, validatePalette, fresh, normalize, parse, discover, withPosition }); }));