{"version":3,"sources":["../src/constants.ts","../src/utils.ts","../src/route-manager.ts","../src/router.ts","../src/scene-registry.ts","../src/scene-manager.ts"],"sourcesContent":["/**\n * Constants for Scene Management System\n */\n\nexport const DEFAULT_PATH = \"/\";\nexport const PATH_SEPARATOR = \"/\";\nexport const PARAM_PATTERN = /:(\\w+)/g;\nexport const PARAM_REPLACEMENT = \"([^/]+)\";\n","/**\n * Utility functions for Scene Management System\n */\n\n/**\n * Check if code is running in browser environment\n */\nexport function isBrowser(): boolean {\n\treturn typeof window !== \"undefined\";\n}\n\n/**\n * Safely execute a function with error handling\n */\nexport function safeExecute<T>(\n\tfn: () => T,\n\terrorHandler: (error: unknown, context?: string) => void,\n\tcontext?: string,\n): T | undefined {\n\ttry {\n\t\treturn fn();\n\t} catch (error) {\n\t\terrorHandler(error, context);\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Check if a value is a valid non-empty string\n */\nexport function isValidString(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length > 0;\n}\n\n/**\n * Check if a value is a valid object\n */\nexport function isValidObject(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Normalize path by removing query string, hash, and ensuring leading slash\n */\nexport function normalizePath(path: string): string {\n\tconst cleanPath = path.split(\"?\")[0].split(\"#\")[0];\n\treturn cleanPath.startsWith(\"/\") ? cleanPath : `/${cleanPath}`;\n}\n","import { PARAM_PATTERN, PARAM_REPLACEMENT } from \"./constants\";\nimport type { RouteDefinition } from \"./types\";\nimport { isValidString } from \"./utils\";\n\nexport class RouteManager {\n\tprivate routes: RouteDefinition[] = [];\n\n\t/**\n\t * Register a route\n\t * @param path Path pattern (e.g. \"/player/:id\")\n\t * @param sceneName Name of the scene to map to\n\t */\n\tregister(path: string, sceneName: string): void {\n\t\tif (!this.validateRouteInputs(path, sceneName)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { regex, keys } = this.parsePath(path);\n\t\tthis.routes.push({\n\t\t\tpath,\n\t\t\tsceneName,\n\t\t\tregex,\n\t\t\tkeys,\n\t\t});\n\t}\n\n\t/**\n\t * Validate route registration inputs\n\t */\n\tprivate validateRouteInputs(path: unknown, sceneName: unknown): path is string {\n\t\tif (!isValidString(path)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!isValidString(sceneName)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Match a path to a route\n\t * @param path Path to match against registered routes\n\t * @returns Route match with scene name and params, or null if no match\n\t */\n\tmatch(path: string): {\n\t\tsceneName: string;\n\t\tparams: Record<string, string>;\n\t} | null {\n\t\tif (!isValidString(path)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfor (const route of this.routes) {\n\t\t\tconst match = this.tryMatchRoute(route, path);\n\t\t\tif (match) {\n\t\t\t\treturn match;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Try to match a single route against a path\n\t */\n\tprivate tryMatchRoute(\n\t\troute: RouteDefinition,\n\t\tpath: string,\n\t): {\n\t\tsceneName: string;\n\t\tparams: Record<string, string>;\n\t} | null {\n\t\tconst regexMatch = route.regex.exec(path);\n\t\tif (!regexMatch) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst params = this.extractParams(route.keys, regexMatch);\n\t\treturn {\n\t\t\tsceneName: route.sceneName,\n\t\t\tparams,\n\t\t};\n\t}\n\n\t/**\n\t * Extract route parameters from regex match\n\t */\n\tprivate extractParams(keys: string[], match: RegExpExecArray): Record<string, string> {\n\t\tconst params: Record<string, string> = {};\n\t\tkeys.forEach((key, index) => {\n\t\t\tparams[key] = match[index + 1];\n\t\t});\n\t\treturn params;\n\t}\n\n\t/**\n\t * Parse path pattern to regex\n\t * Converts route patterns like \"/player/:id\" to regex\n\t */\n\tprivate parsePath(path: string): {\n\t\tregex: RegExp;\n\t\tkeys: string[];\n\t} {\n\t\tconst keys: string[] = [];\n\t\tconst pattern = path\n\t\t\t.replace(PARAM_PATTERN, (_, key) => {\n\t\t\t\tkeys.push(key);\n\t\t\t\treturn PARAM_REPLACEMENT;\n\t\t\t})\n\t\t\t.replace(/\\//g, \"\\\\/\");\n\n\t\treturn {\n\t\t\tregex: new RegExp(`^${pattern}$`),\n\t\t\tkeys,\n\t\t};\n\t}\n\n\t/**\n\t * Clear all routes\n\t */\n\tclear(): void {\n\t\tthis.routes = [];\n\t}\n}\n","import { DEFAULT_PATH } from \"./constants\";\nimport type { RouteManager } from \"./route-manager\";\nimport type { SceneManager } from \"./scene-manager\";\nimport type { RouterState } from \"./types\";\nimport { isBrowser, normalizePath } from \"./utils\";\n\nexport class Router {\n\tprivate routeManager: RouteManager;\n\tprivate sceneManager: SceneManager;\n\tprivate state: RouterState = {\n\t\tpath: DEFAULT_PATH,\n\t\tparams: {},\n\t\tsceneName: null,\n\t};\n\n\tconstructor(routeManager: RouteManager, sceneManager: SceneManager) {\n\t\tthis.routeManager = routeManager;\n\t\tthis.sceneManager = sceneManager;\n\t\tthis.setupPopStateListener();\n\t}\n\n\t/**\n\t * Setup browser history listener\n\t */\n\tprivate setupPopStateListener(): void {\n\t\tif (isBrowser()) {\n\t\t\twindow.addEventListener(\"popstate\", () => {\n\t\t\t\tthis.handlePathChange(window.location.pathname);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Navigate to a path (adds to browser history)\n\t * @param path Path to navigate to (e.g., \"/player/42\")\n\t */\n\tpush(path: string): void {\n\t\tif (!this.validatePath(path)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedPath = normalizePath(path);\n\t\tif (normalizedPath === this.state.path) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.updateBrowserHistory(normalizedPath, \"push\");\n\t\tthis.handlePathChange(normalizedPath);\n\t}\n\n\t/**\n\t * Replace current path (doesn't add to browser history)\n\t * @param path Path to navigate to (e.g., \"/player/42\")\n\t */\n\treplace(path: string): void {\n\t\tif (!this.validatePath(path)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedPath = normalizePath(path);\n\t\tthis.updateBrowserHistory(normalizedPath, \"replace\");\n\t\tthis.handlePathChange(normalizedPath);\n\t}\n\n\t/**\n\t * Go back in browser history\n\t */\n\tback(): void {\n\t\tif (isBrowser()) {\n\t\t\twindow.history.back();\n\t\t}\n\t}\n\n\t/**\n\t * Get current state (returns a copy to prevent mutation)\n\t */\n\tgetState(): RouterState {\n\t\treturn {\n\t\t\t...this.state,\n\t\t};\n\t}\n\n\t/**\n\t * Validate path input\n\t */\n\tprivate validatePath(path: unknown): path is string {\n\t\tif (!path || typeof path !== \"string\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Update browser history\n\t */\n\tprivate updateBrowserHistory(path: string, method: \"push\" | \"replace\"): void {\n\t\tif (!isBrowser()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (method === \"push\") {\n\t\t\twindow.history.pushState({}, \"\", path);\n\t\t} else {\n\t\t\twindow.history.replaceState({}, \"\", path);\n\t\t}\n\t}\n\n\t/**\n\t * Handle path change\n\t * @param path Path to match against routes\n\t */\n\tprivate handlePathChange(path: string): void {\n\t\tconst normalizedPath = normalizePath(path);\n\t\tconst match = this.routeManager.match(normalizedPath);\n\n\t\tif (match) {\n\t\t\tthis.updateStateWithMatch(normalizedPath, match);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.handleNoRouteMatch(normalizedPath);\n\t}\n\n\t/**\n\t * Update state when route matches\n\t */\n\tprivate updateStateWithMatch(\n\t\tpath: string,\n\t\tmatch: {\n\t\t\tsceneName: string;\n\t\t\tparams: Record<string, string>;\n\t\t},\n\t): void {\n\t\tthis.state = {\n\t\t\tpath,\n\t\t\tparams: match.params,\n\t\t\tsceneName: match.sceneName,\n\t\t};\n\t\tthis.sceneManager.setActiveScene(match.sceneName, match.params);\n\t}\n\n\t/**\n\t * Handle case when no route matches\n\t */\n\tprivate handleNoRouteMatch(path: string): void {\n\t\tif (!this.sceneManager.hasActiveScene()) {\n\t\t\tthis.activateFirstAvailableScene(path);\n\t\t}\n\t}\n\n\t/**\n\t * Activate first available scene as fallback\n\t */\n\tprivate activateFirstAvailableScene(path: string): void {\n\t\tconst availableScenes = this.sceneManager.registry.getNames();\n\n\t\tif (availableScenes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst firstScene = availableScenes[0];\n\t\tthis.state = {\n\t\t\tpath,\n\t\t\tparams: {},\n\t\t\tsceneName: firstScene,\n\t\t};\n\t\tthis.sceneManager.setActiveScene(firstScene, {});\n\t}\n\n\t/**\n\t * Initialize router with current window path\n\t * Should be called after routes are registered but before game loop starts\n\t */\n\tinit(): void {\n\t\tconst initialPath = isBrowser() ? window.location.pathname : DEFAULT_PATH;\n\n\t\tthis.handlePathChange(initialPath);\n\t\tthis.ensureActiveScene();\n\t}\n\n\t/**\n\t * Ensure at least one scene is active after initialization\n\t */\n\tprivate ensureActiveScene(): void {\n\t\tif (this.sceneManager.hasActiveScene()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst availableScenes = this.sceneManager.registry.getNames();\n\n\t\tif (availableScenes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst firstScene = availableScenes[0];\n\t\tthis.state = {\n\t\t\tpath: this.state.path,\n\t\t\tparams: {},\n\t\t\tsceneName: firstScene,\n\t\t};\n\t\tthis.sceneManager.setActiveScene(firstScene, {});\n\t}\n\n\t/**\n\t * Get public API interface for VM\n\t * This is what gets exposed to lootiscript as `router`\n\t * Note: VM may not support getters properly, so we use both functions and properties\n\t */\n\tgetInterface(): any {\n\t\tconst routerInterface: any = {\n\t\t\tpush: (path: string) => this.push(path),\n\t\t\treplace: (path: string) => this.replace(path),\n\t\t\tback: () => this.back(),\n\t\t\t// Provide function accessors for VM compatibility (getters may not work in VM)\n\t\t\tgetPath: () => this.state.path,\n\t\t\tgetParams: () => this.state.params,\n\t\t\tgetSceneName: () => this.state.sceneName,\n\t\t};\n\n\t\t// Define dynamic properties that always return current state\n\t\t// Using Object.defineProperty for better VM compatibility than class getters\n\t\tObject.defineProperty(routerInterface, \"path\", {\n\t\t\tget: () => this.state.path,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t\tObject.defineProperty(routerInterface, \"params\", {\n\t\t\tget: () => this.state.params,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t\tObject.defineProperty(routerInterface, \"sceneName\", {\n\t\t\tget: () => this.state.sceneName,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\n\t\treturn routerInterface;\n\t}\n}\n","import type { SceneDefinition } from \"./types\";\n\nexport class SceneRegistry {\n\tprivate scenes: Map<string, SceneDefinition> = new Map();\n\n\t/**\n\t * Register a new scene\n\t */\n\tregister(name: string, definition: SceneDefinition): void {\n\t\tthis.scenes.set(name, definition);\n\t}\n\n\t/**\n\t * Get a scene definition\n\t */\n\tget(name: string): SceneDefinition | undefined {\n\t\treturn this.scenes.get(name);\n\t}\n\n\t/**\n\t * Check if scene exists\n\t */\n\thas(name: string): boolean {\n\t\treturn this.scenes.has(name);\n\t}\n\n\t/**\n\t * Get all registered scene names\n\t */\n\tgetNames(): string[] {\n\t\treturn Array.from(this.scenes.keys());\n\t}\n\n\t/**\n\t * Clear all scenes\n\t */\n\tclear(): void {\n\t\tthis.scenes.clear();\n\t}\n}\n","import { RouteManager } from \"./route-manager\";\nimport { Router } from \"./router\";\nimport { SceneRegistry } from \"./scene-registry\";\nimport type { SceneDefinition } from \"./types\";\nimport { isValidObject, isValidString, safeExecute } from \"./utils\";\n\nexport class SceneManager {\n\tpublic readonly registry: SceneRegistry;\n\tpublic readonly routeManager: RouteManager;\n\tpublic readonly router: Router;\n\n\tprivate activeSceneName: string | null = null;\n\tprivate activeScene: SceneDefinition | null = null;\n\n\tconstructor() {\n\t\tthis.registry = new SceneRegistry();\n\t\tthis.routeManager = new RouteManager();\n\t\t// Router needs reference to this manager, so we create it last\n\t\tthis.router = new Router(this.routeManager, this);\n\t}\n\n\t/**\n\t * Register a scene\n\t * @param name Unique name for the scene\n\t * @param definition Scene definition object with lifecycle methods\n\t */\n\tregisterScene(name: string, definition: SceneDefinition): void {\n\t\tif (!this.validateSceneRegistration(name, definition)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.registry.register(name, definition);\n\t}\n\n\t/**\n\t * Validate scene registration inputs\n\t */\n\tprivate validateSceneRegistration(name: unknown, definition: unknown): definition is SceneDefinition {\n\t\tif (!isValidString(name)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!isValidObject(definition)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Register a route\n\t */\n\tregisterRoute(path: string, sceneName: string): void {\n\t\tthis.routeManager.register(path, sceneName);\n\t}\n\n\t/**\n\t * Set active scene\n\t * @param name Name of the scene to activate\n\t * @param params Route parameters to pass to onEnter\n\t */\n\tsetActiveScene(name: string, params: Record<string, string> = {}): void {\n\t\tconst newScene = this.registry.get(name);\n\n\t\tif (!newScene) {\n\t\t\tthis.handleSceneNotFound(name);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isSameScene(name, newScene)) {\n\t\t\tthis.handleSameSceneActivation(newScene, name, params);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.transitionToScene(name, newScene, params);\n\t}\n\n\t/**\n\t * Handle scene not found error\n\t */\n\tprivate handleSceneNotFound(_name: string): void {\n\t\t// Scene not found - silently fail (validation should prevent this)\n\t}\n\n\t/**\n\t * Check if scene is already active\n\t */\n\tprivate isSameScene(name: string, scene: SceneDefinition): boolean {\n\t\treturn this.activeSceneName === name && this.activeScene === scene;\n\t}\n\n\t/**\n\t * Handle activation of already active scene\n\t */\n\tprivate handleSameSceneActivation(scene: SceneDefinition, _name: string, params: Record<string, string>): void {\n\t\tif (scene.onEnter) {\n\t\t\tsafeExecute(\n\t\t\t\t() => scene.onEnter?.(params),\n\t\t\t\t() => {\n\t\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Transition from current scene to new scene\n\t */\n\tprivate transitionToScene(name: string, newScene: SceneDefinition, params: Record<string, string>): void {\n\t\tthis.leaveCurrentScene();\n\t\tthis.activateNewScene(name, newScene, params);\n\t}\n\n\t/**\n\t * Leave current scene\n\t */\n\tprivate leaveCurrentScene(): void {\n\t\tif (!this.activeScene?.onLeave) {\n\t\t\treturn;\n\t\t}\n\n\t\tsafeExecute(\n\t\t\t() => this.activeScene?.onLeave?.(),\n\t\t\t() => {\n\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Activate new scene\n\t */\n\tprivate activateNewScene(name: string, scene: SceneDefinition, params: Record<string, string>): void {\n\t\tthis.activeSceneName = name;\n\t\tthis.activeScene = scene;\n\n\t\tthis.initializeSceneIfNeeded(name, scene);\n\t\tthis.enterScene(name, scene, params);\n\t}\n\n\t/**\n\t * Initialize scene if not already initialized\n\t */\n\tprivate initializeSceneIfNeeded(_name: string, scene: SceneDefinition): void {\n\t\tif (!scene.init || scene._initialized) {\n\t\t\treturn;\n\t\t}\n\n\t\tsafeExecute(\n\t\t\t() => {\n\t\t\t\tscene.init?.();\n\t\t\t\tscene._initialized = true;\n\t\t\t},\n\t\t\t() => {\n\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Enter scene (call onEnter lifecycle method)\n\t */\n\tprivate enterScene(_name: string, scene: SceneDefinition, params: Record<string, string>): void {\n\t\tif (!scene.onEnter) {\n\t\t\treturn;\n\t\t}\n\n\t\tsafeExecute(\n\t\t\t() => scene.onEnter?.(params),\n\t\t\t() => {\n\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Update active scene (called every frame)\n\t */\n\tupdate(): void {\n\t\tif (!this.activeScene?.update) {\n\t\t\treturn;\n\t\t}\n\n\t\tsafeExecute(\n\t\t\t() => this.activeScene?.update?.(),\n\t\t\t() => {\n\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Draw active scene (called every frame)\n\t */\n\tdraw(): void {\n\t\tif (!this.activeScene) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.activeScene.draw) {\n\t\t\treturn;\n\t\t}\n\n\t\tsafeExecute(\n\t\t\t() => this.activeScene?.draw?.(),\n\t\t\t() => {\n\t\t\t\t// Error handled silently - scene lifecycle errors should be handled by caller\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Check if there is an active scene\n\t */\n\thasActiveScene(): boolean {\n\t\treturn this.activeScene !== null;\n\t}\n\n\t/**\n\t * Get current active scene name\n\t * @returns Name of currently active scene, or null if none\n\t */\n\tgetCurrentSceneName(): string | null {\n\t\treturn this.activeSceneName;\n\t}\n\n\t/**\n\t * Get current active scene definition\n\t * @returns Currently active scene definition, or null if none\n\t */\n\tgetCurrentScene(): SceneDefinition | null {\n\t\treturn this.activeScene;\n\t}\n\n\t/**\n\t * Get public API interface for VM\n\t */\n\tgetInterface(): any {\n\t\treturn {\n\t\t\tregister: (name: string, def: any) => this.registerScene(name, def),\n\t\t\troute: (path: string, sceneName: string) => this.registerRoute(path, sceneName),\n\t\t\tgoto: (name: string, params: any) => this.setActiveScene(name, params),\n\t\t\tcurrent: () => this.activeSceneName,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["DEFAULT_PATH","PARAM_PATTERN","PARAM_REPLACEMENT","isBrowser","window","safeExecute","fn","errorHandler","context","error","undefined","isValidString","value","length","isValidObject","Array","isArray","normalizePath","path","cleanPath","split","startsWith","RouteManager","routes","register","path","sceneName","validateRouteInputs","regex","keys","parsePath","push","isValidString","match","route","tryMatchRoute","regexMatch","exec","params","extractParams","forEach","key","index","pattern","replace","PARAM_PATTERN","_","PARAM_REPLACEMENT","RegExp","clear","Router","routeManager","sceneManager","state","path","DEFAULT_PATH","params","sceneName","setupPopStateListener","isBrowser","window","addEventListener","handlePathChange","location","pathname","push","validatePath","normalizedPath","normalizePath","updateBrowserHistory","replace","back","history","getState","method","pushState","replaceState","match","updateStateWithMatch","handleNoRouteMatch","setActiveScene","hasActiveScene","activateFirstAvailableScene","availableScenes","registry","getNames","length","firstScene","init","initialPath","ensureActiveScene","getInterface","routerInterface","getPath","getParams","getSceneName","Object","defineProperty","get","enumerable","configurable","SceneRegistry","scenes","Map","register","name","definition","set","get","has","getNames","Array","from","keys","clear","SceneManager","registry","routeManager","router","activeSceneName","activeScene","SceneRegistry","RouteManager","Router","registerScene","name","definition","validateSceneRegistration","register","isValidString","isValidObject","registerRoute","path","sceneName","setActiveScene","params","newScene","get","handleSceneNotFound","isSameScene","handleSameSceneActivation","transitionToScene","_name","scene","onEnter","safeExecute","leaveCurrentScene","activateNewScene","onLeave","initializeSceneIfNeeded","enterScene","init","_initialized","update","draw","hasActiveScene","getCurrentSceneName","getCurrentScene","getInterface","def","route","goto","current"]}