@adatechnology/game-test-room 0.11.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -7
- package/dist/index.d.ts +304 -29
- package/dist/index.global.js +5064 -2023
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1678 -1656
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/room.ts","../src/items.ts","../src/build-from-spec.ts","../src/locale.ts","../src/arena.ts","../src/bench.ts","../src/explosives.ts","../src/segment-box.ts","../src/host-events.ts","../src/log.ts","../src/metrics.ts","../src/narrate.ts","../src/player.ts","../src/scenarios.ts","../src/bench-panel.ts","../src/ui.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport { createDestruction, JOINT_DEFAULTS, resolveStrings as resolveDestructionStrings } from '@adatechnology/game-destruction'\nimport type { BlastOptions, DestructibleImpl, DestructibleSpec, DestructionEvent, JointState, Quat, RayHit, ToolKind, Vec3 } from '@adatechnology/game-destruction'\nimport { createAudioEngine, createAudioSink } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { createDestructionRenderer, createDestructionSound, specFromObject3D } from '@adatechnology/game-destruction-three'\nimport type { Piece } from '@adatechnology/game-destruction-three'\nimport { createArsenal, DEFAULT_LOADOUT } from '@adatechnology/game-weapons'\nimport type { MountKind, Shot, TriggerResult, Use, WeaponState } from '@adatechnology/game-weapons'\nimport { createFilmLcg, createFluids, createItemUse, ITEM_USES, resolveStrings as resolveFluidStrings } from '@adatechnology/game-fluids'\nimport type { FluidEvent, ItemUsePlayer, StainState } from '@adatechnology/game-fluids'\nimport { createFilmBridge, createFilmManager, createFluidRenderer } from '@adatechnology/game-fluids-three'\nimport { createGroundField, createVfx } from '@adatechnology/game-vfx'\nimport { createGroundPatch, createVfxRenderer } from '@adatechnology/game-vfx-three'\nimport type { FluidRenderer } from '@adatechnology/game-fluids-three'\nimport { checkAnimation, checkBench, checkDestructible, checkSpec, createEnvironmentBus } from '@adatechnology/game-contracts'\nimport type { AnimationClipSpec, HostEvent, ModuleArea, ModuleBench, ModuleHost, TestableModule, ToolCommand, ToolCommandResult } from '@adatechnology/game-contracts'\nimport { createArena } from './arena'\nimport type { Arena } from './arena'\nimport { createBenchStore } from './bench'\nimport type { BenchStore } from './bench'\nimport type { BenchView, MetricRow } from './bench-panel'\nimport { buildFromSpec } from './build-from-spec'\nimport { createExplosives } from './explosives'\nimport type { BlastSummary } from './explosives'\nimport { toHostEvent } from './host-events'\nimport { DEMO_MATERIALS, demoItems } from './items'\nimport { createLog } from './log'\nimport { createRoomMetrics, ROOM_METRICS } from './metrics'\nimport { createNarrator } from './narrate'\nimport { createPlayer, PLAYER_RADIUS } from './player'\nimport { makeScenarios } from './scenarios'\nimport { resolveStrings } from './locale'\nimport { createUi } from './ui'\nimport type { HudState, InspectInfo, RoomUi } from './ui'\nimport type {\n AnimationInfo,\n ModuleReport,\n RoomMetricId,\n ScenarioContext,\n ScenarioReport,\n SpawnedObject,\n TestRoom,\n TestRoomItem,\n TestRoomOptions,\n TestRoomScenario,\n} from './types'\n\ntype Vars = Record<string, string | number>\n\ninterface Entry {\n so: SpawnedObject\n item?: TestRoomItem\n name: string\n arena: boolean\n containerId?: string\n fluidPart?: string\n fluidOffset: Vec3\n uses: string[]\n piece: Piece | null\n last: Vec3\n velocity: Vec3\n}\n\ninterface FireZone {\n point: Vec3\n radius: number\n temperature: number\n remaining: number\n acc: number\n}\n\ninterface BurningStain {\n center: Vec3\n remaining: number\n acc: number\n}\n\nconst FIXED_DT = 1 / 60\nconst METRICS_INTERVAL_S = 0.25\n\nconst v3 = (v: THREE_NS.Vector3): Vec3 => [v.x, v.y, v.z]\nconst dist3 = (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])\n\n/**\n * Create the test room. See `TestRoomOptions`. The room owns a renderer, scene and camera unless you pass them; with your own renderer you call\n * `room.update(dt)` every frame and render yourself.\n */\nexport function createTestRoom(options: TestRoomOptions): TestRoom {\n const THREE = options.THREE\n const locale = options.locale ?? 'en'\n const S = resolveStrings(locale)\n const dStrings = resolveDestructionStrings(locale)\n const fStrings = resolveFluidStrings(locale)\n const t = (key: string, vars?: Vars): string => {\n let s = S.text[key] ?? key\n if (vars) for (const k of Object.keys(vars)) s = s.split(`{${k}}`).join(String(vars[k]))\n return s\n }\n const num = (n: number, digits = 1): string => {\n const s = (Math.round(n * 10 ** digits) / 10 ** digits).toFixed(digits)\n return locale.toLowerCase().startsWith('pt') ? s.replace('.', ',') : s\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Renderer, scene, camera\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const ownRenderer = !options.renderer\n const gl: THREE_NS.WebGLRenderer = options.renderer ?? new THREE.WebGLRenderer({ antialias: true })\n const container = options.container\n const width = (): number => container.clientWidth || 960\n const height = (): number => container.clientHeight || 600\n if (ownRenderer) {\n const r = gl as THREE_NS.WebGLRenderer\n r.setPixelRatio(Math.min(typeof devicePixelRatio === 'number' ? devicePixelRatio : 1, 2))\n r.shadowMap.enabled = true\n r.shadowMap.type = THREE.PCFSoftShadowMap\n r.toneMapping = THREE.ACESFilmicToneMapping\n r.toneMappingExposure = 1\n r.outputColorSpace = THREE.SRGBColorSpace\n container.appendChild(r.domElement)\n }\n gl.setSize(width(), height())\n const dom = gl.domElement\n if (dom && !dom.hasAttribute?.('tabindex')) dom.setAttribute?.('tabindex', '0')\n const scene = options.scene ?? new THREE.Scene()\n const camera = options.camera ?? new THREE.PerspectiveCamera(72, width() / height(), 0.05, 140)\n if (!options.camera) scene.add(camera)\n const resize = (): void => {\n const w = width()\n const h = height()\n gl.setSize(w, h)\n camera.aspect = w / h\n camera.updateProjectionMatrix()\n }\n const onResize = (): void => resize()\n window.addEventListener('resize', onResize)\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Worlds\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const arenaSize = options.arenaSize ?? 14\n const arena: Arena = createArena(THREE, arenaSize, scene)\n scene.add(arena.group)\n\n const ownWorld = !options.world\n const world = options.world ?? createDestruction({ seed: 1, ...options.worldOptions, materials: [...DEMO_MATERIALS, ...(options.worldOptions?.materials ?? [])] })\n const pristineWorld = ownWorld ? world.serialize() : null\n const tableOk = (): boolean => {\n const p = world.part(arena.table.id, arena.table.topPart)\n return !!p && p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes'\n }\n // tops of spawned objects that hold others (a module's counter, a shelf board): loose things rest on them while the object is in the world\n const restingTops: Array<{ objectId: string; minX: number; maxX: number; minZ: number; maxZ: number; top: number }> = []\n const restingTopAt = (x: number, z: number): number => {\n let top = 0\n for (const c of restingTops) if (x > c.minX && x < c.maxX && z > c.minZ && z < c.maxZ && world.has(c.objectId)) top = Math.max(top, c.top)\n return top\n }\n const groundAt = (x: number, z: number): number =>\n Math.max(x > arena.table.minX && x < arena.table.maxX && z > arena.table.minZ && z < arena.table.maxZ && tableOk() ? arena.table.top : 0, restingTopAt(x, z))\n\n const ownFluids = !options.fluids\n const fluids = options.fluids ?? createFluids({ seed: 1, locale, liquids: options.liquids, groundAt })\n const pristineFluids = ownFluids ? fluids.serialize() : null\n for (const s of [...arena.surfaces, ...(options.surfaces ?? [])]) fluids.addSurface(s)\n const itemUseDefs = [...ITEM_USES, ...(options.itemUses ?? [])]\n\n const quality = options.quality ?? 'medium'\n const pointScale = height() / (2 * Math.tan((camera.fov * Math.PI) / 360))\n const rendererPieces = new Map<string, Piece>()\n const entries = new Map<string, Entry>()\n const splitOf = new Map<string, Entry>()\n let simTime = 0\n const log = createLog({ exportCancelled: () => t('log.export_cancelled') })\n log.setClock(() => simTime)\n\n // sound: one engine for the room (no AudioContext until the first sound), and the destruction renderer's sound keys play on it\n const ownAudio = options.audio === undefined\n const audio: AudioEngine | null = options.audio === false ? null : (options.audio ?? createAudioEngine())\n const destructionSound = audio ? createDestructionSound(audio) : null\n const playSound = (key: string, point: Vec3, volume: number): void => {\n destructionSound?.onSound(key, point, volume)\n options.onSound?.(key, point, volume)\n }\n\n // one effects world for the whole room: the destruction and fluid renderers and every module draw into it, and the room steps it once per frame\n const craterField = options.craters ? createGroundField() : undefined\n const craterPatch = craterField ? createGroundPatch(THREE, { field: craterField, material: new THREE.MeshStandardMaterial({ color: 0x8e8e8a, roughness: 0.95 }) }) : undefined\n if (craterPatch) {\n const floor = arena.group.getObjectByName('floor')\n if (floor) floor.visible = false\n scene.add(craterPatch.mesh)\n }\n const vfx = createVfxRenderer(THREE, {\n scene,\n camera,\n overlay: container,\n quality,\n pointScale,\n vfx: createVfx({\n profile: quality,\n groundAt: (x, z) => groundAt(x, z) + (craterField?.heightAt(x, z) ?? 0),\n ...(craterField ? { ground: craterField } : {}),\n }),\n })\n const renderer = createDestructionRenderer(THREE, {\n scene,\n world,\n vfx: vfx.world,\n quality,\n groundAt,\n pointScale,\n onSound: playSound,\n onPiece: (piece) => {\n rendererPieces.set(piece.objectId, piece)\n loose.push(piece)\n // find the entry it came from: the one whose spec holds all its parts and that is nearest\n const st = world.state(piece.objectId)\n if (!st) return\n let best: Entry | null = null\n let bestD = Infinity\n for (const e of entries.values()) {\n const spec = specs.get(e.so.objectId)\n if (!spec) continue\n const ids = new Set(spec.parts.map((p) => p.id))\n if (!st.parts.every((p) => ids.has(p.id))) continue\n const d = e.so.root.position.distanceTo(piece.root.position)\n if (d < bestD) {\n bestD = d\n best = e\n }\n }\n if (best) splitOf.set(piece.objectId, best)\n },\n })\n const fluidView: FluidRenderer = createFluidRenderer(THREE, { scene, fluids, quality, pointScale, vfx: vfx.world })\n // the running film of the liquids that have one (blood, fuel, oil): grids near the player, fed by the leaks of the fluid world\n const filmRandom = createFilmLcg(1)\n const film = createFilmManager(THREE, {\n scene,\n camera,\n random: filmRandom,\n fluids,\n groundAt,\n ...(typeof (gl as Partial<THREE_NS.WebGLRenderer>).copyTextureToTexture === 'function' ? { gpu: gl as THREE_NS.WebGLRenderer } : {}),\n })\n const filmBridge = createFilmBridge({ fluids, manager: film, random: filmRandom })\n const specs = new Map<string, DestructibleSpec>()\n const loose: Piece[] = []\n\n const arsenal = options.arsenal ?? createArsenal({ locale, weapons: options.weapons, seed: 1 })\n const loadout = (options.loadout ?? DEFAULT_LOADOUT).filter((id) => arsenal.weapons.has(id))\n const tools = new Map<string, WeaponState>()\n let toolIndex = Math.max(0, loadout.indexOf('hand'))\n let toolId = loadout[toolIndex] ?? 'hand'\n const toolSettings: { condition?: string; ammoQuality?: string } = {}\n let fuseLength: number | undefined\n const SETTING_IDS = { condition: 'condition', ammoQuality: 'ammo_quality', fuseLength: 'fuse_length' } as const\n const toolState = (id: string): WeaponState => {\n let s = tools.get(id)\n if (!s) {\n s = arsenal.create(id, { seed: 7, reserve: 999, ...toolSettings })\n s.setFuseLength(fuseLength)\n s.refill()\n tools.set(id, s)\n }\n return s\n }\n let tool = toolState(toolId)\n\n const catalogMap = new Map<string, TestRoomItem>()\n for (const i of demoItems(locale)) catalogMap.set(i.id, i)\n for (const i of options.catalog) catalogMap.set(i.id, i)\n const catalog = [...options.catalog]\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Names and narration\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const entryOf = (objectId: string): Entry | undefined => entries.get(objectId) ?? splitOf.get(objectId)\n const nameOf = (objectId: string): string => {\n const e = entries.get(objectId)\n if (e) return e.name\n const s = splitOf.get(objectId)\n return s ? `${s.name} (${t('piece')})` : objectId\n }\n const narrator = createNarrator({\n world,\n fluids,\n log,\n now: () => simTime,\n t,\n num,\n nameOf,\n itemIdOf: (id) => entryOf(id)?.so.itemId,\n materialName: (id) => S.text[`material.${id}`] ?? dStrings.materialNames[id] ?? id,\n liquidName: (id) => fStrings.liquids[id] ?? id,\n jointKind: (k) => dStrings.jointKinds[k as keyof typeof dStrings.jointKinds] ?? k,\n toolName: (k) => dStrings.toolKinds[k as keyof typeof dStrings.toolKinds] ?? k,\n locatePart: (objectId, partId) => {\n const own = world.part(objectId, partId)\n if (own) return { objectId, part: own }\n for (const [id, owner] of splitOf) {\n if (owner.so.objectId !== objectId) continue\n const p = world.part(id, partId)\n if (p) return { objectId: id, part: p }\n }\n return null\n },\n containerName: (cid) => {\n for (const e of entries.values()) if (e.containerId === cid) return { name: e.name, objectId: e.so.objectId, itemId: e.so.itemId }\n return undefined\n },\n })\n\n let pending: DestructionEvent[] = []\n const eventListeners = new Set<(d: unknown) => void>()\n const listeners: Record<string, Set<(d: unknown) => void>> = { spawn: new Set(), tool: new Set(), grab: new Set(), throw: new Set(), event: eventListeners }\n const fire = (type: string, data: unknown): void => {\n for (const fn of listeners[type] ?? []) fn(data)\n }\n world.on('*', (ev) => {\n pending.push(ev)\n })\n fluids.on('*', (ev: FluidEvent) => {\n narrator.fluid(ev)\n fire('event', ev)\n })\n\n const action = (type: string, text: string, extra: Partial<{ objectId: string; itemId: string; part: string; data: Record<string, unknown>; material: string }> = {}): void => {\n log.add({ channel: 'action', type, text, ...extra })\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Flush: events of the frame -> log, fluids glue, fire glue\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const tmpV = new THREE.Vector3()\n const tmpV2 = new THREE.Vector3()\n const tmpQ = new THREE.Quaternion()\n const tmpM = new THREE.Matrix4()\n\n const hostOf = (e: Entry): { objectId: string; root: THREE_NS.Object3D } => {\n if (e.fluidPart && !e.arena && !world.part(e.so.objectId, e.fluidPart)) {\n for (const [id, owner] of splitOf) {\n if (owner === e && world.part(id, e.fluidPart)) {\n const p = rendererPieces.get(id)\n if (p) return { objectId: id, root: p.root }\n }\n }\n }\n return { objectId: e.so.objectId, root: e.so.root }\n }\n\n const puncture = (ev: Extract<DestructionEvent, { type: 'leak' }>): void => {\n const e = entryOf(ev.object)\n if (!e?.containerId || e.fluidPart !== ev.part) return\n const host = hostOf(e)\n host.root.updateMatrixWorld(true)\n tmpM.copy(host.root.matrixWorld).invert()\n const local = tmpV.set(ev.point[0], ev.point[1], ev.point[2]).applyMatrix4(tmpM)\n local.x -= e.fluidOffset[0]\n local.y -= e.fluidOffset[1]\n local.z -= e.fluidOffset[2]\n host.root.getWorldQuaternion(tmpQ).invert()\n const n = tmpV2.set(ev.direction[0], ev.direction[1], ev.direction[2]).applyQuaternion(tmpQ)\n const part = world.part(host.objectId, ev.part)\n const hole = part?.holes[part.holes.length - 1]\n fluids.puncture(e.containerId, [local.x, local.y, local.z], [n.x, n.y, n.z], hole?.diameter ?? 0.009)\n }\n\n const flush = (): void => {\n if (pending.length === 0) return\n const batch = pending\n pending = []\n narrator.events(batch)\n for (const ev of batch) {\n if (ev.type === 'leak') puncture(ev)\n else if (ev.type === 'ignite') igniteNear(ev.point, 0.9)\n else if (ev.type === 'explode') emitHost({ type: 'explosion', source: ev.object, point: ev.point, energy: ev.energy, radius: ev.radius, cause: 'part', ...(ev.effect !== undefined ? { explosive: ev.effect } : {}) })\n fire('event', ev)\n options.onEvent?.(ev)\n }\n }\n log.setBeforeRead(flush)\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Player\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let useHeld = false\n let useFirst = false\n /** What modules ask the walking player to stay out of (`ModuleHost.addBlocker`). */\n const blockers = new Set<(x: number, z: number, radius: number) => boolean>()\n const player = createPlayer(THREE, {\n camera,\n dom,\n colliders: arena.colliders,\n blockers,\n limit: arenaSize,\n start: arena.playerStart,\n hooks: {\n primaryDown: () => {\n useHeld = true\n useFirst = true\n },\n primaryUp: () => {\n useHeld = false\n releaseTrigger()\n },\n secondary: () => {\n if (heldEntry) throwHeld()\n else grab()\n },\n key: (code, down, e) => onKey(code, down, e),\n wheel: (dir) => cycleTool(dir),\n },\n })\n player.look(arena.playerStart, [0, 1.5, arena.wallZ])\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Spawning\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let counter = 0\n let slot = 0\n const maxCarry = options.maxCarryKg ?? 60\n\n const massOfObject = (id: string): number => {\n const st = world.state(id)\n let m = 0\n for (const p of st?.parts ?? []) if (p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes') m += p.mass\n return m\n }\n\n const registerEntry = (\n objectId: string,\n itemId: string,\n root: THREE_NS.Object3D,\n spec: DestructibleSpec,\n name: string,\n parts: Record<string, THREE_NS.Object3D | THREE_NS.Object3D[]> | undefined,\n item: TestRoomItem | undefined,\n arenaObject: boolean,\n movable: boolean,\n ): Entry => {\n specs.set(objectId, spec)\n renderer.bind(objectId, root, parts ? { parts } : undefined)\n const so: SpawnedObject = { objectId, itemId, root, movable }\n const e: Entry = { so, item, name, arena: arenaObject, fluidOffset: [0, 0, 0], uses: [], piece: null, last: [root.position.x, root.position.y, root.position.z], velocity: [0, 0, 0] }\n entries.set(objectId, e)\n if (movable) {\n e.piece = renderer.makePiece(objectId, { mass: Math.max(0.2, massOfObject(objectId)) })\n rendererPieces.set(objectId, e.piece)\n }\n const f = item?.fluid\n if (f) {\n e.fluidPart = f.part\n e.fluidOffset = f.offset ?? [0, 0, 0]\n e.uses = f.uses ?? ['drink', 'sip', 'pour']\n root.updateMatrixWorld(true)\n const q = root.getWorldQuaternion(tmpQ)\n const p = tmpV.set(e.fluidOffset[0], e.fluidOffset[1], e.fluidOffset[2]).applyMatrix4(root.matrixWorld)\n e.containerId = fluids.addContainer(f.container, { id: `${objectId}_fluid`, position: [p.x, p.y, p.z], rotation: [q.x, q.y, q.z, q.w] })\n fluidView.bindContainer(e.containerId, root, { innerOffset: e.fluidOffset })\n }\n return e\n }\n\n const resolveSpec = (item: TestRoomItem, root: THREE_NS.Object3D): { spec: DestructibleSpec; parts?: Record<string, THREE_NS.Object3D[]> } => {\n if (typeof item.spec === 'function') return { spec: structuredCloneSpec(item.spec(root)) }\n if (item.spec) return { spec: structuredCloneSpec(item.spec) }\n const r = specFromObject3D(THREE, root, { name: item.id, ...item.specOptions })\n return { spec: r.spec, parts: r.parts }\n }\n\n const addArena = (): void => {\n for (const o of arena.objects) {\n const root = buildFromSpec(THREE, o.spec, { colors: o.colors })\n root.position.set(o.position[0], o.position[1], o.position[2])\n scene.add(root)\n root.updateMatrixWorld(true)\n world.add(structuredCloneSpec(o.spec), { id: o.id, position: o.position })\n registerEntry(o.id, o.id, root, o.spec, S.text[`arena.${o.id}`] ?? o.id, undefined, undefined, true, false)\n }\n }\n addArena()\n\n const spawn = (itemId: string, position?: Vec3, rotationY?: number): SpawnedObject => {\n const item = catalogMap.get(itemId)\n if (!item) throw new Error(`game-test-room: unknown item \"${itemId}\"`)\n const root = item.build(THREE)\n let pos: Vec3\n if (position) pos = [position[0], position[1], position[2]]\n else {\n const fx = -Math.sin(player.yaw)\n const fz = -Math.cos(player.yaw)\n const rx = Math.cos(player.yaw)\n const rz = -Math.sin(player.yaw)\n const side = ((slot++ % 5) - 2) * 0.55\n const x = camera.position.x + fx * 2.4 + rx * side\n const z = camera.position.z + fz * 2.4 + rz * side\n const lim = arenaSize - 1\n pos = [Math.max(-lim, Math.min(lim, x)), groundAt(x, z), Math.max(-lim, Math.min(lim, z))]\n }\n root.position.set(pos[0], pos[1], pos[2])\n root.rotation.y = rotationY ?? player.yaw\n root.name = item.id\n scene.add(root)\n root.updateMatrixWorld(true)\n const objectId = `${item.id}_${++counter}`\n let own: DestructibleImpl | undefined\n let resolved: { spec: DestructibleSpec; parts?: Record<string, THREE_NS.Object3D[]> }\n if (item.impl) {\n own = item.impl(root, objectId)\n if (own.id !== objectId) throw new Error(`game-test-room: item \"${item.id}\": DestructibleImpl.id is \"${own.id}\", the room gave it \"${objectId}\" (use the id passed to impl)`)\n resolved = { spec: structuredCloneSpec(own.describe()) }\n } else resolved = resolveSpec(item, root)\n const { spec, parts } = resolved\n root.updateMatrixWorld(true)\n const mass = spec.parts.reduce((m, p) => m + (p.mass ?? 0), 0)\n const heavy = (mass || massGuess(spec)) > maxCarry\n const movable = own ? false : (item.movable ?? !heavy)\n if (movable) {\n // things that can fall rest on the floor or the table by the bottom of their bounding box (or hang at the height asked for): no drop on spawn\n const box = new THREE.Box3().setFromObject(root)\n const base = Math.max(pos[1], groundAt(pos[0], pos[2]))\n pos = [pos[0], pos[1] + (base - box.min.y), pos[2]]\n root.position.set(pos[0], pos[1], pos[2])\n root.updateMatrixWorld(true)\n }\n const q = root.getWorldQuaternion(tmpQ)\n if (own) world.register(own, { id: objectId, position: pos, rotation: [q.x, q.y, q.z, q.w] })\n else world.add(spec, { id: objectId, position: pos, rotation: [q.x, q.y, q.z, q.w] })\n const e = registerEntry(objectId, item.id, root, spec, item.name, parts, item, false, movable)\n action('spawn', t('act.spawn', { name: item.name, x: num(pos[0], 1), z: num(pos[2], 1) }), { objectId, itemId: item.id, data: { position: pos, movable, massKg: Math.round(massOfObject(objectId) * 10) / 10 } })\n fire('spawn', e.so)\n return e.so\n }\n const massGuess = (spec: DestructibleSpec): number => {\n let m = 0\n for (const p of spec.parts) {\n const s = p.shape\n const vol = s.kind === 'box' ? s.size[0] * s.size[1] * s.size[2] : s.kind === 'cylinder' ? Math.PI * s.radius * s.radius * s.height : (4 / 3) * Math.PI * s.radius ** 3\n m += p.mass ?? vol * (world.materials.get(p.material)?.density ?? 500) * (p.fill ?? 1)\n }\n return m\n }\n\n const removeEntry = (id: string): void => {\n const e = entries.get(id)\n if (!e) return\n if (heldEntry === e) releaseHeld()\n for (let i = playing.length - 1; i >= 0; i--) if (playing[i].entry === e) playing.splice(i, 1)\n if (e.containerId) {\n fluidView.unbindContainer(e.containerId)\n fluids.removeContainer(e.containerId)\n }\n try {\n renderer.unbind(id)\n } catch {\n // not bound\n }\n if (world.has(id)) world.remove(id)\n e.so.root.removeFromParent()\n entries.delete(id)\n rendererPieces.delete(id)\n specs.delete(id)\n }\n\n const clearLoose = (): void => {\n for (const [id, owner] of [...splitOf]) {\n void owner\n const p = rendererPieces.get(id)\n try {\n renderer.unbind(id)\n } catch {\n // gone already\n }\n if (world.has(id)) world.remove(id)\n p?.root.removeFromParent()\n rendererPieces.delete(id)\n splitOf.delete(id)\n }\n loose.length = 0\n }\n\n const clearEverything = (): void => {\n if (heldEntry || heldPiece) releaseHeld()\n useItemPlayer = null\n playing.length = 0\n explosives.clear()\n fireZones.length = 0\n burningStains.length = 0\n for (const id of [...entries.keys()]) if (!entries.get(id)?.arena) removeEntry(id)\n clearLoose()\n for (const e of entries.values()) {\n world.reset(e.so.objectId)\n renderer.restore(e.so.objectId)\n }\n renderer.clear()\n vfx.world.clear()\n fluids.clearStains([0, 0, 0], 1e4)\n fluidView.clear()\n film.clear()\n fluids.setTap(TAP_ID, false)\n }\n\n const clearListeners = new Set<() => void>()\n const clear = (): void => {\n clearEverything()\n for (const listener of [...clearListeners]) listener()\n restingTops.length = 0\n pending = []\n action('clear', t('act.clear'))\n }\n\n const resetAll = (): void => {\n for (const e of entries.values()) {\n if (heldEntry === e) continue\n world.reset(e.so.objectId)\n renderer.restore(e.so.objectId)\n if (e.containerId) {\n const c = fluids.container(e.containerId)\n const f = e.item?.fluid?.container\n if (c && f && f.liquid) fluids.fill(e.containerId, f.liquid, Math.max(0, (f.liters ?? 0) - c.liters), f.temperature)\n }\n }\n action('reset', t('act.reset'))\n }\n\n /** Reset the worlds to their seeded start: used by scenarios so that each one is deterministic. */\n const hardReset = (): void => {\n clearEverything()\n for (const id of [...entries.keys()]) removeEntry(id)\n tools.clear()\n tool = toolState(toolId)\n if (pristineWorld) {\n for (const id of world.ids()) world.remove(id)\n world.load(pristineWorld)\n }\n if (pristineFluids) {\n fluids.load(pristineFluids)\n for (const s of [...arena.surfaces, ...(options.surfaces ?? [])]) fluids.addSurface(s)\n }\n pending = []\n rng = 12345\n counter = 0\n slot = 0\n prevVy.clear()\n lastImpact.clear()\n addArena()\n timeScale = 1\n fastForward = false\n walkPlan = null\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Aiming\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const aimO: Vec3 = [0, 0, 0]\n const aimD: Vec3 = [0, 0, -1]\n const aim = (): void => {\n camera.updateMatrixWorld(true)\n camera.getWorldPosition(tmpV)\n camera.getWorldDirection(tmpV2)\n aimO[0] = tmpV.x\n aimO[1] = tmpV.y\n aimO[2] = tmpV.z\n aimD[0] = tmpV2.x\n aimD[1] = tmpV2.y\n aimD[2] = tmpV2.z\n }\n\n const FAR: Quat = [0, 0, 0, 1]\n /** Run `fn` with the held object moved away, so that rays and bullets do not hit what the player carries. */\n const withoutHeld = <T,>(fn: () => T): T => {\n const e = heldEntry\n if (!e || !world.has(e.so.objectId)) return fn()\n const p = e.so.root.position\n const q = e.so.root.quaternion\n world.setTransform(e.so.objectId, [0, -5000, 0], FAR)\n try {\n return fn()\n } finally {\n world.setTransform(e.so.objectId, [p.x, p.y, p.z], [q.x, q.y, q.z, q.w])\n }\n }\n\n const rayWorld = (o: Vec3, d: Vec3, max: number): RayHit | null => withoutHeld(() => world.raycast(o, d, max))\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Particles helpers and a tiny seeded rng for visuals\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let rng = 12345\n const rnd = (): number => {\n rng = (rng * 1664525 + 1013904223) >>> 0\n return rng / 4294967296\n }\n\n const muzzle = (): Vec3 => {\n aim()\n const e = camera.matrixWorld.elements\n // right = x axis, up = y axis of the camera\n return [\n aimO[0] + aimD[0] * 0.45 + e[0] * 0.16 - e[4] * 0.1,\n aimO[1] + aimD[1] * 0.45 + e[1] * 0.16 - e[5] * 0.1,\n aimO[2] + aimD[2] * 0.45 + e[2] * 0.16 - e[6] * 0.1,\n ]\n }\n\n // tracers\n const tracers: Array<{ line: THREE_NS.Line; life: number }> = []\n const tracerMat = new THREE.LineBasicMaterial({ color: 0xffe9a8, transparent: true, opacity: 0.9 })\n const tracer = (a: Vec3, b: Vec3): void => {\n let tr = tracers.find((x) => x.life <= 0)\n if (!tr) {\n if (tracers.length >= 12) return\n const g = new THREE.BufferGeometry()\n g.setAttribute('position', new THREE.Float32BufferAttribute(6, 3))\n const line = new THREE.Line(g, tracerMat)\n line.frustumCulled = false\n scene.add(line)\n tr = { line, life: 0 }\n tracers.push(tr)\n }\n const attr = tr.line.geometry.getAttribute('position') as THREE_NS.BufferAttribute\n attr.setXYZ(0, a[0], a[1], a[2])\n attr.setXYZ(1, b[0], b[1], b[2])\n attr.needsUpdate = true\n tr.line.visible = true\n tr.life = 0.07\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Fire glue: stains of flammable liquids, fire zones (molotov), dry water near fire\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const fireZones: FireZone[] = []\n const burningStains: BurningStain[] = []\n const stainRadius = (s: StainState): number => {\n let sum = 0\n for (const r of s.front) sum += r\n return s.front.length ? sum / s.front.length : 0.1\n }\n const stainBurning = (s: StainState): boolean => burningStains.some((b) => dist3(b.center, s.center) < 0.05)\n\n function igniteNear(point: Vec3, reach: number): void {\n let lit = false\n let water = false\n for (const s of fluids.stains()) {\n if (s.wetness < 0.05) continue\n if (Math.hypot(s.center[0] - point[0], s.center[2] - point[2]) > reach + stainRadius(s) || Math.abs(s.center[1] - point[1]) > 1.5) continue\n if (fluids.liquids.get(s.liquid)?.flammable) {\n if (stainBurning(s)) continue\n const seconds = Math.max(3, Math.min(20, 4 + s.liters * 30 + stainRadius(s) * 6))\n burningStains.push({ center: [s.center[0], s.center[1], s.center[2]], remaining: seconds, acc: 0 })\n lit = true\n log.add({\n channel: 'event',\n type: 'stain_ignite',\n text: t('ev.stain_ignite', { liquid: fStrings.liquids[s.liquid] ?? s.liquid, x: num(s.center[0], 1), z: num(s.center[2], 1), seconds: num(seconds, 0) }),\n data: { stain: s.id, liquid: s.liquid, seconds },\n })\n } else water = true\n }\n if (water && !lit) {\n fluids.clearStains(point, Math.max(0.5, reach))\n log.coalesce('dry', { channel: 'event', type: 'stain_dried_by_fire', text: t('ev.fire_dries'), data: { point } }, 2)\n }\n }\n\n const hitFireAround = (point: Vec3, radius: number, temperature: number, duration: number): void => {\n for (const id of world.ids()) world.hit(id, { type: 'fire', point, temperature, radius, duration, source: 'fire' })\n }\n\n const updateFires = (dt: number): void => {\n for (let i = fireZones.length - 1; i >= 0; i--) {\n const z = fireZones[i]\n z.remaining -= dt\n z.acc += dt\n if (z.acc >= 0.1) {\n hitFireAround(z.point, z.radius, z.temperature, z.acc)\n igniteNear(z.point, z.radius)\n z.acc = 0\n }\n const a = rnd() * Math.PI * 2\n const r = Math.sqrt(rnd()) * z.radius\n renderer.emit('fire', [z.point[0] + Math.cos(a) * r, z.point[1] + 0.05, z.point[2] + Math.sin(a) * r], [0, 1, 0], 2, 1.5)\n if (z.remaining <= 0) fireZones.splice(i, 1)\n }\n if (burningStains.length) {\n const stains = fluids.stains()\n for (let i = burningStains.length - 1; i >= 0; i--) {\n const b = burningStains[i]\n b.remaining -= dt\n b.acc += dt\n const st = stains.find((s) => dist3(s.center, b.center) < 0.05)\n const r = st ? stainRadius(st) : 0.3\n if (b.acc >= 0.1) {\n hitFireAround([b.center[0], b.center[1] + 0.1, b.center[2]], r + 0.2, 800, b.acc)\n b.acc = 0\n }\n const a = rnd() * Math.PI * 2\n const rr = Math.sqrt(rnd()) * r\n renderer.emit('fire', [b.center[0] + Math.cos(a) * rr, b.center[1] + 0.05, b.center[2] + Math.sin(a) * rr], [0, 1, 0], 3, 1.8)\n if (rnd() < 0.2) renderer.emit('smoke', [b.center[0], b.center[1] + 0.3, b.center[2]], [0, 1, 0], 1, 1)\n if (b.remaining <= 0 || !st) {\n fluids.clearStains(b.center, r + 0.1)\n log.add({ channel: 'event', type: 'stain_burned', text: t('ev.stain_burned'), data: { point: b.center } })\n burningStains.splice(i, 1)\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Tools\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let progress: { label: string; value: number; at: number } | null = null\n let statusLine = ''\n let statusAt = 0\n const say = (msg: string): void => {\n statusLine = msg\n statusAt = simTime\n ui?.toast(msg)\n }\n\n const toolName = (id = toolId): string => arsenal.name(id)\n const hitWhere = (r: RayHit): string => {\n const p = world.part(r.object, r.part)\n return `${nameOf(r.object)} › ${r.part}${p ? ` (${dStrings.materialNames[p.material] ?? p.material})` : ''}`\n }\n\n const pushPiece = (objectId: string, dir: Vec3, momentum: number, point: Vec3): void => {\n if (!rendererPieces.has(objectId)) return\n renderer.impulse(objectId, [dir[0] * momentum, dir[1] * momentum, dir[2] * momentum], point)\n }\n\n const fireShots = (shots: Shot[], recoil: [number, number]): void => {\n if (shots.length === 0) return\n const w = toolName()\n const m = muzzle()\n renderer.emit('flash', m, [aimD[0], aimD[1], aimD[2]], 1, 0)\n renderer.emit('sparks', m, [aimD[0], aimD[1], aimD[2]], 4, 6)\n let hits = 0\n let first: RayHit | null = null\n let energy = 0\n withoutHeld(() => {\n for (const s of shots) {\n energy = Math.max(energy, s.energy)\n const results = world.shoot(s.origin, s.direction, s.energy, s.caliber, 'player')\n const r0 = results.find((r) => r.part && r.point)\n let end: Vec3 = [s.origin[0] + s.direction[0] * 40, s.origin[1] + s.direction[1] * 40, s.origin[2] + s.direction[2] * 40]\n if (r0?.point && r0.part) {\n hits++\n end = r0.point\n if (!first) first = { object: r0.object, part: r0.part, point: r0.point, normal: [0, 1, 0], distance: dist3(s.origin, r0.point) }\n const speed = Math.max(80, s.speed)\n pushPiece(r0.object, s.direction, (2 * s.energy) / speed, r0.point)\n }\n if (shots.length <= 3 || rnd() < 0.34) tracer(m, end)\n }\n })\n player.kick(recoil[0], recoil[1])\n const f = first as RayHit | null\n const d = f ? num(f.distance, 1) : ''\n let text: string\n if (shots.length === 1) text = t(f ? 'act.shoot.hit' : 'act.shoot.miss', { weapon: w, energy: num(energy, 0), where: f ? hitWhere(f) : '', dist: d })\n else text = t('act.shoot.pellets', { weapon: w, n: shots.length, energy: num(energy, 0), hits, where: f ? hitWhere(f) : '', dist: d })\n action('shoot', text, {\n objectId: f?.object,\n itemId: f ? entryOf(f.object)?.so.itemId : undefined,\n part: f?.part,\n data: { weapon: toolId, shots: shots.length, hits, energyJ: Math.round(energy), caliberMm: shots[0].caliber, distanceM: f ? Math.round(f.distance * 100) / 100 : null },\n })\n }\n\n const fireRays = (u: { origin: Vec3; direction: Vec3; range: number; cone: boolean; radius: number }): Array<Vec3> => {\n const d = new THREE.Vector3(u.direction[0], u.direction[1], u.direction[2]).normalize()\n const out: Vec3[] = [[d.x, d.y, d.z]]\n if (u.cone) {\n const a = Math.min(0.2, Math.atan2(u.radius, Math.max(0.1, u.range)))\n const right = new THREE.Vector3().crossVectors(d, new THREE.Vector3(0, 1, 0))\n if (right.lengthSq() < 1e-6) right.set(1, 0, 0)\n right.normalize()\n const up = new THREE.Vector3().crossVectors(right, d).normalize()\n for (const [x, y] of [\n [1, 0],\n [-1, 0],\n [0, 1],\n [0, -1],\n ]) {\n const r = d.clone().addScaledVector(right, x * a).addScaledVector(up, y * a).normalize()\n out.push([r.x, r.y, r.z])\n }\n }\n return out\n }\n\n const heatRays = (u: Extract<Use, { kind: 'flame' | 'heat' }>, type: 'fire' | 'heat'): void => {\n const w = toolName()\n const cone = u.kind === 'flame' ? u.cone : false\n const rays = fireRays({ origin: u.origin, direction: u.direction, range: u.range, cone, radius: u.radius })\n let target: RayHit | null = null\n const m = muzzle()\n withoutHeld(() => {\n for (const d of rays) {\n const r = world.raycast(u.origin, d, u.range)\n if (!r) continue\n if (!target) target = r\n world.hit(r.object, { type, point: r.point, direction: d, temperature: u.temperature, radius: Math.min(u.radius, 0.3), duration: u.duration, source: 'player' })\n if (type === 'fire') igniteNear(r.point, 0.25)\n else renderer.emit('sparks', r.point, r.normal, 2, 4)\n }\n })\n if (type === 'fire') {\n renderer.emit('fire', m, [u.direction[0], u.direction[1], u.direction[2]], cone ? 5 : 1, Math.max(0.6, u.range * 1.1))\n if (cone) renderer.emit('smoke', m, [u.direction[0], u.direction[1] + 0.3, u.direction[2]], 1, u.range * 0.5)\n // nothing hit: the stain on the ground in front may still catch\n if (!target && u.direction[1] < -0.2) {\n const t0 = (0.05 - u.origin[1]) / u.direction[1]\n if (t0 > 0 && t0 < u.range) igniteNear([u.origin[0] + u.direction[0] * t0, 0.05, u.origin[2] + u.direction[2] * t0], 0.3)\n }\n }\n const tg = target as RayHit | null\n log.coalesce(\n `use:${toolId}`,\n {\n channel: 'action',\n type,\n text: tg ? t(type === 'fire' ? 'act.flame.hit' : 'act.heat.hit', { weapon: w, where: hitWhere(tg), temp: num(u.temperature, 0) }) : t(type === 'fire' ? 'act.flame.air' : 'act.heat.air', { weapon: w }),\n objectId: tg?.object,\n part: tg?.part,\n data: { weapon: toolId, temperatureC: u.temperature },\n },\n 1,\n )\n }\n\n const meleeUse = (u: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const w = toolName(id)\n const r = rayWorld(u.origin, u.direction, u.reach)\n if (!r) {\n action('melee', t('act.melee.miss', { weapon: w }), { data: { weapon: id } })\n return\n }\n world.hitPart(r.object, r.part, { type: u.damage, point: r.point, direction: u.direction, energy: u.energy, radius: u.radius, source: 'player' })\n pushPiece(r.object, u.direction, (2 * u.energy) / 6, r.point)\n action('melee', t('act.melee.hit', { weapon: w, energy: num(u.energy, 0), where: hitWhere(r), dist: num(r.distance, 1) }), {\n objectId: r.object,\n itemId: entryOf(r.object)?.so.itemId,\n part: r.part,\n data: { weapon: id, damage: u.damage, energyJ: u.energy, distanceM: Math.round(r.distance * 100) / 100 },\n })\n }\n\n const toolWork = (u: Extract<Use, { kind: 'tool' }>, dt: number): void => {\n const w = toolName()\n const r = rayWorld(u.origin, u.direction, u.reach)\n if (!r) {\n progress = null\n log.coalesce(`use:${toolId}`, { channel: 'action', type: 'tool', text: t('act.tool.none', { weapon: w }), data: { weapon: toolId } }, 1)\n return\n }\n const j: JointState | null = world.nearestJoint(r.object, r.point, 0.45, u.tool as ToolKind)\n if (!j) {\n progress = null\n log.coalesce(`use:${toolId}`, { channel: 'action', type: 'tool', text: t('act.tool.nojoint', { weapon: w, where: hitWhere(r) }), objectId: r.object, part: r.part }, 1)\n return\n }\n const tool_ = u.tool as ToolKind\n const p = world.disassemble(r.object, j.id, tool_, dt)\n const kind = dStrings.jointKinds[j.kind] ?? j.kind\n if (p < 0) {\n const need = JOINT_DEFAULTS[j.kind].tools.map((k) => dStrings.toolKinds[k] ?? k).join(', ') || t('tool.none')\n progress = { label: t('hud.refused', { kind }), value: 0, at: simTime }\n log.coalesce(\n `refuse:${r.object}:${j.id}:${toolId}`,\n {\n channel: 'action',\n type: 'tool_refused',\n text: t('act.tool.refused', { weapon: w, kind, obj: nameOf(r.object), need }),\n objectId: r.object,\n itemId: entryOf(r.object)?.so.itemId,\n data: { weapon: toolId, joint: j.id, kind: j.kind, needs: JOINT_DEFAULTS[j.kind].tools },\n },\n 2,\n )\n return\n }\n progress = { label: `${kind} (${j.id})`, value: p, at: simTime }\n renderer.emit('sparks', r.point, r.normal, 1, 2)\n }\n\n const extinguishUse = (u: Extract<Use, { kind: 'extinguish' }>): void => {\n const w = toolName()\n const rays = fireRays({ origin: u.origin, direction: u.direction, range: u.range, cone: true, radius: 0.6 })\n const m = muzzle()\n renderer.emit('foam', m, [u.direction[0], u.direction[1], u.direction[2]], 8, u.range * 1.2)\n const hit = new Set<string>()\n withoutHeld(() => {\n for (const d of rays) {\n const r = world.raycast(u.origin, d, u.range)\n if (!r) continue\n hit.add(r.object)\n world.extinguish(r.object, undefined, u.coolC * Math.max(u.duration, 0.05) * 6)\n fluids.clearStains(r.point, 0.5)\n for (let i = burningStains.length - 1; i >= 0; i--) if (Math.hypot(burningStains[i].center[0] - r.point[0], burningStains[i].center[2] - r.point[2]) < 1.2) burningStains.splice(i, 1)\n for (let i = fireZones.length - 1; i >= 0; i--) if (Math.hypot(fireZones[i].point[0] - r.point[0], fireZones[i].point[2] - r.point[2]) < 1.5) fireZones.splice(i, 1)\n }\n })\n log.coalesce(\n `use:${toolId}`,\n { channel: 'action', type: 'extinguish', text: hit.size ? t('act.extinguish.hit', { weapon: w, what: [...hit].map(nameOf).join(', ') }) : t('act.extinguish.air', { weapon: w }), data: { objects: [...hit] } },\n 1,\n )\n }\n\n const startFire = (weapon: string, at: Vec3, fire: { temperature: number; radius: number; seconds: number }, impact: boolean): void => {\n fluids.splash('fuel', [at[0], Math.max(at[1], groundAt(at[0], at[2])), at[2]], 0.5)\n fireZones.push({ point: [at[0], Math.max(0.02, groundAt(at[0], at[2])), at[2]], radius: fire.radius, temperature: fire.temperature, remaining: fire.seconds, acc: 0 })\n renderer.emit('fire', at, [0, 1, 0], 24, 3)\n action('molotov_fire', t('act.molotov_fire', { weapon: toolName(weapon), seconds: num(fire.seconds, 0), radius: num(fire.radius, 1) }), { data: { weapon, impact } })\n }\n\n /** The bodies that trip a wire: the player (a column from the ground to the eyes) and every object of the room that is not the arena. */\n function crossingBodies(): { id: string; box: THREE_NS.Box3 }[] {\n const bodies = [...entries.values()].filter((e) => !e.arena).map((e) => ({ id: e.so.objectId, box: new THREE.Box3().setFromObject(e.so.root) }))\n const { x, y, z } = camera.position\n const feet = groundAt(x, z)\n bodies.push({ id: 'player', box: new THREE.Box3(new THREE.Vector3(x - PLAYER_RADIUS, feet, z - PLAYER_RADIUS), new THREE.Vector3(x + PLAYER_RADIUS, y + 0.1, z + PLAYER_RADIUS)) })\n return bodies\n }\n\n // ----- the blast options of the room's explosions (the HUD toggles them), and what the last blast did\n let blastOptions: BlastOptions = { ...options.blast }\n let lastBlast: BlastSummary | undefined\n const blastOn = (key: 'shelter' | 'fragmentHits' | 'confinement'): boolean => Boolean(blastOptions[key])\n const toggleBlast = (key: 'shelter' | 'fragmentHits' | 'confinement'): void => {\n blastOptions = { ...blastOptions, [key]: blastOn(key) ? false : true }\n }\n\n // ----- projectiles (grenades, molotovs, rockets) and charges set down: the room lends the explosives its world, log and host\n const explosives = createExplosives({\n THREE,\n scene,\n camera,\n world,\n renderer,\n effects: vfx.world,\n arsenal,\n objects: () => [...entries.values()].filter((e) => !e.arena).map((e) => e.so.root),\n bodies: crossingBodies,\n toolId: () => toolId,\n toolName,\n withoutHeld,\n groundAt,\n blast: () => blastOptions,\n blasted: (summary) => {\n lastBlast = summary\n },\n translate: t,\n format: num,\n action,\n emitHost,\n startFire,\n say,\n })\n\n // ----- the trigger\n const useTool = (dt: number, held: boolean): void => {\n aim()\n const cat = tool.def.category\n if (cat === 'hand') return\n const res = tool.trigger([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], dt, held, 'player')\n flushEvents(toolId, tool, res.recoil)\n if (res.status === 'empty') {\n if (!tool.reloading && tool.reserve > 0) startReload()\n say(t(tool.reloading ? 'hud.reloading' : 'hud.empty'))\n return\n }\n if (res.status !== 'ok') {\n if (res.status === 'reloading') say(t('hud.reloading'))\n else if (res.status === 'no_fuel') say(t('hud.no_fuel'))\n else if (res.status === 'fault' && res.fault) say(t('hud.fault', { fault: t(`fault.${res.fault}`) }))\n else if (res.status === 'safe') say(t('hud.safe'))\n return\n }\n applyUses(res, dt)\n }\n\n const applyUses = (res: TriggerResult, dt: number): void => {\n if (res.shots.length) fireShots(res.shots, res.recoil)\n for (const u of res.uses) {\n switch (u.kind) {\n case 'melee':\n meleeUse(u)\n break\n case 'flame':\n heatRays(u, 'fire')\n break\n case 'heat':\n heatRays(u, 'heat')\n break\n case 'throw':\n explosives.throwUse(u)\n break\n case 'place':\n explosives.placeUse(u)\n break\n case 'backblast':\n explosives.backblastUse(u)\n break\n case 'tool':\n toolWork(u, dt)\n break\n case 'extinguish':\n extinguishUse(u)\n break\n default:\n break\n }\n }\n }\n\n /** The trigger goes up: a grenade being cooked leaves the hand now, with the fuse that is left (or has already gone off in it). */\n const releaseTrigger = (): void => {\n if (!tool.cooking) {\n tool.release()\n return\n }\n aim()\n const res = tool.release([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]])\n flushEvents(toolId, tool)\n if (res) applyUses(res, 0)\n }\n\n /** The V shortcut: a kick with the `kick` tool, whatever tool is selected (it keeps its own cooldown). */\n const kick = (): void => {\n if (!arsenal.weapons.has('kick')) return\n aim()\n const res = toolState('kick').trigger([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 0, false, 'player')\n if (res.status !== 'ok') return\n for (const u of res.uses) if (u.kind === 'melee') meleeUse(u, 'kick')\n }\n const setTool = (id: string): void => {\n if (!arsenal.weapons.has(id)) throw new Error(`game-test-room: unknown weapon \"${id}\"`)\n releaseTrigger()\n toolId = id\n const i = loadout.indexOf(id)\n if (i >= 0) toolIndex = i\n tool = toolState(id)\n progress = null\n action('tool', t('act.tool', { weapon: toolName(id) }), { data: { weapon: id } })\n fire('tool', id)\n tool.draw()\n flushEvents(id, tool)\n }\n const cycleTool = (dir: 1 | -1): void => {\n if (!loadout.length) return\n toolIndex = (toolIndex + dir + loadout.length) % loadout.length\n setTool(loadout[toolIndex])\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Grabbing, carrying, throwing\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let heldEntry: Entry | null = null\n let heldPiece: Piece | null = null\n let heldName = ''\n let heldYaw = 0\n let heldTilt = 0\n let tiltKey = 0\n const heldLocal = new THREE.Vector3()\n const heldVel: Vec3 = [0, 0, 0]\n let useItemPlayer: ItemUsePlayer | null = null\n let useItemName = ''\n\n const releaseHeld = (): void => {\n if (heldPiece) {\n heldPiece.held = false\n heldPiece.sleeping = false\n heldPiece.velocity = [heldVel[0], heldVel[1], heldVel[2]]\n }\n useItemPlayer?.cancel()\n useItemPlayer = null\n heldEntry = null\n heldPiece = null\n heldTilt = 0\n }\n\n const grab = (): boolean => {\n if (heldPiece) {\n const name = heldName\n releaseHeld()\n action('drop', t('act.drop', { name }))\n fire('grab', { held: false })\n return true\n }\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n if (!r) {\n say(t('hud.nothing_to_grab'))\n return false\n }\n const piece = rendererPieces.get(r.object)\n if (!piece) {\n say(t('hud.cannot_grab', { name: nameOf(r.object) }))\n return false\n }\n const kg = piece.mass\n if (kg > maxCarry) {\n say(t('hud.too_heavy', { name: nameOf(r.object), kg: num(kg, 0) }))\n return false\n }\n heldPiece = piece\n heldEntry = entries.get(r.object) ?? null\n heldName = nameOf(r.object)\n piece.held = true\n piece.sleeping = false\n // centre of the object's bounding box in its own space, to hold it by its middle\n const box = new THREE.Box3().setFromObject(piece.root)\n const c = box.getCenter(new THREE.Vector3())\n piece.root.updateMatrixWorld(true)\n heldLocal.copy(c).sub(piece.root.position)\n heldLocal.applyQuaternion(piece.root.quaternion.clone().invert())\n heldYaw = 0\n heldTilt = 0\n heldVel[0] = heldVel[1] = heldVel[2] = 0\n action('grab', t('act.grab', { name: heldName, kg: num(kg, 1) }), { objectId: r.object, itemId: entryOf(r.object)?.so.itemId, data: { massKg: Math.round(kg * 10) / 10 } })\n fire('grab', { held: true, objectId: r.object })\n return true\n }\n\n const throwHeld = (speed = 9): boolean => {\n if (!heldPiece) return false\n const piece = heldPiece\n const name = heldName\n const id = piece.objectId\n aim()\n releaseHeld()\n piece.velocity = [0, 0, 0]\n renderer.impulse(id, [aimD[0] * speed * piece.mass, (aimD[1] * speed + 1.2) * piece.mass, aimD[2] * speed * piece.mass])\n action('throw', t('act.throw', { name, speed: num(speed, 1) }), { objectId: id, itemId: entryOf(id)?.so.itemId, data: { speedMs: speed, massKg: piece.mass } })\n fire('throw', { objectId: id, speed })\n return true\n }\n\n const followHeld = (dt: number): void => {\n const piece = heldPiece\n if (!piece) return\n camera.updateMatrixWorld(true)\n const root = piece.root\n let pos: THREE_NS.Vector3\n const targetQ = tmpQ\n if (useItemPlayer) {\n // the hand frame follows the camera's yaw only, so looking down at the item does not tilt it\n const pose = useItemPlayer.pose()\n const handQ = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw)\n pos = tmpV.set(pose.position[0], pose.position[1], pose.position[2]).applyQuaternion(handQ).add(camera.position)\n const eq = new THREE.Quaternion().setFromEuler(new THREE.Euler(pose.rotation[0], pose.rotation[1], pose.rotation[2], 'XYZ'))\n targetQ.copy(handQ).multiply(eq)\n targetQ.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), heldYaw))\n } else {\n pos = tmpV.set(0.05, -0.28, -1.15).applyMatrix4(camera.matrixWorld)\n targetQ.setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw + heldYaw)\n targetQ.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -heldTilt))\n }\n const k = Math.min(1, (useItemPlayer ? 30 : 16) * dt)\n const px = root.position.x\n const py = root.position.y\n const pz = root.position.z\n root.quaternion.slerp(targetQ, Math.min(1, k * 0.9))\n // the middle of the carried object follows the target; the offset uses the current rotation so it does not orbit\n const off2 = tmpV2.copy(heldLocal).applyQuaternion(root.quaternion)\n root.position.set(root.position.x + (pos.x - off2.x - root.position.x) * k, root.position.y + (pos.y - off2.y - root.position.y) * k, root.position.z + (pos.z - off2.z - root.position.z) * k)\n if (dt > 0) {\n heldVel[0] = (root.position.x - px) / dt\n heldVel[1] = (root.position.y - py) / dt\n heldVel[2] = (root.position.z - pz) / dt\n }\n root.updateMatrixWorld(true)\n }\n\n const useItem = (useId: string): boolean => {\n const e = heldEntry\n if (!e?.containerId) return false\n const def = itemUseDefs.find((u) => u.id === useId)\n if (!def) return false\n const c = fluids.container(e.containerId)\n if (!c) return false\n if (def.liquids && def.liquids.length > 0 && (!c.liquid || !def.liquids.includes(c.liquid))) return false\n if ((useId === 'drink' || useId === 'sip' || useId === 'chug' || useId === 'pour' || useId === 'pour_out') && c.liters <= 1e-6) {\n say(t('hud.empty_container', { name: e.name }))\n return false\n }\n if (useItemPlayer && !useItemPlayer.done) return false\n useItemPlayer = createItemUse(fluids, e.containerId, def)\n useItemName = def.id\n action('use_item', t('act.use_item', { name: e.name, use: S.text[`use.${def.id}`] ?? def.id }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { use: def.id } })\n return true\n }\n\n const updateItemUse = (dt: number): void => {\n if (!useItemPlayer) return\n useItemPlayer.update(dt)\n if (useItemPlayer.done) {\n useItemPlayer = null\n useItemName = ''\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Tap\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const TAP_ID = 'room_tap'\n const TAP_RATE = 0.25\n fluids.addTap({ id: TAP_ID, position: arena.tapSpout, liquid: 'water', rate: TAP_RATE, temperature: 16, on: false })\n const isTapOn = (): boolean => fluids.taps().some((x) => x.id === TAP_ID && x.on)\n const toggleTap = (on = !isTapOn()): boolean => {\n fluids.setTap(TAP_ID, on)\n action('tap', t(on ? 'act.tap.on' : 'act.tap.off'))\n return on\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Thrown and falling pieces: damage to what they hit\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const lastImpact = new Map<string, number>()\n /** Landings slower than this (m/s) are not logged (the renderer only treats 3 m/s and up as a hard landing; nothing below 1.5 m/s is ever worth a line). */\n const MIN_LANDING_LOG = 3\n const updateImpacts = (): void => {\n const check = (piece: Piece): void => {\n if (piece.held || piece.sleeping) return\n const v = piece.velocity\n const speed = Math.hypot(v[0], v[1], v[2])\n if (speed < 3.5) return\n if ((lastImpact.get(piece.objectId) ?? -9) > simTime - 0.25) return\n const dir: Vec3 = [v[0] / speed, v[1] / speed, v[2] / speed]\n const c = tmpV.copy(new THREE.Vector3(0, 0, 0))\n void c\n const box = tmpBox.setFromObject(piece.root)\n const centre = box.getCenter(tmpV)\n const size = box.getSize(tmpV2)\n const reach = Math.max(size.x, size.y, size.z) * 0.5\n const origin: Vec3 = [centre.x + dir[0] * (reach + 0.02), centre.y + dir[1] * (reach + 0.02), centre.z + dir[2] * (reach + 0.02)]\n const r = withoutHeld(() => world.raycast(origin, dir, speed * FIXED_DT * 2 + 0.06))\n if (!r || r.object === piece.objectId) return\n const energy = 0.5 * piece.mass * speed * speed\n lastImpact.set(piece.objectId, simTime)\n world.hitPart(r.object, r.part, { type: 'blunt', point: r.point, direction: dir, energy, radius: 0.08, source: 'thrown' })\n if (world.has(piece.objectId)) world.hit(piece.objectId, { type: 'blunt', point: r.point, direction: [-dir[0], -dir[1], -dir[2]], energy: energy * 0.4, radius: 0.08, source: 'thrown' })\n pushPiece(r.object, dir, piece.mass * speed * 0.5, r.point)\n piece.velocity = [-v[0] * 0.25, Math.abs(v[1]) * 0.3 + 0.5, -v[2] * 0.25]\n action('impact', t('act.impact', { name: nameOf(piece.objectId), where: hitWhere(r), energy: num(energy, 0), speed: num(speed, 1) }), {\n objectId: piece.objectId,\n itemId: entryOf(piece.objectId)?.so.itemId,\n data: { energyJ: Math.round(energy), speedMs: Math.round(speed * 10) / 10, target: r.object, targetPart: r.part },\n })\n }\n const land = (piece: Piece): void => {\n const vy = piece.velocity[1]\n const prev = prevVy.get(piece.objectId) ?? 0\n prevVy.set(piece.objectId, vy)\n // the renderer applies the landing damage itself (source 'fall'); here we only describe it in the log\n if (piece.held || prev > -MIN_LANDING_LOG || vy < prev + 2 || !world.has(piece.objectId)) return\n const energy = 0.5 * piece.mass * prev * prev\n action('landing', t('act.landing', { name: nameOf(piece.objectId), speed: num(-prev, 1), energy: num(energy, energy < 100 ? 1 : 0) }), {\n objectId: piece.objectId,\n itemId: entryOf(piece.objectId)?.so.itemId,\n data: { energyJ: Math.round(energy * 10) / 10, speedMs: Math.round(-prev * 10) / 10 },\n })\n }\n for (const e of entries.values()) if (e.piece) { check(e.piece); land(e.piece) }\n for (const p of loose) { check(p); land(p) }\n }\n const prevVy = new Map<string, number>()\n const tmpBox = new THREE.Box3()\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Keys\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const onKey = (code: string, down: boolean, e: KeyboardEvent): void => {\n if (!down) {\n if (code === 'KeyZ') tiltKey = 0\n return\n }\n const digit = /^Digit(\\d)$/.exec(code)\n if (digit && !e.ctrlKey && !e.metaKey) {\n const n = (Number(digit[1]) + 9) % 10\n const page = Math.floor(toolIndex / 10)\n const idx = page * 10 + n\n if (idx < loadout.length) setTool(loadout[idx])\n return\n }\n switch (code) {\n case 'KeyE':\n grab()\n break\n case 'KeyG':\n throwHeld()\n break\n case 'KeyR':\n if (heldPiece) heldYaw += Math.PI / 8\n else {\n startReload()\n say(t('hud.reloading'))\n }\n break\n case 'KeyQ': {\n tool.cycleMode()\n flushEvents(toolId, tool)\n break\n }\n case 'KeyX':\n clearToolFault()\n break\n case 'KeyB':\n toggleSafety()\n break\n case 'KeyZ':\n tiltKey = 1\n break\n case 'KeyF':\n if (heldEntry?.uses[0]) useItem(heldEntry.uses[0])\n break\n case 'KeyC':\n if (heldEntry?.uses[1]) useItem(heldEntry.uses[1])\n break\n case 'KeyV':\n if (heldEntry?.uses[2]) useItem(heldEntry.uses[2])\n else kick()\n break\n case 'KeyT':\n toggleTap()\n break\n case 'KeyY':\n explosives.detonateCharges()\n break\n case 'KeyH': {\n const w = (heldEntry ?? entryOf(inspectTarget()?.object ?? ''))?.item?.weapon\n if (w) equip(w)\n break\n }\n case 'BracketRight':\n toolIndex = Math.min(loadout.length - 1, (Math.floor(toolIndex / 10) + 1) * 10)\n setTool(loadout[toolIndex])\n break\n case 'BracketLeft':\n toolIndex = Math.max(0, (Math.floor(toolIndex / 10) - 1) * 10)\n setTool(loadout[toolIndex])\n break\n case 'Tab':\n ui?.togglePanels()\n break\n default:\n break\n }\n }\n\n const equip = (weaponId: string): void => {\n if (!arsenal.weapons.has(weaponId)) return\n if (!loadout.includes(weaponId)) loadout.push(weaponId)\n setTool(weaponId)\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Inspector\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const inspectTarget = (): RayHit | null => {\n aim()\n return rayWorld(aimO, aimD, 14)\n }\n\n const inspectInfo = (): InspectInfo | null => {\n const r = inspectTarget()\n if (!r) return null\n const st = world.state(r.object)\n const p = world.part(r.object, r.part)\n if (!st || !p) return null\n const e = entryOf(r.object)\n const joints = st.joints\n .filter((j) => j.a === r.part || j.b === r.part)\n .map((j) => ({\n id: j.id,\n kind: dStrings.jointKinds[j.kind] ?? j.kind,\n tools: JOINT_DEFAULTS[j.kind].tools.map((k) => dStrings.toolKinds[k] ?? k),\n open: j.open,\n progress: j.progress,\n }))\n const ext = p as unknown as { load?: number; stress?: number }\n return {\n object: nameOf(r.object),\n objectId: r.object,\n part: r.part,\n material: S.text[`material.${p.material}`] ?? dStrings.materialNames[p.material] ?? p.material,\n status: dStrings.partStatus[p.status] ?? p.status,\n hp: p.hp,\n maxHp: p.maxHp,\n temperature: p.temperature,\n burning: p.burning,\n char: p.char,\n melt: p.melt,\n liters: p.liters,\n dents: p.dents.length,\n holes: p.holes.length,\n cracks: p.cracks.length,\n mass: p.mass,\n load: ext.load,\n stress: ext.stress,\n joints,\n note: e?.item?.note,\n thumbnail: e?.item?.thumbnail,\n thumbnailCredit: e?.item?.thumbnailCredit,\n distance: r.distance,\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Frame\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let timeScale = 1\n let fastForward = false\n let hudAcc = 1\n let metricsAcc = 0\n // when the room runs its own loop it feeds the counters the unclamped real delta; otherwise update(dt) is the only source\n let ownsLoop = false\n const roomMetricIds: readonly RoomMetricId[] = options.metrics === false ? [] : options.metrics ?? ROOM_METRICS\n const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds, blast: () => lastBlast })\n let qualityName: 'low' | 'medium' | 'high' = quality\n\n const syncContainers = (sdt: number): void => {\n for (const e of entries.values()) {\n if (!e.containerId) continue\n const host = hostOf(e)\n host.root.updateMatrixWorld(true)\n const q = host.root.getWorldQuaternion(tmpQ)\n const p = tmpV.set(e.fluidOffset[0], e.fluidOffset[1], e.fluidOffset[2]).applyMatrix4(host.root.matrixWorld)\n const vel: Vec3 | undefined = sdt > 0 ? [(p.x - e.last[0]) / sdt, (p.y - e.last[1]) / sdt, (p.z - e.last[2]) / sdt] : undefined\n e.last = [p.x, p.y, p.z]\n fluids.setTransform(e.containerId, [p.x, p.y, p.z], [q.x, q.y, q.z, q.w], vel)\n }\n }\n\n const syncLiters = (): void => {\n for (const e of entries.values()) {\n if (!e.containerId || !e.fluidPart) continue\n const c = fluids.container(e.containerId)\n if (!c) continue\n const host = hostOf(e)\n const part = world.part(host.objectId, e.fluidPart)\n if (part && part.liters !== undefined && Math.abs(part.liters - c.liters) > 1e-4) world.setLiters(host.objectId, e.fluidPart, c.liters)\n }\n }\n\n let paused = false\n let walkPlan: { x: number; z: number; remaining: number } | null = null\n const stepWalk = (dt: number): void => {\n if (!walkPlan) return\n const f = walkPlan.remaining <= dt ? 1 : dt / walkPlan.remaining\n player.moveBy((walkPlan.x - camera.position.x) * f, (walkPlan.z - camera.position.z) * f)\n walkPlan.remaining -= dt\n if (walkPlan.remaining <= 1e-9) walkPlan = null\n }\n\n const stepSim = (dt: number): void => {\n if (paused) return\n // `dt` is simulated seconds; real time only drives input\n simTime += dt\n stepWalk(dt)\n const reps = fastForward ? 10 : 1\n updateAnimations(dt)\n updateItemUse(dt)\n explosives.update(dt)\n syncContainers(dt)\n for (let i = 0; i < reps; i++) {\n world.update(dt)\n if (i === 0) updateFires(dt)\n fluids.update(dt)\n }\n syncLiters()\n renderer.update(dt)\n vfx.update(dt)\n craterPatch?.sync()\n updateImpacts()\n fluidView.update(dt)\n filmBridge.update(dt)\n film.update(dt)\n for (const [id, s] of tools) {\n s.update(dt)\n flushEvents(id, s)\n }\n if (audio) {\n // the listener is the camera: where it stands and which way it looks (yaw 0 faces -z)\n const look = camera.getWorldDirection(listenerDirection)\n audio.setListener({ position: [camera.position.x, camera.position.y, camera.position.z], yaw: Math.atan2(-look.x, -look.z) })\n }\n for (const update of frameListeners) update(dt)\n for (const tr of tracers) {\n if (tr.life > 0) {\n tr.life -= dt\n if (tr.life <= 0) tr.line.visible = false\n }\n }\n flush()\n }\n\n const update = (dt: number): void => {\n if (!ownsLoop) roomMetrics.frame(dt)\n player.update(dt)\n if (tiltKey || heldTilt > 0) {\n heldTilt = Math.max(0, Math.min(2.4, heldTilt + (tiltKey ? 2.2 : -3) * dt))\n }\n if (useHeld && !paused) {\n if (tool.def.category === 'hand') {\n if (useFirst) grab()\n } else useTool(dt, !useFirst)\n useFirst = false\n }\n if (!paused) followHeld(dt)\n stepSim(dt * timeScale)\n if (progress && simTime - progress.at > 0.25) progress = null\n hudAcc += dt\n if (hudAcc >= 0.1 && ui) {\n hudAcc = 0\n ui.hud(hudState())\n }\n metricsAcc += dt\n if (metricsAcc >= METRICS_INTERVAL_S && ui) {\n metricsAcc = 0\n if (ui.benchVisible) ui.metrics(metricRows())\n }\n }\n\n const hudState = (): HudState => {\n const page = Math.floor(toolIndex / 10)\n const slots = loadout.slice(page * 10, page * 10 + 10).map((id) => arsenal.name(id))\n const ammo = tool.def.action.kind === 'firearm' ? `${tool.ammo}/${tool.capacity}${tool.reserve ? ` · ${tool.reserve}` : ''}` : tool.def.action.kind === 'hand' ? '' : tool.def.action.kind === 'melee' || tool.def.action.kind === 'tool' ? '' : `${num(tool.ammo, 0)}`\n return {\n toolName: toolName(),\n toolId,\n ammo,\n slots,\n slot: toolIndex - page * 10,\n page: page + 1,\n pages: Math.max(1, Math.ceil(loadout.length / 10)),\n status: simTime - statusAt < 2 ? statusLine : '',\n progress: progress ? { label: progress.label, value: progress.value } : null,\n held: heldEntry || heldPiece ? { name: heldName, uses: (heldEntry?.uses ?? []).map((u, i) => ({ key: ['F', 'C', 'V'][i] ?? '', label: S.text[`use.${u}`] ?? u })), weapon: heldEntry?.item?.weapon ? arsenal.name(heldEntry.item.weapon) : undefined, using: useItemName } : null,\n inspect: inspectInfo(),\n animations: animationsOf(),\n locked: player.locked,\n timeScale,\n fast: fastForward,\n tap: isTapOn(),\n blast: { shelter: blastOn('shelter'), fragmentHits: blastOn('fragmentHits'), confinement: blastOn('confinement') },\n quality: qualityName,\n objects: [...entries.values()].filter((e) => !e.arena).length,\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Item animations (clips of AnimationClipSpec)\n // ---------------------------------------------------------------------------------------------------------------------------------------\n interface Playing {\n entry: Entry\n clip: AnimationClipSpec\n t: number\n fired: number\n targets: Map<string, THREE_NS.Object3D>\n }\n const playing: Playing[] = []\n const restPose = new WeakMap<THREE_NS.Object3D, { p: Vec3; r: Vec3 }>()\n const ZERO: Vec3 = [0, 0, 0]\n const animTarget = (): Entry | undefined => {\n if (heldEntry) return heldEntry\n const r = inspectTarget()\n return r ? entryOf(r.object) : undefined\n }\n const poseAt = (clip: AnimationClipSpec, id: string | null, time: number): { position: Vec3; rotation: Vec3 } => {\n const pick = (k: AnimationClipSpec['keys'][number]): { position?: Vec3; rotation?: Vec3 } | undefined => (id === null ? k : k.parts?.[id])\n const pts = clip.keys.map((k) => ({ t: k.t, position: pick(k)?.position ?? ZERO, rotation: pick(k)?.rotation ?? ZERO }))\n if (pts.length === 0 || pts[0].t > 0) pts.unshift({ t: 0, position: ZERO, rotation: ZERO })\n let a = pts[0]\n let b = pts[pts.length - 1]\n if (time >= b.t) a = b\n else for (let i = 0; i < pts.length - 1; i++) if (time >= pts[i].t && time < pts[i + 1].t) [a, b] = [pts[i], pts[i + 1]]\n const f = a === b || b.t <= a.t ? 0 : (time - a.t) / (b.t - a.t)\n const mix = (x: Vec3, y: Vec3): Vec3 => [x[0] + (y[0] - x[0]) * f, x[1] + (y[1] - x[1]) * f, x[2] + (y[2] - x[2]) * f]\n return { position: mix(a.position, b.position), rotation: mix(a.rotation, b.rotation) }\n }\n const applyClip = (pl: Playing): void => {\n for (const [id, obj] of pl.targets) {\n const rest = restPose.get(obj)\n if (!rest) continue\n const pose = poseAt(pl.clip, id === '' ? null : id, pl.t)\n obj.position.set(rest.p[0] + pose.position[0], rest.p[1] + pose.position[1], rest.p[2] + pose.position[2])\n obj.rotation.set(rest.r[0] + pose.rotation[0], rest.r[1] + pose.rotation[1], rest.r[2] + pose.rotation[2])\n // animations are visual only: move the part's collision/raycast shape to the same pose (spec rest + clip offset)\n const ps = id === '' ? undefined : specs.get(pl.entry.so.objectId)?.parts.find((p) => p.id === id)\n if (ps) {\n const r0 = ps.rotation ?? ZERO\n world.setPartPose(\n pl.entry.so.objectId, id,\n [ps.position[0] + pose.position[0], ps.position[1] + pose.position[1], ps.position[2] + pose.position[2]],\n [r0[0] + pose.rotation[0], r0[1] + pose.rotation[1], r0[2] + pose.rotation[2]],\n )\n }\n }\n }\n const updateAnimations = (dt: number): void => {\n for (let i = playing.length - 1; i >= 0; i--) {\n const pl = playing[i]\n pl.t = Math.min(pl.clip.duration, pl.t + dt)\n applyClip(pl)\n const evs = pl.clip.events ?? []\n while (pl.fired < evs.length && evs[pl.fired].t <= pl.t) {\n const ev = evs[pl.fired++]\n action('animation_event', t('act.anim_event', { name: pl.entry.name, clip: pl.clip.id, type: ev.type }), { objectId: pl.entry.so.objectId, itemId: pl.entry.so.itemId, data: { clip: pl.clip.id, type: ev.type, at: ev.t, ...(ev.data ?? {}) } })\n const key = ev.type === 'sound' ? ev.data?.key : undefined\n if (typeof key === 'string') playSound(key, v3(pl.entry.so.root.getWorldPosition(tmpV)), 1)\n }\n if (pl.t >= pl.clip.duration) {\n playing.splice(i, 1)\n action('animation_end', t('act.anim_end', { name: pl.entry.name, clip: pl.clip.id }), { objectId: pl.entry.so.objectId, itemId: pl.entry.so.itemId, data: { clip: pl.clip.id } })\n }\n }\n }\n const animationsOf = (): AnimationInfo | null => {\n const e = animTarget()\n if (!e || e.arena) return null\n const clips = (e.item?.animations ?? []).map((c) => ({ id: c.id, duration: c.duration }))\n return { objectId: e.so.objectId, itemId: e.so.itemId, name: e.name, clips, playing: playing.find((p) => p.entry === e)?.clip.id ?? null }\n }\n const playAnimation = (clipId: string, objectId?: string): boolean => {\n const e = objectId ? entries.get(objectId) : animTarget()\n const clip = e?.item?.animations?.find((c) => c.id === clipId)\n if (!e || !clip) return false\n for (let i = playing.length - 1; i >= 0; i--) if (playing[i].entry === e && playing[i].clip.id === clipId) playing.splice(i, 1)\n const targets = new Map<string, THREE_NS.Object3D>()\n const ids = new Set<string>()\n for (const k of clip.keys) for (const id of Object.keys(k.parts ?? {})) ids.add(id)\n const grab = (key: string, obj: THREE_NS.Object3D | undefined): void => {\n if (!obj) return\n if (!restPose.has(obj)) restPose.set(obj, { p: [obj.position.x, obj.position.y, obj.position.z], r: [obj.rotation.x, obj.rotation.y, obj.rotation.z] })\n targets.set(key, obj)\n }\n if (clip.keys.some((k) => k.position || k.rotation)) grab('', e.so.root)\n for (const id of ids) grab(id, e.so.root.getObjectByName(id) ?? undefined)\n const pl: Playing = { entry: e, clip, t: 0, fired: 0, targets }\n playing.push(pl)\n applyClip(pl)\n action('animation', t('act.anim_start', { name: e.name, clip: clip.id, seconds: num(clip.duration, 1) }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { clip: clip.id, duration: clip.duration } })\n return true\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Scenarios and modules\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const extraScenarios: TestRoomScenario[] = [...(options.scenarios ?? [])]\n const moduleCheck = (ok: boolean, text: string, data: Record<string, unknown>, itemId?: string): void => {\n log.add({ channel: 'check', type: ok ? 'pass' : 'fail', text: `${ok ? '✓' : '✗'} ${text}`, itemId, data: { ok, ...data } })\n }\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // What modules get from the room (game-contracts ModuleHost): the scene, the tool events and the frame\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const modules = new Map<string, TestableModule<ScenarioContext>>()\n const detachers = new Map<string, () => void>()\n const benches = new Map<string, BenchStore>()\n let activeBench: string | null = null\n const lastBench = (): string | null => [...benches.keys()].pop() ?? null\n const benchView = (): BenchView | null => {\n const store = activeBench ? benches.get(activeBench) : undefined\n if (!store) return null\n return { title: modules.get(store.moduleId)?.name ?? store.moduleId, controls: store.controls(), layers: store.layers(), sheet: store.sheet() }\n }\n const METRIC_UNAVAILABLE = 'n/a'\n const metricText = (value: number | string | undefined, digits: number, unit?: string): string =>\n typeof value === 'number' ? `${num(value, digits)}${unit ? ` ${unit}` : ''}` : value ?? METRIC_UNAVAILABLE\n const reportedFailures = new Set<string>()\n // a module's failure is told once (not every metrics tick) in the room log\n const reportOnce = (key: string, text: string): void => {\n if (reportedFailures.has(key)) return\n reportedFailures.add(key)\n host.log(text)\n }\n const failureText = (error: unknown): string => (error instanceof Error ? error.message : String(error))\n const moduleMetrics = (): Record<string, number | string> => {\n const store = activeBench ? benches.get(activeBench) : undefined\n const out: Record<string, number | string> = {}\n for (const metric of store?.metrics ?? []) {\n try {\n out[metric.id] = metric.read()\n } catch (error) {\n out[metric.id] = METRIC_UNAVAILABLE\n reportOnce(`${store?.moduleId}:metric:${metric.id}`, t('mod.metric_failed', { name: modules.get(store?.moduleId ?? '')?.name ?? '', metric: metric.id, error: failureText(error) }))\n }\n }\n return out\n }\n const metricRows = (): { room: MetricRow[]; module: MetricRow[] } => {\n const sampled = roomMetrics.sample()\n const room = roomMetricIds.flatMap((id) => {\n const value = sampled[id]\n return value === undefined ? [] : [{ id, name: t(`metric.${id}`), text: num(value, id === 'frame_ms' ? 1 : 0) }]\n })\n const values = moduleMetrics()\n const declared = (activeBench ? benches.get(activeBench)?.metrics : undefined) ?? []\n const module = declared.map((metric) => {\n const value = values[metric.id]\n const ratio = metric.max && typeof value === 'number' ? value / metric.max : undefined\n return { id: metric.id, name: metric.name, text: metricText(value, metric.digits ?? 0, metric.unit), ...(typeof value === 'number' ? { value } : {}), ...(ratio === undefined ? {} : { ratio }) }\n })\n return { room, module }\n }\n const showBench = (): void => {\n if (!ui) return\n ui.bench(benchView())\n ui.metrics(metricRows())\n }\n const hostListeners = new Set<(event: HostEvent) => void>()\n const frameListeners = new Set<(dt: number) => void>()\n const listenerDirection = new THREE.Vector3()\n const environment = options.environment ?? createEnvironmentBus()\n const audioSink = audio ? createAudioSink(audio) : undefined\n function emitHost(event: HostEvent): void {\n for (const listener of hostListeners) listener(event)\n }\n function flushEvents(id: string, state: WeaponState, recoil?: [number, number]): void {\n const phase = state.phase\n for (const event of state.drain()) {\n const hostEvent = toHostEvent(id, event, { ...(recoil ? { recoil } : {}), phase })\n if (hostEvent) emitHost(hostEvent)\n }\n }\n function startReload(): void {\n tool.reload()\n flushEvents(toolId, tool)\n }\n function clearToolFault(): void {\n if (!tool.clearFault()) return\n flushEvents(toolId, tool)\n say(t('hud.clearing'))\n }\n function toggleSafety(): void {\n tool.setSafety(!tool.safety)\n flushEvents(toolId, tool)\n say(t(tool.safety ? 'hud.safety_on' : 'hud.safety_off'))\n }\n function runToolCommand(request: ToolCommand): ToolCommandResult {\n // the room is the bench: every accessory can be fitted here, whatever it needs (a tool, a workbench)\n const work = (done: ReturnType<WeaponState['fit']>): ToolCommandResult => (done.ok ? { ok: true, seconds: done.seconds } : { ok: false, reason: done.reason })\n switch (request.type) {\n case 'fit':\n return work(tool.fit(request.attachment, { install: 'bench', ...(request.mount ? { mount: request.mount as MountKind } : {}) }))\n case 'remove':\n return work(tool.remove(request.attachment, { install: 'bench' }))\n case 'toggle':\n return tool.toggle(request.attachment) === null ? { ok: false, reason: 'not_fitted' } : { ok: true }\n case 'stock':\n return tool.setStock(request.state) ? { ok: true } : { ok: false, reason: 'busy' }\n case 'underbarrel':\n return tool.useUnderbarrel(request.on) ? { ok: true } : { ok: false, reason: 'busy' }\n case 'stance':\n tool.setStance({ ...(request.aiming === undefined ? {} : { aiming: request.aiming }), ...(request.supported === undefined ? {} : { supported: request.supported }) })\n return { ok: true }\n default:\n return { ok: false, reason: 'unknown' }\n }\n }\n const host: ModuleHost = {\n THREE,\n scene,\n camera,\n locale,\n ...(audioSink ? { audio: audioSink } : {}),\n environment,\n groundAt,\n effects: vfx,\n tool: () => ({\n weapon: toolId,\n category: tool.def.category,\n ammo: tool.ammo,\n capacity: tool.capacity,\n reserve: tool.reserve,\n reloading: tool.reloading,\n mode: tool.mode,\n ...(tool.fault ? { fault: tool.fault } : {}),\n safety: tool.safety,\n heat: tool.heatLevel,\n attachments: tool.attachments.map((part) => ({ id: part.id, mount: part.mount, ...(part.integral ? { integral: true } : {}), ...(part.on === undefined ? {} : { on: part.on }) })),\n stock: tool.stock,\n suppressed: tool.suppressed,\n underbarrelActive: tool.underbarrelActive,\n mass: tool.mass,\n aimSeconds: tool.aimSeconds,\n }),\n command(request) {\n const result = runToolCommand(request)\n flushEvents(toolId, tool)\n return result\n },\n configureTool(settings) {\n const condition = settings[SETTING_IDS.condition]\n const ammoQuality = settings[SETTING_IDS.ammoQuality]\n if (condition !== undefined) toolSettings.condition = condition\n if (ammoQuality !== undefined) toolSettings.ammoQuality = ammoQuality\n const fuseMetres = settings[SETTING_IDS.fuseLength] === undefined ? undefined : Number(settings[SETTING_IDS.fuseLength])\n if (fuseMetres !== undefined && fuseMetres > 0) fuseLength = fuseMetres\n for (const state of tools.values()) {\n if (condition !== undefined) state.setCondition(condition)\n if (ammoQuality !== undefined) state.setAmmoQuality(ammoQuality)\n if (fuseMetres !== undefined && fuseMetres > 0) state.setFuseLength(fuseMetres)\n }\n },\n on(listener) {\n hostListeners.add(listener)\n return () => hostListeners.delete(listener)\n },\n onFrame(update) {\n frameListeners.add(update)\n return () => frameListeners.delete(update)\n },\n log(text, data) {\n action('module_note', text, { data })\n },\n addBlocker(blocked) {\n blockers.add(blocked)\n return () => blockers.delete(blocked)\n },\n onClear(listener) {\n clearListeners.add(listener)\n return () => clearListeners.delete(listener)\n },\n }\n const lendBench = (store: BenchStore): ModuleBench => ({\n value: store.value,\n layer: store.layer,\n onChange: store.onChange,\n patch: store.patch,\n sheet: store.setSheet,\n look: (eye, target) => room.look(eye, target),\n })\n const checkModuleBench = (mod: TestableModule<ScenarioContext>, fail: (problem: string) => void): BenchStore | null => {\n const store = createBenchStore(mod, locale, (error) => reportOnce(`${mod.id}:listener`, t('mod.listener_failed', { name: mod.name, error: failureText(error) })))\n const { controls, layers, metrics } = store.declared\n if (controls.length + layers.length + metrics.length === 0) return null\n const r = checkBench(store.declared)\n const text = r.ok ? t('mod.bench_ok', { name: mod.name, controls: controls.length, layers: layers.length, metrics: metrics.length }) : t('mod.bench_fail', { name: mod.name, problems: r.problems.join('; ') })\n moduleCheck(r.ok, text, { module: mod.id, check: 'bench', problems: r.problems })\n for (const p of r.problems) fail(`bench: ${p}`)\n return r.ok ? store : null\n }\n\n const loadModule = (mod: TestableModule<ScenarioContext>): ModuleReport => {\n const report: ModuleReport = { module: mod.id, items: [], scenarios: [], ok: true, problems: [] }\n const fail = (problem: string): void => {\n report.ok = false\n report.problems.push(problem)\n }\n const added = mod.items(locale)\n for (const ti of added) {\n const item: TestRoomItem = {\n id: ti.id,\n name: ti.name,\n group: mod.group,\n build: (T) => ti.build(T) as THREE_NS.Object3D,\n spec: ti.spec as TestRoomItem['spec'],\n movable: ti.movable,\n fluid: ti.fluid,\n weapon: ti.weapon,\n impl: ti.impl as TestRoomItem['impl'],\n animations: ti.animations,\n thumbnail: ti.thumbnail,\n thumbnailCredit: ti.thumbnailCredit,\n }\n catalogMap.set(item.id, item)\n const at = catalog.findIndex((c) => c.id === item.id)\n if (at >= 0) catalog[at] = item\n else catalog.push(item)\n report.items.push(item.id)\n // contract checks on a throwaway build of the item (never added to the scene)\n let partIds: string[] = []\n const base = { module: mod.id, item: item.id }\n try {\n const root = item.build(THREE)\n root.updateMatrixWorld(true)\n if (item.impl) {\n const probe = item.impl(root, `${item.id}_check`)\n const r = checkDestructible(probe, { materials: world.materials.keys() })\n partIds = probe.describe().parts.map((p) => p.id)\n moduleCheck(r.ok, r.ok ? t('mod.destructible_ok', { name: item.name, parts: partIds.length }) : t('mod.destructible_fail', { name: item.name, problems: r.problems.join('; ') }), { ...base, check: 'destructible', problems: r.problems }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n }\n if (!item.impl || item.spec) {\n // the spec is resolved after the build (it may be a function of the root, or derived from the meshes)\n const spec = resolveSpec(item, root).spec\n if (!item.impl) partIds = spec.parts.map((p) => p.id)\n const r = checkSpec(spec, { materials: world.materials.keys() })\n moduleCheck(r.ok, r.ok ? t('mod.spec_ok', { name: item.name, parts: spec.parts.length }) : t('mod.spec_fail', { name: item.name, problems: r.problems.join('; ') }), { ...base, check: 'spec', problems: r.problems, warnings: r.warnings }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n for (const w of r.warnings) log.add({ channel: 'check', type: 'warn', text: `⚠ ${t('mod.spec_warn', { name: item.name, warning: w })}`, itemId: item.id, data: { ok: true, ...base, check: 'spec', warning: w } })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n moduleCheck(false, t('mod.destructible_fail', { name: item.name, problems: msg }), { ...base, check: 'destructible', problems: [msg] }, item.id)\n fail(`${item.id}: ${msg}`)\n }\n for (const clip of item.animations ?? []) {\n const r = checkAnimation(clip, partIds)\n moduleCheck(r.ok, r.ok ? t('mod.animation_ok', { name: item.name, clip: clip.id, seconds: num(clip.duration, 1) }) : t('mod.animation_fail', { name: item.name, clip: clip.id, problems: r.problems.join('; ') }), { ...base, check: 'animation', clip: clip.id, problems: r.problems }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n }\n }\n for (const ms of mod.scenarios?.(locale) ?? []) {\n const sc: TestRoomScenario = { id: ms.id, name: ms.name, run: ms.run }\n const at = extraScenarios.findIndex((x) => x.id === sc.id)\n if (at >= 0) extraScenarios[at] = sc\n else extraScenarios.push(sc)\n report.scenarios.push(sc.id)\n }\n action('module', t('act.module_loaded', { name: mod.name, items: report.items.length, scenarios: report.scenarios.length, result: t(report.ok ? 'mod.all_ok' : 'mod.some_failed') }), { data: { module: mod.id, items: report.items, scenarios: report.scenarios, ok: report.ok } })\n const bench = checkModuleBench(mod, fail)\n detachers.get(mod.id)?.()\n detachers.delete(mod.id)\n // a reloaded module keeps its live bench state; the host's state only seeds a module the room has not seen\n const previous = benches.get(mod.id)\n const kept = previous?.encode()\n previous?.dispose()\n benches.delete(mod.id)\n for (const key of [...reportedFailures]) if (key.startsWith(`${mod.id}:`)) reportedFailures.delete(key)\n modules.set(mod.id, mod)\n if (bench) {\n const seed = options.bench?.state?.[mod.id]\n const restored = kept ?? (typeof seed === 'string' ? seed : undefined)\n if (restored !== undefined) bench.restore(restored)\n benches.set(mod.id, bench)\n bench.watch(() => {\n options.bench?.onChange?.(mod.id, bench.encode())\n if (activeBench === mod.id) ui?.bench(benchView())\n })\n if (!activeBench || !benches.has(activeBench)) activeBench = mod.id\n } else if (activeBench === mod.id) activeBench = lastBench()\n if (mod.attach) detachers.set(mod.id, mod.attach(bench ? { ...host, bench: lendBench(bench) } : host))\n bench?.sendInitial()\n showBench()\n ui?.refresh()\n return report\n }\n\n const allScenarios = (): TestRoomScenario[] => [...makeScenarios(t, num, locale), ...extraScenarios]\n let scenarioRunning = false\n\n const step = (seconds: number): void => {\n const dt = seconds > 6 ? 1 / 30 : FIXED_DT\n const n = Math.max(1, Math.round(seconds / dt))\n for (let i = 0; i < n; i++) {\n player.update(0)\n followHeld(dt)\n stepSim(dt)\n }\n }\n\n const runScenarios = async (list?: TestRoomScenario[]): Promise<ScenarioReport> => {\n const all = list ?? allScenarios()\n const report: ScenarioReport = { passed: 0, failed: 0, results: [] }\n scenarioRunning = true\n const wasPaused = paused\n paused = false\n try {\n for (const sc of all) {\n hardReset()\n player.look(arena.playerStart, [0, 1.5, arena.wallZ])\n useHeld = false\n const checks: Array<{ label: string; ok: boolean }> = []\n log.add({ channel: 'check', type: 'scenario', text: t('sc.start', { name: sc.name }), data: { id: sc.id } })\n const ctx: ScenarioContext = {\n room,\n step,\n expect(condition, label, data) {\n checks.push({ label, ok: !!condition })\n log.add({ channel: 'check', type: condition ? 'pass' : 'fail', text: `${condition ? '✓' : '✗'} ${label}`, data: { scenario: sc.id, ok: !!condition, ...(data ?? {}) } })\n },\n }\n try {\n await sc.run(ctx)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n ctx.expect(false, t('sc.error', { msg }))\n }\n flush()\n const ok = checks.length > 0 && checks.every((c) => c.ok)\n report.results.push({ id: sc.id, name: sc.name, ok, checks })\n if (ok) report.passed++\n else report.failed++\n log.add({ channel: 'check', type: ok ? 'scenario_pass' : 'scenario_fail', text: t(ok ? 'sc.pass' : 'sc.fail', { name: sc.name }), data: { id: sc.id, ok } })\n await new Promise<void>((res) => setTimeout(res, 0))\n }\n } finally {\n scenarioRunning = false\n paused = wasPaused\n }\n return report\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // The room object\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // lays a module area: things that hold others first, so what goes on them finds their top\n const layArea = (layout: ModuleArea): SpawnedObject[] => {\n const holders = layout.placements.filter((p) => p.surface)\n const rest = layout.placements.filter((p) => !p.surface)\n const placed = [...holders, ...rest].map((p) => {\n const so = spawn(p.item, p.position, p.rotationY ?? 0)\n if (p.surface) {\n const [hx, hz] = p.surface.halfSize\n restingTops.push({ objectId: so.objectId, minX: p.position[0] - hx, maxX: p.position[0] + hx, minZ: p.position[2] - hz, maxZ: p.position[2] + hz, top: p.surface.height })\n }\n return { so, asleep: p.asleep === true }\n })\n for (const { so, asleep } of placed) {\n const piece = asleep ? rendererPieces.get(so.objectId) : undefined\n if (piece) piece.sleeping = true\n }\n if (layout.view) room.look(layout.view.eye, layout.view.target)\n return placed.map(({ so }) => so)\n }\n\n // a test environment per catalogue group, the way the demo site links each area of the index: a loaded module brings its own area,\n // any other group is laid in rows (small things in front, fixed big ones behind)\n const openArea = (area: string): SpawnedObject[] => {\n clear()\n const mod = [...modules.values()].find((m) => m.id === area || m.group === area)\n const label = mod?.group ?? S.groups[area] ?? area\n ui?.showGroup(label)\n activeBench = mod && benches.has(mod.id) ? mod.id : lastBench()\n showBench()\n const layout = mod?.area?.(locale)\n if (layout) return layArea(layout)\n const items = catalog.filter((item) => item.group === label)\n const front = items.filter((item) => item.movable !== false)\n const back = items.filter((item) => item.movable === false)\n const row = (list: TestRoomItem[], gap: number, z: number): SpawnedObject[] => list.map((item, index) => spawn(item.id, [(index - (list.length - 1) / 2) * gap, 0, z], 0))\n return [...row(front, 1.6, 1.5), ...row(back, 4.5, -4)]\n }\n\n const room: TestRoom & {\n tilt(rad: number): void\n toggleTap(on?: boolean): boolean\n blast(): BlastOptions\n setBlast(options: BlastOptions): void\n setSlowMotion(on: boolean): void\n setFastForward(on: boolean): void\n equip(weaponId: string): void\n readonly scenarios: TestRoomScenario[]\n readonly fluidRenderer: FluidRenderer\n inspectInfo(): InspectInfo | null\n } = {\n world,\n renderer,\n scene,\n camera,\n arsenal,\n fluids,\n film: filmBridge,\n vfx: vfx.world,\n fluidRenderer: fluidView,\n audio,\n environment,\n log,\n get tool() {\n return tool\n },\n get scenarios() {\n return allScenarios()\n },\n spawn,\n clear,\n resetAll,\n setTool,\n useItem,\n use(hold = 0) {\n if (tool.def.category === 'hand') {\n grab()\n return\n }\n useTool(FIXED_DT, false)\n flush()\n let t0 = 0\n while (t0 < hold) {\n useTool(FIXED_DT, true)\n stepSim(FIXED_DT)\n t0 += FIXED_DT\n }\n releaseTrigger()\n },\n grab,\n throwHeld,\n look(position, target) {\n player.look(position, target)\n },\n inspect() {\n const r = inspectTarget()\n if (!r) return null\n return { objectId: r.object, partId: r.part, itemId: entryOf(r.object)?.so.itemId ?? '' }\n },\n inspectInfo,\n spawned() {\n return [...entries.values()].filter((e) => !e.arena).map((e) => e.so)\n },\n update,\n waitUntilReady(maxSeconds = 5) {\n let waited = 0\n while (tool.phase && waited < maxSeconds) {\n update(FIXED_DT)\n waited += FIXED_DT\n }\n // the trigger judges a frame by where it starts: one more frame, or the first pull of a fresh draw still answers `drawing`\n update(FIXED_DT)\n return waited + FIXED_DT\n },\n on(type, fn) {\n listeners[type].add(fn)\n return () => listeners[type].delete(fn)\n },\n runScenarios,\n tilt(rad) {\n heldTilt = rad\n },\n toggleTap,\n blast: () => ({ ...blastOptions }),\n setBlast: (next) => {\n blastOptions = { ...blastOptions, ...next }\n },\n pause() {\n paused = true\n },\n resume() {\n paused = false\n },\n get paused() {\n return paused\n },\n walk(to, seconds) {\n walkPlan = seconds > 0 ? { x: to[0], z: to[2], remaining: seconds } : null\n if (!walkPlan) player.moveBy(to[0] - camera.position.x, to[2] - camera.position.z)\n },\n setSlowMotion(on) {\n timeScale = on ? 0.25 : 1\n },\n setFastForward(on) {\n fastForward = on\n },\n equip,\n openArea,\n loadModule,\n animations: animationsOf,\n playAnimation,\n bench(moduleId) {\n const id = moduleId ?? activeBench\n return (id ? benches.get(id) : undefined) ?? null\n },\n applyCamera: () => vfx.applyCamera(),\n metrics() {\n return { room: roomMetrics.sample(), module: moduleMetrics() }\n },\n dispose() {\n destructionSound?.dispose()\n if (ownAudio) audio?.dispose()\n for (const detach of detachers.values()) detach()\n detachers.clear()\n for (const store of benches.values()) store.dispose()\n benches.clear()\n cancelAnimationFrame?.(raf)\n window.removeEventListener('resize', onResize)\n player.dispose()\n ui?.dispose()\n renderer.dispose()\n vfx.dispose()\n craterPatch?.dispose()\n fluidView.dispose()\n filmBridge.dispose()\n film.dispose()\n for (const tr of tracers) tr.line.removeFromParent()\n explosives.clear()\n if (ownRenderer) {\n gl.dispose()\n dom.remove()\n }\n },\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // UI and loop\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let ui: RoomUi | null = null\n if (options.ui !== false) {\n const groups = (): Map<string, TestRoomItem[]> => {\n const m = new Map<string, TestRoomItem[]>()\n for (const i of catalog) {\n const g = m.get(i.group) ?? []\n g.push(i)\n m.set(i.group, g)\n }\n return m\n }\n ui = createUi({\n container,\n strings: S,\n t,\n log,\n groups,\n loadout: () => loadout.map((id) => ({ id, name: arsenal.name(id) })),\n onSpawn: (id) => {\n spawn(id)\n },\n onEquip: (itemId) => {\n const w = catalogMap.get(itemId)?.weapon\n if (w) equip(w)\n },\n onClear: clear,\n onResetAll: resetAll,\n onSlow: (on) => room.setSlowMotion(on),\n onFast: (on) => room.setFastForward(on),\n onQuality: (q) => {\n qualityName = q\n if (ownRenderer) {\n gl.shadowMap.enabled = q !== 'low'\n gl.setPixelRatio(q === 'low' ? 1 : Math.min(typeof devicePixelRatio === 'number' ? devicePixelRatio : 1, 2))\n arena.sun.shadow.mapSize.set(q === 'high' ? 2048 : 1024, q === 'high' ? 2048 : 1024)\n arena.sun.shadow.map?.dispose()\n arena.sun.shadow.map = null\n resize()\n }\n },\n quality: qualityName,\n scenarios: allScenarios,\n onRun: async (sc) => {\n await runScenarios([sc])\n },\n onRunAll: async () => {\n await runScenarios()\n },\n onTool: (index) => {\n toolIndex = index\n setTool(loadout[index])\n },\n onTap: () => toggleTap(),\n onBlast: (key) => toggleBlast(key),\n onPlay: (objectId, clipId) => {\n playAnimation(clipId, objectId)\n },\n onResize: resize,\n onControl: (id, value) => {\n if (activeBench) benches.get(activeBench)?.set(id, value)\n },\n onLayer: (id, on) => {\n if (activeBench) benches.get(activeBench)?.setLayer(id, on)\n },\n onAction: (id) => {\n if (activeBench) benches.get(activeBench)?.act(id)\n },\n })\n ui.hud(hudState())\n showBench()\n }\n\n let raf = 0\n if (ownRenderer && typeof requestAnimationFrame === 'function') {\n let last = performance.now()\n ownsLoop = true\n const loop = (now: number): void => {\n raf = requestAnimationFrame(loop)\n const realDelta = (now - last) / 1000\n roomMetrics.frame(realDelta)\n const dt = Math.min(0.05, realDelta)\n last = now\n if (!scenarioRunning) update(dt)\n const restoreCamera = vfx.applyCamera()\n gl.render(scene, camera)\n restoreCamera()\n roomMetrics.rendered()\n }\n raf = requestAnimationFrame(loop)\n }\n\n if (options.initial) {\n for (const [i, id] of options.initial.entries()) spawn(id, [(i - (options.initial.length - 1) / 2) * 1.3, 0, 0.5])\n }\n if (options.area) openArea(options.area)\n\n return room\n}\n\nfunction structuredCloneSpec(spec: DestructibleSpec): DestructibleSpec {\n return JSON.parse(JSON.stringify(spec)) as DestructibleSpec\n}\n","import type * as THREE_NS from 'three'\nimport { buildFrame } from '@adatechnology/game-destruction'\nimport type { DestructibleSpec, JointSpec, MaterialDef, PartSpec, Vec3 } from '@adatechnology/game-destruction'\nimport { buildFromSpec } from './build-from-spec'\nimport { resolveStrings } from './locale'\nimport type { TestRoomItem } from './types'\n\n/**\n * Extra materials the demo items need on top of the core ones. None any more (the bottle uses the core `glass`, which now breaks from a drop);\n * kept so that code passing it to `worldOptions.materials` keeps working.\n */\nexport const DEMO_MATERIALS: MaterialDef[] = []\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Small spec helpers\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\ntype Extra = Partial<Omit<PartSpec, 'id' | 'material' | 'shape' | 'position'>>\n\nconst box = (id: string, material: string, size: Vec3, position: Vec3, extra: Extra = {}): PartSpec => ({ id, material, shape: { kind: 'box', size }, position, ...extra })\nconst cyl = (id: string, material: string, radius: number, height: number, position: Vec3, extra: Extra = {}): PartSpec => ({\n id,\n material,\n shape: { kind: 'cylinder', radius, height },\n position,\n ...extra,\n})\nconst sph = (id: string, material: string, radius: number, position: Vec3, extra: Extra = {}): PartSpec => ({ id, material, shape: { kind: 'sphere', radius }, position, ...extra })\nconst joint = (a: string, b: string, kind: JointSpec['kind'], extra: Partial<JointSpec> = {}): JointSpec => ({ a, b, kind, ...extra })\n\n/** Spec of the brick target wall: `cols` x `rows` brick panels, the bottom row anchored, mortar joints between neighbours. */\nexport function brickWallSpec(cols = 8, rows = 6, panel: Vec3 = [1.25, 0.5, 0.2]): DestructibleSpec {\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n const id = (c: number, r: number): string => `brick_${r}_${c}`\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n parts.push(box(id(c, r), 'brick', panel, [(c - (cols - 1) / 2) * panel[0], panel[1] / 2 + r * panel[1], 0], { anchored: r === 0 }))\n if (c > 0) joints.push(joint(id(c - 1, r), id(c, r), 'mortar'))\n if (r > 0) joints.push(joint(id(c, r - 1), id(c, r), 'mortar'))\n }\n }\n return { name: 'brick wall', parts, joints, tags: ['structure'] }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Demo specs\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\nconst chair = (): DestructibleSpec => {\n const legs = [\n [-0.18, -0.18],\n [0.18, -0.18],\n [-0.18, 0.18],\n [0.18, 0.18],\n ]\n return {\n name: 'chair',\n parts: [\n box('seat', 'wood_soft', [0.42, 0.04, 0.42], [0, 0.45, 0]),\n ...legs.map(([x, z], i) => box(`leg_${i + 1}`, 'wood_soft', [0.04, 0.43, 0.04], [x, 0.215, z])),\n box('backrest', 'wood_soft', [0.4, 0.3, 0.03], [0, 0.64, -0.195]),\n ],\n joints: [...legs.map((_, i) => joint(`leg_${i + 1}`, 'seat', 'screw')), joint('backrest', 'seat', 'screw')],\n tags: ['furniture'],\n }\n}\n\nconst crate = (): DestructibleSpec => ({\n name: 'wooden crate',\n parts: [\n box('front', 'wood_soft', [0.5, 0.5, 0.02], [0, 0.25, 0.24], { hp: 70 }),\n box('back', 'wood_soft', [0.5, 0.5, 0.02], [0, 0.25, -0.24], { hp: 70 }),\n box('left', 'wood_soft', [0.02, 0.5, 0.46], [-0.24, 0.25, 0], { hp: 70 }),\n box('right', 'wood_soft', [0.02, 0.5, 0.46], [0.24, 0.25, 0], { hp: 70 }),\n box('bottom', 'wood_soft', [0.46, 0.02, 0.46], [0, 0.01, 0], { hp: 70 }),\n ],\n joints: [\n joint('front', 'left', 'nail'),\n joint('front', 'right', 'nail'),\n joint('back', 'left', 'nail'),\n joint('back', 'right', 'nail'),\n joint('front', 'bottom', 'nail'),\n joint('back', 'bottom', 'nail'),\n joint('left', 'bottom', 'nail'),\n joint('right', 'bottom', 'nail'),\n ],\n tags: ['container'],\n})\n\nconst drum = (): DestructibleSpec => ({\n name: 'steel drum',\n parts: [\n cyl('drum_body', 'steel', 0.29, 0.86, [0, 0.45, 0], { mass: 12, thickness: 0.0012 }),\n cyl('drum_top', 'steel', 0.29, 0.02, [0, 0.89, 0], { mass: 1.5, thickness: 0.0012 }),\n cyl('drum_bottom', 'steel', 0.29, 0.02, [0, 0.01, 0], { mass: 1.5, thickness: 0.0012 }),\n ],\n joints: [joint('drum_body', 'drum_top', 'weld'), joint('drum_body', 'drum_bottom', 'weld')],\n tags: ['container'],\n})\n\nconst steelSheet = (): DestructibleSpec => ({\n name: 'steel sheet',\n parts: [\n box('sheet', 'steel', [1, 1, 0.003], [0, 1.1, 0]),\n box('post_l', 'steel', [0.04, 0.54, 0.04], [-0.35, 0.33, 0], { mass: 4 }),\n box('post_r', 'steel', [0.04, 0.54, 0.04], [0.35, 0.33, 0], { mass: 4 }),\n box('foot_l', 'steel', [0.06, 0.06, 0.5], [-0.35, 0.03, 0], { mass: 6 }),\n box('foot_r', 'steel', [0.06, 0.06, 0.5], [0.35, 0.03, 0], { mass: 6 }),\n ],\n joints: [joint('sheet', 'post_l', 'weld'), joint('sheet', 'post_r', 'weld'), joint('post_l', 'foot_l', 'weld'), joint('post_r', 'foot_r', 'weld')],\n tags: ['structure'],\n})\n\nconst glassPane = (): DestructibleSpec => ({\n name: 'glass pane',\n parts: [\n box('pane', 'glass', [0.8, 1, 0.006], [0, 1.05, 0], { hp: 40 }),\n box('frame_top', 'aluminium', [0.88, 0.04, 0.04], [0, 1.57, 0], { mass: 1 }),\n box('frame_bottom', 'aluminium', [0.88, 0.04, 0.04], [0, 0.53, 0], { mass: 1 }),\n box('frame_l', 'aluminium', [0.04, 1.04, 0.04], [-0.42, 1.05, 0], { mass: 1 }),\n box('frame_r', 'aluminium', [0.04, 1.04, 0.04], [0.42, 1.05, 0], { mass: 1 }),\n box('foot_l', 'steel', [0.06, 0.5, 0.4], [-0.35, 0.25, 0], { mass: 5 }),\n box('foot_r', 'steel', [0.06, 0.5, 0.4], [0.35, 0.25, 0], { mass: 5 }),\n ],\n joints: [\n joint('pane', 'frame_top', 'clip'),\n joint('pane', 'frame_bottom', 'clip'),\n joint('pane', 'frame_l', 'clip'),\n joint('pane', 'frame_r', 'clip'),\n joint('frame_bottom', 'foot_l', 'bolt'),\n joint('frame_bottom', 'foot_r', 'bolt'),\n joint('frame_l', 'frame_top', 'weld'),\n joint('frame_r', 'frame_top', 'weld'),\n joint('frame_l', 'frame_bottom', 'weld'),\n joint('frame_r', 'frame_bottom', 'weld'),\n ],\n tags: ['structure'],\n})\n\nconst concreteBlock = (): DestructibleSpec => ({\n name: 'concrete block',\n parts: [box('block', 'concrete', [0.4, 0.4, 0.4], [0, 0.2, 0])],\n tags: ['structure'],\n})\n\nconst brickColumn = (): DestructibleSpec => {\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n const layers = 8\n const id = (l: number, x: number, z: number): string => `brick_${l}_${x}${z}`\n for (let l = 0; l < layers; l++) {\n for (let x = 0; x < 2; x++) {\n for (let z = 0; z < 2; z++) {\n parts.push(box(id(l, x, z), 'brick', [0.2, 0.2, 0.2], [(x - 0.5) * 0.2, 0.1 + l * 0.2, (z - 0.5) * 0.2], { anchored: l === 0 }))\n if (x > 0) joints.push(joint(id(l, x - 1, z), id(l, x, z), 'mortar'))\n if (z > 0) joints.push(joint(id(l, x, z - 1), id(l, x, z), 'mortar'))\n if (l > 0) joints.push(joint(id(l - 1, x, z), id(l, x, z), 'mortar'))\n }\n }\n }\n return { name: 'brick column', parts, joints, tags: ['structure'] }\n}\n\n/**\n * A small house frame (2 x 2 columns on foundations, beams, a roof slab) from the core's `buildFrame`. The columns are rated at 4.4 t so that\n * losing one column leaves the roof standing (the others carry about 90% of their capacity) and losing two overloads the rest until the roof\n * comes down.\n */\nconst frame = (): DestructibleSpec => ({ ...buildFrame({ spanX: 4, spanZ: 4, columnsX: 2, columnsZ: 2, height: 2.8, floors: 1, walls: false, roof: true, columnCapacity: 4400 }), name: 'building frame' })\n\nconst bucket = (): DestructibleSpec => ({\n name: 'plastic bucket',\n parts: [\n cyl('bucket_body', 'plastic', 0.14, 0.28, [0, 0.14, 0], { mass: 0.5, thickness: 0.002 }),\n box('handle', 'plastic', [0.3, 0.012, 0.012], [0, 0.3, 0], { mass: 0.05 }),\n ],\n joints: [joint('handle', 'bucket_body', 'clip')],\n tags: ['container'],\n})\n\nconst bottle = (): DestructibleSpec => ({\n name: 'glass bottle',\n parts: [\n cyl('bottle_body', 'glass', 0.037, 0.17, [0, 0.085, 0], { mass: 0.3, thickness: 0.003, contains: { fluid: 'water', liters: 0.5 } }),\n cyl('bottle_neck', 'glass', 0.015, 0.09, [0, 0.215, 0], { mass: 0.08, thickness: 0.002 }),\n ],\n joints: [joint('bottle_neck', 'bottle_body', 'fused')],\n tags: ['item'],\n})\n\nconst cup = (): DestructibleSpec => ({\n name: 'coffee cup',\n parts: [\n cyl('cup', 'ceramic', 0.05, 0.11, [0, 0.055, 0], { mass: 0.3, thickness: 0.004, contains: { fluid: 'coffee', liters: 0.25 } }),\n box('cup_handle', 'ceramic', [0.02, 0.06, 0.014], [0.068, 0.06, 0], { mass: 0.04 }),\n ],\n joints: [joint('cup_handle', 'cup', 'fused')],\n tags: ['item'],\n})\n\nconst jerrycan = (): DestructibleSpec => ({\n name: 'jerrycan',\n parts: [\n box('tank', 'plastic', [0.34, 0.45, 0.14], [0, 0.225, 0], { mass: 1.2, thickness: 0.003, contains: { fluid: 'fuel', liters: 20 } }),\n cyl('cap', 'plastic', 0.025, 0.03, [0.08, 0.465, 0], { mass: 0.05 }),\n box('handle', 'plastic', [0.1, 0.03, 0.03], [-0.07, 0.465, 0], { mass: 0.1 }),\n ],\n joints: [joint('cap', 'tank', 'screw'), joint('handle', 'tank', 'fused')],\n tags: ['container'],\n})\n\nconst gasBottle = (): DestructibleSpec => ({\n name: 'gas bottle',\n parts: [\n cyl('cylinder', 'steel', 0.15, 0.7, [0, 0.4, 0], {\n mass: 11,\n thickness: 0.003,\n contains: { fluid: 'gas', liters: 13, pressurized: true },\n explodes: { energy: 120000, radius: 5, atC: 300 },\n }),\n cyl('valve', 'steel', 0.03, 0.1, [0, 0.8, 0], { mass: 0.5 }),\n cyl('foot_ring', 'steel', 0.14, 0.05, [0, 0.025, 0], { mass: 1 }),\n ],\n joints: [joint('valve', 'cylinder', 'weld'), joint('foot_ring', 'cylinder', 'weld')],\n tags: ['container'],\n})\n\nconst tree = (): DestructibleSpec => ({\n name: 'small tree',\n parts: [\n cyl('trunk', 'green_wood', 0.08, 2.2, [0, 1.1, 0], { anchored: true }),\n cyl('branch_1', 'green_wood', 0.03, 0.8, [0.34, 1.7, 0], { rotation: [0, 0, -0.9] }),\n cyl('branch_2', 'green_wood', 0.03, 0.8, [-0.3, 1.9, 0.12], { rotation: [0, 0, 0.8] }),\n cyl('branch_3', 'green_wood', 0.025, 0.7, [0.05, 2.0, -0.28], { rotation: [0.8, 0, 0] }),\n sph('crown_top', 'foliage', 0.55, [0, 2.55, 0], { mass: 2 }),\n sph('crown_1', 'foliage', 0.38, [0.62, 2.0, 0], { mass: 1 }),\n sph('crown_2', 'foliage', 0.38, [-0.58, 2.2, 0.15], { mass: 1 }),\n sph('crown_3', 'foliage', 0.32, [0.05, 2.3, -0.55], { mass: 1 }),\n ],\n joints: [\n joint('branch_1', 'trunk', 'stem'),\n joint('branch_2', 'trunk', 'stem'),\n joint('branch_3', 'trunk', 'stem'),\n joint('crown_top', 'trunk', 'stem'),\n joint('crown_1', 'branch_1', 'stem'),\n joint('crown_2', 'branch_2', 'stem'),\n joint('crown_3', 'branch_3', 'stem'),\n ],\n tags: ['plant'],\n})\n\nconst pottedPlant = (): DestructibleSpec => ({\n name: 'potted plant',\n parts: [\n cyl('pot', 'ceramic', 0.15, 0.25, [0, 0.125, 0], { mass: 2, thickness: 0.008 }),\n cyl('soil', 'soil', 0.14, 0.06, [0, 0.26, 0], { mass: 1.5 }),\n sph('leaves_1', 'foliage', 0.16, [0, 0.46, 0], { mass: 0.3 }),\n sph('leaves_2', 'foliage', 0.12, [0.12, 0.38, 0.04], { mass: 0.2 }),\n sph('leaves_3', 'foliage', 0.12, [-0.1, 0.4, -0.06], { mass: 0.2 }),\n ],\n joints: [joint('soil', 'pot', 'fused'), joint('leaves_1', 'soil', 'stem'), joint('leaves_2', 'soil', 'stem'), joint('leaves_3', 'soil', 'stem')],\n tags: ['plant'],\n})\n\nconst oldTv = (): DestructibleSpec => ({\n name: 'old TV',\n parts: [\n box('stand', 'wood_soft', [0.6, 0.35, 0.42], [0, 0.175, 0]),\n box('shell', 'plastic', [0.58, 0.44, 0.42], [0, 0.57, 0], { mass: 3, thickness: 0.004 }),\n box('screen', 'glass', [0.42, 0.32, 0.012], [0, 0.57, 0.212], { mass: 1.5 }),\n box('coil', 'copper', [0.2, 0.1, 0.2], [0, 0.55, -0.05], { mass: 1.5 }),\n ],\n joints: [joint('shell', 'stand', 'screw'), joint('screen', 'shell', 'clip'), joint('coil', 'shell', 'screw')],\n tags: ['furniture'],\n})\n\nconst carDoor = (): DestructibleSpec => ({\n name: 'car door',\n parts: [\n box('post', 'steel', [0.1, 1.3, 0.1], [-0.58, 0.65, 0], { mass: 12, anchored: true }),\n box('skin', 'steel', [1, 0.8, 0.05], [0, 0.75, 0], { mass: 14, thickness: 0.0008 }),\n box('window', 'glass', [0.78, 0.32, 0.01], [0.04, 1.31, 0.01], { mass: 3 }),\n box('seal', 'rubber', [0.84, 0.03, 0.03], [0.04, 1.14, 0.01], { mass: 0.3 }),\n ],\n joints: [\n joint('skin', 'post', 'hinge', { id: 'hinge_upper' }),\n joint('skin', 'post', 'hinge', { id: 'hinge_lower' }),\n joint('window', 'seal', 'clip'),\n joint('seal', 'skin', 'clip'),\n ],\n tags: ['vehicle'],\n})\n\nconst sofa = (): DestructibleSpec => ({\n name: 'sofa',\n parts: [\n box('frame', 'wood_soft', [1.8, 0.3, 0.8], [0, 0.15, 0], { mass: 14 }),\n box('seat_cushion', 'foam', [1.5, 0.18, 0.62], [0, 0.39, 0.06], { mass: 4 }),\n box('back_cushion', 'foam', [1.5, 0.5, 0.16], [0, 0.65, -0.3], { mass: 4 }),\n box('arm_l', 'fabric', [0.15, 0.4, 0.8], [-0.82, 0.5, 0], { mass: 3 }),\n box('arm_r', 'fabric', [0.15, 0.4, 0.8], [0.82, 0.5, 0], { mass: 3 }),\n ],\n joints: [\n joint('seat_cushion', 'frame', 'clip'),\n joint('back_cushion', 'frame', 'clip'),\n joint('arm_l', 'frame', 'screw'),\n joint('arm_r', 'frame', 'screw'),\n ],\n tags: ['furniture'],\n})\n\nconst shelf = (): DestructibleSpec => ({\n name: 'shelf',\n parts: [\n box('back', 'plywood', [0.84, 1.5, 0.012], [0, 0.75, -0.14], { anchored: true }),\n box('board_1', 'wood_soft', [0.8, 0.025, 0.28], [0, 0.35, 0]),\n box('board_2', 'wood_soft', [0.8, 0.025, 0.28], [0, 0.75, 0]),\n box('board_3', 'wood_soft', [0.8, 0.025, 0.28], [0, 1.15, 0]),\n box('board_4', 'wood_soft', [0.8, 0.025, 0.28], [0, 1.5, 0]),\n ],\n joints: [joint('board_1', 'back', 'screw'), joint('board_2', 'back', 'screw'), joint('board_3', 'back', 'screw'), joint('board_4', 'back', 'screw')],\n tags: ['furniture'],\n})\n\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n// Catalogue\n// ---------------------------------------------------------------------------------------------------------------------------------------------\n\ninterface DemoDef {\n id: string\n group: string\n spec: () => DestructibleSpec\n colors?: Record<string, number>\n movable?: boolean\n fluid?: TestRoomItem['fluid']\n}\n\nconst DEFS: DemoDef[] = [\n { id: 'chair', group: 'furniture', spec: chair, colors: { wood_soft: 0xa8703a } },\n { id: 'sofa', group: 'furniture', spec: sofa, colors: { frame: 0x6b4426, seat_cushion: 0x7d3b4c, back_cushion: 0x7d3b4c, arm_l: 0x6a2f40, arm_r: 0x6a2f40 } },\n { id: 'shelf', group: 'furniture', spec: shelf, colors: { back: 0xd9c9a3 }, movable: false },\n { id: 'old_tv', group: 'furniture', spec: oldTv, colors: { shell: 0x6d5a3e, stand: 0x8a5a30, screen: 0x4f6f68 } },\n { id: 'steel_sheet', group: 'structure', spec: steelSheet, movable: false, colors: { sheet: 0xb5bcc4 } },\n { id: 'glass_pane', group: 'structure', spec: glassPane, movable: false },\n { id: 'concrete_block', group: 'structure', spec: concreteBlock },\n { id: 'brick_column', group: 'structure', spec: brickColumn, movable: false },\n { id: 'building_frame', group: 'structure', spec: frame, movable: false, colors: { roof: 0x7d7d79 } },\n { id: 'car_door', group: 'vehicles', spec: carDoor, movable: false, colors: { skin: 0xc0392b, window: 0x9cd6e6 } },\n { id: 'small_tree', group: 'plants', spec: tree, movable: false },\n { id: 'potted_plant', group: 'plants', spec: pottedPlant, colors: { pot: 0xc4673a } },\n { id: 'coffee_cup', group: 'items', spec: cup, colors: { cup: 0xf3efe6 }, fluid: { container: { capacity: 0.6, liquid: 'coffee', liters: 0.25, temperature: 80, shape: { kind: 'cylinder', radius: 0.045, height: 0.1 }, opening: 0.045 }, part: 'cup', uses: ['drink', 'sip', 'pour'], offset: [0, 0.01, 0] } },\n {\n id: 'glass_bottle',\n group: 'items',\n spec: bottle,\n colors: { bottle_body: 0x7fd6b0, bottle_neck: 0x7fd6b0 },\n fluid: { container: { capacity: 0.5, liquid: 'water', liters: 0.5, temperature: 18, shape: { kind: 'cylinder', radius: 0.034, height: 0.14 }, opening: 0.012 }, part: 'bottle_body', uses: ['drink', 'sip', 'pour'], offset: [0, 0.015, 0] },\n },\n { id: 'wooden_crate', group: 'containers', spec: crate },\n { id: 'steel_drum', group: 'containers', spec: drum, colors: { drum_body: 0x2b5f9e, drum_top: 0x2b5f9e, drum_bottom: 0x2b5f9e } },\n { id: 'plastic_bucket', group: 'containers', spec: bucket, colors: { bucket_body: 0xd9482b, handle: 0x8a8a8a } },\n {\n id: 'jerrycan',\n group: 'containers',\n spec: jerrycan,\n colors: { tank: 0xc23b22, cap: 0xf2c230, handle: 0xc23b22 },\n fluid: { container: { capacity: 20, liquid: 'fuel', liters: 20, temperature: 20, shape: { kind: 'box', size: [0.33, 0.44, 0.13] }, opening: 0.025, closed: true }, part: 'tank', uses: ['pour', 'open', 'close'], offset: [0, 0.008, 0] },\n },\n { id: 'gas_bottle', group: 'containers', spec: gasBottle, colors: { cylinder: 0xd8d8d0, valve: 0x777777, foot_ring: 0x555555 } },\n]\n\n/**\n * The generic demo catalogue, names and groups translated for `locale` (`en` or `pt-BR`). Every item is a procedural low-poly build (one mesh per\n * destruction part, drawn by `buildFromSpec`) plus an explicit destruction spec. Containers carry a fluid container where it makes sense.\n */\nexport function demoItems(locale = 'en', extra: TestRoomItem[] = []): TestRoomItem[] {\n const s = resolveStrings(locale)\n const out: TestRoomItem[] = DEFS.map((d) => ({\n id: d.id,\n name: s.items[d.id] ?? d.id,\n group: s.groups[d.group] ?? d.group,\n build: (THREE: typeof THREE_NS) => buildFromSpec(THREE, d.spec(), { colors: d.colors }),\n spec: d.spec,\n movable: d.movable,\n fluid: d.fluid,\n }))\n return [...out, ...extra]\n}\n\n/** The demo catalogue in English (see `demoItems` for other locales). */\nexport const DEMO_ITEMS: TestRoomItem[] = demoItems('en')\n","import type * as THREE_NS from 'three'\nimport type { DestructibleSpec, PartSpec } from '@adatechnology/game-destruction'\n\n/** Default look of each built-in destruction material (`0xRRGGBB`). */\nexport const MATERIAL_COLORS: Record<string, number> = {\n steel: 0x8d949c,\n cast_iron: 0x4a4d52,\n aluminium: 0xc4c9ce,\n copper: 0xb8733a,\n wood_soft: 0xb9854f,\n wood_hard: 0x7a4a26,\n plywood: 0xc9a46a,\n mdf: 0xa88b64,\n glass: 0x9cd6e6,\n tempered_glass: 0x9cd6e6,\n ceramic: 0xe9e4da,\n concrete: 0x9a9a96,\n brick: 0xa5472e,\n plaster: 0xe6e1d4,\n stone: 0x77746f,\n plastic: 0x3b78c4,\n rubber: 0x1f1f22,\n fabric: 0x8a4b5e,\n foam: 0xe3c458,\n leather: 0x5b3a26,\n paper: 0xeeeadf,\n foliage: 0x3f8f3a,\n green_wood: 0x6b4a2b,\n cactus: 0x3e7d4a,\n flesh_fruit: 0xd24b32,\n wax: 0xefe2b5,\n soil: 0x4a3322,\n}\n\nexport interface BuildFromSpecOptions {\n /** Colour per part id, then per material id (falls back to `MATERIAL_COLORS`, then grey). */\n colors?: Record<string, number>\n /** Segments of cylinders and spheres (default 12: low poly on purpose). */\n segments?: number\n /** Cast and receive shadows (default true). */\n shadows?: boolean\n}\n\nconst TRANSPARENT: Record<string, number> = { glass: 0.38, tempered_glass: 0.38 }\n\n/**\n * Draw any `DestructibleSpec` as plain meshes: one mesh per part (box, cylinder or sphere) with `name` and `userData.destructionPart` set to the\n * part id and `userData.destructionMaterial` to its material, so `renderer.bind` and `specFromObject3D` find them. Useful for teams that describe\n * objects as specs and want something to look at while they tune them.\n */\nexport function buildFromSpec(THREE: typeof THREE_NS, spec: DestructibleSpec, options: BuildFromSpecOptions = {}): THREE_NS.Group {\n const root = new THREE.Group()\n root.name = spec.name ?? 'object'\n const seg = options.segments ?? 12\n const shadows = options.shadows !== false\n const mats = new Map<string, THREE_NS.Material>()\n const materialFor = (p: PartSpec): THREE_NS.Material => {\n const color = options.colors?.[p.id] ?? options.colors?.[p.material] ?? MATERIAL_COLORS[p.material] ?? 0x888888\n const key = `${p.material}:${color}`\n let m = mats.get(key)\n if (!m) {\n const alpha = TRANSPARENT[p.material]\n const metal = p.material === 'steel' || p.material === 'aluminium' || p.material === 'copper' || p.material === 'cast_iron'\n m = new THREE.MeshStandardMaterial({\n color,\n roughness: alpha ? 0.1 : metal ? 0.45 : 0.85,\n metalness: metal ? 0.7 : 0,\n transparent: !!alpha,\n opacity: alpha ?? 1,\n depthWrite: !alpha,\n })\n mats.set(key, m)\n }\n return m\n }\n for (const p of spec.parts) {\n let geo: THREE_NS.BufferGeometry\n const s = p.shape\n if (s.kind === 'box') geo = new THREE.BoxGeometry(s.size[0], s.size[1], s.size[2])\n else if (s.kind === 'cylinder') geo = new THREE.CylinderGeometry(s.radius, s.radius, s.height, seg)\n else geo = new THREE.SphereGeometry(s.radius, seg, Math.max(6, seg - 4))\n const mesh = new THREE.Mesh(geo, materialFor(p))\n mesh.name = p.id\n mesh.userData.destructionPart = p.id\n mesh.userData.destructionMaterial = p.material\n mesh.position.set(p.position[0], p.position[1], p.position[2])\n if (p.rotation) mesh.rotation.set(p.rotation[0], p.rotation[1], p.rotation[2], 'XYZ')\n mesh.castShadow = shadows && !TRANSPARENT[p.material]\n mesh.receiveShadow = shadows\n root.add(mesh)\n }\n return root\n}\n","/** Locales shipped with the package. Unknown locales fall back to `en`. */\nexport type TestRoomLocale = 'en' | 'pt-BR'\n\nexport interface RoomStrings {\n /** Display name per demo item id (see `DEMO_ITEMS`). */\n items: Record<string, string>\n /** Display name per demo catalogue group. */\n groups: Record<string, string>\n /** Every other text: UI, log lines, scenario names and checks. `{name}` placeholders are replaced. */\n text: Record<string, string>\n}\n\nconst en: RoomStrings = {\n items: {\n chair: 'Wooden chair',\n sofa: 'Sofa',\n shelf: 'Shelf with boards',\n old_tv: 'Old TV',\n steel_sheet: 'Steel sheet on a stand',\n glass_pane: 'Glass pane',\n concrete_block: 'Concrete block',\n brick_column: 'Brick column',\n building_frame: 'Building frame',\n car_door: 'Car door',\n small_tree: 'Small tree',\n potted_plant: 'Potted plant',\n coffee_cup: 'Cup of coffee',\n glass_bottle: 'Glass bottle',\n wooden_crate: 'Wooden crate',\n steel_drum: 'Steel drum',\n plastic_bucket: 'Plastic bucket',\n jerrycan: 'Jerrycan',\n gas_bottle: 'Gas bottle',\n },\n groups: { furniture: 'Furniture', structure: 'Structure', vehicles: 'Vehicles', plants: 'Plants', items: 'Items', containers: 'Containers' },\n text: {\n 'locale.decimal': '.',\n yes: 'yes',\n no: 'no',\n piece: 'piece',\n coords: 'x {x} · z {z}',\n 'count.piece.one': '1 piece',\n 'count.piece.other': '{n} pieces',\n 'count.joint.one': '1 joint',\n 'count.joint.other': '{n} joints',\n 'count.dent.one': '1 dent',\n 'count.dent.other': '{n} dents',\n 'count.hole.one': '1 hole',\n 'count.hole.other': '{n} holes',\n 'count.crack.one': '1 crack',\n 'count.crack.other': '{n} cracks',\n 'joint.generic': 'joint',\n 'lost.broken': 'broke',\n 'lost.melted': 'melted away',\n 'lost.ashes': 'burned to ash',\n 'tool.none': 'by hand only',\n 'arena.target_wall': 'Target wall',\n 'arena.table': 'Table',\n 'arena.shelf': 'Shelf',\n 'surface.floor': 'on the floor',\n 'surface.ground': 'on the floor',\n 'surface.table': 'on the table',\n 'by.break': 'broken loose',\n 'by.tool': 'undone with a tool',\n 'by.part_lost': 'the part next to it was lost',\n 'dmg.ballistic': 'ballistic',\n 'dmg.blunt': 'blunt',\n 'dmg.slash': 'slash',\n 'dmg.explosive': 'blast',\n 'dmg.fire': 'fire',\n 'dmg.heat': 'heat',\n 'effect.caffeine': 'caffeine',\n 'effect.alcohol': 'alcohol',\n 'effect.poison': 'poison',\n 'effect.disgust': 'disgust',\n\n 'ev.dent': '{where}: dent of {mm} mm, {hp}',\n 'ev.hole.through': '{where}: {mm} mm hole went through, {hp}',\n 'ev.hole.stuck': '{where}: {mm} mm hole, did not go through, {hp}',\n 'ev.dents': '{where}: {n} dents, deepest {mm} mm, {hp}',\n 'ev.holes': '{where}: {n} holes of {mm} mm, {thr} went through, {hp}',\n 'ev.leak.tail': ', leaking {liquid} at {rate} l/s',\n 'ev.leak.alone': '{where}: leaking {liquid} at {rate} l/s',\n 'ev.crack': '{where}: cracked, {rays} rays up to {cm} cm, {hp}',\n 'ev.ricochet': '{where}: bullet ricocheted, {energy} J left',\n 'ev.fracture.shatter': '{where}: shattered into {n} shards',\n 'ev.fracture.crumble': '{where}: crumbled into {n} chunks',\n 'ev.fracture.splinter': '{where}: splintered into {n} pieces',\n 'ev.fracture.tear': '{where}: torn into {n} scraps',\n 'ev.fracture.snap': '{where}: snapped into {n} pieces',\n 'ev.fracture.none': '{where}: broke into {n} pieces',\n 'ev.detach': '{obj}: {a} came off {b} ({by}); the object now has {pieces}',\n 'ev.detach.many.break': '{obj}: {joints} broke loose; the object now has {pieces}',\n 'ev.detach.many.tool': '{obj}: {joints} undone with a tool; the object now has {pieces}',\n 'ev.lost.tail': ' and came loose from {joints}; the object now has {pieces}',\n 'ev.lost.alone': '{where}: {verb} and came loose from {joints}; the object now has {pieces}',\n 'ev.cracks': '{where}: cracking under the load, {n} cracks so far, longest {cm} cm, {hp}',\n 'ev.disassemble': '{obj}: undoing the {kind} between {a} and {b} with {tool}: {pct}%',\n 'ev.ignite': '{where}: caught fire at {temp} °C',\n 'ev.ignite.many': '{obj}: {n} parts caught fire at {temp} °C ({parts})',\n 'ev.extinguish': '{where}: fire put out',\n 'ev.extinguish.many': '{obj}: fire put out on {n} parts ({parts})',\n 'ev.burnout': '{where}: burned to ash',\n 'ev.melt': '{where}: melting, {pct}% melted away',\n 'ev.drip': '{where}: dripping molten material',\n 'ev.explode': '{where}: exploded, {energy} J within {radius} m',\n 'ev.destroyed': '{obj}: destroyed',\n 'ev.damage': '{where}: {type} damage {amount}, {hp}',\n 'ev.damage.overload': '{where}: crushed by the weight it carries, lost {amount} hp so far, {hp}',\n 'ev.stress': '{where}: overloaded at {stress}% of its capacity, carrying {load} kg',\n 'ev.collapse': '{obj}: collapsed, {pieces} fell ({mass} kg): {parts}',\n 'ev.stain_ignite': 'The {liquid} stain at x {x} · z {z} caught fire and will burn for about {seconds} s',\n 'ev.stain_burned': 'The burning stain burned itself out',\n 'ev.fire_dries': 'Fire dried the wet stains nearby',\n\n 'fl.fill': '{who}: filled with {liquid} (+{liters} l)',\n 'fl.pour': '{who}: pouring {liquid} at {rate} l/s',\n 'fl.spill': '{who}: spilled {liquid} over the lip at {rate} l/s',\n 'fl.leak': '{who}: leaking {liquid} at {rate} l/s',\n 'fl.drink': '{who}: drank {liters} l, thirst +{thirst}',\n 'fl.burn': 'too hot: burned the mouth',\n 'fl.empty': '{who}: empty',\n 'fl.splash': 'Splash of {liquid}',\n 'fl.stain': 'Stain of {liquid} {surface} at {where}',\n 'fl.stains': '{n} stains of {liquid} {surface}, the latest at {where}',\n 'fl.dried': 'A stain dried up',\n 'fl.dried.mark': 'A stain dried and left a mark',\n 'fl.dried.known': 'The {liquid} stain {surface} at {where} dried up',\n 'fl.dried.known.mark': 'The {liquid} stain {surface} at {where} dried and left a mark',\n 'fl.dried.many': '{n} {liquid} stains dried up',\n 'fl.dried.many.mark': '{n} {liquid} stains dried and left marks',\n 'fl.mix': '{who}: {from} mixed into {into}',\n\n 'act.anim_start': '{name}: animation \"{clip}\" ({seconds} s)',\n 'act.anim_event': '{name}: \"{clip}\" event {type}',\n 'act.anim_end': '{name}: animation \"{clip}\" finished',\n 'act.module_loaded': 'Module \"{name}\" loaded: {items} item(s), {scenarios} scenario(s), contract checks: {result}',\n 'mod.all_ok': 'all passed',\n 'mod.some_failed': 'some FAILED',\n 'mod.destructible_ok': '{name}: destructible contract ok ({parts} parts, hit and state well-formed)',\n 'mod.destructible_fail': '{name}: destructible contract broken: {problems}',\n 'mod.animation_ok': '{name}: animation \"{clip}\" ok ({seconds} s)',\n 'mod.spec_ok': '{name}: spec ok ({parts} parts)',\n 'mod.spec_fail': '{name}: spec broken: {problems}',\n 'mod.spec_warn': '{name}: spec warning: {warning}',\n 'mod.animation_fail': '{name}: animation \"{clip}\" broken: {problems}',\n 'ui.animations': 'Animations',\n 'ui.animations_aim': 'Aim at an item or hold it to see its animations.',\n 'ui.animations_none': 'This item brings no animations.',\n 'mod.bench_ok': '{name}: bench ok ({controls} controls, {layers} layers, {metrics} metrics)',\n 'mod.bench_fail': '{name}: bench broken: {problems}',\n 'mod.metric_failed': '{name}: metric \"{metric}\" threw and shows n/a: {error}',\n 'mod.listener_failed': '{name}: a bench listener threw: {error}',\n 'ui.bench': 'Bench',\n 'ui.layers': 'Layers',\n 'ui.metrics': 'Counters',\n 'metric.fps': 'FPS',\n 'metric.frame_ms': 'ms/frame',\n 'metric.draw_calls': 'Draw calls',\n 'metric.triangles': 'Triangles',\n 'metric.objects': 'Objects',\n 'metric.fragments': 'Fragments',\n 'metric.particles': 'Particles',\n 'metric.decals': 'Decals',\n 'act.spawn': 'Spawned {name} at x {x} · z {z}',\n 'act.clear': 'Cleared the room',\n 'act.reset': 'Repaired every object',\n 'act.tool': 'Equipped {weapon}',\n 'act.shoot.hit': '{weapon}: shot, {energy} J, hit {where} at {dist} m',\n 'act.shoot.miss': '{weapon}: shot, {energy} J, hit nothing',\n 'act.shoot.pellets': '{weapon}: shot, {n} projectiles of up to {energy} J, {hits} hit {where} at {dist} m',\n 'act.melee.hit': '{weapon}: strike, {energy} J, hit {where} at {dist} m',\n 'act.melee.miss': '{weapon}: struck the air',\n 'act.flame.hit': '{weapon}: flame at {temp} °C on {where}',\n 'act.flame.air': '{weapon}: flame, nothing in range',\n 'act.heat.hit': '{weapon}: heating {where} at {temp} °C',\n 'act.heat.air': '{weapon}: nothing in range',\n 'act.throw.grenade': '{weapon}: thrown, fuse {fuse} s',\n 'act.throw.molotov': '{weapon}: thrown, breaks on impact',\n 'act.launch': '{weapon}: launched, arms after {arm} m',\n 'act.place': '{weapon}: charge set down, waits for {triggers}',\n 'act.tripwire': '{weapon}: {who} crossed the trip wire',\n 'act.dud': '{weapon}: hit before arming ({distance} m), did not explode',\n 'act.backblast': '{weapon}: blast behind the tube, {radius} m, {n} objects in the cone, {player} on the shooter',\n 'act.blast_player': '{weapon}: you are in the {zone} zone, {distance} m away (stun {stun} s)',\n 'hud.no_charges': 'No charge set down waits for the remote detonator',\n 'blast.zone.lethal': 'lethal',\n 'blast.zone.injury': 'injury',\n 'act.explode': '{weapon}: exploded, {energy} J within {radius} m, {n} objects in range',\n 'act.molotov_fire': '{weapon}: fire on the ground, radius {radius} m for {seconds} s',\n 'act.tool.none': '{weapon}: nothing in reach',\n 'act.tool.nojoint': '{weapon}: no joint near {where}',\n 'act.tool.refused': '{weapon} cannot undo the {kind} of {obj}; it needs: {need}',\n 'act.extinguish.hit': '{weapon}: foam on {what}',\n 'act.extinguish.air': '{weapon}: foam, nothing in range',\n 'act.grab': 'Grabbed {name} ({kg} kg)',\n 'act.drop': 'Dropped {name}',\n 'act.throw': 'Threw {name} at {speed} m/s',\n 'act.landing': '{name} landed at {speed} m/s: {energy} J',\n 'act.impact': '{name} hit {where} at {speed} m/s: {energy} J of blunt damage',\n 'act.use_item': '{name}: {use}',\n 'act.tap.on': 'Tap opened',\n 'act.tap.off': 'Tap closed',\n\n 'use.drink': 'drink',\n 'use.sip': 'sip',\n 'use.chug': 'chug',\n 'use.pour': 'pour',\n 'use.pour_out': 'pour out',\n 'use.open': 'open',\n 'use.close': 'close',\n\n 'hud.reloading': 'Reloading...',\n 'hud.empty': 'Empty',\n 'hud.no_fuel': 'Out of fuel',\n 'hud.fault': 'Jammed ({fault}): press X to clear',\n 'hud.safe': 'Safety on: press B',\n 'hud.clearing': 'Clearing the jam...',\n 'hud.safety_on': 'Safety on',\n 'hud.safety_off': 'Safety off',\n 'fault.misfire': 'misfire',\n 'fault.stovepipe': 'stovepipe',\n 'fault.double_feed': 'double feed',\n 'fault.failure_to_extract': 'failure to extract',\n 'hud.nothing_to_grab': 'Nothing to grab here',\n 'hud.cannot_grab': '{name} cannot be picked up',\n 'hud.too_heavy': '{name} is too heavy ({kg} kg)',\n 'hud.empty_container': '{name} is empty',\n 'hud.refused': 'Wrong tool for the {kind}',\n 'hud.drop': 'drop',\n 'hud.rotate': 'rotate',\n 'hud.throw': 'throw',\n 'hud.tilt': 'tilt (hold)',\n 'hud.equip': 'equip {weapon}',\n\n 'ui.help': 'Click: look · WASD: walk · Shift: run · Space: jump · 1-0 / wheel: tool · LMB: use · E: grab/drop · G or RMB: throw · R: reload · Q: fire mode · X: clear a jam · B: safety · Y: detonate charges set down · Tab: panels · Esc: free the mouse',\n 'ui.log': 'Behaviour log',\n 'ui.filter.action': 'actions',\n 'ui.filter.event': 'events',\n 'ui.filter.check': 'checks',\n 'ui.autoscroll': 'autoscroll',\n 'log.export_cancelled': 'export cancelled',\n 'ui.copy_json': 'Copy JSON',\n 'ui.download_ndjson': 'Download NDJSON',\n 'ui.download_txt': 'Download TXT',\n 'ui.clear_log': 'Clear',\n 'ui.catalog': 'Catalogue',\n 'ui.clear': 'Clear',\n 'ui.reset_all': 'Reset all',\n 'ui.slow': 'Slow motion 0.25×',\n 'ui.fast': 'Time ×10',\n 'ui.tap': 'Tap',\n 'ui.blast.shelter': 'Shelter',\n 'ui.blast.fragmentHits': 'Fragments',\n 'ui.blast.confinement': 'Confinement',\n 'ui.blast.shelter.hint': 'Blasts: walls and other parts between the blast and the target take their share',\n 'ui.blast.fragmentHits.hint': 'Blasts: the pieces of what breaks fly on and hit what is behind',\n 'ui.blast.confinement.hint': 'Blasts: pressure builds up in an enclosed room',\n 'metric.blast_shelter': 'Blast reaching (%)',\n 'metric.blast_confinement': 'Blast pressure (x)',\n 'metric.blast_fragments': 'Fragment hits',\n 'act.blast_report': 'Blast: {shelter}% reached the most sheltered target, pressure x{confinement}, {fragments} fragment hits, {n} targets',\n 'ui.quality': 'Quality',\n 'ui.quality.low': 'low',\n 'ui.quality.medium': 'medium',\n 'ui.quality.high': 'high',\n 'ui.equip': 'Equip as a tool',\n 'ui.search_items': 'Search items (all groups)',\n 'ui.search_tests': 'Search tests',\n 'ui.no_results': 'Nothing found',\n 'ui.objects': '{n} objects',\n 'ui.tests': 'Tests',\n 'ui.run_all': 'Run all',\n 'ui.running': 'Running...',\n 'ui.report': '{passed} passed, {failed} failed',\n 'ui.panel': 'Panels',\n 'ui.inspector': 'Inspector',\n 'ui.aim_at_something': 'Aim at an object',\n 'ins.material': 'Material',\n 'ins.status': 'Status',\n 'ins.burning': 'burning',\n 'ins.hp': 'Hit points',\n 'ins.temperature': 'Temperature',\n 'ins.char': 'Charred',\n 'ins.melt': 'Melted',\n 'ins.liters': 'Liquid',\n 'ins.damage': 'Marks',\n 'ins.damage_counts': '{dents}, {holes}, {cracks}',\n 'ins.mass': 'Mass',\n 'ins.load': 'Load',\n 'ins.stress': 'Stress',\n 'ins.joints': 'Joints',\n 'ins.open': 'open',\n\n 'sc.start': 'Scenario: {name}',\n 'sc.pass': 'Scenario passed: {name}',\n 'sc.fail': 'Scenario FAILED: {name}',\n 'sc.error': 'the scenario threw an error: {msg}',\n 'leg.still': 'leg_1 still attached',\n 'leg.gone': 'leg_1 came off',\n\n 'sc.steel_through_hole': '9 mm into a steel sheet makes a through hole',\n 'sc.steel_through_hole.check': '9 mm into 3 mm steel: {holes} hole(s) of {mm} mm, went through: {through}, sheet {hp} hp (expected: through)',\n 'sc.concrete_stops_bullet': '9 mm into a concrete block does not go through',\n 'sc.concrete_stops_bullet.check': '9 mm into 40 cm of concrete: went through: {through}, {dents}, {holes}, {cracks}, block {hp} hp (expected: stopped, wall behind untouched)',\n 'sc.hammer_dents_drum': 'Hammer dents a steel drum',\n 'sc.hammer_dents_drum.check': 'Hammer on the drum: {swings} swing(s), {dents} dent(s), first {depth} mm deep, body {hp} hp (expected: dented, not broken)',\n 'sc.glass_shatters': 'Glass pane shatters on the first 9 mm shot',\n 'sc.glass_shatters.check': 'Glass pane: broken after {shots} shot(s) into {n} shards (expected: broken on the first shot, at least 4 shards)',\n 'sc.shotgun_splinters_crate': 'Shotgun splinters a wooden crate',\n 'sc.shotgun_splinters_crate.check': '12 ga on the crate: {shots} shot(s), {splinters} board(s) splintered, {holes} holes (expected: at least one splintered)',\n 'sc.kick_chair_leg': 'A kick takes a chair leg off',\n 'sc.kick_chair_leg.check': 'Chair: {kicks} kick(s), {groups} group(s), loose pieces {before} → {after}, {leg} (expected: a loose piece appears)',\n 'sc.kick_detaches_leg_via_tool': 'The kick tool (hotbar) takes a chair leg off',\n 'sc.kick_detaches_leg_via_tool.check': 'Chair, kick tool: {kicks} kick(s), loose pieces {before} → {after}, {leg} (expected: a loose piece appears)',\n 'sc.screwdriver_shelf_board': 'Screwdriver takes a screwed shelf board off in about 2.5 s',\n 'sc.screwdriver_shelf_board.check': 'Screwdriver on the shelf board: took {secs} s, expected about {want} s, the shelf is now in {pieces}',\n 'sc.wrong_tool_refused': 'The wrong tool is refused',\n 'sc.wrong_tool_refused.check': 'Screwdriver on a weld: refused {refused} time(s), joints opened {opened} (expected: refused, none opened)',\n 'sc.lighter_burns_crate': 'A lighter ignites a wooden crate and it ends as ash',\n 'sc.lighter_burns_crate.lit': 'Lighter on the crate: burning: {lit} (expected: yes)',\n 'sc.lighter_burns_crate.ash': 'After burning for 500 s: {ash} of {total} boards are ash, most charred {char}% (expected: all ash or charred)',\n 'sc.torch_melts_steel': 'Wood fire does not melt a steel drum, the cutting torch does',\n 'sc.torch_melts_steel.wood': 'Burning crate next to the drum: drum peaked at {peak} °C, melted {melt}%, crate still burning: {crate} (expected: no melt)',\n 'sc.torch_melts_steel.torch': 'Cutting torch on the drum: {temp} °C, melted {melt}% (expected: melting)',\n 'sc.bucket_melts_drips': 'A plastic bucket melts and drips near fire',\n 'sc.bucket_melts_drips.check': 'Bucket in flames: melted {melt}%, {temp} °C, {drips} drip line(s) (expected: melting)',\n 'sc.gas_bottle_explodes': 'A gas bottle in a fire explodes and pushes a crate',\n 'sc.gas_bottle_explodes.explode': 'Gas bottle in fire: exploded after {seconds} s (expected: explodes)',\n 'sc.gas_bottle_explodes.push': 'Crate 1.3 m away: moved {moved} m, lost {lost} (expected: pushed or broken)',\n 'sc.bottle_drop_shatters': 'A glass bottle dropped from 1.5 m shatters',\n 'sc.bottle_drop_shatters.check': 'Bottle dropped from 1.5 m: status {status}, {cracks} cracks, water stain: {stain} (expected: broken, water on the floor)',\n 'sc.throw_chair_at_wall': 'A chair thrown at the wall deals blunt damage',\n 'sc.throw_chair_at_wall.check': 'Chair thrown at the wall: {impacts} impact(s), first {energy} J, {wall} damage line(s) on the wall (expected: impact and damage)',\n 'sc.coffee_three_sips': 'Three sips of coffee lower the level and log caffeine',\n 'sc.coffee_three_sips.check': 'Coffee: {sips} sip(s), level {before} → {after} l, caffeine logged: {caffeine}, burned the mouth: {burn} (expected: 3 sips, caffeine)',\n 'sc.tilt_cup_spills': 'Tilting the cup spills coffee and leaves a stain',\n 'sc.tilt_cup_spills.check': 'Cup tilted: level {before} → {after} l, {stains} coffee stain(s) (expected: spilled with a stain)',\n 'sc.jerrycan_leaks_fuel': 'Shooting the jerrycan makes a leak and a fuel stain',\n 'sc.jerrycan_leaks_fuel.check': 'Jerrycan shot: {streams} leak stream(s), fuel stain: {stain}, {left} l left of 20, hole line mentions the leak: {leak} (expected: leaking, stain)',\n 'sc.fuel_stain_burns': 'A lit fuel stain burns',\n 'sc.fuel_stain_burns.stain': 'Fuel stain on the floor after the leak: {stain} (expected: yes)',\n 'sc.fuel_stain_burns.ignite': 'Lighter on the stain: {ignited} ignition(s), fire reached nearby objects: {near} (expected: ignited)',\n 'sc.fuel_stain_burns.out': 'After 30 s the stain burned out: {burned} (expected: yes)',\n 'roof.standing': 'roof standing',\n 'roof.fell': 'roof fell',\n 'sc.one_column_roof_stands': 'One column destroyed: the roof stays up',\n 'sc.one_column_roof_stands.check': 'Frame with one column gone: {roof}, heaviest collapse {heavy} kg, peak stress {stress}% (expected: standing, no big collapse)',\n 'sc.two_columns_roof_collapses': 'Two columns destroyed: the roof collapses',\n 'sc.two_columns_roof_collapses.check': 'Frame with two columns gone: the others at {stress}% right away, then heavy loose pieces: {pieces} ({kg} kg), collapse event logged: {logged} (expected: the roof comes down)',\n 'sc.extinguisher_puts_out_fire': 'The extinguisher puts out a burning crate',\n 'sc.extinguisher_puts_out_fire.burning': 'Crate set on fire: burning: {burning} (expected: yes)',\n 'sc.extinguisher_puts_out_fire.out': 'After the extinguisher: still burning: {burning}, {events} extinguish event(s) (expected: out)',\n },\n}\n\nconst ptBR: RoomStrings = {\n items: {\n chair: 'Cadeira de madeira',\n sofa: 'Sofá',\n shelf: 'Estante com prateleiras',\n old_tv: 'TV antiga',\n steel_sheet: 'Chapa de aço com suporte',\n glass_pane: 'Vidro de janela',\n concrete_block: 'Bloco de concreto',\n brick_column: 'Coluna de tijolos',\n building_frame: 'Estrutura de prédio',\n car_door: 'Porta de carro',\n small_tree: 'Árvore pequena',\n potted_plant: 'Vaso de planta',\n coffee_cup: 'Copo de café',\n glass_bottle: 'Garrafa de vidro',\n wooden_crate: 'Caixote de madeira',\n steel_drum: 'Tambor de aço',\n plastic_bucket: 'Balde de plástico',\n jerrycan: 'Galão',\n gas_bottle: 'Botijão de gás',\n },\n groups: { furniture: 'Móveis', structure: 'Estrutura', vehicles: 'Veículos', plants: 'Plantas', items: 'Itens', containers: 'Recipientes' },\n text: {\n 'locale.decimal': ',',\n yes: 'sim',\n no: 'não',\n piece: 'peça',\n coords: 'x {x} · z {z}',\n 'count.piece.one': '1 peça',\n 'count.piece.other': '{n} peças',\n 'count.joint.one': '1 encaixe',\n 'count.joint.other': '{n} encaixes',\n 'count.dent.one': '1 amassado',\n 'count.dent.other': '{n} amassados',\n 'count.hole.one': '1 furo',\n 'count.hole.other': '{n} furos',\n 'count.crack.one': '1 trinca',\n 'count.crack.other': '{n} trincas',\n 'joint.generic': 'junta',\n 'lost.broken': 'quebrou',\n 'lost.melted': 'derreteu',\n 'lost.ashes': 'virou cinza',\n 'tool.none': 'só com a mão',\n 'arena.target_wall': 'Parede de alvo',\n 'arena.table': 'Mesa',\n 'arena.shelf': 'Estante',\n 'surface.floor': 'no chão',\n 'surface.ground': 'no chão',\n 'surface.table': 'na mesa',\n 'by.break': 'arrebentou',\n 'by.tool': 'desmontado com ferramenta',\n 'by.part_lost': 'a peça ao lado se perdeu',\n 'dmg.ballistic': 'de tiro',\n 'dmg.blunt': 'de impacto',\n 'dmg.slash': 'de corte',\n 'dmg.explosive': 'de explosão',\n 'dmg.fire': 'de fogo',\n 'dmg.heat': 'de calor',\n 'effect.caffeine': 'cafeína',\n 'effect.alcohol': 'álcool',\n 'effect.poison': 'veneno',\n 'effect.disgust': 'nojo',\n\n 'ev.dent': '{where}: amassado de {mm} mm, {hp}',\n 'ev.hole.through': '{where}: furo de {mm} mm atravessou, {hp}',\n 'ev.hole.stuck': '{where}: furo de {mm} mm não atravessou, {hp}',\n 'ev.dents': '{where}: {n} amassados, o mais fundo com {mm} mm, {hp}',\n 'ev.holes': '{where}: {n} furos de {mm} mm, {thr} atravessaram, {hp}',\n 'ev.leak.tail': ', vazando {liquid} a {rate} l/s',\n 'ev.leak.alone': '{where}: vazando {liquid} a {rate} l/s',\n 'ev.crack': '{where}: trincou, {rays} raios de até {cm} cm, {hp}',\n 'ev.ricochet': '{where}: a bala ricocheteou, sobraram {energy} J',\n 'ev.fracture.shatter': '{where}: estilhaçou em {n} cacos',\n 'ev.fracture.crumble': '{where}: esfarelou em {n} pedaços',\n 'ev.fracture.splinter': '{where}: lascou em {n} pedaços',\n 'ev.fracture.tear': '{where}: rasgou em {n} retalhos',\n 'ev.fracture.snap': '{where}: partiu em {n} pedaços',\n 'ev.fracture.none': '{where}: quebrou em {n} pedaços',\n 'ev.detach': '{obj}: {a} soltou de {b} ({by}); o objeto agora tem {pieces}',\n 'ev.detach.many.break': '{obj}: {joints} arrebentaram; o objeto agora tem {pieces}',\n 'ev.detach.many.tool': '{obj}: {joints} soltos com ferramenta; o objeto agora tem {pieces}',\n 'ev.lost.tail': ' e se soltou de {joints}; o objeto agora tem {pieces}',\n 'ev.lost.alone': '{where}: {verb} e se soltou de {joints}; o objeto agora tem {pieces}',\n 'ev.cracks': '{where}: rachando sob o peso, {n} trincas até agora, a maior com {cm} cm, {hp}',\n 'ev.disassemble': '{obj}: soltando {kind} entre {a} e {b} com {tool}: {pct}%',\n 'ev.ignite': '{where}: pegou fogo a {temp} °C',\n 'ev.ignite.many': '{obj}: {n} peças pegaram fogo a {temp} °C ({parts})',\n 'ev.extinguish': '{where}: fogo apagado',\n 'ev.extinguish.many': '{obj}: fogo apagado em {n} peças ({parts})',\n 'ev.burnout': '{where}: virou cinza',\n 'ev.melt': '{where}: derretendo, {pct}% já derreteu',\n 'ev.drip': '{where}: pingando material derretido',\n 'ev.explode': '{where}: explodiu, {energy} J em {radius} m',\n 'ev.destroyed': '{obj}: destruído',\n 'ev.damage': '{where}: dano {type} de {amount}, {hp}',\n 'ev.damage.overload': '{where}: esmagado pelo peso que sustenta, perdeu {amount} hp até agora, {hp}',\n 'ev.stress': '{where}: sobrecarregado a {stress}% da capacidade, sustentando {load} kg',\n 'ev.collapse': '{obj}: desabou, caíram {pieces} ({mass} kg): {parts}',\n 'ev.stain_ignite': 'A mancha de {liquid} em x {x} · z {z} pegou fogo e vai queimar por uns {seconds} s',\n 'ev.stain_burned': 'A mancha em chamas se consumiu',\n 'ev.fire_dries': 'O fogo secou as manchas molhadas por perto',\n\n 'fl.fill': '{who}: encheu de {liquid} (+{liters} l)',\n 'fl.pour': '{who}: despejando {liquid} a {rate} l/s',\n 'fl.spill': '{who}: derramou {liquid} pela borda a {rate} l/s',\n 'fl.leak': '{who}: vazando {liquid} a {rate} l/s',\n 'fl.drink': '{who}: bebeu {liters} l, sede +{thirst}',\n 'fl.burn': 'quente demais: queimou a boca',\n 'fl.empty': '{who}: vazio',\n 'fl.splash': 'Respingo de {liquid}',\n 'fl.stain': 'Mancha de {liquid} {surface} em {where}',\n 'fl.stains': '{n} manchas de {liquid} {surface}, a última em {where}',\n 'fl.dried': 'Uma mancha secou',\n 'fl.dried.mark': 'Uma mancha secou e deixou marca',\n 'fl.dried.known': 'A mancha de {liquid} {surface} em {where} secou',\n 'fl.dried.known.mark': 'A mancha de {liquid} {surface} em {where} secou e deixou marca',\n 'fl.dried.many': '{n} manchas de {liquid} secaram',\n 'fl.dried.many.mark': '{n} manchas de {liquid} secaram e deixaram marca',\n 'fl.mix': '{who}: {from} misturou em {into}',\n\n 'act.anim_start': '{name}: animação \"{clip}\" ({seconds} s)',\n 'act.anim_event': '{name}: \"{clip}\" evento {type}',\n 'act.anim_end': '{name}: animação \"{clip}\" terminou',\n 'act.module_loaded': 'Módulo \"{name}\" carregado: {items} item(ns), {scenarios} cenário(s), verificações do contrato: {result}',\n 'mod.all_ok': 'todas passaram',\n 'mod.some_failed': 'algumas FALHARAM',\n 'mod.destructible_ok': '{name}: contrato de destruição ok ({parts} peças, golpe e estado bem formados)',\n 'mod.destructible_fail': '{name}: contrato de destruição quebrado: {problems}',\n 'mod.animation_ok': '{name}: animação \"{clip}\" ok ({seconds} s)',\n 'mod.spec_ok': '{name}: spec ok ({parts} peças)',\n 'mod.spec_fail': '{name}: spec quebrada: {problems}',\n 'mod.spec_warn': '{name}: aviso na spec: {warning}',\n 'mod.animation_fail': '{name}: animação \"{clip}\" quebrada: {problems}',\n 'ui.animations': 'Animações',\n 'ui.animations_aim': 'Mire num item ou segure-o para ver as animações.',\n 'ui.animations_none': 'Este item não traz animações.',\n 'mod.bench_ok': '{name}: bancada ok ({controls} controles, {layers} camadas, {metrics} contadores)',\n 'mod.bench_fail': '{name}: bancada quebrada: {problems}',\n 'mod.metric_failed': '{name}: o contador \"{metric}\" lançou erro e mostra n/a: {error}',\n 'mod.listener_failed': '{name}: um ouvinte da bancada lançou erro: {error}',\n 'ui.bench': 'Bancada',\n 'ui.layers': 'Camadas',\n 'ui.metrics': 'Contadores',\n 'metric.fps': 'FPS',\n 'metric.frame_ms': 'ms/quadro',\n 'metric.draw_calls': 'Chamadas de desenho',\n 'metric.triangles': 'Triângulos',\n 'metric.objects': 'Objetos',\n 'metric.fragments': 'Fragmentos',\n 'metric.particles': 'Partículas',\n 'metric.decals': 'Decalques',\n 'act.spawn': 'Criou {name} em x {x} · z {z}',\n 'act.clear': 'Limpou a sala',\n 'act.reset': 'Consertou todos os objetos',\n 'act.tool': 'Equipou {weapon}',\n 'act.shoot.hit': '{weapon}: disparo, {energy} J, acertou {where} a {dist} m',\n 'act.shoot.miss': '{weapon}: disparo, {energy} J, não acertou nada',\n 'act.shoot.pellets': '{weapon}: disparo, {n} projéteis de até {energy} J, {hits} acertaram {where} a {dist} m',\n 'act.melee.hit': '{weapon}: golpe, {energy} J, acertou {where} a {dist} m',\n 'act.melee.miss': '{weapon}: golpe no ar',\n 'act.flame.hit': '{weapon}: chama a {temp} °C em {where}',\n 'act.flame.air': '{weapon}: chama, nada ao alcance',\n 'act.heat.hit': '{weapon}: esquentando {where} a {temp} °C',\n 'act.heat.air': '{weapon}: nada ao alcance',\n 'act.throw.grenade': '{weapon}: arremessada, pavio de {fuse} s',\n 'act.throw.molotov': '{weapon}: arremessado, quebra no impacto',\n 'act.launch': '{weapon}: disparado, arma depois de {arm} m',\n 'act.place': '{weapon}: carga posta, espera {triggers}',\n 'act.tripwire': '{weapon}: {who} cruzou o fio',\n 'act.dud': '{weapon}: bateu antes de armar ({distance} m), não explodiu',\n 'act.backblast': '{weapon}: sopro atrás do tubo, {radius} m, {n} objetos no cone, {player} no atirador',\n 'act.blast_player': '{weapon}: você está na zona {zone}, a {distance} m (atordoado {stun} s)',\n 'hud.no_charges': 'Nenhuma carga posta espera o detonador',\n 'blast.zone.lethal': 'letal',\n 'blast.zone.injury': 'de ferimento',\n 'act.explode': '{weapon}: explodiu, {energy} J em {radius} m, {n} objetos ao alcance',\n 'act.molotov_fire': '{weapon}: fogo no chão, raio de {radius} m por {seconds} s',\n 'act.tool.none': '{weapon}: nada ao alcance',\n 'act.tool.nojoint': '{weapon}: nenhuma junta perto de {where}',\n 'act.tool.refused': '{weapon} não solta {kind} de {obj}; precisa de: {need}',\n 'act.extinguish.hit': '{weapon}: espuma em {what}',\n 'act.extinguish.air': '{weapon}: espuma, nada ao alcance',\n 'act.grab': 'Pegou {name} ({kg} kg)',\n 'act.drop': 'Soltou {name}',\n 'act.throw': 'Arremessou {name} a {speed} m/s',\n 'act.landing': '{name} caiu a {speed} m/s: {energy} J',\n 'act.impact': '{name} bateu em {where} a {speed} m/s: {energy} J de dano de impacto',\n 'act.use_item': '{name}: {use}',\n 'act.tap.on': 'Abriu a torneira',\n 'act.tap.off': 'Fechou a torneira',\n\n 'use.drink': 'beber',\n 'use.sip': 'golinho',\n 'use.chug': 'virar',\n 'use.pour': 'despejar',\n 'use.pour_out': 'esvaziar',\n 'use.open': 'abrir',\n 'use.close': 'fechar',\n\n 'hud.reloading': 'Recarregando...',\n 'hud.empty': 'Sem munição',\n 'hud.no_fuel': 'Sem combustível',\n 'hud.fault': 'Travou ({fault}): aperte X para destravar',\n 'hud.safe': 'Trava ligada: aperte B',\n 'hud.clearing': 'Destravando...',\n 'hud.safety_on': 'Trava ligada',\n 'hud.safety_off': 'Trava desligada',\n 'fault.misfire': 'nega',\n 'fault.stovepipe': 'chaminé',\n 'fault.double_feed': 'dupla alimentação',\n 'fault.failure_to_extract': 'falha de extração',\n 'hud.nothing_to_grab': 'Nada para pegar aqui',\n 'hud.cannot_grab': '{name} não dá para pegar',\n 'hud.too_heavy': '{name} é pesado demais ({kg} kg)',\n 'hud.empty_container': '{name} está vazio',\n 'hud.refused': 'Ferramenta errada para {kind}',\n 'hud.drop': 'soltar',\n 'hud.rotate': 'girar',\n 'hud.throw': 'arremessar',\n 'hud.tilt': 'inclinar (segurar)',\n 'hud.equip': 'equipar {weapon}',\n\n 'ui.help': 'Clique: olhar · WASD: andar · Shift: correr · Espaço: pular · 1-0 / roda: ferramenta · botão esquerdo: usar · E: pegar/soltar · G ou botão direito: arremessar · R: recarregar · Q: modo de tiro · X: destravar · B: trava · Y: detonar cargas postas · Tab: painéis · Esc: soltar o mouse',\n 'ui.log': 'Registro de comportamento',\n 'ui.filter.action': 'ações',\n 'ui.filter.event': 'eventos',\n 'ui.filter.check': 'testes',\n 'ui.autoscroll': 'rolar sozinho',\n 'log.export_cancelled': 'exportação cancelada',\n 'ui.copy_json': 'Copiar JSON',\n 'ui.download_ndjson': 'Baixar NDJSON',\n 'ui.download_txt': 'Baixar TXT',\n 'ui.clear_log': 'Limpar',\n 'ui.catalog': 'Catálogo',\n 'ui.clear': 'Limpar',\n 'ui.reset_all': 'Consertar tudo',\n 'ui.slow': 'Câmera lenta 0,25×',\n 'ui.fast': 'Tempo ×10',\n 'ui.tap': 'Torneira',\n 'ui.blast.shelter': 'Abrigo',\n 'ui.blast.fragmentHits': 'Estilhaços',\n 'ui.blast.confinement': 'Confinamento',\n 'ui.blast.shelter.hint': 'Explosões: paredes e outras partes entre a explosão e o alvo ficam com a sua parte',\n 'ui.blast.fragmentHits.hint': 'Explosões: os pedaços do que quebra voam e acertam o que está atrás',\n 'ui.blast.confinement.hint': 'Explosões: a pressão sobe num ambiente fechado',\n 'metric.blast_shelter': 'Explosão que chegou (%)',\n 'metric.blast_confinement': 'Pressão da explosão (x)',\n 'metric.blast_fragments': 'Estilhaços que acertaram',\n 'act.blast_report': 'Explosão: {shelter}% chegou ao alvo mais abrigado, pressão x{confinement}, {fragments} estilhaços acertaram, {n} alvos',\n 'ui.quality': 'Qualidade',\n 'ui.quality.low': 'baixa',\n 'ui.quality.medium': 'média',\n 'ui.quality.high': 'alta',\n 'ui.equip': 'Equipar como ferramenta',\n 'ui.search_items': 'Buscar item (todas as abas)',\n 'ui.search_tests': 'Buscar teste',\n 'ui.no_results': 'Nada encontrado',\n 'ui.objects': '{n} objetos',\n 'ui.tests': 'Testes',\n 'ui.run_all': 'Rodar todos',\n 'ui.running': 'Rodando...',\n 'ui.report': '{passed} passaram, {failed} falharam',\n 'ui.panel': 'Painéis',\n 'ui.inspector': 'Inspetor',\n 'ui.aim_at_something': 'Mire em um objeto',\n 'ins.material': 'Material',\n 'ins.status': 'Estado',\n 'ins.burning': 'em chamas',\n 'ins.hp': 'Pontos de vida',\n 'ins.temperature': 'Temperatura',\n 'ins.char': 'Carbonizado',\n 'ins.melt': 'Derretido',\n 'ins.liters': 'Líquido',\n 'ins.damage': 'Marcas',\n 'ins.damage_counts': '{dents}, {holes}, {cracks}',\n 'ins.mass': 'Massa',\n 'ins.load': 'Carga',\n 'ins.stress': 'Tensão',\n 'ins.joints': 'Juntas',\n 'ins.open': 'aberta',\n\n 'sc.start': 'Cenário: {name}',\n 'sc.pass': 'Cenário passou: {name}',\n 'sc.fail': 'Cenário FALHOU: {name}',\n 'sc.error': 'o cenário lançou um erro: {msg}',\n 'leg.still': 'leg_1 continua presa',\n 'leg.gone': 'leg_1 soltou',\n\n 'sc.steel_through_hole': 'Tiro de 9 mm em chapa de aço faz furo que atravessa',\n 'sc.steel_through_hole.check': '9 mm em aço de 3 mm: {holes} furo(s) de {mm} mm, atravessou: {through}, chapa com {hp} hp (esperado: atravessar)',\n 'sc.concrete_stops_bullet': 'Tiro de 9 mm em bloco de concreto não atravessa',\n 'sc.concrete_stops_bullet.check': '9 mm em 40 cm de concreto: atravessou: {through}, {dents}, {holes}, {cracks}, bloco com {hp} hp (esperado: parou, parede atrás intacta)',\n 'sc.hammer_dents_drum': 'Martelo amassa um tambor de aço',\n 'sc.hammer_dents_drum.check': 'Martelo no tambor: {swings} golpe(s), {dents} amassado(s), o primeiro com {depth} mm, corpo com {hp} hp (esperado: amassado, sem quebrar)',\n 'sc.glass_shatters': 'Vidro estilhaça no primeiro tiro de 9 mm',\n 'sc.glass_shatters.check': 'Vidro: quebrou depois de {shots} tiro(s) em {n} cacos (esperado: quebrado no primeiro tiro, pelo menos 4 cacos)',\n 'sc.shotgun_splinters_crate': 'Escopeta lasca um caixote de madeira',\n 'sc.shotgun_splinters_crate.check': 'Calibre 12 no caixote: {shots} tiro(s), {splinters} tábua(s) lascada(s), {holes} furos (esperado: pelo menos uma lascada)',\n 'sc.kick_chair_leg': 'Um chute solta a perna da cadeira',\n 'sc.kick_chair_leg.check': 'Cadeira: {kicks} chute(s), {groups} grupo(s), peças soltas {before} → {after}, {leg} (esperado: aparece uma peça solta)',\n 'sc.kick_detaches_leg_via_tool': 'A ferramenta chute (barra de atalhos) solta a perna da cadeira',\n 'sc.kick_detaches_leg_via_tool.check': 'Cadeira, ferramenta chute: {kicks} chute(s), peças soltas {before} → {after}, {leg} (esperado: aparece uma peça solta)',\n 'sc.screwdriver_shelf_board': 'Chave de fenda solta a prateleira parafusada em cerca de 2,5 s',\n 'sc.screwdriver_shelf_board.check': 'Chave de fenda na prateleira: levou {secs} s, esperado cerca de {want} s, a estante agora está em {pieces}',\n 'sc.wrong_tool_refused': 'A ferramenta errada é recusada',\n 'sc.wrong_tool_refused.check': 'Chave de fenda numa solda: recusou {refused} vez(es), juntas abertas {opened} (esperado: recusar, nenhuma aberta)',\n 'sc.lighter_burns_crate': 'Isqueiro acende o caixote de madeira e ele vira cinza',\n 'sc.lighter_burns_crate.lit': 'Isqueiro no caixote: pegou fogo: {lit} (esperado: sim)',\n 'sc.lighter_burns_crate.ash': 'Depois de queimar por 500 s: {ash} de {total} tábuas viraram cinza, a mais queimada {char}% (esperado: tudo cinza ou carbonizado)',\n 'sc.torch_melts_steel': 'Fogo de madeira não derrete o tambor de aço, o maçarico derrete',\n 'sc.torch_melts_steel.wood': 'Caixote em chamas ao lado do tambor: o tambor chegou a {peak} °C, derreteu {melt}%, caixote ainda queimando: {crate} (esperado: sem derreter)',\n 'sc.torch_melts_steel.torch': 'Maçarico no tambor: {temp} °C, derreteu {melt}% (esperado: derretendo)',\n 'sc.bucket_melts_drips': 'Balde de plástico derrete e pinga perto do fogo',\n 'sc.bucket_melts_drips.check': 'Balde nas chamas: derreteu {melt}%, {temp} °C, {drips} linha(s) de pingos (esperado: derretendo)',\n 'sc.gas_bottle_explodes': 'Botijão de gás no fogo explode e empurra um caixote',\n 'sc.gas_bottle_explodes.explode': 'Botijão no fogo: explodiu depois de {seconds} s (esperado: explode)',\n 'sc.gas_bottle_explodes.push': 'Caixote a 1,3 m: andou {moved} m, perdeu {lost} (esperado: empurrado ou quebrado)',\n 'sc.bottle_drop_shatters': 'Garrafa de vidro solta de 1,5 m estilhaça',\n 'sc.bottle_drop_shatters.check': 'Garrafa solta de 1,5 m: estado {status}, {cracks} trincas, mancha de água: {stain} (esperado: quebrada, água no chão)',\n 'sc.throw_chair_at_wall': 'Cadeira arremessada na parede causa dano de impacto',\n 'sc.throw_chair_at_wall.check': 'Cadeira na parede: {impacts} impacto(s), o primeiro com {energy} J, {wall} linha(s) de dano na parede (esperado: impacto e dano)',\n 'sc.coffee_three_sips': 'Três goles de café baixam o nível e registram cafeína',\n 'sc.coffee_three_sips.check': 'Café: {sips} gole(s), nível {before} → {after} l, cafeína registrada: {caffeine}, queimou a boca: {burn} (esperado: 3 goles, cafeína)',\n 'sc.tilt_cup_spills': 'Inclinar o copo derrama café e deixa mancha',\n 'sc.tilt_cup_spills.check': 'Copo inclinado: nível {before} → {after} l, {stains} mancha(s) de café (esperado: derramou com mancha)',\n 'sc.jerrycan_leaks_fuel': 'Tiro no galão faz vazamento e mancha de combustível',\n 'sc.jerrycan_leaks_fuel.check': 'Galão baleado: {streams} jato(s) de vazamento, mancha de combustível: {stain}, restam {left} l de 20, a linha do furo cita o vazamento: {leak} (esperado: vazando, mancha)',\n 'sc.fuel_stain_burns': 'Mancha de combustível acesa queima',\n 'sc.fuel_stain_burns.stain': 'Mancha de combustível no chão depois do vazamento: {stain} (esperado: sim)',\n 'sc.fuel_stain_burns.ignite': 'Isqueiro na mancha: {ignited} ignição(ões), o fogo alcançou objetos por perto: {near} (esperado: acendeu)',\n 'sc.fuel_stain_burns.out': 'Depois de 30 s a mancha se consumiu: {burned} (esperado: sim)',\n 'roof.standing': 'laje de pé',\n 'roof.fell': 'laje caiu',\n 'sc.one_column_roof_stands': 'Pilar destruído: a laje fica de pé',\n 'sc.one_column_roof_stands.check': 'Estrutura sem um pilar: {roof}, maior desabamento {heavy} kg, tensão máxima {stress}% (esperado: de pé, sem desabamento grande)',\n 'sc.two_columns_roof_collapses': 'Dois pilares destruídos: a laje desaba',\n 'sc.two_columns_roof_collapses.check': 'Estrutura sem dois pilares: os outros logo a {stress}%, depois peças pesadas soltas: {pieces} ({kg} kg), evento de desabamento registrado: {logged} (esperado: a laje desaba)',\n 'sc.extinguisher_puts_out_fire': 'Extintor apaga um caixote em chamas',\n 'sc.extinguisher_puts_out_fire.burning': 'Caixote incendiado: queimando: {burning} (esperado: sim)',\n 'sc.extinguisher_puts_out_fire.out': 'Depois do extintor: ainda queimando: {burning}, {events} evento(s) de apagar (esperado: apagado)',\n },\n}\n\nexport const locales: Record<TestRoomLocale, RoomStrings> = { en, 'pt-BR': ptBR }\n\nexport const resolveStrings = (locale: string | undefined): RoomStrings => locales[(locale as TestRoomLocale) ?? 'en'] ?? locales.en\n","import type * as THREE_NS from 'three'\nimport type { DestructibleSpec, JointSpec, PartSpec, Vec3 } from '@adatechnology/game-destruction'\nimport type { SurfaceSpec } from '@adatechnology/game-fluids'\nimport { brickWallSpec } from './items'\n\nexport interface ArenaObject {\n id: string\n spec: DestructibleSpec\n position: Vec3\n colors?: Record<string, number>\n}\n\n/** The static part of the room: lights, floor, grid, ruler and the destructible scenery. */\nexport interface Arena {\n group: THREE_NS.Group\n /** Objects to register in the world (target wall, table, shelf). */\n objects: ArenaObject[]\n surfaces: SurfaceSpec[]\n /** `[minX, minZ, maxX, maxZ]` boxes the player cannot walk into. */\n colliders: Array<[number, number, number, number]>\n playerStart: Vec3\n wallZ: number\n /** Rectangle and height of the table top (pieces rest on it while the table stands). */\n table: { minX: number; maxX: number; minZ: number; maxZ: number; top: number; id: string; topPart: string }\n tapSpout: Vec3\n sun: THREE_NS.DirectionalLight\n}\n\nconst tableSpec = (): DestructibleSpec => {\n const parts: PartSpec[] = [{ id: 'top', material: 'wood_hard', shape: { kind: 'box', size: [1.6, 0.05, 0.8] }, position: [0, 0.755, 0] }]\n const joints: JointSpec[] = []\n for (const [i, [x, z]] of [\n [-0.72, -0.32],\n [0.72, -0.32],\n [-0.72, 0.32],\n [0.72, 0.32],\n ].entries()) {\n parts.push({ id: `leg_${i + 1}`, material: 'wood_hard', shape: { kind: 'box', size: [0.06, 0.73, 0.06] }, position: [x, 0.365, z], anchored: true })\n joints.push({ a: `leg_${i + 1}`, b: 'top', kind: 'screw' })\n }\n return { name: 'table', parts, joints, tags: ['furniture'] }\n}\n\nconst shelfSpec = (): DestructibleSpec => {\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n for (const [i, x] of [-0.6, 0.6].entries()) {\n parts.push({ id: `upright_${i + 1}`, material: 'wood_hard', shape: { kind: 'box', size: [0.04, 1.7, 0.4] }, position: [x, 0.85, 0], anchored: true })\n }\n for (const [i, y] of [0.4, 0.9, 1.4].entries()) {\n parts.push({ id: `board_${i + 1}`, material: 'wood_soft', shape: { kind: 'box', size: [1.2, 0.03, 0.4] }, position: [0, y, 0] })\n joints.push({ a: `board_${i + 1}`, b: 'upright_1', kind: 'screw' }, { a: `board_${i + 1}`, b: 'upright_2', kind: 'screw' })\n }\n return { name: 'shelf', parts, joints, tags: ['furniture'] }\n}\n\nexport function createArena(THREE: typeof THREE_NS, size: number, scene: THREE_NS.Scene): Arena {\n const group = new THREE.Group()\n group.name = 'test-room-arena'\n scene.background = new THREE.Color(0x9fb4c8)\n\n group.add(new THREE.HemisphereLight(0xcfe3ff, 0x6b6257, 0.75))\n const sun = new THREE.DirectionalLight(0xffffff, 2.1)\n sun.position.set(7, 13, 8)\n sun.castShadow = true\n sun.shadow.mapSize.set(1024, 1024)\n const sc = sun.shadow.camera\n sc.left = -16\n sc.right = 16\n sc.top = 16\n sc.bottom = -16\n sc.near = 1\n sc.far = 40\n sun.shadow.bias = -0.0006\n group.add(sun)\n\n const floor = new THREE.Mesh(new THREE.PlaneGeometry(size * 2, size * 2), new THREE.MeshStandardMaterial({ color: 0x8e8e8a, roughness: 0.95 }))\n floor.rotation.x = -Math.PI / 2\n floor.receiveShadow = true\n floor.name = 'floor'\n group.add(floor)\n\n const grid = new THREE.GridHelper(size * 2, size * 2, 0x4c4c52, 0x77777b)\n grid.position.y = 0.004\n group.add(grid)\n\n const wallZ = -11\n const playerStart: Vec3 = [0, 1.7, 5]\n\n // distance ruler along the left of the lane: a tick every metre (taller every 5 m) and a label every 5 m\n const pts: number[] = []\n const rx = -1.6\n for (let z = Math.round(playerStart[2]); z >= wallZ; z--) {\n const d = playerStart[2] - z\n const len = d % 5 === 0 ? 0.5 : 0.2\n pts.push(rx, 0.01, z, rx + len, 0.01, z)\n }\n pts.push(rx, 0.01, playerStart[2], rx, 0.01, wallZ)\n const rg = new THREE.BufferGeometry()\n rg.setAttribute('position', new THREE.Float32BufferAttribute(pts, 3))\n group.add(new THREE.LineSegments(rg, new THREE.LineBasicMaterial({ color: 0xffd23f })))\n for (let d = 5; playerStart[2] - d >= wallZ; d += 5) {\n try {\n const canvas = document.createElement('canvas')\n canvas.width = 128\n canvas.height = 64\n const ctx = canvas.getContext('2d')\n if (!ctx) break\n ctx.fillStyle = '#ffd23f'\n ctx.font = 'bold 44px sans-serif'\n ctx.textAlign = 'center'\n ctx.fillText(`${d} m`, 64, 48)\n const sprite = new THREE.Sprite(new THREE.SpriteMaterial({ map: new THREE.CanvasTexture(canvas), transparent: true, depthWrite: false }))\n sprite.scale.set(1.2, 0.6, 1)\n sprite.position.set(rx - 0.8, 0.45, playerStart[2] - d)\n group.add(sprite)\n } catch {\n break\n }\n }\n\n // tap on a post at the end of the table, spout over the tabletop\n const tableX = 3.5\n const tapMat = new THREE.MeshStandardMaterial({ color: 0xb9bec4, metalness: 0.8, roughness: 0.35 })\n const post = new THREE.Mesh(new THREE.CylinderGeometry(0.04, 0.04, 1.4, 10), tapMat)\n post.position.set(tableX + 1.15, 0.7, 0)\n const arm = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 1.15 - 0.3, 10), tapMat)\n arm.rotation.z = Math.PI / 2\n arm.position.set(tableX + (1.15 + 0.3) / 2, 1.38, 0)\n const spoutMesh = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.1, 10), tapMat)\n spoutMesh.position.set(tableX + 0.3, 1.33, 0)\n for (const m of [post, arm, spoutMesh]) {\n m.castShadow = true\n group.add(m)\n }\n const tapSpout: Vec3 = [tableX + 0.3, 1.28, 0]\n\n const objects: ArenaObject[] = [\n { id: 'target_wall', spec: brickWallSpec(), position: [0, 0, wallZ], colors: { brick: 0xa5472e } },\n { id: 'table', spec: tableSpec(), position: [tableX, 0, 0] },\n { id: 'shelf', spec: shelfSpec(), position: [-3.5, 0, 0], colors: { wood_soft: 0xc79a62 } },\n ]\n\n return {\n group,\n objects,\n surfaces: [\n { id: 'floor', point: [0, 0, 0], normal: [0, 1, 0], halfSize: [size, size], porosity: 0.05 },\n { id: 'table', point: [tableX, 0.78, 0], normal: [0, 1, 0], halfSize: [0.8, 0.4], porosity: 0.3 },\n ],\n colliders: [\n [tableX - 0.8, -0.4, tableX + 0.8, 0.4],\n [tableX + 1.1, -0.1, tableX + 1.2, 0.1],\n [-3.5 - 0.62, -0.2, -3.5 + 0.62, 0.2],\n [-size, wallZ - 1, size, wallZ + 0.2],\n ],\n playerStart,\n wallZ,\n table: { minX: tableX - 0.8, maxX: tableX + 0.8, minZ: -0.4, maxZ: 0.4, top: 0.78, id: 'table', topPart: 'top' },\n tapSpout,\n sun,\n }\n}\n","import type { BenchChange, BenchSheet, ControlPatch, ControlValue, ModuleControl, ModuleLayer, ModuleMetric, TestableModule } from '@adatechnology/game-contracts'\nimport type { BenchControl, BenchHandle, BenchLayer } from './types'\n\n/** What the room keeps per module bench: the declarations, the module's patches, the values and the layers. Pure: no DOM, no three.js. */\nexport interface BenchStore extends BenchHandle {\n readonly moduleId: string\n readonly metrics: readonly ModuleMetric[]\n readonly declared: { readonly controls: readonly ModuleControl[]; readonly layers: readonly ModuleLayer[]; readonly metrics: readonly ModuleMetric[] }\n /** Changes for the module (the `ModuleBench.onChange` listeners). */\n onChange(listener: (change: BenchChange) => void): () => void\n /** Any change of state, the module's patches included (the panel and the URL follow it). */\n watch(listener: () => void): () => void\n patch(id: string, patch: ControlPatch): void\n /** The sheet the module put on the panel, if any. */\n sheet(): BenchSheet | null\n setSheet(sheet: BenchSheet | null): void\n /** One change per control (not actions) and per layer, in declaration order. */\n sendInitial(): void\n /** Apply an encoded state without emitting. */\n restore(encoded: string): void\n /** Drops every listener and watcher (the room is gone). */\n dispose(): void\n}\n\ntype ControlState = ModuleControl & { disabled: boolean }\n\nconst snap = (control: Extract<ModuleControl, { kind: 'number' }>, value: number): number => {\n const clamped = Math.min(control.max, Math.max(control.min, value))\n if (!control.step) return clamped\n const stepped = control.min + Math.round((clamped - control.min) / control.step) * control.step\n return Number(Math.min(control.max, stepped).toFixed(10))\n}\n\n/** The value a control takes for `value`, or undefined when it does not fit (wrong type, option not offered, action). */\nfunction fitValue(control: ModuleControl, value: unknown): ControlValue | undefined {\n if (control.kind === 'number') return typeof value === 'number' && Number.isFinite(value) ? snap(control, value) : undefined\n if (control.kind === 'boolean') return typeof value === 'boolean' ? value : undefined\n if (control.kind === 'choice') return typeof value === 'string' && control.options.some((option) => option.id === value) ? value : undefined\n return undefined\n}\n\nconst fromText = (control: ModuleControl, text: string): unknown => {\n if (control.kind === 'number') return text.trim() === '' ? Number.NaN : Number(text)\n if (control.kind === 'boolean') return text === '1' ? true : text === '0' ? false : undefined\n return text\n}\n\nconst toText = (value: ControlValue): string => (typeof value === 'boolean' ? (value ? '1' : '0') : String(value))\n\n/** `id=value;id=value`, values with `encodeURIComponent`, booleans and layers as `1` / `0`. */\nexport function encodeBenchState(controls: readonly BenchControl[], layers: readonly BenchLayer[]): string {\n const pairs: string[] = []\n for (const control of controls) if (control.value !== undefined) pairs.push(`${control.id}=${encodeURIComponent(toText(control.value))}`)\n for (const layer of layers) pairs.push(`${layer.id}=${layer.on ? '1' : '0'}`)\n return pairs.join(';')\n}\n\n/** Reads an encoded state as hostile input: unknown ids, NaN, options not offered and malformed pairs are dropped; numbers are clamped. */\nexport function decodeBenchState(encoded: string, controls: readonly ModuleControl[], layers: readonly ModuleLayer[]): Map<string, ControlValue> {\n const out = new Map<string, ControlValue>()\n for (const pair of encoded.split(';')) {\n const at = pair.indexOf('=')\n if (at <= 0) continue\n const id = pair.slice(0, at)\n let text: string\n try {\n text = decodeURIComponent(pair.slice(at + 1))\n } catch {\n continue\n }\n const control = controls.find((c) => c.id === id)\n if (control) {\n const value = fitValue(control, fromText(control, text))\n if (value !== undefined) out.set(id, value)\n continue\n }\n if (layers.some((layer) => layer.id === id) && (text === '1' || text === '0')) out.set(id, text === '1')\n }\n return out\n}\n\nexport function createBenchStore(module: TestableModule<unknown>, locale: string, onListenerError?: (error: unknown) => void): BenchStore {\n const declared = { controls: module.controls?.(locale) ?? [], layers: module.layers?.(locale) ?? [], metrics: module.metrics?.(locale) ?? [] }\n const controls: ControlState[] = declared.controls.map((control) => ({ ...control, disabled: false }))\n const values = new Map<string, ControlValue>()\n for (const control of controls) if (control.kind !== 'action') values.set(control.id, control.default)\n const layers = new Map<string, boolean>(declared.layers.map((layer) => [layer.id, layer.default !== false]))\n const listeners = new Set<(change: BenchChange) => void>()\n const watchers = new Set<() => void>()\n const emit = (change: BenchChange): void => {\n for (const listener of listeners) {\n try {\n listener(change)\n } catch (error) {\n onListenerError?.(error)\n }\n }\n }\n const changed = (): void => {\n for (const watcher of watchers) watcher()\n }\n let sheet: BenchSheet | null = null\n const controlOf = (id: string): ControlState | undefined => controls.find((control) => control.id === id)\n\n const store: BenchStore = {\n moduleId: module.id,\n metrics: declared.metrics,\n declared,\n controls: () => controls.map((control) => ({ ...control, value: values.get(control.id) })),\n layers: () => declared.layers.map((layer) => ({ ...layer, on: layers.get(layer.id) === true })),\n value: (id) => values.get(id),\n layer: (id) => layers.get(id) === true,\n set(id, value) {\n const control = controlOf(id)\n if (!control || control.disabled) return false\n const fitted = fitValue(control, value)\n if (fitted === undefined) return false\n values.set(id, fitted)\n emit({ kind: 'control', id, value: fitted })\n changed()\n return true\n },\n setLayer(id, on) {\n if (!layers.has(id)) return false\n layers.set(id, on)\n emit({ kind: 'layer', id, on })\n changed()\n return true\n },\n act(id) {\n const control = controlOf(id)\n if (!control || control.kind !== 'action' || control.disabled) return false\n emit({ kind: 'action', id })\n return true\n },\n encode: () => encodeBenchState(store.controls(), store.layers()),\n onChange(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n watch(listener) {\n watchers.add(listener)\n return () => watchers.delete(listener)\n },\n sheet: () => sheet,\n setSheet(next) {\n sheet = next\n changed()\n },\n patch(id, patch) {\n const index = controls.findIndex((control) => control.id === id)\n if (index < 0) return\n let control = controls[index]\n if (patch.hidden !== undefined) control = { ...control, hidden: patch.hidden }\n if (patch.disabled !== undefined) control = { ...control, disabled: patch.disabled }\n if (patch.options && control.kind === 'choice' && patch.options.length > 0) {\n control = { ...control, options: [...patch.options] }\n const offered = control.options\n if (!offered.some((option) => option.id === values.get(id))) values.set(id, offered[0].id)\n }\n controls[index] = control\n if (patch.value !== undefined) {\n const fitted = fitValue(control, patch.value)\n if (fitted !== undefined) values.set(id, fitted)\n }\n changed()\n },\n sendInitial() {\n for (const control of controls) {\n const value = values.get(control.id)\n if (value !== undefined) emit({ kind: 'control', id: control.id, value })\n }\n for (const layer of declared.layers) emit({ kind: 'layer', id: layer.id, on: layers.get(layer.id) === true })\n changed()\n },\n restore(encoded) {\n for (const [id, value] of decodeBenchState(encoded, controls, declared.layers)) {\n if (typeof value === 'boolean' && layers.has(id)) layers.set(id, value)\n else values.set(id, value)\n }\n },\n dispose() {\n listeners.clear()\n watchers.clear()\n },\n }\n return store\n}\n","import type * as THREE_NS from 'three'\nimport type { BlastOptions, DestructionWorld, HitResult, Vec3 } from '@adatechnology/game-destruction'\nimport type { DestructionRenderer } from '@adatechnology/game-destruction-three'\nimport type { VfxWorld } from '@adatechnology/game-vfx'\nimport { backblastEffect, blastEffect, createExplosiveBody, tripwireSegment } from '@adatechnology/game-weapons'\nimport type { Arsenal, Detonation, ExplosiveBody, SurfaceProbe, Use } from '@adatechnology/game-weapons'\nimport type { HostEvent } from '@adatechnology/game-contracts'\n\nimport { segmentTouchesBox } from './segment-box'\n\ntype Vars = Record<string, string | number>\ntype Fire = { temperature: number; radius: number; seconds: number }\n\n/** Radius of the blast a cone gives to each object inside it: the blast is the object's own, not the area around it. */\nconst CONE_BLAST_RADIUS = 0.5\n\ninterface Projectile {\n mesh: THREE_NS.Object3D\n pos: THREE_NS.Vector3\n vel: THREE_NS.Vector3\n weapon: string\n fuse: number\n burstOnImpact: boolean\n energy: number\n radius: number\n fire?: Fire | undefined\n age: number\n /** The explosive that flies or waits (`game-weapons`): when set, it decides the flight and the blast. */\n body?: ExplosiveBody | undefined\n /** Points along its velocity (a rocket). */\n aligned?: boolean\n /** Set down where it was used: waits for its trigger instead of flying. */\n placed?: boolean\n /** The wire of a charge that waits for a body to cross it, and the bodies already touching it when it was set (they are let out first). */\n wire?: { from: Vec3; to: Vec3; letThrough: Set<string> }\n /** What shows where it was set down (marker and wire), taken away with it. */\n attached?: THREE_NS.Object3D[]\n}\n\n/** What a blast did, summed over everything it reached: the share that got to the most sheltered target (0..1), the pressure multiplier, the fragment hits. */\nexport type BlastSummary = { readonly shelter: number; readonly confinement: number; readonly fragmentHits: number; readonly targets: number }\n\nexport const summarizeBlast = (results: readonly HitResult[]): BlastSummary | undefined => {\n const reports = results.flatMap((r) => (r.blast ? [r.blast] : []))\n if (reports.length === 0) return undefined\n return {\n shelter: Math.min(...reports.map((r) => r.shelter)),\n confinement: reports[0]!.confinement,\n fragmentHits: reports.reduce((n, r) => n + r.fragmentHits, 0),\n targets: reports.length,\n }\n}\n\n/** A body that can set off a trip wire: the player, a physics object, or anything a module brings. */\nexport type CrossingBody = { readonly id: string; readonly box: THREE_NS.Box3 }\n\n/** What the explosives need from the room: the world to blast, the renderer to draw it, the log and the host to tell, and the few room rules (ground, held object, fire). */\nexport type ExplosivesContext = {\n readonly THREE: typeof THREE_NS\n readonly scene: THREE_NS.Scene\n readonly camera: THREE_NS.Camera\n readonly world: Pick<DestructionWorld, 'raycast' | 'explode'>\n readonly renderer: Pick<DestructionRenderer, 'emit' | 'explode'>\n /** The effects world that draws the blast of an explosive by its id; the renderer keeps the shove on pieces and the sound. */\n readonly effects: Pick<VfxWorld, 'explosion'>\n readonly arsenal: Pick<Arsenal, 'explosives' | 'rules'>\n /** The roots of the objects a blast can reach (the arena is not one). */\n readonly objects: () => readonly THREE_NS.Object3D[]\n /** The bodies that set off a trip wire when they cross it: their world boxes, now. */\n readonly bodies: () => readonly CrossingBody[]\n readonly toolId: () => string\n readonly toolName: (id?: string) => string\n readonly withoutHeld: <TResult>(run: () => TResult) => TResult\n readonly groundAt: (x: number, z: number) => number\n /** The blast options every explosion starts with (the room's toggles). */\n readonly blast: () => BlastOptions\n /** What the last blast did, once it carried a report (shelter, confinement, fragment hits). */\n readonly blasted: (summary: BlastSummary) => void\n readonly translate: (key: string, vars?: Vars) => string\n readonly format: (value: number, digits?: number) => string\n readonly action: (type: string, text: string, extra?: { data?: Record<string, unknown> }) => void\n readonly emitHost: (event: HostEvent) => void\n readonly startFire: (weapon: string, at: Vec3, fire: Fire, isImpact: boolean) => void\n readonly say: (message: string) => void\n}\n\nexport type Explosives = {\n throwUse: (use: Extract<Use, { kind: 'throw' }>) => void\n placeUse: (use: Extract<Use, { kind: 'place' }>) => void\n backblastUse: (use: Extract<Use, { kind: 'backblast' }>) => void\n /** Sets off the charges set down that wait for the remote detonator; returns how many went off. A trip wire charge goes off by itself, when a body crosses the wire. */\n detonateCharges: () => number\n update: (dt: number) => void\n /** Removes every projectile and charge, and their meshes. */\n clear: () => void\n}\n\nconst toArray = (vector: THREE_NS.Vector3): Vec3 => [vector.x, vector.y, vector.z]\n\n/** The projectiles (grenades, molotovs, rockets) and charges set down: an `ExplosiveBody` of game-weapons flies or waits, the room only draws it and applies the blast. */\nexport function createExplosives(context: ExplosivesContext): Explosives {\n const { THREE, scene, camera, world, renderer, arsenal, translate, format, action } = context\n const projectiles: Projectile[] = []\n const meshes: THREE_NS.Object3D[] = []\n const up = new THREE.Vector3(0, 1, 0)\n\n const clear = (): void => {\n projectiles.length = 0\n for (const mesh of meshes) mesh.removeFromParent()\n meshes.length = 0\n }\n\n const addMesh = (geometry: THREE_NS.BufferGeometry, color: number, metalness: number, at: Vec3): THREE_NS.Mesh => {\n const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color, roughness: 0.6, metalness }))\n mesh.castShadow = true\n mesh.position.set(at[0], at[1], at[2])\n scene.add(mesh)\n meshes.push(mesh)\n return mesh\n }\n\n const remove = (projectile: Projectile): void => {\n for (const extra of projectile.attached ?? []) {\n extra.removeFromParent()\n const extraAt = meshes.indexOf(extra)\n if (extraAt >= 0) meshes.splice(extraAt, 1)\n }\n projectile.mesh.removeFromParent()\n const meshAt = meshes.indexOf(projectile.mesh)\n if (meshAt >= 0) meshes.splice(meshAt, 1)\n const at = projectiles.indexOf(projectile)\n if (at >= 0) projectiles.splice(at, 1)\n }\n\n const throwUse = (use: Extract<Use, { kind: 'throw' }>): void => {\n const isMolotov = !!use.fire\n const isRocket = use.trigger === 'impact' && (use.armDistance ?? 0) > 0\n const geometry = isRocket ? new THREE.CylinderGeometry(0.04, 0.04, 0.5, 8) : isMolotov ? new THREE.CylinderGeometry(0.035, 0.04, 0.2, 8) : new THREE.SphereGeometry(0.045, 8, 6)\n const mesh = addMesh(geometry, isMolotov ? 0x3b7a3b : isRocket ? 0x6b705c : 0x4b5320, isMolotov ? 0 : 0.4, use.origin)\n projectiles.push({\n mesh,\n pos: new THREE.Vector3(use.origin[0], use.origin[1], use.origin[2]),\n vel: new THREE.Vector3(use.velocity[0], use.velocity[1], use.velocity[2]),\n weapon: context.toolId(),\n fuse: use.fuse,\n burstOnImpact: isMolotov && use.fuse <= 0,\n energy: use.energy,\n radius: use.radius,\n fire: use.fire,\n age: 0,\n ...(use.explosive !== undefined ? { body: createExplosiveBody(use, arsenal.explosives, arsenal.rules.explosives), aligned: isRocket } : {}),\n })\n const key = isRocket ? 'act.launch' : isMolotov ? 'act.throw.molotov' : 'act.throw.grenade'\n action(isRocket ? 'launch_projectile' : 'throw_projectile', translate(key, { weapon: context.toolName(), fuse: format(use.fuse, 1), arm: format(use.armDistance ?? 0, 0) }), {\n data: { weapon: context.toolId(), fuse: use.fuse, explosive: use.explosive },\n })\n }\n\n /** A charge goes where the player aims, on the first surface within reach, else on the floor 2 m ahead. */\n const placementPoint = (use: Extract<Use, { kind: 'place' }>): Vec3 => {\n const hit = context.withoutHeld(() => world.raycast(use.origin, use.direction, 3))\n if (hit) return [hit.point[0] + hit.normal[0] * 0.03, hit.point[1] + hit.normal[1] * 0.03, hit.point[2] + hit.normal[2] * 0.03]\n const x = use.origin[0] + use.direction[0] * 2\n const z = use.origin[2] + use.direction[2] * 2\n return [x, context.groundAt(x, z) + 0.03, z]\n }\n\n /** The marker that shows where a charge was set down: a stake with a flag, so it can be found (and avoided). */\n const markerAt = (at: Vec3): THREE_NS.Group => {\n const marker = new THREE.Group()\n marker.name = 'charge_marker'\n const stake = new THREE.Mesh(new THREE.CylinderGeometry(0.01, 0.01, 0.4, 6), new THREE.MeshStandardMaterial({ color: 0x8b6b3d, roughness: 0.8 }))\n stake.position.y = 0.2\n const flag = new THREE.Mesh(new THREE.ConeGeometry(0.06, 0.12, 4), new THREE.MeshStandardMaterial({ color: 0xff6a00, emissive: 0xff3300, emissiveIntensity: 0.4 }))\n flag.position.y = 0.46\n marker.add(stake, flag)\n marker.position.set(at[0] + 0.12, at[1] - 0.03, at[2])\n scene.add(marker)\n meshes.push(marker)\n return marker\n }\n\n const wireLine = (from: Vec3, to: Vec3): THREE_NS.Line => {\n const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(...from), new THREE.Vector3(...to)])\n const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xe8e4c8 }))\n line.name = 'charge_wire'\n scene.add(line)\n meshes.push(line)\n return line\n }\n\n /** The bodies whose box the wire touches right now. */\n const touching = (wire: NonNullable<Projectile['wire']>): string[] =>\n context\n .bodies()\n .filter((body) => segmentTouchesBox(wire.from, wire.to, toArray(body.box.min), toArray(body.box.max)))\n .map((body) => body.id)\n\n const placeUse = (use: Extract<Use, { kind: 'place' }>): void => {\n const at = placementPoint(use)\n const placed = { ...use, origin: at }\n const body = createExplosiveBody(placed, arsenal.explosives, arsenal.rules.explosives)\n if (!body) return\n const mesh = addMesh(new THREE.BoxGeometry(0.18, 0.06, 0.1), use.explosive === 'claymore' ? 0x556b2f : 0xc2a878, 0.1, at)\n mesh.rotation.y = Math.atan2(use.direction[0], use.direction[2])\n const attached: THREE_NS.Object3D[] = [markerAt(at)]\n const segment = tripwireSegment(placed)\n const projectile: Projectile = { mesh, pos: new THREE.Vector3(at[0], at[1], at[2]), vel: new THREE.Vector3(), weapon: context.toolId(), fuse: 0, burstOnImpact: false, energy: use.energy, radius: use.radius, age: 0, body, placed: true, attached }\n if (segment) {\n const wire = { from: segment.from, to: segment.to, letThrough: new Set<string>() }\n for (const id of touching(wire)) wire.letThrough.add(id)\n attached.push(wireLine(segment.from, segment.to))\n projectile.wire = wire\n }\n projectiles.push(projectile)\n action('place_charge', translate('act.place', { weapon: context.toolName(), triggers: use.triggers.join('/') || '-' }), { data: { weapon: context.toolId(), explosive: use.explosive, triggers: [...use.triggers], point: at, ...(segment ? { wire: segment } : {}) } })\n }\n\n /** The blast behind a launcher: a puff of dust in the cone and what lies inside it, counted. */\n const backblastUse = (use: Extract<Use, { kind: 'backblast' }>): void => {\n renderer.emit('smoke', use.origin, use.direction, 14, use.radius)\n let reached = 0\n for (const object of context.objects()) if (backblastEffect(use, toArray(object.position)) > 0) reached++\n const onPlayer = backblastEffect(use, toArray(camera.position))\n action('backblast', translate('act.backblast', { weapon: context.toolName(), radius: format(use.radius, 0), n: reached, player: format(onPlayer, 2) }), {\n data: { weapon: context.toolId(), radius: use.radius, halfAngleDeg: use.halfAngleDeg, objects: reached, onPlayer },\n })\n }\n\n const surfaceProbe: SurfaceProbe = (from, to) => {\n const dx = to[0] - from[0]\n const dy = to[1] - from[1]\n const dz = to[2] - from[2]\n const length = Math.hypot(dx, dy, dz)\n if (length < 1e-6) return null\n const direction: Vec3 = [dx / length, dy / length, dz / length]\n const ray = context.withoutHeld(() => world.raycast(from, direction, length + 0.03))\n let best: { point: Vec3; normal: Vec3; ground: boolean; at: number } | null = ray && ray.distance <= length + 0.03 ? { point: ray.point, normal: ray.normal, ground: ray.normal[1] > 0.7, at: ray.distance } : null\n const floor = context.groundAt(to[0], to[2]) + 0.045\n if (to[1] < floor) {\n const point: Vec3 = [to[0], floor, to[2]]\n const at = Math.hypot(point[0] - from[0], point[1] - from[1], point[2] - from[2])\n if (!best || at < best.at) best = { point, normal: [0, 1, 0], ground: true, at }\n }\n return best ? { point: best.point, normal: best.normal, ground: best.ground } : null\n }\n\n /** The point of the object's box (its center, its corners, the closest to the charge) that takes the most of the blast, or undefined when none is inside the cone. */\n const mostExposedPoint = (box: THREE_NS.Box3, detonation: Detonation): Vec3 | undefined => {\n const { min, max } = box\n const candidates: Vec3[] = [toArray(box.getCenter(new THREE.Vector3())), toArray(box.clampPoint(new THREE.Vector3(...detonation.point), new THREE.Vector3()))]\n for (const x of [min.x, max.x]) for (const y of [min.y, max.y]) for (const z of [min.z, max.z]) candidates.push([x, y, z])\n let best: { point: Vec3; falloff: number } | undefined\n for (const point of candidates) {\n const effect = blastEffect(detonation, point)\n if (effect.zone !== 'none' && (!best || effect.falloff > best.falloff)) best = { point, falloff: effect.falloff }\n }\n return best?.point\n }\n\n /** A directional charge only reaches what is inside its cone: each object whose box has a point in reach takes a blast of its own there, scaled by how close that point is. */\n const coneBlast = (detonation: Detonation): number => {\n let reached = 0\n for (const object of context.objects()) {\n const box = new THREE.Box3().setFromObject(object)\n if (box.isEmpty()) box.expandByPoint(object.position)\n const at = mostExposedPoint(box, detonation)\n if (!at) continue\n const results = world.explode(at, detonation.energy * blastEffect(detonation, at).falloff, CONE_BLAST_RADIUS, 'player', context.blast())\n reached += results.length\n told(results)\n }\n return reached\n }\n\n /** Tells the room what a blast with a report did (for its metrics and its log). */\n const told = (results: readonly HitResult[]): void => {\n const summary = summarizeBlast(results)\n if (!summary) return\n context.blasted(summary)\n action('blast_report', translate('act.blast_report', { shelter: format(summary.shelter * 100, 0), confinement: format(summary.confinement, 2), fragments: summary.fragmentHits, n: summary.targets }), { data: { ...summary } })\n }\n\n /** The only place a blast is applied: the world, the drawing, the log, the player's share, the host event and the fire. */\n const detonate = (projectile: Projectile, detonation: Detonation): void => {\n const weaponName = context.toolName(projectile.weapon)\n const reach = Math.max(detonation.injuryRadius, detonation.lethalRadius)\n const results = detonation.energy <= 0 || detonation.cone ? [] : world.explode(detonation.point, detonation.energy, reach, 'player', context.blast())\n const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : results.length\n if (!detonation.cone) told(results)\n if (detonation.energy > 0) {\n const isPlayed = context.effects.explosion(detonation.explosive, detonation.point, { direction: detonation.direction }) !== null\n renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed, report: results })\n }\n if (detonation.stunSeconds !== undefined) renderer.emit('flash', detonation.point, [0, 1, 0], 1, 1)\n const onPlayer = blastEffect(detonation, toArray(camera.position))\n action('explode', translate('act.explode', { weapon: weaponName, energy: format(detonation.energy, 0), radius: format(reach, 1), n: reached }), {\n data: { weapon: projectile.weapon, explosive: detonation.explosive, cause: detonation.cause, energyJ: detonation.energy, radius: reach, point: detonation.point, player: onPlayer.zone, stunSeconds: onPlayer.stunSeconds },\n })\n if (onPlayer.zone !== 'none') {\n action('blast_player', translate('act.blast_player', { weapon: weaponName, zone: translate(`blast.zone.${onPlayer.zone}`), distance: format(onPlayer.distance, 1), stun: format(onPlayer.stunSeconds, 1) }), { data: { ...onPlayer } })\n }\n context.emitHost({ type: 'explosion', source: projectile.weapon, point: detonation.point, energy: detonation.energy, radius: reach, cause: detonation.cause, explosive: detonation.explosive })\n if (detonation.fire) context.startFire(projectile.weapon, detonation.point, detonation.fire, detonation.cause === 'impact')\n }\n\n /** A projectile with no `ExplosiveBody` (a use that names no explosive) blasts a sphere of its own radius, with the same effects as any other. */\n const detonateBare = (projectile: Projectile, isImpact: boolean): void => {\n detonate(projectile, {\n explosive: projectile.weapon,\n cause: isImpact ? 'impact' : 'timer',\n point: toArray(projectile.pos),\n direction: [0, 1, 0],\n at: projectile.age,\n energy: projectile.energy,\n lethalRadius: 0,\n injuryRadius: projectile.radius,\n noise: 0,\n destructionLevel: 0,\n ...(projectile.fire ? { fire: projectile.fire } : {}),\n })\n }\n\n const detonateCharges = (): number => {\n let count = 0\n for (const projectile of [...projectiles]) {\n if (!projectile.placed || !projectile.body) continue\n const event = projectile.body.trigger('remote')\n if (event?.type !== 'detonate') continue\n detonate(projectile, event.detonation)\n remove(projectile)\n count++\n }\n if (count === 0) context.say(translate('hud.no_charges'))\n return count\n }\n\n const stepBody = (projectile: Projectile, body: ExplosiveBody, dt: number): void => {\n const events = body.step(dt, surfaceProbe)\n projectile.pos.set(body.position[0], body.position[1], body.position[2])\n projectile.mesh.position.copy(projectile.pos)\n if (projectile.aligned && body.velocity[0] ** 2 + body.velocity[1] ** 2 + body.velocity[2] ** 2 > 1e-6) {\n projectile.mesh.quaternion.setFromUnitVectors(up, new THREE.Vector3(body.velocity[0], body.velocity[1], body.velocity[2]).normalize())\n } else if (!projectile.placed) projectile.mesh.rotation.x += dt * 8\n for (const event of events) {\n if (event.type === 'dud') action('dud', translate('act.dud', { weapon: context.toolName(projectile.weapon), distance: format(body.travelled, 1) }), { data: { weapon: projectile.weapon, point: event.point } })\n else if (event.type === 'detonate') detonate(projectile, event.detonation)\n }\n }\n\n /** Moves a bare projectile one step (gravity, bounce on the first surface or the ground); true when it bursts on impact. */\n const flyBare = (projectile: Projectile, dt: number): boolean => {\n const { gravity } = arsenal.rules.explosives\n let isBurst = false\n projectile.vel.y -= gravity * dt\n const speed = projectile.vel.length()\n const step = speed * dt\n if (step > 1e-6) {\n const direction: Vec3 = [projectile.vel.x / speed, projectile.vel.y / speed, projectile.vel.z / speed]\n const hit = context.withoutHeld(() => world.raycast(toArray(projectile.pos), direction, step + 0.05))\n if (hit && hit.distance <= step + 0.04) {\n projectile.pos.set(hit.point[0] - direction[0] * 0.03, hit.point[1] - direction[1] * 0.03, hit.point[2] - direction[2] * 0.03)\n if (projectile.burstOnImpact) isBurst = true\n else {\n const normal = hit.normal\n const normalSpeed = projectile.vel.x * normal[0] + projectile.vel.y * normal[1] + projectile.vel.z * normal[2]\n projectile.vel.x = (projectile.vel.x - 2 * normalSpeed * normal[0]) * 0.35\n projectile.vel.y = (projectile.vel.y - 2 * normalSpeed * normal[1]) * 0.35\n projectile.vel.z = (projectile.vel.z - 2 * normalSpeed * normal[2]) * 0.35\n }\n } else projectile.pos.addScaledVector(projectile.vel, dt)\n }\n const ground = context.groundAt(projectile.pos.x, projectile.pos.z) + 0.045\n if (projectile.pos.y < ground) {\n projectile.pos.y = ground\n if (projectile.burstOnImpact) isBurst = true\n else {\n projectile.vel.y = Math.abs(projectile.vel.y) * 0.35\n projectile.vel.x *= 0.7\n projectile.vel.z *= 0.7\n }\n }\n return isBurst\n }\n\n /** A body crossed the wire: the charge goes off. Bodies already on the wire when it was set are let through until they step off it. */\n const checkWire = (projectile: Projectile, body: ExplosiveBody): void => {\n const wire = projectile.wire\n if (!wire) return\n const crossing = touching(wire)\n for (const id of [...wire.letThrough]) if (!crossing.includes(id)) wire.letThrough.delete(id)\n const crosser = crossing.find((id) => !wire.letThrough.has(id))\n if (crosser === undefined) return\n const event = body.trigger('wire')\n if (event?.type !== 'detonate') return\n action('tripwire', translate('act.tripwire', { weapon: context.toolName(projectile.weapon), who: crosser }), { data: { weapon: projectile.weapon, body: crosser } })\n detonate(projectile, event.detonation)\n }\n\n const update = (dt: number): void => {\n for (let index = projectiles.length - 1; index >= 0; index--) {\n const projectile = projectiles[index]\n if (!projectile) continue\n projectile.age += dt\n if (projectile.body) {\n if (projectile.wire && !projectile.body.done) checkWire(projectile, projectile.body)\n stepBody(projectile, projectile.body, dt)\n if (projectile.body.done || (!projectile.placed && projectile.age > 60)) remove(projectile)\n continue\n }\n const isBurst = flyBare(projectile, dt)\n projectile.mesh.position.copy(projectile.pos)\n projectile.mesh.rotation.x += dt * 8\n projectile.fuse -= dt\n if (isBurst || (!projectile.burstOnImpact && projectile.fuse <= 0) || projectile.age > 30) {\n detonateBare(projectile, isBurst)\n remove(projectile)\n }\n }\n }\n\n return { throwUse, placeUse, backblastUse, detonateCharges, update, clear }\n}\n","import type { Vec3 } from '@adatechnology/game-destruction'\n\n/** Whether the segment `from` to `to` touches the axis-aligned box `min` to `max` (slab test): the check of \"a body crossed the wire\". */\nexport const segmentTouchesBox = (from: Vec3, to: Vec3, min: Vec3, max: Vec3): boolean => {\n let near = 0\n let far = 1\n for (let axis = 0; axis < 3; axis++) {\n const start = from[axis] as number\n const delta = (to[axis] as number) - start\n const low = min[axis] as number\n const high = max[axis] as number\n if (Math.abs(delta) < 1e-12) {\n if (start < low || start > high) return false\n continue\n }\n const entering = (low - start) / delta\n const leaving = (high - start) / delta\n near = Math.max(near, Math.min(entering, leaving))\n far = Math.min(far, Math.max(entering, leaving))\n if (near > far) return false\n }\n return true\n}\n","import type { HostEvent } from '@adatechnology/game-contracts'\nimport type { WeaponEvent, WeaponPhase } from '@adatechnology/game-weapons'\n\nconst NO_RECOIL: [number, number] = [0, 0]\n\nexport interface HostEventOptions {\n recoil?: [number, number]\n /** What the weapon is busy with when the event is drained: the start of a phase takes its duration from it. */\n phase?: WeaponPhase | null\n}\n\nconst durationOf = (phase: WeaponPhase | null | undefined, id: WeaponPhase['id']): { duration?: number } => (phase?.id === id ? { duration: Math.round((phase.end - phase.start) * 1e6) / 1e6 } : {})\n\n/** What the host tells a module about a weapon event: the whole cycle, with the seconds the rule gave each phase. */\nexport const toHostEvent = (weapon: string, event: WeaponEvent, options: HostEventOptions = {}): HostEvent | null => {\n const { recoil = NO_RECOIL, phase } = options\n switch (event.type) {\n case 'draw':\n return event.phase === 'start' ? { type: 'tool', weapon, ...durationOf(phase, 'draw') } : null\n // a launcher spends a round and throws one projectile: the weapon counts none because it is a throw, a host counts the one that leaves\n case 'shot':\n return { type: 'shot', weapon, shots: Math.max(1, event.shots), recoil, rounds: event.rounds, mode: event.mode, ...(event.suppressed ? { suppressed: true } : {}) }\n case 'misfire':\n return { type: 'misfire', weapon }\n case 'reload':\n return { type: 'reload', weapon, phase: event.phase, ...(event.phase === 'start' ? { kind: event.kind, ...durationOf(phase, 'reload') } : {}) }\n case 'reload_stage':\n return { type: 'stage', weapon, stage: event.stage }\n case 'feed':\n return { type: 'feed', weapon }\n case 'cycle':\n return { type: 'cycle', weapon, phase: event.phase, ...(event.phase === 'start' ? durationOf(phase, 'cycle') : {}) }\n case 'empty':\n return { type: 'empty', weapon }\n case 'mode':\n return { type: 'mode', weapon, mode: event.mode }\n case 'fault':\n return { type: 'fault', weapon, fault: event.fault }\n case 'clear':\n return { type: 'clear', weapon, fault: event.fault, phase: event.phase, ...(event.phase === 'start' ? durationOf(phase, 'clear') : {}) }\n case 'safety':\n return { type: 'safety', weapon, on: event.on }\n case 'cook':\n return { type: 'cook', weapon, phase: event.phase, fuse: event.fuse }\n case 'attachment':\n return { type: 'attachment', weapon, action: event.action, attachment: event.id, mount: event.mount, ...(event.action === 'break' ? {} : durationOf(phase, 'fit')) }\n case 'toggle':\n return { type: 'toggle', weapon, attachment: event.id, on: event.on }\n case 'stock':\n return { type: 'stock', weapon, state: event.state, kind: event.kind, ...durationOf(phase, 'stock') }\n case 'underbarrel':\n return { type: 'underbarrel', weapon, on: event.on, ...durationOf(phase, 'switch') }\n default:\n return null\n }\n}\n","import type { LogEntry, NewLogEntry, TestRoomLog } from './types'\n\nexport type NewEntry = NewLogEntry\n\n/** The log the room writes to (a `TestRoomLog` plus the write side). */\nexport interface WritableLog extends TestRoomLog {\n /** Called before every read, so pending work (the room batches events per frame) is flushed first. */\n setBeforeRead(fn: (() => void) | null): void\n setClock(fn: () => number): void\n}\n\nconst MAX_ENTRIES = 5000\n\nconst pad = (n: number, w = 2): string => String(n).padStart(w, '0')\n\n/** `00:03.21` style clock for the text export. */\nexport const formatTime = (t: number): string => {\n const m = Math.floor(t / 60)\n const s = t - m * 60\n return `${pad(m)}:${s.toFixed(2).padStart(5, '0')}`\n}\n\n/** Minimal shape of the `downloads` capability a claude.ai Artifact page gets from `claude.use('downloads')`. */\ninterface DownloadsApi {\n save(request: { filename: string; data: string }): Promise<unknown>\n}\n\nexport interface LogOptions {\n /** Text of the `action` line written when the viewer declines (or fails) an export from an Artifact page. */\n exportCancelled?: () => string\n}\n\nexport function createLog(options: LogOptions = {}): WritableLog {\n // In a claude.ai Artifact the page cannot use <a download> / blob links: it asks the host for the `downloads` capability. The promise is\n // created once, never awaited here (`use` may take up to 10 s and resolve null); `download` awaits it when somebody actually exports.\n const host = (globalThis as { claude?: { use?: (name: string) => Promise<unknown> } }).claude\n let downloadsP: Promise<DownloadsApi | null> | null = null\n if (host && typeof host.use === 'function') {\n try {\n downloadsP = Promise.resolve(host.use('downloads')).then((d) => (d as DownloadsApi | null) ?? null, () => null)\n } catch {\n downloadsP = null\n }\n }\n let list: LogEntry[] = []\n let seq = 0\n let clock = (): number => 0\n let beforeRead: (() => void) | null = null\n const listeners = new Set<(entry: LogEntry, updated: boolean) => void>()\n const keyed = new Map<string, { entry: LogEntry; last: number; count: number }>()\n\n const read = (): LogEntry[] => {\n beforeRead?.()\n return list\n }\n const emit = (e: LogEntry, updated: boolean): void => {\n for (const fn of listeners) {\n try {\n fn(e, updated)\n } catch {\n // a broken listener must not break the room\n }\n }\n }\n\n const add = (entry: NewEntry): LogEntry => {\n const { t, ...rest } = entry\n const e: LogEntry = { seq: seq++, t: Math.round((t ?? clock()) * 1000) / 1000, ...rest }\n list.push(e)\n if (list.length > MAX_ENTRIES) list = list.slice(list.length - MAX_ENTRIES)\n emit(e, false)\n return e\n }\n\n const log: WritableLog = {\n add,\n coalesce(key, entry, windowS = 1) {\n const now = entry.t ?? clock()\n const k = keyed.get(key)\n if (k && now - k.last <= windowS && list.includes(k.entry)) {\n const { t: _t, ...rest } = entry\n k.count++\n Object.assign(k.entry, rest)\n k.entry.data = { ...(rest.data ?? {}), updates: k.count }\n k.last = now\n emit(k.entry, true)\n return k.entry\n }\n const e = add(entry)\n keyed.set(key, { entry: e, last: now, count: 1 })\n return e\n },\n setBeforeRead(fn) {\n beforeRead = fn\n },\n setClock(fn) {\n clock = fn\n },\n entries(filter) {\n const all = read()\n if (!filter) return all.slice()\n return all.filter(\n (e) =>\n (!filter.channel || e.channel === filter.channel) && (!filter.type || e.type === filter.type) && (!filter.objectId || e.objectId === filter.objectId),\n )\n },\n clear() {\n beforeRead?.()\n list = []\n keyed.clear()\n },\n toJSON: () => JSON.stringify(read(), null, 2),\n toNDJSON: () => read().map((e) => JSON.stringify(e)).join('\\n') + (list.length ? '\\n' : ''),\n toText: () => read().map((e) => `[${formatTime(e.t)}] ${e.channel.padEnd(6)} ${e.text}`).join('\\n'),\n async download(format = 'ndjson') {\n const body = format === 'json' ? log.toJSON() : format === 'txt' ? log.toText() : log.toNDJSON()\n const downloads = downloadsP ? await downloadsP : null\n if (downloads) {\n // the Artifact allowlist has no `.ndjson`: it goes out as text\n const filename = format === 'ndjson' ? 'test-room-log.ndjson.txt' : `test-room-log.${format}`\n try {\n await downloads.save({ filename, data: body })\n } catch (err) {\n const code = (err as { code?: unknown } | null)?.code\n log.add({ channel: 'action', type: 'export_cancelled', text: options.exportCancelled?.() ?? 'export cancelled', data: { format, ...(typeof code === 'string' ? { code } : {}) } })\n }\n return\n }\n if (typeof document === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) return\n const mime = format === 'json' ? 'application/json' : 'text/plain'\n const url = URL.createObjectURL(new Blob([body], { type: mime }))\n const a = document.createElement('a')\n a.href = url\n a.download = `test-room-log.${format}`\n document.body.appendChild(a)\n a.click()\n a.remove()\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n },\n summary() {\n const byType: Record<string, number> = {}\n const byMaterial: Record<string, number> = {}\n const objects = new Set<string>()\n let destroyed = 0\n for (const e of read()) {\n byType[e.type] = (byType[e.type] ?? 0) + 1\n if (e.material) byMaterial[e.material] = (byMaterial[e.material] ?? 0) + 1\n if (e.objectId) objects.add(e.objectId)\n if (e.type === 'destroyed') destroyed++\n }\n return { byType, byMaterial, objects: objects.size, destroyed }\n },\n on(fn) {\n listeners.add(fn)\n return () => listeners.delete(fn)\n },\n }\n return log\n}\n","import type { RoomMetricId } from './types'\n\nexport const ROOM_METRICS: readonly RoomMetricId[] = ['fps', 'frame_ms', 'draw_calls', 'triangles', 'objects', 'fragments', 'particles', 'decals', 'blast_shelter', 'blast_confinement', 'blast_fragments']\n\nconst WINDOW_S = 0.5\n\ninterface RenderInfo {\n info?: { render?: { calls: number; triangles: number } }\n}\n\nexport interface RoomMetricsSources {\n readonly gl: unknown\n readonly destruction: { stats(): { fragments: number; particles: number; pieces: number; decals: number } }\n readonly fluids: { stats(): { particles: number; stains: number } }\n readonly effects: { stats(): { puffs: number; sparks: number; glows: number; chunks: number } }\n readonly ids: readonly RoomMetricId[]\n /** What the last blast with a report did (none until one). */\n readonly blast?: () => { shelter: number; confinement: number; fragmentHits: number } | undefined\n}\n\nexport interface RoomMetrics {\n /** Every frame with the real `dt`, before the time scale. */\n frame(dt: number): void\n /** Right after the room renders (only when it owns the loop). */\n rendered(): void\n sample(): Partial<Record<RoomMetricId, number>>\n}\n\nexport function createRoomMetrics(sources: RoomMetricsSources): RoomMetrics {\n const wanted = new Set(sources.ids)\n const gl = sources.gl as RenderInfo\n let windowS = 0\n let frames = 0\n let fps: number | undefined\n let frameMs: number | undefined\n let calls: number | undefined\n let triangles: number | undefined\n let ownsRender = false\n return {\n frame(dt) {\n frames++\n windowS += dt\n if (windowS < WINDOW_S) return\n fps = frames / windowS\n frameMs = (windowS / frames) * 1000\n frames = 0\n windowS = 0\n },\n rendered() {\n ownsRender = true\n calls = gl.info?.render?.calls\n triangles = gl.info?.render?.triangles\n },\n sample() {\n const out: Partial<Record<RoomMetricId, number>> = {}\n const put = (id: RoomMetricId, value: number | undefined): void => {\n if (wanted.has(id) && value !== undefined) out[id] = value\n }\n put('fps', fps)\n put('frame_ms', frameMs)\n const render = ownsRender ? { calls, triangles } : gl.info?.render\n put('draw_calls', render?.calls)\n put('triangles', render?.triangles)\n const blast = sources.blast?.()\n if (blast) {\n put('blast_shelter', blast.shelter * 100)\n put('blast_confinement', blast.confinement)\n put('blast_fragments', blast.fragmentHits)\n }\n if (!['objects', 'fragments', 'particles', 'decals'].some((id) => wanted.has(id as RoomMetricId))) return out\n const destruction = sources.destruction.stats()\n const fluids = sources.fluids.stats()\n const effects = sources.effects.stats()\n put('objects', destruction.pieces)\n put('fragments', destruction.fragments)\n put('particles', destruction.particles + fluids.particles + effects.puffs + effects.sparks + effects.glows + effects.chunks)\n put('decals', destruction.decals + fluids.stains)\n return out\n },\n }\n}\n","import type { DestructionEvent, DestructionWorld, PartState, ToolKind } from '@adatechnology/game-destruction'\nimport type { FluidEvent, FluidWorld } from '@adatechnology/game-fluids'\nimport type { WritableLog } from './log'\nimport type { LogEntry } from './types'\n\ntype Vars = Record<string, string | number>\n\n/** What the narrator needs to know about the room. */\nexport interface NarrateContext {\n world: DestructionWorld\n fluids: FluidWorld\n log: WritableLog\n /** Current room time in seconds. */\n now: () => number\n t: (key: string, vars?: Vars) => string\n /** Locale number: `1.5` -> `1,5` in pt-BR. */\n num: (n: number, digits?: number) => string\n /** Item display name of an object id (also loose pieces). */\n nameOf: (objectId: string) => string\n itemIdOf: (objectId: string) => string | undefined\n materialName: (id: string) => string\n liquidName: (id: string) => string\n jointKind: (kind: string) => string\n toolName: (tool: string) => string\n /** Display name of the item that carries a fluid container. */\n containerName: (containerId: string) => { name: string; objectId?: string; itemId?: string } | undefined\n /** Where a part lives now: its object, or the loose piece it broke off into. */\n locatePart?: (objectId: string, partId: string) => { objectId: string; part: PartState } | null\n}\n\nconst SKIP_DAMAGE: ReadonlySet<string> = new Set(['fire', 'heat'])\n\n/**\n * Turns destruction and fluid events into plain log lines in the room locale. Events of one frame arrive as a batch: a `damage` event is merged\n * into the dent, hole or crack it caused, a `leak` event into the hole that opened it, and the noisy ones (melt, drip, disassembly) become one\n * line that is updated while it goes on.\n */\nexport function createNarrator(c: NarrateContext) {\n const { t, num } = c\n\n /** Materials seen per `object|part`, so a line about a part that already broke off its object still names the material. */\n const materialMemo = new Map<string, string>()\n const findPart = (objectId: string, partId: string): PartState | null => {\n const p = c.world.part(objectId, partId) ?? c.locatePart?.(objectId, partId)?.part ?? null\n if (p) materialMemo.set(`${objectId}|${partId}`, p.material)\n return p\n }\n const plural = (key: string, n: number): string => t(`${key}.${n === 1 ? 'one' : 'other'}`, { n })\n const pieces = (n: number): string => plural('count.piece', n)\n const joints = (n: number): string => plural('count.joint', n)\n const xz = (x: number, z: number): string => t('coords', { x: num(x, 1), z: num(z, 1) })\n\n const where = (objectId: string, partId: string): string => {\n const p = findPart(objectId, partId)\n const m = p?.material ?? materialMemo.get(`${objectId}|${partId}`)\n return `${c.nameOf(objectId)} › ${partId}${m ? ` (${c.materialName(m)})` : ''}`\n }\n\n const stateOf = (objectId: string, partId: string): LogEntry['state'] => {\n const p = findPart(objectId, partId)\n if (!p) return undefined\n const s: Record<string, number | string | boolean> = {\n status: p.status,\n hp: Math.round(p.hp * 10) / 10,\n maxHp: Math.round(p.maxHp * 10) / 10,\n temperature: Math.round(p.temperature),\n char: Math.round(p.char * 100) / 100,\n melt: Math.round(p.melt * 100) / 100,\n }\n if (p.liters !== undefined) s.liters = Math.round(p.liters * 1000) / 1000\n return s\n }\n\n const base = (ev: DestructionEvent, part?: string): Pick<LogEntry, 'channel' | 'objectId' | 'itemId' | 'part' | 'material' | 'state'> => ({\n channel: 'event',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n part,\n material: part ? (findPart(ev.object, part)?.material ?? materialMemo.get(`${ev.object}|${part}`)) : undefined,\n state: part ? stateOf(ev.object, part) : undefined,\n })\n\n const hpText = (obj: string, part: string): string => {\n const p = findPart(obj, part)\n return p ? `hp ${num(p.hp, 0)}/${num(p.maxHp, 0)}` : ''\n }\n\n const isLost = (obj: string, part: string): boolean => {\n const st = findPart(obj, part)?.status\n return st === 'broken' || st === 'melted' || st === 'ashes'\n }\n\n /** Per-part running totals for lines that repeat while something goes on (cracks under load, overload damage). */\n const crackAcc = new Map<string, { n: number; cm: number; last: number }>()\n const damageAcc = new Map<string, { total: number; last: number }>()\n const stressAt = new Map<string, number>()\n const leakAt = new Map<string, number>()\n const list = (names: string[]): string => (names.length > 6 ? `${names.slice(0, 6).join(', ')}…` : names.join(', '))\n\n const events = (batch: DestructionEvent[]): void => {\n const now = c.now()\n const damage = new Map<string, { amount: number; type: string }>()\n const holes = new Map<string, LogEntry>()\n const dents = new Map<string, LogEntry>()\n for (const ev of batch) {\n if (ev.type !== 'damage') continue\n const k = `${ev.object}|${ev.part}`\n const prev = damage.get(k)\n damage.set(k, { amount: (prev?.amount ?? 0) + ev.amount, type: ev.damageType })\n }\n\n // A part that breaks, melts or burns away opens every joint it had: those `detach` events become part of ONE line about the part\n // (appended to its fracture or burnout line, or standing alone), instead of one line per joint.\n const lostJoints = new Map<string, { obj: string; part: string; joints: number; groups: number; merged: boolean }>()\n // Joints that open for another reason (a blow, a tool) are counted per object.\n const openJoints = new Map<string, { obj: string; by: string; list: Array<{ joint: string; a: string; b: string }>; groups: number; done: boolean }>()\n // Several parts of one object catching fire or being put out at once are one line.\n const fireParts = new Map<string, { obj: string; parts: string[]; temp: number; done: boolean }>()\n const outParts = new Map<string, { obj: string; parts: string[]; done: boolean }>()\n for (const ev of batch) {\n if (ev.type === 'detach') {\n if (ev.by === 'part_lost') {\n const [a, b] = ev.parts\n const lost = isLost(ev.object, a) && !isLost(ev.object, b) ? a : isLost(ev.object, b) && !isLost(ev.object, a) ? b : isLost(ev.object, a) ? a : b\n const key = `${ev.object}|${lost}`\n const g = lostJoints.get(key) ?? { obj: ev.object, part: lost, joints: 0, groups: 0, merged: false }\n g.joints++\n g.groups = ev.groups.length\n lostJoints.set(key, g)\n } else {\n const key = `${ev.object}|${ev.by}`\n const g = openJoints.get(key) ?? { obj: ev.object, by: ev.by, list: [], groups: 0, done: false }\n const [a, b] = ev.parts\n g.list.push({ joint: ev.joint, a, b })\n g.groups = ev.groups.length\n openJoints.set(key, g)\n }\n } else if (ev.type === 'ignite') {\n const g = fireParts.get(ev.object) ?? { obj: ev.object, parts: [], temp: 0, done: false }\n g.parts.push(ev.part)\n g.temp = Math.max(g.temp, findPart(ev.object, ev.part)?.temperature ?? 0)\n fireParts.set(ev.object, g)\n } else if (ev.type === 'extinguish') {\n const g = outParts.get(ev.object) ?? { obj: ev.object, parts: [], done: false }\n g.parts.push(ev.part)\n outParts.set(ev.object, g)\n }\n }\n const lostTail = (key: string): string => {\n const g = lostJoints.get(key)\n if (!g) return ''\n g.merged = true\n return t('ev.lost.tail', { joints: joints(g.joints), pieces: pieces(g.groups) })\n }\n const lostData = (key: string): Record<string, unknown> => {\n const g = lostJoints.get(key)\n return g ? { jointsOpened: g.joints, pieces: g.groups } : {}\n }\n\n for (const ev of batch) {\n switch (ev.type) {\n case 'damage':\n break\n case 'dent': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n const mm = ev.dent.depth * 1000\n const prev = dents.get(k)\n if (prev) {\n const n = Number(prev.data?.count ?? 1) + 1\n const deepest = Math.max(Number(prev.data?.depthMm ?? 0), mm)\n prev.text = t('ev.dents', { where: where(ev.object, ev.part), n, mm: num(deepest, 0), hp: hpText(ev.object, ev.part) })\n prev.data = { ...prev.data, count: n, depthMm: Math.round(deepest * 10) / 10 }\n break\n }\n dents.set(\n k,\n c.log.add({\n ...base(ev, ev.part),\n type: 'dent',\n text: t('ev.dent', { where: where(ev.object, ev.part), mm: num(mm, 0), hp: hpText(ev.object, ev.part) }),\n data: { count: 1, depthMm: Math.round(mm * 10) / 10, radius: ev.dent.radius, damage: d?.amount, point: ev.worldPoint, source: ev.source },\n }),\n )\n break\n }\n case 'hole': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n const mm = ev.hole.diameter * 1000\n const prev = holes.get(k)\n if (prev) {\n const n = Number(prev.data?.count ?? 1) + 1\n const through = Number(prev.data?.throughCount ?? 0) + (ev.hole.through ? 1 : 0)\n prev.text = t('ev.holes', { where: where(ev.object, ev.part), n, mm: num(mm, 0), thr: through, hp: hpText(ev.object, ev.part) })\n prev.data = { ...prev.data, count: n, throughCount: through, through: through > 0 }\n break\n }\n holes.set(\n k,\n c.log.add({\n ...base(ev, ev.part),\n type: 'hole',\n text: t(ev.hole.through ? 'ev.hole.through' : 'ev.hole.stuck', { where: where(ev.object, ev.part), mm: num(mm, 0), hp: hpText(ev.object, ev.part) }),\n data: { count: 1, throughCount: ev.hole.through ? 1 : 0, diameterMm: Math.round(mm * 10) / 10, through: ev.hole.through, damage: d?.amount, point: ev.worldPoint, source: ev.source },\n }),\n )\n break\n }\n case 'crack': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n // a part under load cracks again and again: that is one line that counts them (a cracking shot or blow stays its own line)\n const loaded = (findPart(ev.object, ev.part)?.stress ?? 0) > 0.8 && ev.source === undefined\n const cm = ev.crack.length * 100\n if (loaded) {\n const acc = crackAcc.get(k)\n const n = acc && now - acc.last <= 1 ? acc.n + 1 : 1\n const longest = acc && n > 1 ? Math.max(acc.cm, cm) : cm\n crackAcc.set(k, { n, cm: longest, last: now })\n c.log.coalesce(\n `crack:${k}`,\n {\n ...base(ev, ev.part),\n type: 'crack',\n text: t('ev.cracks', { where: where(ev.object, ev.part), n, cm: num(longest, 0), hp: hpText(ev.object, ev.part) }),\n data: { rays: ev.crack.rays, lengthM: ev.crack.length, count: n, underLoad: true },\n },\n 1,\n )\n break\n }\n c.log.add({\n ...base(ev, ev.part),\n type: 'crack',\n text: t('ev.crack', { where: where(ev.object, ev.part), rays: ev.crack.rays, cm: num(cm, 0), hp: hpText(ev.object, ev.part) }),\n data: { rays: ev.crack.rays, lengthM: ev.crack.length, damage: d?.amount, source: ev.source },\n })\n break\n }\n case 'ricochet':\n c.log.add({\n ...base(ev, ev.part),\n type: 'ricochet',\n text: t('ev.ricochet', { where: where(ev.object, ev.part), energy: num(ev.energy, 0) }),\n data: { energy: ev.energy, direction: ev.direction },\n })\n break\n case 'leak': {\n const k = `${ev.object}|${ev.part}`\n const liquid = c.liquidName(ev.fluid)\n const hole = holes.get(k)\n const rate = num(ev.rate, 2)\n leakAt.set(ev.object, now)\n if (hole) {\n hole.text += t('ev.leak.tail', { liquid, rate })\n hole.data = { ...hole.data, leak: { fluid: ev.fluid, ratePerS: ev.rate, pressurized: ev.pressurized } }\n } else {\n c.log.add({ ...base(ev, ev.part), type: 'leak', text: t('ev.leak.alone', { where: where(ev.object, ev.part), liquid, rate }), data: { fluid: ev.fluid, ratePerS: ev.rate } })\n }\n break\n }\n case 'fracture': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n c.log.add({\n ...base(ev, ev.part),\n type: 'fracture',\n text: t(`ev.fracture.${ev.style}`, { where: where(ev.object, ev.part), n: ev.fragments.length }) + lostTail(k),\n data: { style: ev.style, fragments: ev.fragments.length, damage: d?.amount, point: ev.point, source: ev.source, ...lostData(k) },\n })\n break\n }\n case 'detach': {\n if (ev.by === 'part_lost') {\n // the part's own line (fracture, burnout) already says it; with none in this batch, say it here, once\n const [a, b] = ev.parts\n const lost = isLost(ev.object, a) && !isLost(ev.object, b) ? a : isLost(ev.object, b) && !isLost(ev.object, a) ? b : isLost(ev.object, a) ? a : b\n const key = `${ev.object}|${lost}`\n const g = lostJoints.get(key)\n if (!g || g.merged) break\n const hasOwnLine = batch.some((e) => (e.type === 'fracture' || e.type === 'burnout') && e.object === ev.object && e.part === lost)\n if (hasOwnLine) break\n g.merged = true\n const status = findPart(ev.object, lost)?.status\n const verb = t(`lost.${status === 'ashes' ? 'ashes' : status === 'melted' ? 'melted' : 'broken'}`)\n c.log.add({\n ...base(ev, lost),\n type: 'detach',\n text: t('ev.lost.alone', { where: where(ev.object, lost), verb, joints: joints(g.joints), pieces: pieces(g.groups) }),\n data: { parts: [a, b], by: ev.by, ...lostData(key) },\n })\n break\n }\n const key = `${ev.object}|${ev.by}`\n const g = openJoints.get(key)\n if (!g || g.done) break\n g.done = true\n const [a, b] = ev.parts\n const many = g.list.length > 1\n c.log.add({\n channel: 'event',\n type: 'detach',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: many\n ? t(`ev.detach.many.${ev.by === 'tool' ? 'tool' : 'break'}`, { obj: c.nameOf(ev.object), joints: joints(g.list.length), pieces: pieces(g.groups) })\n : t('ev.detach', { obj: c.nameOf(ev.object), a, b, by: t(`by.${ev.by}`), pieces: pieces(g.groups) }),\n data: { joint: ev.joint, joints: g.list.map((j) => j.joint), parts: ev.parts, by: ev.by, groups: g.groups },\n })\n break\n }\n case 'disassemble_progress': {\n const pct = Math.round(ev.progress * 100)\n const kind = kindOf(ev.object, ev.joint)\n const [a, b] = ev.joint.split('~')\n c.log.coalesce(\n `dis:${ev.object}:${ev.joint}`,\n {\n channel: 'event',\n type: 'disassemble_progress',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.disassemble', { obj: c.nameOf(ev.object), a: a ?? ev.joint, b: b ?? '', kind: kind ? c.jointKind(kind) : t('joint.generic'), tool: c.toolName(ev.tool as ToolKind), pct }),\n data: { joint: ev.joint, tool: ev.tool, progress: ev.progress },\n },\n 1.5,\n )\n break\n }\n case 'ignite': {\n const g = fireParts.get(ev.object)\n if (g && g.parts.length >= 3) {\n if (g.done) break\n g.done = true\n c.log.add({\n channel: 'event',\n type: 'ignite',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.ignite.many', { obj: c.nameOf(ev.object), n: g.parts.length, temp: num(g.temp, 0), parts: list(g.parts) }),\n data: { parts: g.parts, temperature: Math.round(g.temp) },\n })\n break\n }\n c.log.add({ ...base(ev, ev.part), type: 'ignite', text: t('ev.ignite', { where: where(ev.object, ev.part), temp: num(findPart(ev.object, ev.part)?.temperature ?? 0, 0) }) })\n break\n }\n case 'extinguish': {\n const g = outParts.get(ev.object)\n if (g && g.parts.length >= 3) {\n if (g.done) break\n g.done = true\n c.log.add({\n channel: 'event',\n type: 'extinguish',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.extinguish.many', { obj: c.nameOf(ev.object), n: g.parts.length, parts: list(g.parts) }),\n data: { parts: g.parts },\n })\n break\n }\n c.log.add({ ...base(ev, ev.part), type: 'extinguish', text: t('ev.extinguish', { where: where(ev.object, ev.part) }) })\n break\n }\n case 'burnout': {\n const k = `${ev.object}|${ev.part}`\n c.log.add({ ...base(ev, ev.part), type: 'burnout', text: t('ev.burnout', { where: where(ev.object, ev.part) }) + lostTail(k), data: lostData(k) })\n break\n }\n case 'melt':\n c.log.coalesce(\n `melt:${ev.object}:${ev.part}`,\n { ...base(ev, ev.part), type: 'melt', text: t('ev.melt', { where: where(ev.object, ev.part), pct: Math.round(ev.melt * 100) }), data: { melt: ev.melt } },\n 2,\n )\n break\n case 'drip':\n c.log.coalesce(`drip:${ev.object}:${ev.part}`, { ...base(ev, ev.part), type: 'drip', text: t('ev.drip', { where: where(ev.object, ev.part) }), data: { point: ev.point } }, 2)\n break\n case 'explode':\n c.log.add({\n ...base(ev, ev.part),\n type: 'explode',\n text: t('ev.explode', { where: where(ev.object, ev.part), energy: num(ev.energy, 0), radius: num(ev.radius, 1) }),\n data: { energy: ev.energy, radius: ev.radius, point: ev.point },\n })\n break\n case 'destroyed':\n c.log.add({ channel: 'event', type: 'destroyed', objectId: ev.object, itemId: c.itemIdOf(ev.object), text: t('ev.destroyed', { obj: c.nameOf(ev.object) }) })\n break\n default: {\n // structural events (`stress`, `collapse`) come from newer versions of the core\n const x = ev as unknown as Record<string, unknown> & { type: string; object: string; time: number }\n if (x.type === 'stress') {\n const part = String(x.part ?? '')\n stressAt.set(`${x.object}|${part}`, now)\n c.log.coalesce(\n `stress:${x.object}:${part}`,\n {\n ...base(ev, part),\n type: 'stress',\n text: t('ev.stress', { where: where(x.object, part), stress: num(Number(x.stress ?? 0) * 100, 0), load: num(Number(x.load ?? 0), 0) }),\n data: { stress: x.stress, load: x.load },\n },\n 1,\n )\n } else if (x.type === 'collapse') {\n const parts = Array.isArray(x.parts) ? (x.parts as unknown[]).map(String) : []\n c.log.add({\n channel: 'event',\n type: 'collapse',\n objectId: x.object,\n itemId: c.itemIdOf(x.object),\n text: t('ev.collapse', { obj: c.nameOf(x.object), pieces: pieces(parts.length), mass: num(Number(x.mass ?? 0), 0), parts: list(parts) }),\n data: { parts: parts.length, partIds: parts, massKg: x.mass, cause: x.cause },\n })\n }\n }\n }\n }\n // damage that no dent, hole, crack or fracture explained (blunt thuds, blast, absorbed bullets, a structure carrying too much)\n for (const [k, d] of damage) {\n if (SKIP_DAMAGE.has(d.type) || d.amount < 0.5) continue\n const [obj, part] = k.split('|')\n const overload = d.type === 'blunt' && now - (stressAt.get(k) ?? -99) <= 3\n const entry = {\n channel: 'event' as const,\n type: 'damage',\n objectId: obj,\n itemId: c.itemIdOf(obj),\n part,\n material: findPart(obj, part)?.material ?? materialMemo.get(k),\n state: stateOf(obj, part),\n }\n if (!overload) {\n c.log.add({ ...entry, text: t('ev.damage', { where: where(obj, part), type: t(`dmg.${d.type}`), amount: num(d.amount, 0), hp: hpText(obj, part) }), data: { amount: d.amount, damageType: d.type } })\n continue\n }\n // a structure carrying too much loses hit points every tick: one line with the running total\n const acc = damageAcc.get(k)\n const total = acc && now - acc.last <= 1 ? acc.total + d.amount : d.amount\n damageAcc.set(k, { total, last: now })\n c.log.coalesce(\n `damage:${k}`,\n { ...entry, text: t('ev.damage.overload', { where: where(obj, part), amount: num(total, 0), hp: hpText(obj, part) }), data: { amount: total, damageType: d.type, overload: true } },\n 1,\n )\n }\n }\n\n const kindMemo = new Map<string, string>()\n const kindOf = (objectId: string, jointId: string): string => {\n const key = `${objectId}|${jointId}`\n const own = c.world.state(objectId)?.joints.find((j) => j.id === jointId)?.kind\n if (own) {\n kindMemo.set(key, own)\n return own\n }\n const known = kindMemo.get(key)\n if (known) return known\n for (const id of c.world.ids()) {\n const k = c.world.state(id)?.joints.find((j) => j.id === jointId)?.kind\n if (k) return k\n }\n return ''\n }\n\n const stainInfo = new Map<string, { liquid: string; surface: string; x: number; z: number }>()\n const stainAcc = new Map<string, { n: number; last: number }>()\n const driedAcc = new Map<string, { n: number; last: number }>()\n const drinkAcc = new Map<string, { liters: number; thirst: number; burn: boolean; effects: Set<string>; last: number; start: number }>()\n const fluid = (ev: FluidEvent): void => {\n const who = (id: string): string => c.containerName(id)?.name ?? id\n const meta = (id: string): { objectId?: string; itemId?: string } => {\n const m = c.containerName(id)\n return { objectId: m?.objectId, itemId: m?.itemId }\n }\n const f = 'fluid.'\n switch (ev.type) {\n case 'fill':\n c.log.coalesce(`fill:${ev.container}`, { channel: 'event', type: f + 'fill', ...meta(ev.container), text: t('fl.fill', { who: who(ev.container), liquid: c.liquidName(ev.liquid), liters: num(ev.liters, 2) }), data: { liters: ev.liters } }, 1.5)\n break\n case 'pour':\n c.log.coalesce(`pour:${ev.container}`, { channel: 'event', type: f + 'pour', ...meta(ev.container), text: t('fl.pour', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, 2) }), data: { rate: ev.rate } }, 2)\n break\n case 'spill':\n c.log.coalesce(`spill:${ev.container}`, { channel: 'event', type: f + 'spill', ...meta(ev.container), text: t('fl.spill', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, 2) }), data: { rate: ev.rate } }, 2)\n break\n case 'leak': {\n // the hole line of the destruction event already says the object is leaking\n const owner = meta(ev.container).objectId\n if (owner && c.now() - (leakAt.get(owner) ?? -99) <= 2) break\n c.log.coalesce(`fleak:${ev.container}`, { channel: 'event', type: f + 'leak', ...meta(ev.container), text: t('fl.leak', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, ev.rate < 0.01 ? 3 : 2) }), data: { rate: ev.rate, point: ev.point } }, 2)\n break\n }\n case 'drink': {\n // a sip arrives as many small drink events: one line per sip, updated while it goes on\n const now = c.now()\n let acc = drinkAcc.get(ev.container)\n if (!acc || now - acc.last > 0.5) acc = { liters: 0, thirst: 0, burn: false, effects: new Set<string>(), last: now, start: now }\n acc.liters += ev.liters\n acc.thirst += ev.thirst\n acc.burn = acc.burn || ev.burn\n for (const e of ev.effects) acc.effects.add(e)\n acc.last = now\n drinkAcc.set(ev.container, acc)\n const effects = [...acc.effects].map((e) => t(`effect.${e}`)).join(', ')\n c.log.coalesce(\n `drink:${ev.container}:${acc.start}`,\n {\n channel: 'event',\n type: f + 'drink',\n ...meta(ev.container),\n text:\n t('fl.drink', { who: who(ev.container), liters: num(acc.liters, 2), thirst: num(acc.thirst, 0) }) +\n (effects ? `, ${effects}` : '') +\n (acc.burn ? `, ${t('fl.burn')}` : ''),\n data: { liters: acc.liters, temperature: ev.temperature, thirst: acc.thirst, effects: [...acc.effects], burn: acc.burn },\n },\n 0.5,\n )\n break\n }\n case 'empty':\n c.log.add({ channel: 'event', type: f + 'empty', ...meta(ev.container), text: t('fl.empty', { who: who(ev.container) }) })\n break\n case 'splash':\n c.log.coalesce(`splash:${ev.liquid}`, { channel: 'event', type: f + 'splash', text: t('fl.splash', { liquid: c.liquidName(ev.liquid) }), data: { point: ev.point, intensity: ev.intensity } }, 1)\n break\n case 'stain': {\n const surface = t(`surface.${ev.surface}`)\n const liquid = c.liquidName(ev.liquid)\n stainInfo.set(ev.stain, { liquid: ev.liquid, surface, x: ev.point[0], z: ev.point[2] })\n // a leak or a spill makes several stains in a row: one line that counts them\n const key = `stain:${ev.liquid}:${ev.surface}`\n const acc = stainAcc.get(key)\n const n = acc && c.now() - acc.last <= 1 ? acc.n + 1 : 1\n stainAcc.set(key, { n, last: c.now() })\n c.log.coalesce(\n key,\n {\n channel: 'event',\n type: f + 'stain',\n text: n > 1 ? t('fl.stains', { n, liquid, surface, where: xz(ev.point[0], ev.point[2]) }) : t('fl.stain', { liquid, surface, where: xz(ev.point[0], ev.point[2]) }),\n data: { stain: ev.stain, surface: ev.surface, liquid: ev.liquid, point: ev.point, count: n },\n },\n 1,\n )\n break\n }\n case 'dried': {\n const info = stainInfo.get(ev.stain)\n const key = `dried:${info?.liquid ?? '?'}:${ev.mark}`\n const acc = driedAcc.get(key)\n const n = acc && c.now() - acc.last <= 1.5 ? acc.n + 1 : 1\n driedAcc.set(key, { n, last: c.now() })\n const vars = { liquid: info ? c.liquidName(info.liquid) : '', surface: info?.surface ?? '', where: info ? xz(info.x, info.z) : '', n }\n const text = !info\n ? t(ev.mark ? 'fl.dried.mark' : 'fl.dried')\n : n > 1\n ? t(ev.mark ? 'fl.dried.many.mark' : 'fl.dried.many', vars)\n : t(ev.mark ? 'fl.dried.known.mark' : 'fl.dried.known', vars)\n c.log.coalesce(key, { channel: 'event', type: f + 'dried', text, data: { stain: ev.stain, mark: ev.mark, count: n } }, 1.5)\n break\n }\n case 'mix':\n c.log.add({ channel: 'event', type: f + 'mix', ...meta(ev.container), text: t('fl.mix', { who: who(ev.container), from: c.liquidName(ev.from), into: c.liquidName(ev.into) }) })\n break\n default:\n break\n }\n }\n\n return { events, fluid }\n}\n","import type * as THREE_NS from 'three'\nimport type { Vec3 } from '@adatechnology/game-destruction'\n\nexport interface PlayerHooks {\n /** Primary button pressed / released (use the tool). `click` is a press without a drag, for the no-pointer-lock fallback. */\n primaryDown(): void\n primaryUp(): void\n secondary(): void\n key(code: string, down: boolean, event: KeyboardEvent): void\n wheel(direction: 1 | -1): void\n}\n\nexport interface PlayerOptions {\n camera: THREE_NS.PerspectiveCamera\n dom: HTMLElement\n /** `[minX, minZ, maxX, maxZ]` boxes to stay out of. */\n colliders: Array<[number, number, number, number]>\n /** Extra places to stay out of, asked on every step (a module's walls): `(x, z, radius) => blocked`. The set may change while the player walks. */\n blockers?: ReadonlySet<(x: number, z: number, radius: number) => boolean>\n /** Half size of the arena. */\n limit: number\n start: Vec3\n hooks: PlayerHooks\n}\n\nexport interface Player {\n readonly yaw: number\n readonly pitch: number\n readonly locked: boolean\n /** Held keys, by `KeyboardEvent.code`. */\n keys: ReadonlySet<string>\n update(dt: number): void\n setPose(position: Vec3, yaw: number, pitch: number): void\n /** Put the eye at `position` looking at `target`. */\n look(position: Vec3, target: Vec3): void\n /** Camera kick in degrees. */\n kick(pitchDeg: number, yawDeg: number): void\n /** Move the player by a world offset on the floor plane, stopped by the colliders and the arena limit (scripted walks). */\n moveBy(dx: number, dz: number): void\n /** Walk by hand (tests): moves the player `forward` and `right` metres along its facing. */\n walk(forward: number, right: number): void\n dispose(): void\n}\n\nconst EYE = 1.7\n/** Horizontal radius of the player, metres: what the colliders and a trip wire see. */\nexport const PLAYER_RADIUS = 0.3\nconst WALK = 3.4\nconst RUN = 6.2\nconst JUMP = 4.6\nconst GRAVITY = 13\nconst LOOK = 0.0022\n\n/**\n * First-person controller: WASD, Shift, Space, mouse look with pointer lock, and a drag-to-look fallback for pages where the lock is not\n * available (iframes, headless browsers, touch). In the fallback a press that does not move is a click (tool use), a drag looks around.\n */\nexport function createPlayer(THREE: typeof THREE_NS, o: PlayerOptions): Player {\n const cam = o.camera\n let yaw = 0\n let pitch = 0\n let y = 0\n let eye = EYE\n let vy = 0\n const px = { x: o.start[0], z: o.start[2] }\n let locked = false\n const keys = new Set<string>()\n const euler = new THREE.Euler(0, 0, 0, 'YXZ')\n\n const apply = (): void => {\n euler.set(pitch, yaw, 0, 'YXZ')\n cam.quaternion.setFromEuler(euler)\n cam.position.set(px.x, eye + y, px.z)\n cam.updateMatrixWorld(true)\n }\n apply()\n\n const blocked = (x: number, z: number): boolean => {\n if (Math.abs(x) > o.limit - PLAYER_RADIUS || Math.abs(z) > o.limit - PLAYER_RADIUS) return true\n for (const c of o.colliders) if (x > c[0] - PLAYER_RADIUS && x < c[2] + PLAYER_RADIUS && z > c[1] - PLAYER_RADIUS && z < c[3] + PLAYER_RADIUS) return true\n if (o.blockers) for (const blocked of o.blockers) if (blocked(x, z, PLAYER_RADIUS)) return true\n return false\n }\n const move = (dx: number, dz: number): void => {\n if (!blocked(px.x + dx, px.z)) px.x += dx\n if (!blocked(px.x, px.z + dz)) px.z += dz\n }\n\n let dragging = false\n let moved = 0\n let downAt = 0\n let useStarted = false\n let holdTimer: ReturnType<typeof setTimeout> | null = null\n\n const look = (dx: number, dy: number): void => {\n yaw -= dx * LOOK\n pitch = Math.max(-1.5, Math.min(1.5, pitch - dy * LOOK))\n }\n const onLockChange = (): void => {\n locked = document.pointerLockElement === o.dom\n }\n const onMouseDown = (e: MouseEvent): void => {\n o.dom.focus?.()\n if (e.button === 2) {\n e.preventDefault()\n o.hooks.secondary()\n return\n }\n if (e.button !== 0) return\n if (!locked) {\n try {\n const r = (o.dom.requestPointerLock as unknown as (() => Promise<void> | void) | undefined)?.call(o.dom)\n if (r && typeof (r as Promise<void>).catch === 'function') (r as Promise<void>).catch(() => undefined)\n } catch {\n // no pointer lock here: drag to look\n }\n dragging = true\n moved = 0\n downAt = performance.now()\n useStarted = false\n holdTimer = setTimeout(() => {\n if (dragging && moved < 4 && !useStarted) {\n useStarted = true\n o.hooks.primaryDown()\n }\n }, 220)\n return\n }\n useStarted = true\n o.hooks.primaryDown()\n }\n const onMouseUp = (e: MouseEvent): void => {\n if (e.button !== 0) return\n if (holdTimer) clearTimeout(holdTimer)\n if (dragging) {\n dragging = false\n if (!useStarted && moved < 4 && performance.now() - downAt < 400) {\n o.hooks.primaryDown()\n o.hooks.primaryUp()\n } else if (useStarted) o.hooks.primaryUp()\n useStarted = false\n return\n }\n if (useStarted) o.hooks.primaryUp()\n useStarted = false\n }\n const onMouseMove = (e: MouseEvent): void => {\n if (locked) look(e.movementX, e.movementY)\n else if (dragging) {\n moved += Math.abs(e.movementX) + Math.abs(e.movementY)\n if (moved >= 4) {\n if (useStarted) {\n useStarted = false\n o.hooks.primaryUp()\n }\n look(e.movementX, e.movementY)\n }\n }\n }\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault()\n o.hooks.wheel(e.deltaY > 0 ? 1 : -1)\n }\n const typing = (e: Event): boolean => {\n const t = e.target as HTMLElement | null\n return !!t && (t.tagName === 'INPUT' || t.tagName === 'SELECT' || t.tagName === 'TEXTAREA')\n }\n const onKeyDown = (e: KeyboardEvent): void => {\n if (typing(e)) return\n if (e.code === 'Space' || e.code === 'Tab') e.preventDefault()\n if (!e.repeat) keys.add(e.code)\n o.hooks.key(e.code, true, e)\n }\n const onKeyUp = (e: KeyboardEvent): void => {\n keys.delete(e.code)\n if (typing(e)) return\n o.hooks.key(e.code, false, e)\n }\n const onContext = (e: Event): void => e.preventDefault()\n const onBlur = (): void => keys.clear()\n\n o.dom.addEventListener('mousedown', onMouseDown)\n window.addEventListener('mouseup', onMouseUp)\n window.addEventListener('mousemove', onMouseMove)\n o.dom.addEventListener('wheel', onWheel, { passive: false })\n o.dom.addEventListener('contextmenu', onContext)\n document.addEventListener('pointerlockchange', onLockChange)\n window.addEventListener('keydown', onKeyDown)\n window.addEventListener('keyup', onKeyUp)\n window.addEventListener('blur', onBlur)\n\n return {\n get yaw() {\n return yaw\n },\n get pitch() {\n return pitch\n },\n get locked() {\n return locked\n },\n keys,\n update(dt) {\n const run = keys.has('ShiftLeft') || keys.has('ShiftRight')\n const speed = run ? RUN : WALK\n let f = 0\n let r = 0\n if (keys.has('KeyW') || keys.has('ArrowUp')) f += 1\n if (keys.has('KeyS') || keys.has('ArrowDown')) f -= 1\n if (keys.has('KeyD') || keys.has('ArrowRight')) r += 1\n if (keys.has('KeyA') || keys.has('ArrowLeft')) r -= 1\n if ((f || r || keys.has('Space')) && eye !== EYE) eye = EYE\n if (f || r) {\n const len = Math.hypot(f, r)\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const rx = Math.cos(yaw)\n const rz = -Math.sin(yaw)\n move(((fx * f + rx * r) / len) * speed * dt, ((fz * f + rz * r) / len) * speed * dt)\n }\n if (y <= 0 && keys.has('Space')) vy = JUMP\n if (y > 0 || vy > 0) {\n vy -= GRAVITY * dt\n y += vy * dt\n if (y <= 0) {\n y = 0\n vy = 0\n }\n }\n apply()\n },\n setPose(position, yw, pt) {\n px.x = position[0]\n px.z = position[2]\n eye = position[1]\n y = 0\n vy = 0\n yaw = yw\n pitch = pt\n apply()\n },\n look(position, target) {\n px.x = position[0]\n px.z = position[2]\n eye = position[1]\n y = 0\n vy = 0\n const dx = target[0] - position[0]\n const dy = target[1] - position[1]\n const dz = target[2] - position[2]\n yaw = Math.atan2(-dx, -dz)\n pitch = Math.atan2(dy, Math.hypot(dx, dz))\n apply()\n },\n kick(pitchDeg, yawDeg) {\n pitch = Math.max(-1.5, Math.min(1.5, pitch + (pitchDeg * Math.PI) / 180))\n yaw += (yawDeg * Math.PI) / 180\n apply()\n },\n moveBy(dx, dz) {\n move(dx, dz)\n apply()\n },\n walk(forward, right) {\n move(-Math.sin(yaw) * forward + Math.cos(yaw) * right, -Math.cos(yaw) * forward - Math.sin(yaw) * right)\n apply()\n },\n dispose() {\n if (holdTimer) clearTimeout(holdTimer)\n o.dom.removeEventListener('mousedown', onMouseDown)\n window.removeEventListener('mouseup', onMouseUp)\n window.removeEventListener('mousemove', onMouseMove)\n o.dom.removeEventListener('wheel', onWheel)\n o.dom.removeEventListener('contextmenu', onContext)\n document.removeEventListener('pointerlockchange', onLockChange)\n window.removeEventListener('keydown', onKeyDown)\n window.removeEventListener('keyup', onKeyUp)\n window.removeEventListener('blur', onBlur)\n if (document.pointerLockElement === o.dom) document.exitPointerLock?.()\n },\n }\n}\n","import { JOINT_DEFAULTS, rotateVec, toWorld } from '@adatechnology/game-destruction'\nimport type { Vec3 } from '@adatechnology/game-destruction'\nimport { resolveStrings } from './locale'\nimport type { ScenarioContext, TestRoom, TestRoomScenario } from './types'\n\ntype T = (key: string, vars?: Record<string, string | number>) => string\ntype Num = (n: number, digits?: number) => string\n\n/** Built-in scripted checks over the generic `DEMO_ITEMS`. Names and check texts come from the room locale. */\nexport function makeScenarios(t: T, num: Num, _locale = 'en'): TestRoomScenario[] {\n const yn = (b: boolean): string => t(b ? 'yes' : 'no')\n const cn = (what: string, n: number): string => t(`count.${what}.${n === 1 ? 'one' : 'other'}`, { n })\n const pc = (n: number): string => t(n === 1 ? 'count.piece.one' : 'count.piece.other', { n })\n const sc = (id: string, run: (c: ScenarioContext) => void | Promise<void>): TestRoomScenario => ({ id, name: t(`sc.${id}`), run })\n\n const at = (room: TestRoom, itemId: string, x: number, z: number, y = 0, rot = 0): string => room.spawn(itemId, [x, y, z], rot).objectId\n const look = (room: TestRoom, from: Vec3, to: Vec3): void => room.look(from, to)\n const part = (room: TestRoom, id: string, p: string) => room.world.part(id, p)\n const count = (room: TestRoom, type: string, objectId?: string): number => room.log.entries({ type, objectId }).length\n const anyBurning = (room: TestRoom, id: string): boolean => (room.world.state(id)?.parts ?? []).some((p) => p.burning)\n const igniteHit = (room: TestRoom, id: string, point: Vec3, temperature = 900, seconds = 3): void => {\n room.world.hit(id, { type: 'fire', point, temperature, radius: 0.6, duration: seconds })\n }\n\n // columns of the demo `building_frame` placed at (0, 0, -6): x = -2 / 2, z = -8 / -4\n const COLUMN: Record<string, Vec3> = { column_0_0_0: [-2, 1.4, -8], column_0_1_0: [2, 1.4, -8], column_0_0_1: [-2, 1.4, -4], column_0_1_1: [2, 1.4, -4] }\n const killColumns = (room: TestRoom, id: string, ids: string[]): void => {\n for (const c of ids) room.world.hitPart(id, c, { type: 'blunt', point: COLUMN[c], energy: 3e6, radius: 0.05, source: 'test' })\n }\n const heavyCollapse = (room: TestRoom): number => room.log.entries({ type: 'collapse' }).reduce((m, e) => Math.max(m, Number(e.data?.massKg ?? 0)), 0)\n\n return [\n sc('steel_through_hole', ({ room, step, expect }) => {\n const id = at(room, 'steel_sheet', 0, -4)\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n look(room, [0, 1.1, -1.5], [0, 1.1, -4])\n room.use()\n step(0.2)\n const p = part(room, id, 'sheet')\n const hole = p?.holes[0]\n expect(\n !!hole?.through,\n t('sc.steel_through_hole.check', { mm: num((hole?.diameter ?? 0) * 1000, 0), through: yn(!!hole?.through), holes: p?.holes.length ?? 0, hp: `${num(p?.hp ?? 0, 0)}/${num(p?.maxHp ?? 0, 0)}` }),\n { holes: p?.holes.length, through: hole?.through },\n )\n }),\n\n sc('concrete_stops_bullet', ({ room, step, expect }) => {\n const id = at(room, 'concrete_block', 0, -4)\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n look(room, [0, 0.5, -1.5], [0, 0.2, -3.8])\n room.use()\n step(0.2)\n const p = part(room, id, 'block')\n const wall = part(room, 'target_wall', 'brick_1_4')\n const through = p?.holes.some((h) => h.through) ?? true\n expect(\n !through && (p?.holes.length ?? 0) + (p?.dents.length ?? 0) + (p?.cracks.length ?? 0) > 0 && (wall?.holes.length ?? 0) === 0,\n t('sc.concrete_stops_bullet.check', { through: yn(through), dents: cn('dent', p?.dents.length ?? 0), holes: cn('hole', p?.holes.length ?? 0), cracks: cn('crack', p?.cracks.length ?? 0), hp: `${num(p?.hp ?? 0, 0)}/${num(p?.maxHp ?? 0, 0)}` }),\n { through },\n )\n }),\n\n sc('hammer_dents_drum', ({ room, step, expect }) => {\n const id = at(room, 'steel_drum', 0, -4)\n room.setTool('hammer')\n room.waitUntilReady()\n look(room, [0, 0.6, -3.35], [0, 0.5, -4])\n let swings = 0\n for (; swings < 8 && (part(room, id, 'drum_body')?.dents.length ?? 0) === 0; swings++) {\n room.use()\n step(1)\n }\n const p = part(room, id, 'drum_body')\n expect(\n (p?.dents.length ?? 0) > 0 && p?.status !== 'broken',\n t('sc.hammer_dents_drum.check', { swings, dents: p?.dents.length ?? 0, depth: num((p?.dents[0]?.depth ?? 0) * 1000, 1), hp: `${num(p?.hp ?? 0, 0)}/${num(p?.maxHp ?? 0, 0)}` }),\n { swings },\n )\n }),\n\n sc('glass_shatters', ({ room, step, expect }) => {\n const id = at(room, 'glass_pane', 0, -4)\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n look(room, [0, 1.3, -1.5], [0, 1.05, -4])\n let shots = 0\n for (; shots < 10 && part(room, id, 'pane')?.status !== 'broken'; shots++) {\n room.use()\n step(0.25)\n }\n step(0.5)\n const fr = room.log.entries({ type: 'fracture', objectId: id }).find((e) => e.part === 'pane')\n const n = Number(fr?.data?.fragments ?? 0)\n expect(part(room, id, 'pane')?.status === 'broken' && shots === 1 && n >= 4, t('sc.glass_shatters.check', { shots, n }), { shots, fragments: n })\n }),\n\n sc('shotgun_splinters_crate', ({ room, step, expect }) => {\n const id = at(room, 'wooden_crate', 0, -4)\n room.setTool('shotgun_pump_12')\n room.waitUntilReady()\n look(room, [0, 0.6, -1.8], [0, 0.25, -3.77])\n let shots = 0\n const splinters = (): number => room.log.entries({ type: 'fracture', objectId: id }).filter((e) => e.data?.style === 'splinter').length\n for (; shots < 4 && splinters() === 0; shots++) {\n room.use()\n step(1.1)\n }\n const holes = (room.world.state(id)?.parts ?? []).reduce((n, p) => n + p.holes.length, 0)\n expect(splinters() > 0, t('sc.shotgun_splinters_crate.check', { shots, splinters: splinters(), holes }), { shots })\n }),\n\n sc('kick_chair_leg', ({ room, step, expect }) => {\n const id = at(room, 'chair', 0, -4)\n const before = room.renderer.pieces().length\n const leg = part(room, id, 'leg_1')\n void leg\n let kicks = 0\n for (; kicks < 6 && room.renderer.pieces().length <= before && part(room, id, 'leg_1'); kicks++) {\n room.world.hitPart(id, 'leg_1', { type: 'blunt', point: [-0.18, 0.2, -4.18], direction: [1, 0, 0], energy: 220, radius: 0.05, source: 'kick' })\n step(0.3)\n }\n step(0.5)\n const after = room.renderer.pieces().length\n const groups = room.world.state(id)?.groups.length ?? 1\n expect(\n after > before,\n t('sc.kick_chair_leg.check', { kicks, groups, before, after, leg: part(room, id, 'leg_1') ? t('leg.still') : t('leg.gone') }),\n { kicks, before, after },\n )\n }),\n\n sc('kick_detaches_leg_via_tool', ({ room, step, expect }) => {\n const id = at(room, 'chair', 0, -4)\n const before = room.renderer.pieces().length\n room.setTool('kick')\n room.waitUntilReady()\n let kicks = 0\n for (; kicks < 8 && room.renderer.pieces().length <= before && part(room, id, 'leg_1'); kicks++) {\n // the chair moves when it is kicked: aim at the leg where it is now, from the side\n const st = room.world.state(id)!\n const leg = toWorld(st.position, st.rotation, [-0.18, 0.2, -0.18])\n const side = rotateVec(st.rotation, [-0.8, 0, 0])\n look(room, [leg[0] + side[0], leg[1] + side[1], leg[2] + side[2]], leg)\n room.use()\n step(1.05)\n }\n step(0.5)\n const after = room.renderer.pieces().length\n expect(after > before, t('sc.kick_detaches_leg_via_tool.check', { kicks, before, after, leg: part(room, id, 'leg_1') ? t('leg.still') : t('leg.gone') }), { kicks, before, after })\n }),\n\n sc('screwdriver_shelf_board', ({ room, step, expect }) => {\n const id = at(room, 'shelf', 0, -4)\n room.setTool('screwdriver')\n room.waitUntilReady()\n look(room, [0, 0.8, -3.5], [0, 0.75, -3.86])\n const t0 = room.log.entries().length ? room.log.entries().slice(-1)[0].t : 0\n room.use(5)\n const done = room.log.entries({ type: 'detach', objectId: id })[0]\n const elapsed = done ? done.t - t0 : 5\n const want = JOINT_DEFAULTS.screw.seconds\n const groups = room.renderer.pieces().length\n expect(!!done && Math.abs(elapsed - want) < 0.6 && groups >= 1, t('sc.screwdriver_shelf_board.check', { secs: num(elapsed, 1), want: num(want, 1), pieces: pc(groups) }), { elapsed, want })\n step(0.2)\n }),\n\n sc('wrong_tool_refused', ({ room, expect }) => {\n const id = at(room, 'steel_sheet', 0, -4)\n room.setTool('screwdriver')\n room.waitUntilReady()\n look(room, [0.2, 1.05, -3.6], [0.34, 1.0, -4])\n room.use(0.5)\n const refused = count(room, 'tool_refused')\n const opened = (room.world.state(id)?.joints ?? []).filter((j) => j.open).length\n expect(refused > 0 && opened === 0, t('sc.wrong_tool_refused.check', { refused, opened }), { refused, opened })\n }),\n\n sc('lighter_burns_crate', ({ room, step, expect }) => {\n const id = at(room, 'wooden_crate', 0, -4)\n room.setTool('lighter')\n room.waitUntilReady()\n look(room, [0, 0.3, -3.65], [0, 0.25, -3.76])\n room.use(5)\n const lit = anyBurning(room, id)\n expect(lit, t('sc.lighter_burns_crate.lit', { lit: yn(lit) }))\n step(500)\n const parts = room.world.state(id)?.parts ?? []\n const ash = parts.filter((p) => p.status === 'ashes').length\n const charred = Math.max(...parts.map((p) => p.char))\n expect(ash === parts.length || (ash > 0 && parts.every((p) => p.status === 'ashes' || p.status === 'broken' || p.char > 0.8)), t('sc.lighter_burns_crate.ash', { ash, total: parts.length, char: num(charred * 100, 0) }), { ash, total: parts.length })\n }),\n\n sc('torch_melts_steel', ({ room, step, expect }) => {\n const drum = at(room, 'steel_drum', 0, -4)\n const crate = at(room, 'wooden_crate', 0.7, -4)\n igniteHit(room, crate, [0.7, 0.25, -3.8], 900, 2)\n let peak = 0\n for (let i = 0; i < 40; i++) {\n step(1)\n peak = Math.max(peak, part(room, drum, 'drum_body')?.temperature ?? 0)\n }\n const melt0 = part(room, drum, 'drum_body')?.melt ?? 0\n expect(melt0 === 0 && peak < 1450, t('sc.torch_melts_steel.wood', { peak: num(peak, 0), melt: num(melt0 * 100, 0), crate: yn(anyBurning(room, crate)) }), { peak })\n room.setTool('cutting_torch')\n room.waitUntilReady()\n look(room, [-0.15, 0.55, -3.55], [-0.15, 0.5, -3.72])\n room.use(20)\n const p = part(room, drum, 'drum_body')\n expect((p?.melt ?? 0) > 0.02 || p?.status === 'melted' || (p?.holes.length ?? 0) > 0, t('sc.torch_melts_steel.torch', { temp: num(p?.temperature ?? 0, 0), melt: num((p?.melt ?? 0) * 100, 0) }), { temperature: p?.temperature, melt: p?.melt })\n }),\n\n sc('bucket_melts_drips', ({ room, step, expect }) => {\n const id = at(room, 'plastic_bucket', 0, -4)\n room.setTool('flamethrower')\n room.waitUntilReady()\n look(room, [0, 0.5, -2.4], [0, 0.15, -4])\n room.use(2.5)\n step(10)\n const p = part(room, id, 'bucket_body')\n const drips = count(room, 'drip', id)\n expect((p?.melt ?? 0) > 0.05 || p?.status === 'melted', t('sc.bucket_melts_drips.check', { melt: num((p?.melt ?? 0) * 100, 0), drips, temp: num(p?.temperature ?? 0, 0) }), { melt: p?.melt, drips })\n }),\n\n sc('gas_bottle_explodes', ({ room, step, expect }) => {\n const bottle = at(room, 'gas_bottle', 0, -4)\n const crate = at(room, 'wooden_crate', 1.3, -4)\n const c0 = room.spawned().find((s) => s.objectId === crate)?.root.position.clone()\n let seconds = 0\n for (; seconds < 60 && count(room, 'explode', bottle) === 0; seconds++) {\n igniteHit(room, bottle, [0, 0.4, -3.9], 1000, 1)\n step(1)\n }\n step(1.5)\n const c1 = room.spawned().find((s) => s.objectId === crate)?.root.position\n const moved = c0 && c1 ? c0.distanceTo(c1) : 0\n const state = room.world.state(crate)\n const lost = (state?.parts ?? []).filter((p) => p.status === 'broken').length + (state && state.groups.length > 1 ? 1 : 0)\n expect(count(room, 'explode', bottle) > 0, t('sc.gas_bottle_explodes.explode', { seconds }), { seconds })\n expect(moved > 0.3 || lost > 0, t('sc.gas_bottle_explodes.push', { moved: num(moved, 1), lost: pc(lost) }), { moved, lost })\n }),\n\n sc('bottle_drop_shatters', ({ room, step, expect }) => {\n const id = at(room, 'glass_bottle', 0, -3, 1.5)\n step(2)\n const p = part(room, id, 'bottle_body')\n const stain = room.fluids.stains().find((s) => s.liquid === 'water')\n expect(p?.status === 'broken', t('sc.bottle_drop_shatters.check', { status: p?.status ?? '?', cracks: p?.cracks.length ?? 0, stain: yn(!!stain) }), { status: p?.status })\n }),\n\n sc('throw_chair_at_wall', ({ room, step, expect }) => {\n const id = at(room, 'chair', 0, -5.2)\n look(room, [0, 1.7, -4.2], [0, 0.35, -5.2])\n room.grab()\n look(room, [0, 1.7, -4.2], [0, 2.3, -11])\n step(0.3)\n room.throwHeld(16)\n step(2.5)\n const hits = room.log.entries({ type: 'impact' })\n const wallDamage = room.log.entries().filter((e) => e.objectId === 'target_wall' && (e.type === 'dent' || e.type === 'damage' || e.type === 'crack' || e.type === 'fracture')).length\n expect(hits.length > 0 && wallDamage > 0, t('sc.throw_chair_at_wall.check', { impacts: hits.length, wall: wallDamage, energy: num(Number(hits[0]?.data?.energyJ ?? 0), 0) }), { id })\n }),\n\n sc('coffee_three_sips', ({ room, step, expect }) => {\n const id = at(room, 'coffee_cup', 0, -3)\n look(room, [0, 1.0, -1.8], [0, 0.05, -3])\n const cid = `${id}_fluid`\n const before = room.fluids.container(cid)?.liters ?? 0\n room.grab()\n for (let i = 0; i < 3; i++) {\n room.useItem('sip')\n step(1.4)\n }\n const after = room.fluids.container(cid)?.liters ?? 0\n const drinks = room.log.entries().filter((e) => e.type === 'fluid.drink')\n const caffeine = drinks.some((e) => Array.isArray(e.data?.effects) && (e.data?.effects as string[]).includes('caffeine'))\n expect(drinks.length === 3 && before - after > 0.06 && caffeine, t('sc.coffee_three_sips.check', { sips: drinks.length, before: num(before, 2), after: num(after, 2), caffeine: yn(caffeine), burn: yn(drinks.some((e) => !!e.data?.burn)) }), { before, after })\n }),\n\n sc('tilt_cup_spills', ({ room, step, expect }) => {\n const id = at(room, 'coffee_cup', 0, -3)\n look(room, [0, 1.0, -1.8], [0, 0.05, -3])\n const cid = `${id}_fluid`\n const before = room.fluids.container(cid)?.liters ?? 0\n room.grab()\n step(0.6)\n room.tilt(2.0)\n step(2.5)\n const after = room.fluids.container(cid)?.liters ?? 0\n const stains = room.fluids.stains().filter((s) => s.liquid === 'coffee').length\n expect(before - after > 0.03 && stains > 0, t('sc.tilt_cup_spills.check', { before: num(before, 2), after: num(after, 2), stains }), { before, after })\n }),\n\n sc('jerrycan_leaks_fuel', ({ room, step, expect }) => {\n const id = at(room, 'jerrycan', 0, -3.5)\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n look(room, [0, 0.4, -1.5], [0, 0.12, -3.43])\n room.use()\n step(1.5)\n const streams = room.fluids.streams().filter((s) => s.cause === 'leak' && s.liquid === 'fuel')\n step(5)\n const stain = room.fluids.stains().find((s) => s.liquid === 'fuel')\n const left = room.fluids.container(`${id}_fluid`)?.liters ?? 20\n const hole = room.log.entries({ type: 'hole', objectId: id })[0]\n expect(streams.length > 0 && !!stain && left < 20, t('sc.jerrycan_leaks_fuel.check', { streams: streams.length, stain: yn(!!stain), left: num(left, 2), leak: hole?.data?.leak ? yn(true) : yn(false) }), { left })\n }),\n\n sc('fuel_stain_burns', ({ room, step, expect }) => {\n const id = at(room, 'jerrycan', 0, -3.5)\n const crate = at(room, 'wooden_crate', 0.9, -3.2)\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n look(room, [0, 0.4, -1.5], [0, 0.12, -3.43])\n room.use()\n step(6)\n const stain = room.fluids.stains().find((s) => s.liquid === 'fuel')\n expect(!!stain, t('sc.fuel_stain_burns.stain', { stain: yn(!!stain) }))\n if (!stain) return\n room.setTool('lighter')\n room.waitUntilReady()\n look(room, [stain.center[0], 0.1, stain.center[2] + 0.06], [stain.center[0], 0, stain.center[2]])\n room.use(1)\n step(4)\n const ignited = count(room, 'stain_ignite')\n const fireHits = (room.world.state(id)?.parts ?? []).some((p) => p.burning || p.temperature > 100) || anyBurning(room, crate)\n expect(ignited > 0, t('sc.fuel_stain_burns.ignite', { ignited, near: yn(fireHits) }), { ignited })\n step(30)\n expect(count(room, 'stain_burned') > 0 || room.fluids.stains().filter((s) => s.liquid === 'fuel' && s.wetness > 0.05).length === 0, t('sc.fuel_stain_burns.out', { burned: count(room, 'stain_burned') }))\n }),\n\n sc('one_column_roof_stands', ({ room, step, expect }) => {\n const id = at(room, 'building_frame', 0, -6)\n killColumns(room, id, ['column_0_0_0'])\n step(40)\n const roof = part(room, id, 'roof')\n const neighbour = (part(room, id, 'column_0_0_1') as unknown as { stress?: number } | null)?.stress ?? 0\n const heavy = Math.max(heavyCollapse(room), ...room.renderer.pieces().map((p) => p.mass))\n expect(!!roof && roof.status !== 'broken' && heavy < 2000, t('sc.one_column_roof_stands.check', { roof: roof ? t('roof.standing') : t('roof.fell'), heavy: num(heavy, 0), stress: num(neighbour * 100, 0) }), { heavy, neighbour })\n }),\n\n sc('two_columns_roof_collapses', ({ room, step, expect }) => {\n const id = at(room, 'building_frame', 0, -6)\n killColumns(room, id, ['column_0_0_0', 'column_0_1_0'])\n const stress0 = (room.world.part(id, 'column_0_0_1') as unknown as { stress?: number } | null)?.stress ?? 0\n step(40)\n const pieces = room.renderer.pieces().filter((p) => p.mass >= 2000)\n const logged = heavyCollapse(room) >= 2000\n const kg = pieces.reduce((m, p) => m + p.mass, 0)\n expect(!part(room, id, 'roof') && pieces.length > 0, t('sc.two_columns_roof_collapses.check', { stress: num(stress0 * 100, 0), pieces: pc(pieces.length), kg: num(kg, 0), logged: yn(logged) }), { kg, logged })\n }),\n\n sc('extinguisher_puts_out_fire', ({ room, step, expect }) => {\n const id = at(room, 'wooden_crate', 0, -4)\n igniteHit(room, id, [0, 0.25, -3.8], 900, 4)\n step(6)\n const before = anyBurning(room, id)\n expect(before, t('sc.extinguisher_puts_out_fire.burning', { burning: yn(before) }))\n room.setTool('extinguisher')\n room.waitUntilReady()\n look(room, [0, 0.9, -2.2], [0, 0.25, -4])\n room.use(2.5)\n step(1)\n const after = anyBurning(room, id)\n expect(!after, t('sc.extinguisher_puts_out_fire.out', { burning: yn(after), events: count(room, 'extinguish', id) }), { events: count(room, 'extinguish', id) })\n }),\n ]\n}\n\nconst makeT =\n (locale: string): T =>\n (key, vars) => {\n let s = resolveStrings(locale).text[key] ?? key\n if (vars) for (const k of Object.keys(vars)) s = s.split(`{${k}}`).join(String(vars[k]))\n return s\n }\n\n/** The built-in scenarios for a locale (`en` or `pt-BR`), standalone: no room needed to list them. */\nexport function scenariosFor(locale = 'en'): TestRoomScenario[] {\n const pt = locale.toLowerCase().startsWith('pt')\n return makeScenarios(makeT(locale), (n, d = 1) => (pt ? (Math.round(n * 10 ** d) / 10 ** d).toFixed(d).replace('.', ',') : (Math.round(n * 10 ** d) / 10 ** d).toFixed(d)), locale)\n}\n\n/** The built-in scenarios in English. The room offers them in its own locale. */\nexport const SCENARIOS: TestRoomScenario[] = scenariosFor('en')\n","import type { BenchSheet, ControlValue } from '@adatechnology/game-contracts'\nimport type { BenchControl, BenchLayer } from './types'\n\n/** What the bench panel shows: the active module's bench, or only the room counters. */\nexport interface BenchView {\n readonly title: string\n readonly controls: readonly BenchControl[]\n readonly layers: readonly BenchLayer[]\n readonly sheet?: BenchSheet | null\n}\n\nexport interface MetricRow {\n readonly id: string\n readonly name: string\n readonly text: string\n /** The number behind `text`, when the metric reads one (a sheet's playhead follows it). */\n readonly value?: number\n /** Value over the budget, when the metric has one. */\n readonly ratio?: number\n}\n\nexport interface BenchPanelOptions {\n t: (key: string, vars?: Record<string, string | number>) => string\n num: (n: number, digits?: number) => string\n onControl: (id: string, value: ControlValue) => void\n onLayer: (id: string, on: boolean) => void\n onAction: (id: string) => void\n}\n\nexport interface BenchPanel {\n readonly element: HTMLElement\n show(view: BenchView | null): void\n metrics(rows: { room: readonly MetricRow[]; module: readonly MetricRow[] }): void\n readonly visible: boolean\n}\n\nconst SEGMENTED_MAX = 4\n\nconst mk = <K extends keyof HTMLElementTagNameMap>(tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] => {\n const e = document.createElement(tag)\n if (cls) e.className = cls\n if (text !== undefined) e.textContent = text\n return e\n}\n\n// the shape of the panel without the values: when it is unchanged the values are updated in place (a range being dragged keeps its focus)\nconst shapeOf = (view: BenchView): string =>\n JSON.stringify([view.title, view.controls.map((c) => ({ ...c, value: undefined })), view.layers.map((l) => [l.id, l.name]), view.sheet ?? null])\n\nexport function createBenchPanel(o: BenchPanelOptions): BenchPanel {\n const { t } = o\n const element = mk('div', 'tr-panel tr-bench')\n element.style.display = 'none'\n element.addEventListener('keydown', (e) => e.stopPropagation())\n const roomLine = mk('div', 'sub tr-bench-room')\n const body = mk('div')\n const metricTitle = mk('div', 'sub', t('ui.metrics'))\n metricTitle.style.display = 'none'\n const metricList = mk('dl', 'tr-metrics')\n element.append(mk('h3', undefined, t('ui.bench')), roomLine, body, metricTitle, metricList)\n\n let shape = ''\n let hasRoom = false\n let hasBench = false\n const refreshers: Array<(view: BenchView) => void> = []\n const metricNodes = new Map<string, { text: HTMLElement; bar: HTMLElement | null }>()\n let metricKey = ''\n\n const syncDisplay = (): void => {\n element.style.display = hasRoom || hasBench ? '' : 'none'\n }\n\n const numberControl = (control: Extract<BenchControl, { kind: 'number' }>): HTMLElement => {\n const wrap = mk('label', 'tr-ctl')\n const input = mk('input')\n input.type = 'range'\n input.min = String(control.min)\n input.max = String(control.max)\n input.step = control.step ? String(control.step) : 'any'\n input.disabled = control.disabled\n const reading = mk('output')\n input.oninput = () => o.onControl(control.id, Number(input.value))\n wrap.append(mk('span', undefined, control.name), input, reading)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n if (typeof value !== 'number') return\n if (Number(input.value) !== value) input.value = String(value)\n reading.textContent = `${o.num(value, control.step && control.step >= 1 ? 0 : 2)}${control.unit ? ` ${control.unit}` : ''}`\n })\n return wrap\n }\n\n const booleanControl = (control: BenchControl): HTMLElement => {\n const wrap = mk('label', 'tr-ctl')\n const box = mk('input')\n box.type = 'checkbox'\n box.disabled = control.disabled\n box.onchange = () => o.onControl(control.id, box.checked)\n wrap.append(box, document.createTextNode(` ${control.name}`))\n refreshers.push((view) => {\n box.checked = view.controls.find((c) => c.id === control.id)?.value === true\n })\n return wrap\n }\n\n const choiceControl = (control: Extract<BenchControl, { kind: 'choice' }>): HTMLElement => {\n const wrap = mk('div', 'tr-ctl')\n wrap.appendChild(mk('span', undefined, control.name))\n const grouped = control.options.some((option) => option.group !== undefined)\n if (control.options.length <= SEGMENTED_MAX && !grouped) {\n const group = mk('div', 'tr-seg')\n group.setAttribute('role', 'group')\n const buttons = control.options.map((option) => {\n const b = mk('button', 'tr-btn', option.name)\n b.type = 'button'\n b.disabled = control.disabled\n b.onclick = () => o.onControl(control.id, option.id)\n group.appendChild(b)\n return { b, id: option.id }\n })\n wrap.appendChild(group)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n for (const { b, id } of buttons) {\n b.setAttribute('aria-pressed', String(id === value))\n b.classList.toggle('on', id === value)\n }\n })\n return wrap\n }\n const select = mk('select')\n select.disabled = control.disabled\n let heading: string | undefined\n let section: HTMLElement = select\n for (const option of control.options) {\n if (option.group !== heading) {\n heading = option.group\n section = select\n if (heading !== undefined) {\n const optgroup = mk('optgroup')\n optgroup.label = heading\n select.appendChild(optgroup)\n section = optgroup\n }\n }\n const op = mk('option', undefined, option.name)\n op.value = option.id\n section.appendChild(op)\n }\n select.onchange = () => o.onControl(control.id, select.value)\n wrap.appendChild(select)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n if (typeof value === 'string') select.value = value\n })\n return wrap\n }\n\n const actionControl = (control: BenchControl): HTMLElement => {\n const b = mk('button', 'tr-btn', control.name)\n b.type = 'button'\n b.disabled = control.disabled\n b.onclick = () => o.onAction(control.id)\n return b\n }\n\n const controlElement = (control: BenchControl): HTMLElement => {\n const el = control.kind === 'number' ? numberControl(control) : control.kind === 'boolean' ? booleanControl(control) : control.kind === 'choice' ? choiceControl(control) : actionControl(control)\n if (control.hint) el.title = control.hint\n return el\n }\n\n const layerList = (layers: readonly BenchLayer[]): HTMLElement => {\n const wrap = mk('div', 'tr-layers')\n wrap.appendChild(mk('div', 'sub', t('ui.layers')))\n for (const layer of layers) {\n const label = mk('label', 'tr-ctl')\n const box = mk('input')\n box.type = 'checkbox'\n box.onchange = () => o.onLayer(layer.id, box.checked)\n label.append(box, document.createTextNode(` ${layer.name}`))\n wrap.appendChild(label)\n refreshers.push((view) => {\n box.checked = view.layers.find((l) => l.id === layer.id)?.on === true\n })\n }\n return wrap\n }\n\n let playhead: { node: HTMLElement; metric: string; end: number } | null = null\n\n const sheetCard = (sheet: BenchSheet): HTMLElement => {\n const card = mk('div', 'tr-sheet')\n if (sheet.kicker) card.appendChild(mk('div', 'sub', sheet.kicker))\n card.appendChild(mk('h4', undefined, sheet.title))\n if (sheet.body) card.appendChild(mk('p', undefined, sheet.body))\n if (sheet.facts?.length) {\n const facts = mk('dl', 'tr-facts')\n for (const fact of sheet.facts) facts.append(mk('dt', undefined, fact.label), mk('dd', undefined, fact.value))\n card.appendChild(facts)\n }\n if (sheet.steps?.length) {\n const steps = mk('ol', 'tr-steps')\n for (const step of sheet.steps) {\n const li = mk('li')\n li.append(mk('b', undefined, step.at), document.createTextNode(` ${step.text}`))\n steps.appendChild(li)\n }\n card.appendChild(steps)\n }\n if (sheet.swatches?.length) {\n const row = mk('div', 'tr-swatches')\n for (const swatch of sheet.swatches) {\n const chip = mk('span', 'tr-swatch')\n const dot = mk('i')\n dot.style.background = swatch.color\n chip.append(dot, document.createTextNode(swatch.name))\n row.appendChild(chip)\n }\n card.appendChild(row)\n }\n if (sheet.timeline) {\n const { segments, ticks, metric } = sheet.timeline\n const end = Math.max(0.001, ...segments.map((segment) => segment.end), ...ticks)\n const strip = mk('div', 'tr-timeline')\n for (const segment of segments) {\n const bar = mk('div', 'tr-segment', segment.name)\n bar.style.left = `${(segment.start / end) * 100}%`\n bar.style.width = `${((segment.end - segment.start) / end) * 100}%`\n bar.style.background = segment.color\n strip.appendChild(bar)\n }\n for (const tick of ticks) {\n const mark = mk('u', 'tr-tick')\n mark.style.left = `${(tick / end) * 100}%`\n strip.appendChild(mark)\n }\n const head = mk('s', 'tr-playhead')\n strip.appendChild(head)\n playhead = { node: head, metric, end }\n card.appendChild(strip)\n }\n if (sheet.note) card.appendChild(mk('p', 'sub', sheet.note))\n return card\n }\n\n const rebuild = (view: BenchView): void => {\n playhead = null\n body.textContent = ''\n refreshers.length = 0\n body.appendChild(mk('div', 'sub', view.title))\n const list = mk('div', 'tr-ctls')\n for (const control of view.controls) if (!control.hidden) list.appendChild(controlElement(control))\n body.appendChild(list)\n if (view.layers.length) body.appendChild(layerList(view.layers))\n if (view.sheet) body.appendChild(sheetCard(view.sheet))\n }\n\n const renderMetrics = (rows: readonly MetricRow[]): void => {\n metricList.textContent = ''\n metricNodes.clear()\n metricTitle.style.display = rows.length ? '' : 'none'\n for (const row of rows) {\n const dd = mk('dd')\n const text = mk('span', undefined, row.text)\n dd.appendChild(text)\n let bar: HTMLElement | null = null\n if (row.ratio !== undefined) {\n bar = mk('div', 'tr-bar')\n bar.appendChild(mk('i'))\n dd.appendChild(bar)\n }\n metricList.append(mk('dt', undefined, row.name), dd)\n metricNodes.set(row.id, { text, bar })\n }\n }\n\n const fillBar = (bar: HTMLElement, ratio: number): void => {\n bar.className = `tr-bar${ratio > 1 ? ' bad' : ratio >= 0.8 ? ' warn' : ''}`\n const fill = bar.firstElementChild as HTMLElement\n fill.style.width = `${Math.round(Math.max(0, Math.min(1, ratio)) * 100)}%`\n }\n\n return {\n element,\n show(view) {\n hasBench = view !== null\n syncDisplay()\n if (!view) {\n playhead = null\n shape = ''\n body.textContent = ''\n refreshers.length = 0\n renderMetrics([])\n metricKey = ''\n return\n }\n const next = shapeOf(view)\n if (next !== shape) {\n shape = next\n rebuild(view)\n }\n for (const refresh of refreshers) refresh(view)\n },\n metrics(rows) {\n hasRoom = rows.room.length > 0\n syncDisplay()\n roomLine.textContent = rows.room.map((row) => `${row.name} ${row.text}`).join(' · ')\n const key = rows.module.map((row) => `${row.id}:${row.ratio !== undefined}`).join('|')\n if (key !== metricKey) {\n metricKey = key\n renderMetrics(rows.module)\n }\n for (const row of rows.module) {\n const node = metricNodes.get(row.id)\n if (!node) continue\n node.text.textContent = row.text\n if (node.bar && row.ratio !== undefined) fillBar(node.bar, row.ratio)\n }\n if (playhead) {\n const at = rows.module.find((row) => row.id === playhead?.metric)?.value\n playhead.node.style.left = `${Math.max(0, Math.min(1, (at ?? 0) / playhead.end)) * 100}%`\n }\n },\n get visible() {\n if (element.style.display === 'none') return false\n const parent = element.parentElement\n return !parent || getComputedStyle(parent).display !== 'none'\n },\n }\n}\n","import type { ControlValue } from '@adatechnology/game-contracts'\nimport { createBenchPanel } from './bench-panel'\nimport type { BenchView, MetricRow } from './bench-panel'\nimport type { WritableLog } from './log'\nimport type { RoomStrings } from './locale'\nimport type { AnimationInfo, LogEntry, ScenarioReport, TestRoomItem, TestRoomScenario } from './types'\n\nexport interface InspectInfo {\n object: string\n objectId: string\n part: string\n material: string\n status: string\n hp: number\n maxHp: number\n temperature: number\n burning: boolean\n char: number\n melt: number\n liters?: number\n dents: number\n holes: number\n cracks: number\n mass: number\n /** Structural load in kg and stress (load / capacity) when the core reports them. */\n load?: number\n stress?: number\n joints: Array<{ id: string; kind: string; tools: string[]; open: boolean; progress: number }>\n note?: string\n /** Thumbnail of the aimed item (`TestRoomItem.thumbnail`). */\n thumbnail?: string\n /** Author and licence of the thumbnail (`TestRoomItem.thumbnailCredit`). */\n thumbnailCredit?: string\n distance: number\n}\n\nexport interface HudState {\n toolName: string\n toolId: string\n ammo: string\n slots: string[]\n slot: number\n page: number\n pages: number\n status: string\n progress: { label: string; value: number } | null\n held: { name: string; uses: Array<{ key: string; label: string }>; weapon?: string; using: string } | null\n inspect: InspectInfo | null\n /** Animations of the aimed or held item. */\n animations: AnimationInfo | null\n locked: boolean\n timeScale: number\n fast: boolean\n tap: boolean\n /** The room's blast options that are on. */\n blast: { shelter: boolean; fragmentHits: boolean; confinement: boolean }\n quality: string\n objects: number\n}\n\nexport interface UiOptions {\n container: HTMLElement\n strings: RoomStrings\n t: (key: string, vars?: Record<string, string | number>) => string\n log: WritableLog\n groups: () => Map<string, TestRoomItem[]>\n loadout: () => Array<{ id: string; name: string }>\n onSpawn: (itemId: string) => void\n onEquip: (itemId: string) => void\n onClear: () => void\n onResetAll: () => void\n onSlow: (on: boolean) => void\n onFast: (on: boolean) => void\n onQuality: (q: 'low' | 'medium' | 'high') => void\n quality: 'low' | 'medium' | 'high'\n scenarios: () => TestRoomScenario[]\n onRun: (s: TestRoomScenario) => Promise<ScenarioReport | void>\n onRunAll: () => Promise<ScenarioReport | void>\n onTool: (index: number) => void\n onTap: () => void\n onBlast: (key: 'shelter' | 'fragmentHits' | 'confinement') => void\n onPlay: (objectId: string, clipId: string) => void\n onResize: () => void\n onControl: (id: string, value: ControlValue) => void\n onLayer: (id: string, on: boolean) => void\n onAction: (id: string) => void\n}\n\nexport interface RoomUi {\n hud(state: HudState): void\n toast(text: string): void\n /** Re-read the catalogue and the scenarios (after `loadModule`). */\n refresh(): void\n /** Open the catalogue on a group tab (its translated name), clearing the search. */\n showGroup(group: string): void\n togglePanels(): void\n /** The active module's bench (null: none). */\n bench(view: BenchView | null): void\n /** Room counters and the active module's metrics, text only. */\n metrics(rows: { room: readonly MetricRow[]; module: readonly MetricRow[] }): void\n /** The bench panel has something to show and is on screen (the room samples its counters only then). */\n readonly benchVisible: boolean\n dispose(): void\n}\n\nconst CSS = `\n.tr-root{position:absolute;inset:0;pointer-events:none;font:12px/1.35 system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;color:#e8eaee;overflow:hidden}\n.tr-root *{box-sizing:border-box}\n.tr-root button,.tr-root select,.tr-root label,.tr-root input{pointer-events:auto}\n.tr-search{width:100%;margin:0 0 6px;padding:5px 8px;border-radius:5px;border:1px solid #3a404c;background:#0f1116;color:#e8eaee;font:inherit}\n.tr-search::placeholder{color:#7d8594}\n.tr-item small{color:#7d8594;margin-left:4px}\n.tr-thumb{display:block;width:100%;height:26px;background:currentColor;-webkit-mask:var(--tr-thumb) center/contain no-repeat;mask:var(--tr-thumb) center/contain no-repeat}\n.tr-item{min-width:0}\n.tr-item .tr-btn.has-thumb{display:flex;flex-direction:column;gap:3px;min-width:0}.tr-item .tr-btn.has-thumb .tr-name{overflow:hidden;text-overflow:ellipsis}\n.tr-insp .tr-thumb{width:140px;height:28px;margin-bottom:3px}\n.tr-empty{color:#9aa3b2;padding:4px 2px;grid-column:1/-1}\n.tr-cross{position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px}\n.tr-cross:before,.tr-cross:after{content:\"\";position:absolute;background:#fff;opacity:.85;box-shadow:0 0 2px #000}\n.tr-cross:before{left:8px;top:0;width:2px;height:18px}.tr-cross:after{top:8px;left:0;height:2px;width:18px}\n.tr-cross i{position:absolute;left:6px;top:6px;width:6px;height:6px;background:#0b0c0e;border-radius:50%;z-index:1}\n.tr-top{position:absolute;top:8px;left:50%;transform:translateX(-50%);text-align:center;max-width:46vw}\n.tr-tool{display:inline-block;background:rgba(10,12,16,.72);padding:4px 12px;border-radius:6px;font-size:14px;font-weight:600}\n.tr-tool small{font-weight:400;opacity:.8;margin-left:8px}\n.tr-status{margin-top:4px;min-height:16px;color:#ffd23f;text-shadow:0 1px 2px #000}\n.tr-prog{margin:4px auto 0;width:260px;background:rgba(10,12,16,.72);border-radius:6px;padding:4px 8px;display:none}\n.tr-prog b{display:block;font-weight:500;margin-bottom:3px}\n.tr-sheet{margin-top:8px;padding:8px;border:1px solid #2a2e36;border-radius:6px;font-size:12px;line-height:1.4}\n.tr-sheet h4{margin:2px 0 4px;font-size:13px}.tr-sheet p{margin:4px 0}\n.tr-facts{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;margin:4px 0}.tr-facts dt{opacity:.7}.tr-facts dd{margin:0}\n.tr-steps{margin:4px 0;padding-left:16px}.tr-swatches{display:flex;flex-wrap:wrap;gap:6px}.tr-swatch i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:4px}\n.tr-timeline{position:relative;height:22px;margin:8px 0;background:#1b1e24;border-radius:4px;overflow:hidden}\n.tr-segment{position:absolute;top:0;height:100%;font-size:10px;overflow:hidden;white-space:nowrap;opacity:.85;padding:0 3px;box-sizing:border-box;color:#000}\n.tr-tick{position:absolute;top:0;bottom:0;width:1px;background:#fff6;text-decoration:none}.tr-playhead{position:absolute;top:0;bottom:0;width:2px;background:#fff;text-decoration:none}\n.tr-bar{height:7px;background:#2a2e36;border-radius:4px;overflow:hidden}\n.tr-bar i{display:block;height:100%;background:#4fc3f7;width:0}\n.tr-bar.hp i{background:#66bb6a}.tr-bar.warn i{background:#ffb300}.tr-bar.bad i{background:#ef5350}\n.tr-bottom{position:absolute;bottom:8px;left:50%;transform:translateX(-50%);text-align:center;max-width:56vw}\n.tr-held{margin-bottom:6px;background:rgba(10,12,16,.72);padding:4px 10px;border-radius:6px;display:none}\n.tr-held kbd,.tr-help kbd{background:#2a2e36;border:1px solid #4a505c;border-radius:3px;padding:0 4px;font:inherit;font-weight:700}\n.tr-hotbar{display:inline-flex;gap:3px;flex-wrap:wrap;justify-content:center}\n.tr-slot{pointer-events:auto;min-width:64px;max-width:92px;padding:3px 5px;background:rgba(10,12,16,.68);border:1px solid #3a404c;border-radius:5px;color:#cfd3da;cursor:pointer;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-slot b{color:#ffd23f;margin-right:3px}\n.tr-slot.on{border-color:#ffd23f;color:#fff;background:rgba(60,50,10,.8)}\n.tr-help{position:absolute;left:8px;bottom:8px;max-width:360px;opacity:.75;font-size:11px;background:rgba(10,12,16,.55);padding:4px 8px;border-radius:6px}\n.tr-left{position:absolute;top:8px;left:8px;bottom:70px;width:min(400px,36vw);display:flex;flex-direction:column;gap:8px}\n.tr-right{position:absolute;top:8px;right:8px;bottom:8px;width:min(310px,34vw);display:flex;flex-direction:column;gap:8px}\n.tr-panel{background:rgba(12,14,19,.82);border:1px solid #2c313b;border-radius:8px;padding:8px;pointer-events:auto;overflow:auto}\n.tr-panel h3{margin:0 0 6px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#9aa3b2;font-weight:600}\n.tr-insp{flex:0 0 auto;max-height:46%;min-height:60px}\n.tr-insp .r{display:flex;justify-content:space-between;gap:8px}.tr-insp .r span:first-child{color:#9aa3b2}\n.tr-insp .t{font-weight:600;font-size:13px;margin-bottom:3px}\n.tr-log{flex:1 1 auto;display:flex;flex-direction:column;min-height:120px;overflow:hidden}\n.tr-logbar{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:5px;align-items:center}\n.tr-logbody{flex:1;overflow:auto;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;background:#090a0d;border-radius:5px;padding:4px 6px}\n.tr-logbody div{white-space:pre-wrap;word-break:break-word;border-bottom:1px solid #15171c}\n.tr-logbody .action{color:#8fd3ff}.tr-logbody .event{color:#dfe3ea}.tr-logbody .check{color:#c8e6c9}.tr-logbody .check.fail{color:#ff8a80;font-weight:700}.tr-logbody .check.pass{color:#9be59f}\n.tr-logbody time{color:#6b7280;margin-right:6px}\n.tr-btn,.tr-root button.tr-btn{background:#232831;border:1px solid #3a404c;color:#e8eaee;border-radius:5px;padding:3px 8px;cursor:pointer;font:inherit}\n.tr-btn:hover{background:#2d3440}.tr-btn.on{background:#3b3a14;border-color:#ffd23f;color:#fff}\n.tr-btn.pass{border-color:#4caf50}.tr-btn.fail{border-color:#ef5350;background:#3a1d1d}\n.tr-tabs{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:6px}\n.tr-items{display:grid;grid-template-columns:1fr 1fr;gap:4px}\n.tr-item{display:flex;gap:2px}.tr-item .tr-btn:first-child{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-cat{flex:0 1 auto;max-height:40%}\n.tr-anim{flex:0 0 auto;max-height:18%}\n.tr-anim .list{display:flex;flex-wrap:wrap;gap:4px}.tr-anim .sub{color:#9aa3b2;margin-bottom:4px}\n.tr-bench{flex:0 1 auto;max-height:34%}\n.tr-bench .sub{color:#9aa3b2;margin-bottom:4px}\n.tr-ctls{display:flex;flex-direction:column;gap:5px}\n.tr-ctl{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.tr-ctl input[type=range]{flex:1;min-width:90px}.tr-ctl output{min-width:48px;text-align:right;color:#cfd3da}\n.tr-seg{display:inline-flex;flex-wrap:wrap;gap:2px}\n.tr-layers{margin-top:6px;display:flex;flex-direction:column;gap:2px}\n.tr-metrics{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;margin:6px 0 0}.tr-metrics dt{color:#9aa3b2}.tr-metrics dd{margin:0}\n.tr-tests{flex:1 1 auto;min-height:100px}\n.tr-tests .list{display:flex;flex-direction:column;gap:3px;margin-top:6px}.tr-tests .list .tr-btn{text-align:left}\n.tr-row{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;align-items:center}\n.tr-toggle{position:absolute;top:8px;right:8px;display:none}\n.tr-summary{margin-top:6px;color:#9aa3b2}\n@media (max-width:980px){.tr-left,.tr-right{display:none}.tr-root.open .tr-left,.tr-root.open .tr-right{display:flex}.tr-toggle{display:block;pointer-events:auto}.tr-root.open .tr-toggle{right:min(310px,34vw)}.tr-left{width:min(400px,46vw)}.tr-help{display:none}}\n`\n\n// accents are dropped on both sides of a search, so \"gas\" finds \"gás\"\nconst fold = (text: string): string => text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase()\n\nconst mk = <K extends keyof HTMLElementTagNameMap>(tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] => {\n const e = document.createElement(tag)\n if (cls) e.className = cls\n if (text !== undefined) e.textContent = text\n return e\n}\n\n// An SVG given as markup becomes a data URI; either way the picture is a mask over the text colour, so a one-colour silhouette follows the theme.\nconst thumbSource = (thumbnail: string): string => {\n const source = thumbnail.trim().startsWith('<') ? `data:image/svg+xml,${encodeURIComponent(thumbnail.trim())}` : thumbnail.trim()\n return source.replace(/[\"\\\\\\n\\r]/g, (char) => encodeURIComponent(char))\n}\nconst thumb = (thumbnail: string, credit?: string): HTMLElement => {\n const e = mk('span', 'tr-thumb')\n if (credit) e.title = credit\n else e.setAttribute('aria-hidden', 'true')\n e.style.setProperty('--tr-thumb', `url(\"${thumbSource(thumbnail)}\")`)\n return e\n}\n\nexport function createUi(o: UiOptions): RoomUi {\n const { t } = o\n const style = mk('style')\n style.textContent = CSS\n const root = mk('div', 'tr-root')\n const pos = getComputedStyle?.(o.container)?.position\n if (!pos || pos === 'static') o.container.style.position = 'relative'\n root.appendChild(style)\n o.container.appendChild(root)\n\n // crosshair, top bar\n const cross = mk('div', 'tr-cross')\n cross.appendChild(mk('i'))\n const top = mk('div', 'tr-top')\n const toolBox = mk('div', 'tr-tool')\n const status = mk('div', 'tr-status')\n const prog = mk('div', 'tr-prog')\n const progLabel = mk('b')\n const progBar = mk('div', 'tr-bar')\n const progFill = mk('i')\n progBar.appendChild(progFill)\n prog.append(progLabel, progBar)\n top.append(toolBox, status, prog)\n\n // bottom: held hint and hotbar\n const bottom = mk('div', 'tr-bottom')\n const held = mk('div', 'tr-held')\n const hotbar = mk('div', 'tr-hotbar')\n bottom.append(held, hotbar)\n const help = mk('div', 'tr-help')\n help.textContent = t('ui.help')\n\n // left: inspector + log\n const left = mk('div', 'tr-left')\n const insp = mk('div', 'tr-panel tr-insp')\n const logPanel = mk('div', 'tr-panel tr-log')\n left.append(insp, logPanel)\n\n // log panel\n const logTitle = mk('h3', undefined, t('ui.log'))\n const logBar = mk('div', 'tr-logbar')\n const logBody = mk('div', 'tr-logbody')\n const filters: Record<LogEntry['channel'], boolean> = { action: true, event: true, check: true }\n const filterBtns: HTMLButtonElement[] = []\n for (const ch of ['action', 'event', 'check'] as const) {\n const b = mk('button', 'tr-btn on', t(`ui.filter.${ch}`))\n b.type = 'button'\n b.onclick = () => {\n filters[ch] = !filters[ch]\n b.classList.toggle('on', filters[ch])\n rebuildLog()\n }\n filterBtns.push(b)\n logBar.appendChild(b)\n }\n let autoscroll = true\n const asLabel = mk('label')\n const asBox = mk('input')\n asBox.type = 'checkbox'\n asBox.checked = true\n asBox.onchange = () => {\n autoscroll = asBox.checked\n }\n asLabel.append(asBox, document.createTextNode(' ' + t('ui.autoscroll')))\n logBar.appendChild(asLabel)\n const logBtn = (label: string, fn: () => void): void => {\n const b = mk('button', 'tr-btn', label)\n b.type = 'button'\n b.onclick = fn\n logBar.appendChild(b)\n }\n logBtn(t('ui.copy_json'), () => {\n const text = o.log.toJSON()\n // no clipboard API (an Artifact iframe, file://): select the text in a textarea and ask the browser to copy it, leaving it selected\n const select = (): void => {\n const ta = mk('textarea')\n ta.value = text\n ta.setAttribute('readonly', '')\n ta.style.cssText = 'position:fixed;left:8px;bottom:8px;width:min(480px,80vw);height:120px;z-index:99999'\n document.body.appendChild(ta)\n ta.focus()\n ta.select()\n let copied = false\n try {\n copied = !!document.execCommand?.('copy')\n } catch {\n copied = false\n }\n if (copied) ta.remove()\n else ta.onblur = () => ta.remove()\n }\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) navigator.clipboard.writeText(text).catch(select)\n else select()\n })\n logBtn(t('ui.download_ndjson'), () => o.log.download('ndjson'))\n logBtn(t('ui.download_txt'), () => o.log.download('txt'))\n logBtn(t('ui.clear_log'), () => {\n o.log.clear()\n logBody.textContent = ''\n nodes.clear()\n })\n logPanel.append(logTitle, logBar, logBody)\n\n const MAX_LINES = 200\n const nodes = new Map<number, HTMLElement>()\n const fmtTime = (s: number): string => `${Math.floor(s / 60)\n .toString()\n .padStart(2, '0')}:${(s % 60).toFixed(1).padStart(4, '0')}`\n const lineClass = (e: LogEntry): string => `${e.channel}${e.type === 'fail' || e.type === 'scenario_fail' ? ' fail' : e.type === 'pass' || e.type === 'scenario_pass' ? ' pass' : ''}`\n const fill = (n: HTMLElement, e: LogEntry): void => {\n n.className = lineClass(e)\n n.textContent = ''\n const tm = mk('time', undefined, fmtTime(e.t))\n n.append(tm, document.createTextNode(e.text))\n }\n const addNode = (e: LogEntry): void => {\n if (!filters[e.channel]) return\n const n = mk('div')\n fill(n, e)\n nodes.set(e.seq, n)\n logBody.appendChild(n)\n while (logBody.childElementCount > MAX_LINES) {\n const first = logBody.firstElementChild as HTMLElement\n for (const [k, v] of nodes) if (v === first) nodes.delete(k)\n first.remove()\n }\n if (autoscroll) logBody.scrollTop = logBody.scrollHeight\n }\n function rebuildLog(): void {\n logBody.textContent = ''\n nodes.clear()\n for (const e of o.log.entries().slice(-MAX_LINES * 3)) addNode(e)\n }\n const offLog = o.log.on((e, updated) => {\n if (updated) {\n const n = nodes.get(e.seq)\n if (n) fill(n, e)\n } else addNode(e)\n })\n\n // right: catalogue and tests\n const right = mk('div', 'tr-right')\n const cat = mk('div', 'tr-panel tr-cat')\n const anim = mk('div', 'tr-panel tr-anim')\n const tests = mk('div', 'tr-panel tr-tests')\n const benchPanel = createBenchPanel({ t, num: (n, d) => num(n, d), onControl: o.onControl, onLayer: o.onLayer, onAction: o.onAction })\n right.append(cat, anim, benchPanel.element, tests)\n\n cat.appendChild(mk('h3', undefined, t('ui.catalog')))\n const itemSearch = mk('input', 'tr-search')\n itemSearch.type = 'search'\n itemSearch.placeholder = t('ui.search_items')\n const tabs = mk('div', 'tr-tabs')\n const items = mk('div', 'tr-items')\n cat.append(itemSearch, tabs, items)\n let activeGroup = ''\n // a search looks in every group, so an item is found without knowing its tab\n const visibleItems = (): Array<{ item: TestRoomItem; group: string }> => {\n const term = fold(itemSearch.value.trim())\n if (!term) return (o.groups().get(activeGroup) ?? []).map((item) => ({ item, group: activeGroup }))\n return [...o.groups()].flatMap(([group, list]) => list.filter((item) => fold(`${item.name} ${item.id} ${group}`).includes(term)).map((item) => ({ item, group })))\n }\n const renderItems = (): void => {\n items.textContent = ''\n const searching = itemSearch.value.trim() !== ''\n const found = visibleItems()\n if (!found.length) items.appendChild(mk('div', 'tr-empty', t('ui.no_results')))\n for (const { item: it, group } of found) {\n const wrap = mk('div', 'tr-item')\n const b = mk('button', it.thumbnail ? 'tr-btn has-thumb' : 'tr-btn', it.thumbnail ? undefined : it.name)\n if (it.thumbnail) b.append(thumb(it.thumbnail), mk('span', 'tr-name', it.name))\n if (searching) b.appendChild(mk('small', undefined, group))\n b.type = 'button'\n b.title = it.note ?? it.name\n b.onclick = () => o.onSpawn(it.id)\n wrap.appendChild(b)\n if (it.weapon) {\n const w = mk('button', 'tr-btn', '⚔')\n w.type = 'button'\n w.title = t('ui.equip')\n w.onclick = () => o.onEquip(it.id)\n wrap.appendChild(w)\n }\n items.appendChild(wrap)\n }\n }\n const renderTabs = (): void => {\n tabs.textContent = ''\n const groupNames = [...o.groups().keys()]\n if (!groupNames.includes(activeGroup)) activeGroup = groupNames[0] ?? ''\n for (const g of groupNames) {\n const b = mk('button', g === activeGroup ? 'tr-btn on' : 'tr-btn', g)\n b.type = 'button'\n b.onclick = () => {\n activeGroup = g\n renderTabs()\n }\n tabs.appendChild(b)\n }\n renderItems()\n }\n renderTabs()\n itemSearch.oninput = renderItems\n // typing in a search box must not move the player or switch tools\n for (const box of [itemSearch]) box.addEventListener('keydown', (e) => e.stopPropagation())\n\n const controls = mk('div', 'tr-row')\n const ctl = (label: string, fn: (b: HTMLButtonElement) => void): HTMLButtonElement => {\n const b = mk('button', 'tr-btn', label)\n b.type = 'button'\n b.onclick = () => fn(b)\n controls.appendChild(b)\n return b\n }\n ctl(t('ui.clear'), () => o.onClear())\n ctl(t('ui.reset_all'), () => o.onResetAll())\n let slow = false\n ctl(t('ui.slow'), (b) => {\n slow = !slow\n b.classList.toggle('on', slow)\n o.onSlow(slow)\n })\n let fast = false\n ctl(t('ui.fast'), (b) => {\n fast = !fast\n b.classList.toggle('on', fast)\n o.onFast(fast)\n })\n const tapBtn = ctl(t('ui.tap'), () => o.onTap())\n const blastBtns = (['shelter', 'fragmentHits', 'confinement'] as const).map((key) => ({ key, b: ctl(t(`ui.blast.${key}`), () => o.onBlast(key)) }))\n for (const { key, b } of blastBtns) b.title = t(`ui.blast.${key}.hint`)\n const qSel = mk('select')\n for (const q of ['low', 'medium', 'high'] as const) {\n const op = mk('option', undefined, t(`ui.quality.${q}`))\n op.value = q\n qSel.appendChild(op)\n }\n qSel.value = o.quality\n qSel.onchange = () => o.onQuality(qSel.value as 'low' | 'medium' | 'high')\n const qLabel = mk('label', undefined, t('ui.quality') + ' ')\n qLabel.appendChild(qSel)\n controls.appendChild(qLabel)\n const count = mk('span')\n controls.appendChild(count)\n cat.appendChild(controls)\n\n // tests\n tests.appendChild(mk('h3', undefined, t('ui.tests')))\n const runAll = mk('button', 'tr-btn', t('ui.run_all'))\n runAll.type = 'button'\n const summary = mk('div', 'tr-summary')\n const testSearch = mk('input', 'tr-search')\n testSearch.type = 'search'\n testSearch.placeholder = t('ui.search_tests')\n testSearch.addEventListener('keydown', (e) => e.stopPropagation())\n const list = mk('div', 'list')\n tests.append(runAll, summary, testSearch, list)\n testSearch.oninput = () => {\n const term = fold(testSearch.value.trim())\n for (const b of scBtns.values()) b.style.display = !term || fold(b.textContent ?? '').includes(term) ? '' : 'none'\n }\n const scBtns = new Map<string, HTMLButtonElement>()\n let busy = false\n const mark = (rep: ScenarioReport | void): void => {\n if (!rep) return\n for (const r of rep.results) {\n const b = scBtns.get(r.id)\n if (!b) continue\n b.classList.remove('pass', 'fail')\n b.classList.add(r.ok ? 'pass' : 'fail')\n b.textContent = `${r.ok ? '✓' : '✗'} ${r.name}`\n }\n summary.textContent = t('ui.report', { passed: rep.passed, failed: rep.failed })\n }\n const renderScenarios = (): void => {\n list.textContent = ''\n scBtns.clear()\n for (const s of o.scenarios()) {\n const b = mk('button', 'tr-btn', s.name)\n b.type = 'button'\n b.onclick = async () => {\n if (busy) return\n busy = true\n try {\n mark(await o.onRun(s))\n } finally {\n busy = false\n }\n }\n scBtns.set(s.id, b)\n list.appendChild(b)\n }\n }\n renderScenarios()\n runAll.onclick = async () => {\n if (busy) return\n busy = true\n summary.textContent = t('ui.running')\n try {\n mark(await o.onRunAll())\n } finally {\n busy = false\n }\n }\n\n const toggle = mk('button', 'tr-btn tr-toggle', t('ui.panel'))\n toggle.type = 'button'\n const togglePanels = (): void => {\n root.classList.toggle('open')\n o.onResize()\n }\n toggle.onclick = togglePanels\n\n root.append(cross, top, bottom, help, left, right, toggle)\n\n // inspector\n const bar = (value: number, max: number, cls: string): HTMLElement => {\n const b = mk('div', `tr-bar ${cls}`)\n const i = mk('i')\n i.style.width = `${Math.max(0, Math.min(100, (value / Math.max(1e-9, max)) * 100))}%`\n b.appendChild(i)\n return b\n }\n const row = (k: string, v: string): HTMLElement => {\n const r = mk('div', 'r')\n r.append(mk('span', undefined, k), mk('span', undefined, v))\n return r\n }\n const num = (n: number, d = 1): string => {\n const s = (Math.round(n * 10 ** d) / 10 ** d).toFixed(d)\n return t('locale.decimal') === ',' ? s.replace('.', ',') : s\n }\n const renderInspector = (i: InspectInfo | null): void => {\n insp.textContent = ''\n insp.appendChild(mk('h3', undefined, t('ui.inspector')))\n if (!i) {\n insp.appendChild(mk('div', undefined, t('ui.aim_at_something')))\n return\n }\n if (i.thumbnail) insp.appendChild(thumb(i.thumbnail, i.thumbnailCredit))\n insp.appendChild(mk('div', 't', `${i.object} › ${i.part}`))\n insp.appendChild(row(t('ins.material'), i.material))\n insp.appendChild(row(t('ins.status'), i.status + (i.burning ? ` · ${t('ins.burning')}` : '')))\n insp.appendChild(row(t('ins.hp'), `${num(i.hp, 0)} / ${num(i.maxHp, 0)}`))\n const frac = i.hp / Math.max(1e-9, i.maxHp)\n insp.appendChild(bar(i.hp, i.maxHp, frac < 0.25 ? 'bad' : frac < 0.6 ? 'warn' : 'hp'))\n insp.appendChild(row(t('ins.temperature'), `${num(i.temperature, 0)} °C`))\n if (i.char > 0.01) insp.appendChild(row(t('ins.char'), `${num(i.char * 100, 0)} %`))\n if (i.melt > 0.01) insp.appendChild(row(t('ins.melt'), `${num(i.melt * 100, 0)} %`))\n if (i.liters !== undefined) insp.appendChild(row(t('ins.liters'), `${num(i.liters, 2)} l`))\n const cn = (what: string, n: number): string => t(`count.${what}.${n === 1 ? 'one' : 'other'}`, { n })\n insp.appendChild(row(t('ins.damage'), t('ins.damage_counts', { dents: cn('dent', i.dents), holes: cn('hole', i.holes), cracks: cn('crack', i.cracks) })))\n insp.appendChild(row(t('ins.mass'), `${num(i.mass, 1)} kg`))\n if (i.load !== undefined) insp.appendChild(row(t('ins.load'), `${num(i.load, 0)} kg`))\n if (i.stress !== undefined) {\n insp.appendChild(row(t('ins.stress'), `${num(i.stress * 100, 0)} %`))\n insp.appendChild(bar(Math.min(i.stress, 1.2), 1.2, i.stress > 1 ? 'bad' : i.stress > 0.7 ? 'warn' : 'hp'))\n }\n if (i.joints.length) {\n insp.appendChild(mk('div', undefined, t('ins.joints') + ':'))\n for (const j of i.joints) {\n const tools = j.tools.length ? j.tools.join(', ') : t('tool.none')\n insp.appendChild(mk('div', undefined, `• ${j.kind} (${j.id})${j.open ? ` · ${t('ins.open')}` : ` → ${tools}`}`))\n }\n }\n if (i.note) insp.appendChild(mk('div', undefined, i.note))\n }\n\n let lastAnim = ''\n const renderAnimations = (a: AnimationInfo | null): void => {\n anim.textContent = ''\n anim.appendChild(mk('h3', undefined, t('ui.animations')))\n if (!a) {\n anim.appendChild(mk('div', 'sub', t('ui.animations_aim')))\n return\n }\n anim.appendChild(mk('div', 'sub', a.name))\n if (a.clips.length === 0) {\n anim.appendChild(mk('div', 'sub', t('ui.animations_none')))\n return\n }\n const l = mk('div', 'list')\n for (const c of a.clips) {\n const b = mk('button', a.playing === c.id ? 'tr-btn on' : 'tr-btn', `▶ ${t(`anim.${c.id}`) === `anim.${c.id}` ? c.id : t(`anim.${c.id}`)} (${num(c.duration, 1)} s)`)\n b.type = 'button'\n b.onclick = () => o.onPlay(a.objectId, c.id)\n l.appendChild(b)\n }\n anim.appendChild(l)\n }\n renderAnimations(null)\n\n let toastTimer: ReturnType<typeof setTimeout> | null = null\n const slotsEl: HTMLButtonElement[] = []\n let lastSlotsKey = ''\n let lastInspect = ''\n let hudPage = 0\n\n const api: RoomUi = {\n hud(s) {\n toolBox.textContent = ''\n toolBox.append(document.createTextNode(s.toolName))\n if (s.ammo) toolBox.append(mk('small', undefined, s.ammo))\n if (s.status) status.textContent = s.status\n else if (!toastTimer) status.textContent = ''\n if (s.progress) {\n prog.style.display = 'block'\n progLabel.textContent = s.progress.label\n progFill.style.width = `${Math.round(s.progress.value * 100)}%`\n } else prog.style.display = 'none'\n if (s.held) {\n held.style.display = 'block'\n held.textContent = ''\n held.append(document.createTextNode(`${s.held.name} · `))\n const keys: Array<[string, string]> = [\n ['E', t('hud.drop')],\n ['R', t('hud.rotate')],\n ['G', t('hud.throw')],\n ['Z', t('hud.tilt')],\n ...s.held.uses.map((u) => [u.key, u.label] as [string, string]),\n ]\n if (s.held.weapon) keys.push(['H', t('hud.equip', { weapon: s.held.weapon })])\n for (const [k, label] of keys) {\n held.append(mk('kbd', undefined, k), document.createTextNode(` ${label} `))\n }\n } else held.style.display = 'none'\n const key = s.slots.join('|') + s.page\n if (key !== lastSlotsKey) {\n lastSlotsKey = key\n hotbar.textContent = ''\n slotsEl.length = 0\n hudPage = s.page - 1\n s.slots.forEach((name, i) => {\n const b = mk('button', 'tr-slot')\n b.type = 'button'\n b.append(mk('b', undefined, String((i + 1) % 10)), document.createTextNode(name))\n b.title = name\n b.onclick = () => o.onTool(hudPage * 10 + i)\n hotbar.appendChild(b)\n slotsEl.push(b)\n })\n }\n slotsEl.forEach((b, i) => b.classList.toggle('on', i === s.slot))\n tapBtn.classList.toggle('on', s.tap)\n for (const { key, b } of blastBtns) b.classList.toggle('on', s.blast[key])\n count.textContent = t('ui.objects', { n: s.objects })\n const ak = JSON.stringify(s.animations)\n if (ak !== lastAnim) {\n lastAnim = ak\n renderAnimations(s.animations)\n }\n const ik = JSON.stringify(s.inspect)\n if (ik !== lastInspect) {\n lastInspect = ik\n renderInspector(s.inspect)\n }\n },\n toast(text) {\n status.textContent = text\n if (toastTimer) clearTimeout(toastTimer)\n toastTimer = setTimeout(() => {\n toastTimer = null\n }, 2000)\n },\n refresh() {\n renderTabs()\n renderScenarios()\n },\n showGroup(group) {\n activeGroup = group\n itemSearch.value = ''\n renderTabs()\n },\n togglePanels,\n bench: benchPanel.show,\n metrics: benchPanel.metrics,\n get benchVisible() {\n return benchPanel.visible\n },\n dispose() {\n offLog()\n if (toastTimer) clearTimeout(toastTimer)\n root.remove()\n },\n }\n rebuildLog()\n return api\n}\n"],"mappings":"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","names":["JOINT_DEFAULTS","control","box","a","b","key","g","blocked","drum","crate","bottle","box","mk","list","box","key","host","box","JOINT_DEFAULTS","fire","update","grab","room"]}
|
|
1
|
+
{"version":3,"sources":["../src/room.ts","../src/items.ts","../src/arena.ts","../src/bench.ts","../src/build-from-spec.ts","../src/explosives.ts","../src/segment-box.ts","../src/host-events.ts","../src/loading-view.ts","../src/loading.ts","../src/log.ts","../src/metrics.ts","../src/narrate.ts","../src/player.ts","../src/avatar.ts","../src/locale.ts","../src/bench-panel.ts","../src/ui.ts"],"sourcesContent":["import type * as THREE_NS from 'three'\nimport { createDestruction, JOINT_DEFAULTS, resolveStrings as resolveDestructionStrings } from '@adatechnology/game-destruction'\nimport type { BlastOptions, DestructibleImpl, DestructibleSpec, DestructionEvent, JointState, Quat, RayHit, ToolKind, Vec3 } from '@adatechnology/game-destruction'\nimport { createAudioEngine, createAudioSink } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { createDestructionRenderer, createDestructionSound, specFromObject3D } from '@adatechnology/game-destruction-three'\nimport type { Piece } from '@adatechnology/game-destruction-three'\nimport { createArsenal, DEFAULT_LOADOUT } from '@adatechnology/game-weapons'\nimport type { MountKind, Shot, TriggerResult, Use, WeaponState } from '@adatechnology/game-weapons'\nimport { createFilmLcg, createFluids, createItemUse, ITEM_USES, resolveStrings as resolveFluidStrings } from '@adatechnology/game-fluids'\nimport type { FluidEvent, ItemUsePlayer, StainState } from '@adatechnology/game-fluids'\nimport { createFilmBridge, createFilmManager, createFluidRenderer } from '@adatechnology/game-fluids-three'\nimport { createGroundField, createVfx } from '@adatechnology/game-vfx'\nimport { createGroundPatch, createVfxRenderer } from '@adatechnology/game-vfx-three'\nimport type { FluidRenderer } from '@adatechnology/game-fluids-three'\nimport { checkAnimation, checkBench, checkDestructible, checkSpec, createEnvironmentBus, shotExtras, useToHit } from '@adatechnology/game-contracts'\nimport type { AnimationClipSpec, HandTargetSource, HandTargets, HostEvent, ModuleArea, ModuleBench, ModuleHost, TestableModule, ToolCommand, ToolCommandResult } from '@adatechnology/game-contracts'\nimport type { RoomFirstPersonState } from './avatar'\nimport { createArena } from './arena'\nimport type { Arena, ArenaTop } from './arena'\nimport { createBenchStore } from './bench'\nimport type { BenchStore } from './bench'\nimport type { BenchView, MetricRow } from './bench-panel'\nimport { buildFromSpec } from './build-from-spec'\nimport { createExplosives } from './explosives'\nimport type { BlastSummary } from './explosives'\nimport { toHostEvent } from './host-events'\nimport { createLoading } from './loading'\nimport { createLog } from './log'\nimport { createRoomMetrics, ROOM_METRICS } from './metrics'\nimport { createNarrator } from './narrate'\nimport { createPlayer, PLAYER_RADIUS } from './player'\nimport { DEFAULT_HAND_STANCES, DEFAULT_STRIKE_CLIPS, THIRD_PERSON_DEFAULTS, thirdPersonPose } from './avatar'\nimport type { CameraMode, RoomAvatar, RoomAvatarState, ThirdPersonOptions, ThirdPersonPose } from './avatar'\nimport { resolveStrings } from './locale'\nimport { createUi } from './ui'\nimport type { HudState, InspectInfo, RoomUi } from './ui'\nimport type {\n AnimationInfo,\n ModuleReport,\n RoomMetricId,\n ScenarioContext,\n ScenarioReport,\n SpawnedObject,\n TestRoom,\n TestRoomItem,\n TestRoomOptions,\n TestRoomScenario,\n} from './types'\n\ntype Vars = Record<string, string | number>\n\ninterface Entry {\n so: SpawnedObject\n item?: TestRoomItem\n name: string\n arena: boolean\n containerId?: string\n fluidPart?: string\n fluidOffset: Vec3\n uses: string[]\n piece: Piece | null\n last: Vec3\n velocity: Vec3\n /** Heavy but not fixed (a fridge, a table): not grabbable, yet a blast that reaches it with enough speed makes it a piece and shoves it. */\n free?: boolean\n}\n\ninterface FireZone {\n point: Vec3\n radius: number\n temperature: number\n remaining: number\n acc: number\n}\n\ninterface BurningStain {\n center: Vec3\n remaining: number\n acc: number\n}\n\nconst FIXED_DT = 1 / 60\nconst METRICS_INTERVAL_S = 0.25\n/** The carried item in first person: how far the nearest of a small item is held (m), how far the palm sits under it and how closed the fingers are. */\nconst CARRY_NEAR = 0.62\nconst CARRY_PALM = 0.012\nconst CARRY_GRIP = 0.45\n/** Faster than this (m/s) a change of the player's position is a teleport, not walking: the avatar does not stride for it. The player runs at 6.2. */\nconst MAX_STRIDE_SPEED = 10\n\nconst v3 = (v: THREE_NS.Vector3): Vec3 => [v.x, v.y, v.z]\nconst dist3 = (a: Vec3, b: Vec3): number => Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])\n\n/**\n * Create the test room. See `TestRoomOptions`. The room owns a renderer, scene and camera unless you pass them; with your own renderer you call\n * `room.update(dt)` every frame and render yourself.\n */\nexport function createTestRoom(options: TestRoomOptions): TestRoom {\n const THREE = options.THREE\n const locale = options.locale ?? 'en'\n const S = resolveStrings(locale)\n const dStrings = resolveDestructionStrings(locale)\n const fStrings = resolveFluidStrings(locale)\n const t = (key: string, vars?: Vars): string => {\n let s = S.text[key] ?? key\n if (vars) for (const k of Object.keys(vars)) s = s.split(`{${k}}`).join(String(vars[k]))\n return s\n }\n // the loading indicator of the room (and of its modules, as `host.loading`): any slow job shows a spinner or a bar so that the page never looks frozen; `ui: false` keeps the state and draws nothing\n const loading = createLoading({ container: options.container, draw: options.ui !== false, working: t('loading.working') })\n const num = (n: number, digits = 1): string => {\n const s = (Math.round(n * 10 ** digits) / 10 ** digits).toFixed(digits)\n return locale.toLowerCase().startsWith('pt') ? s.replace('.', ',') : s\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Renderer, scene, camera\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const ownRenderer = !options.renderer\n const gl: THREE_NS.WebGLRenderer = options.renderer ?? new THREE.WebGLRenderer({ antialias: true })\n const container = options.container\n const width = (): number => container.clientWidth || 960\n const height = (): number => container.clientHeight || 600\n if (ownRenderer) {\n const r = gl as THREE_NS.WebGLRenderer\n r.setPixelRatio(Math.min(typeof devicePixelRatio === 'number' ? devicePixelRatio : 1, 2))\n r.shadowMap.enabled = true\n r.shadowMap.type = THREE.PCFSoftShadowMap\n r.toneMapping = THREE.ACESFilmicToneMapping\n r.toneMappingExposure = 1\n r.outputColorSpace = THREE.SRGBColorSpace\n container.appendChild(r.domElement)\n }\n gl.setSize(width(), height())\n const dom = gl.domElement\n if (dom && !dom.hasAttribute?.('tabindex')) dom.setAttribute?.('tabindex', '0')\n const scene = options.scene ?? new THREE.Scene()\n const camera = options.camera ?? new THREE.PerspectiveCamera(72, width() / height(), 0.05, 140)\n if (!options.camera) scene.add(camera)\n const resize = (): void => {\n const w = width()\n const h = height()\n gl.setSize(w, h)\n camera.aspect = w / h\n camera.updateProjectionMatrix()\n }\n const onResize = (): void => resize()\n window.addEventListener('resize', onResize)\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Worlds\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const arenaSize = options.arenaSize ?? 14\n const arena: Arena = createArena(THREE, arenaSize, scene, options.scenery, options.tap)\n scene.add(arena.group)\n\n const ownWorld = !options.world\n const world = options.world ?? createDestruction({ seed: 1, ...options.worldOptions, materials: [...(options.worldOptions?.materials ?? [])] })\n const pristineWorld = ownWorld ? world.serialize() : null\n const topOk = (t: ArenaTop): boolean => {\n const p = world.part(t.id, t.topPart)\n return !!p && p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes'\n }\n // tops of spawned objects that hold others (a module's counter, a shelf board): loose things rest on them while the object is in the world\n const restingTops: Array<{ objectId: string; minX: number; maxX: number; minZ: number; maxZ: number; top: number }> = []\n const restingTopAt = (x: number, z: number): number => {\n let top = 0\n for (const c of restingTops) if (x > c.minX && x < c.maxX && z > c.minZ && z < c.maxZ && world.has(c.objectId)) top = Math.max(top, c.top)\n return top\n }\n const sceneryTopAt = (x: number, z: number): number => {\n let top = 0\n for (const t of arena.tops) if (t.top > top && x > t.minX && x < t.maxX && z > t.minZ && z < t.maxZ && topOk(t)) top = t.top\n return top\n }\n const groundAt = (x: number, z: number): number => Math.max(sceneryTopAt(x, z), restingTopAt(x, z))\n\n const ownFluids = !options.fluids\n const fluids = options.fluids ?? createFluids({ seed: 1, locale, liquids: options.liquids, groundAt })\n const pristineFluids = ownFluids ? fluids.serialize() : null\n for (const s of [...arena.surfaces, ...(options.surfaces ?? [])]) fluids.addSurface(s)\n const itemUseDefs = [...ITEM_USES, ...(options.itemUses ?? [])]\n\n const quality = options.quality ?? 'medium'\n const pointScale = height() / (2 * Math.tan((camera.fov * Math.PI) / 360))\n const rendererPieces = new Map<string, Piece>()\n const entries = new Map<string, Entry>()\n const splitOf = new Map<string, Entry>()\n let simTime = 0\n const log = createLog({ exportCancelled: () => t('log.export_cancelled') })\n log.setClock(() => simTime)\n\n // sound: one engine for the room (no AudioContext until the first sound), and the destruction renderer's sound keys play on it\n const ownAudio = options.audio === undefined\n const audio: AudioEngine | null = options.audio === false ? null : (options.audio ?? createAudioEngine())\n const destructionSound = audio ? createDestructionSound(audio) : null\n const playSound = (key: string, point: Vec3, volume: number): void => {\n destructionSound?.onSound(key, point, volume)\n options.onSound?.(key, point, volume)\n }\n\n // one effects world for the whole room: the destruction and fluid renderers and every module draw into it, and the room steps it once per frame\n const craterField = options.craters ? createGroundField() : undefined\n const craterPatch = craterField ? createGroundPatch(THREE, { field: craterField, material: new THREE.MeshStandardMaterial({ color: 0x8e8e8a, roughness: 0.95 }) }) : undefined\n if (craterPatch) {\n const floor = arena.group.getObjectByName('floor')\n if (floor) floor.visible = false\n scene.add(craterPatch.mesh)\n }\n const vfx = createVfxRenderer(THREE, {\n scene,\n camera,\n overlay: container,\n quality,\n pointScale,\n vfx: createVfx({\n profile: quality,\n groundAt: (x, z) => groundAt(x, z) + (craterField?.heightAt(x, z) ?? 0),\n ...(craterField ? { ground: craterField } : {}),\n }),\n })\n const renderer = createDestructionRenderer(THREE, {\n scene,\n world,\n vfx: vfx.world,\n quality,\n groundAt,\n pointScale,\n onSound: playSound,\n ...(options.blastShove ? { blastShove: options.blastShove } : {}),\n // a blast moves what is heavy but not nailed down: the renderer makes it a piece the moment the shove reaches it\n shoveable: (objectId) => {\n const e = entries.get(objectId)\n return e?.free === true && !e.piece\n },\n onLoosened: (objectId, piece) => {\n const e = entries.get(objectId)\n if (!e) return\n e.piece = piece\n rendererPieces.set(objectId, piece)\n action('loosened', t('act.loosened', { name: e.name }), { objectId, itemId: e.so.itemId })\n },\n onPiece: (piece) => {\n rendererPieces.set(piece.objectId, piece)\n loose.push(piece)\n // find the entry it came from: the one whose spec holds all its parts and that is nearest\n const st = world.state(piece.objectId)\n if (!st) return\n let best: Entry | null = null\n let bestD = Infinity\n for (const e of entries.values()) {\n const spec = specs.get(e.so.objectId)\n if (!spec) continue\n const ids = new Set(spec.parts.map((p) => p.id))\n if (!st.parts.every((p) => ids.has(p.id))) continue\n const d = e.so.root.position.distanceTo(piece.root.position)\n if (d < bestD) {\n bestD = d\n best = e\n }\n }\n if (best) splitOf.set(piece.objectId, best)\n },\n })\n const fluidView: FluidRenderer = createFluidRenderer(THREE, { scene, fluids, quality, pointScale, vfx: vfx.world })\n // the running film of the liquids that have one (blood, fuel, oil): grids near the player, fed by the leaks of the fluid world\n const filmRandom = createFilmLcg(1)\n const film = createFilmManager(THREE, {\n scene,\n camera,\n random: filmRandom,\n fluids,\n groundAt,\n ...(typeof (gl as Partial<THREE_NS.WebGLRenderer>).copyTextureToTexture === 'function' ? { gpu: gl as THREE_NS.WebGLRenderer } : {}),\n })\n const filmBridge = createFilmBridge({ fluids, manager: film, random: filmRandom })\n const specs = new Map<string, DestructibleSpec>()\n const loose: Piece[] = []\n\n const arsenal = options.arsenal ?? createArsenal({ locale, weapons: options.weapons, seed: 1 })\n const loadout = (options.loadout ?? DEFAULT_LOADOUT).filter((id) => arsenal.weapons.has(id))\n const tools = new Map<string, WeaponState>()\n let toolIndex = Math.max(0, loadout.indexOf('hand'))\n let toolId = loadout[toolIndex] ?? 'hand'\n const toolSettings: { condition?: string; ammoQuality?: string } = {}\n let fuseLength: number | undefined\n const SETTING_IDS = { condition: 'condition', ammoQuality: 'ammo_quality', fuseLength: 'fuse_length' } as const\n const toolState = (id: string): WeaponState => {\n let s = tools.get(id)\n if (!s) {\n s = arsenal.create(id, { seed: 7, reserve: 999, ...toolSettings })\n s.setFuseLength(fuseLength)\n s.refill()\n tools.set(id, s)\n }\n return s\n }\n let tool = toolState(toolId)\n\n const catalogMap = new Map<string, TestRoomItem>()\n for (const i of options.catalog) catalogMap.set(i.id, i)\n const catalog = [...options.catalog]\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Names and narration\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const entryOf = (objectId: string): Entry | undefined => entries.get(objectId) ?? splitOf.get(objectId)\n const nameOf = (objectId: string): string => {\n const e = entries.get(objectId)\n if (e) return e.name\n const s = splitOf.get(objectId)\n return s ? `${s.name} (${t('piece')})` : objectId\n }\n const narrator = createNarrator({\n world,\n fluids,\n log,\n now: () => simTime,\n t,\n num,\n nameOf,\n itemIdOf: (id) => entryOf(id)?.so.itemId,\n materialName: (id) => S.text[`material.${id}`] ?? dStrings.materialNames[id] ?? id,\n liquidName: (id) => fStrings.liquids[id] ?? id,\n jointKind: (k) => dStrings.jointKinds[k as keyof typeof dStrings.jointKinds] ?? k,\n toolName: (k) => dStrings.toolKinds[k as keyof typeof dStrings.toolKinds] ?? k,\n locatePart: (objectId, partId) => {\n const own = world.part(objectId, partId)\n if (own) return { objectId, part: own }\n for (const [id, owner] of splitOf) {\n if (owner.so.objectId !== objectId) continue\n const p = world.part(id, partId)\n if (p) return { objectId: id, part: p }\n }\n return null\n },\n containerName: (cid) => {\n for (const e of entries.values()) if (e.containerId === cid) return { name: e.name, objectId: e.so.objectId, itemId: e.so.itemId }\n return undefined\n },\n })\n\n let pending: DestructionEvent[] = []\n const eventListeners = new Set<(d: unknown) => void>()\n const listeners: Record<string, Set<(d: unknown) => void>> = { spawn: new Set(), tool: new Set(), grab: new Set(), throw: new Set(), event: eventListeners, camera: new Set() }\n const fire = (type: string, data: unknown): void => {\n for (const fn of listeners[type] ?? []) fn(data)\n }\n world.on('*', (ev) => {\n pending.push(ev)\n })\n fluids.on('*', (ev: FluidEvent) => {\n narrator.fluid(ev)\n fire('event', ev)\n })\n\n const action = (type: string, text: string, extra: Partial<{ objectId: string; itemId: string; part: string; data: Record<string, unknown>; material: string }> = {}): void => {\n log.add({ channel: 'action', type, text, ...extra })\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Flush: events of the frame -> log, fluids glue, fire glue\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const tmpV = new THREE.Vector3()\n const tmpV2 = new THREE.Vector3()\n const tmpQ = new THREE.Quaternion()\n const tmpM = new THREE.Matrix4()\n\n const hostOf = (e: Entry): { objectId: string; root: THREE_NS.Object3D } => {\n if (e.fluidPart && !e.arena && !world.part(e.so.objectId, e.fluidPart)) {\n for (const [id, owner] of splitOf) {\n if (owner === e && world.part(id, e.fluidPart)) {\n const p = rendererPieces.get(id)\n if (p) return { objectId: id, root: p.root }\n }\n }\n }\n return { objectId: e.so.objectId, root: e.so.root }\n }\n\n const puncture = (ev: Extract<DestructionEvent, { type: 'leak' }>): void => {\n const e = entryOf(ev.object)\n if (!e?.containerId || e.fluidPart !== ev.part) return\n const host = hostOf(e)\n host.root.updateMatrixWorld(true)\n tmpM.copy(host.root.matrixWorld).invert()\n const local = tmpV.set(ev.point[0], ev.point[1], ev.point[2]).applyMatrix4(tmpM)\n local.x -= e.fluidOffset[0]\n local.y -= e.fluidOffset[1]\n local.z -= e.fluidOffset[2]\n host.root.getWorldQuaternion(tmpQ).invert()\n const n = tmpV2.set(ev.direction[0], ev.direction[1], ev.direction[2]).applyQuaternion(tmpQ)\n const part = world.part(host.objectId, ev.part)\n const hole = part?.holes[part.holes.length - 1]\n fluids.puncture(e.containerId, [local.x, local.y, local.z], [n.x, n.y, n.z], hole?.diameter ?? 0.009)\n }\n\n const flush = (): void => {\n if (pending.length === 0) return\n const batch = pending\n pending = []\n narrator.events(batch)\n for (const ev of batch) {\n if (ev.type === 'leak') puncture(ev)\n else if (ev.type === 'ignite') igniteNear(ev.point, 0.9)\n else if (ev.type === 'explode') emitHost({ type: 'explosion', source: ev.object, point: ev.point, energy: ev.energy, radius: ev.radius, cause: 'part', ...(ev.effect !== undefined ? { explosive: ev.effect } : {}) })\n fire('event', ev)\n options.onEvent?.(ev)\n }\n }\n log.setBeforeRead(flush)\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Player\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let useHeld = false\n let useFirst = false\n /** What modules ask the walking player to stay out of (`ModuleHost.addBlocker`). */\n const blockers = new Set<(x: number, z: number, radius: number) => boolean>()\n const player = createPlayer(THREE, {\n camera,\n dom,\n colliders: arena.colliders,\n blockers,\n limit: arenaSize,\n start: arena.playerStart,\n crouchKeys: options.crouch?.keys,\n hooks: {\n primaryDown: () => {\n useHeld = true\n useFirst = true\n },\n primaryUp: () => {\n useHeld = false\n releaseTrigger()\n },\n secondary: () => {\n if (heldEntry) throwHeld()\n else grab()\n },\n key: (code, down, e) => onKey(code, down, e),\n wheel: (dir) => cycleTool(dir),\n },\n })\n player.look(arena.playerStart, [0, 1.5, arena.wallZ])\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Spawning\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let counter = 0\n let slot = 0\n const maxCarry = options.maxCarryKg ?? 60\n\n const massOfObject = (id: string): number => {\n const st = world.state(id)\n let m = 0\n for (const p of st?.parts ?? []) if (p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes') m += p.mass\n return m\n }\n\n const registerEntry = (\n objectId: string,\n itemId: string,\n root: THREE_NS.Object3D,\n spec: DestructibleSpec,\n name: string,\n parts: Record<string, THREE_NS.Object3D | THREE_NS.Object3D[]> | undefined,\n item: TestRoomItem | undefined,\n arenaObject: boolean,\n movable: boolean,\n ): Entry => {\n specs.set(objectId, spec)\n renderer.bind(objectId, root, parts ? { parts } : undefined)\n const so: SpawnedObject = { objectId, itemId, root, movable }\n const e: Entry = { so, item, name, arena: arenaObject, fluidOffset: [0, 0, 0], uses: [], piece: null, last: [root.position.x, root.position.y, root.position.z], velocity: [0, 0, 0] }\n entries.set(objectId, e)\n if (movable) {\n e.piece = renderer.makePiece(objectId, { mass: Math.max(0.2, massOfObject(objectId)) })\n rendererPieces.set(objectId, e.piece)\n }\n const f = item?.fluid\n if (f) {\n e.fluidPart = f.part\n e.fluidOffset = f.offset ?? [0, 0, 0]\n e.uses = f.uses ?? ['drink', 'sip', 'pour']\n root.updateMatrixWorld(true)\n const q = root.getWorldQuaternion(tmpQ)\n const p = tmpV.set(e.fluidOffset[0], e.fluidOffset[1], e.fluidOffset[2]).applyMatrix4(root.matrixWorld)\n e.containerId = fluids.addContainer(f.container, { id: `${objectId}_fluid`, position: [p.x, p.y, p.z], rotation: [q.x, q.y, q.z, q.w] })\n fluidView.bindContainer(e.containerId, root, { innerOffset: e.fluidOffset })\n }\n return e\n }\n\n const resolveSpec = (item: TestRoomItem, root: THREE_NS.Object3D): { spec: DestructibleSpec; parts?: Record<string, THREE_NS.Object3D[]> } => {\n if (typeof item.spec === 'function') return { spec: structuredCloneSpec(item.spec(root)) }\n if (item.spec) return { spec: structuredCloneSpec(item.spec) }\n const r = specFromObject3D(THREE, root, { name: item.id, ...item.specOptions })\n return { spec: r.spec, parts: r.parts }\n }\n\n const addArena = (): void => {\n for (const o of arena.objects) {\n const root = o.build ? o.build(THREE) : buildFromSpec(THREE, o.spec, { colors: o.colors })\n root.position.set(o.position[0], o.position[1], o.position[2])\n root.rotation.y = o.rotationY\n scene.add(root)\n root.updateMatrixWorld(true)\n world.add(structuredCloneSpec(o.spec), { id: o.id, position: o.position, ...(o.rotationY ? { rotation: [0, Math.sin(o.rotationY / 2), 0, Math.cos(o.rotationY / 2)] as [number, number, number, number] } : {}) })\n registerEntry(o.id, o.id, root, o.spec, o.label ?? S.text[`arena.${o.id}`] ?? o.id, undefined, undefined, true, false)\n }\n }\n addArena()\n\n /**\n * The object of an item, with its root at scale 1: a builder that sizes its model by the scale of the root (the showcase models of game-items-three do, page units to metres) is wrapped\n * in a group, so that the destruction spec, the piece box and the mass read the object in metres like the eye does.\n */\n const wrapped = new WeakMap<THREE_NS.Object3D, THREE_NS.Object3D>()\n /** A holder that leaves the scene lets go of the object it held: the module that built it reads `root.parent === null` as \"not on show\". */\n const letGo = (root: THREE_NS.Object3D): void => {\n const inner = wrapped.get(root)\n if (!inner) return\n inner.removeFromParent()\n wrapped.delete(root)\n }\n const buildRoot = (item: TestRoomItem): THREE_NS.Object3D => {\n const built = item.build(THREE)\n if (item.impl || (Math.abs(built.scale.x - 1) < 1e-6 && Math.abs(built.scale.y - 1) < 1e-6 && Math.abs(built.scale.z - 1) < 1e-6)) return built\n const holder = new THREE.Group()\n holder.name = built.name\n holder.userData = built.userData\n holder.add(built)\n wrapped.set(holder, built)\n // a module hides or shows its object through the root it built (the category filter of the items area does): the holder answers for it\n Object.defineProperty(holder, 'visible', { get: () => built.visible, set: (v: boolean) => void (built.visible = v), configurable: true })\n return holder\n }\n\n const spawn = (itemId: string, position?: Vec3, rotationY?: number): SpawnedObject => {\n const item = catalogMap.get(itemId)\n if (!item) throw new Error(`game-test-room: unknown item \"${itemId}\"`)\n const root = buildRoot(item)\n let pos: Vec3\n if (position) pos = [position[0], position[1], position[2]]\n else {\n const fx = -Math.sin(player.yaw)\n const fz = -Math.cos(player.yaw)\n const rx = Math.cos(player.yaw)\n const rz = -Math.sin(player.yaw)\n const side = ((slot++ % 5) - 2) * 0.55\n const x = camera.position.x + fx * 2.4 + rx * side\n const z = camera.position.z + fz * 2.4 + rz * side\n const lim = arenaSize - 1\n pos = [Math.max(-lim, Math.min(lim, x)), groundAt(x, z), Math.max(-lim, Math.min(lim, z))]\n }\n root.position.set(pos[0], pos[1], pos[2])\n root.rotation.y = rotationY ?? player.yaw\n root.name = item.id\n scene.add(root)\n root.updateMatrixWorld(true)\n const objectId = `${item.id}_${++counter}`\n let own: DestructibleImpl | undefined\n let resolved: { spec: DestructibleSpec; parts?: Record<string, THREE_NS.Object3D[]> }\n if (item.impl) {\n own = item.impl(root, objectId)\n if (own.id !== objectId) throw new Error(`game-test-room: item \"${item.id}\": DestructibleImpl.id is \"${own.id}\", the room gave it \"${objectId}\" (use the id passed to impl)`)\n resolved = { spec: structuredCloneSpec(own.describe()) }\n } else resolved = resolveSpec(item, root)\n const { spec, parts } = resolved\n root.updateMatrixWorld(true)\n const mass = spec.parts.reduce((m, p) => m + (p.mass ?? 0), 0)\n const heavy = (mass || massGuess(spec)) > maxCarry\n const movable = own ? false : (item.movable ?? !heavy)\n if (movable) {\n // things that can fall rest on the floor or the table by the bottom of their bounding box (or hang at the height asked for): no drop on spawn\n const box = new THREE.Box3().setFromObject(root)\n const base = Math.max(pos[1], groundAt(pos[0], pos[2]))\n pos = [pos[0], pos[1] + (base - box.min.y), pos[2]]\n root.position.set(pos[0], pos[1], pos[2])\n root.updateMatrixWorld(true)\n }\n const q = root.getWorldQuaternion(tmpQ)\n if (own) world.register(own, { id: objectId, position: pos, rotation: [q.x, q.y, q.z, q.w] })\n else world.add(spec, { id: objectId, position: pos, rotation: [q.x, q.y, q.z, q.w] })\n const e = registerEntry(objectId, item.id, root, spec, item.name, parts, item, false, movable)\n // heavy by its mass and not said to be fixed: a blast can still push it\n if (!own && !movable && item.movable === undefined) e.free = true\n action('spawn', t('act.spawn', { name: item.name, x: num(pos[0], 1), z: num(pos[2], 1) }), { objectId, itemId: item.id, data: { position: pos, movable, massKg: Math.round(massOfObject(objectId) * 10) / 10 } })\n fire('spawn', e.so)\n return e.so\n }\n const massGuess = (spec: DestructibleSpec): number => {\n let m = 0\n for (const p of spec.parts) {\n const s = p.shape\n const vol = s.kind === 'box' ? s.size[0] * s.size[1] * s.size[2] : s.kind === 'cylinder' ? Math.PI * s.radius * s.radius * s.height : (4 / 3) * Math.PI * s.radius ** 3\n m += p.mass ?? vol * (world.materials.get(p.material)?.density ?? 500) * (p.fill ?? 1)\n }\n return m\n }\n\n const removeEntry = (id: string): void => {\n const e = entries.get(id)\n if (!e) return\n if (heldEntry === e) releaseHeld()\n for (let i = playing.length - 1; i >= 0; i--) if (playing[i].entry === e) playing.splice(i, 1)\n if (e.containerId) {\n fluidView.unbindContainer(e.containerId)\n fluids.removeContainer(e.containerId)\n }\n try {\n renderer.unbind(id)\n } catch {\n // not bound\n }\n if (world.has(id)) world.remove(id)\n e.so.root.removeFromParent()\n letGo(e.so.root)\n entries.delete(id)\n rendererPieces.delete(id)\n specs.delete(id)\n }\n\n const clearLoose = (): void => {\n for (const [id, owner] of [...splitOf]) {\n void owner\n const p = rendererPieces.get(id)\n try {\n renderer.unbind(id)\n } catch {\n // gone already\n }\n if (world.has(id)) world.remove(id)\n p?.root.removeFromParent()\n rendererPieces.delete(id)\n splitOf.delete(id)\n }\n loose.length = 0\n }\n\n const clearEverything = (): void => {\n if (heldEntry || heldPiece) releaseHeld()\n useItemPlayer = null\n playing.length = 0\n explosives.clear()\n fireZones.length = 0\n burningStains.length = 0\n for (const id of [...entries.keys()]) if (!entries.get(id)?.arena) removeEntry(id)\n clearLoose()\n for (const e of entries.values()) {\n world.reset(e.so.objectId)\n renderer.restore(e.so.objectId)\n }\n renderer.clear()\n vfx.world.clear()\n fluids.clearStains([0, 0, 0], 1e4)\n fluidView.clear()\n film.clear()\n fluids.setTap(TAP_ID, false)\n }\n\n const clearListeners = new Set<() => void>()\n const clear = (): void => {\n clearEverything()\n for (const listener of [...clearListeners]) listener()\n restingTops.length = 0\n pending = []\n action('clear', t('act.clear'))\n }\n\n const resetAll = (): void => {\n for (const e of entries.values()) {\n if (heldEntry === e) continue\n world.reset(e.so.objectId)\n renderer.restore(e.so.objectId)\n if (e.containerId) {\n const c = fluids.container(e.containerId)\n const f = e.item?.fluid?.container\n if (c && f && f.liquid) fluids.fill(e.containerId, f.liquid, Math.max(0, (f.liters ?? 0) - c.liters), f.temperature)\n }\n }\n action('reset', t('act.reset'))\n }\n\n /** Reset the worlds to their seeded start: used by scenarios so that each one is deterministic. */\n const hardReset = (): void => {\n clearEverything()\n for (const id of [...entries.keys()]) removeEntry(id)\n tools.clear()\n tool = toolState(toolId)\n if (pristineWorld) {\n for (const id of world.ids()) world.remove(id)\n world.load(pristineWorld)\n }\n if (pristineFluids) {\n fluids.load(pristineFluids)\n for (const s of [...arena.surfaces, ...(options.surfaces ?? [])]) fluids.addSurface(s)\n }\n pending = []\n strikes = []\n rng = 12345\n counter = 0\n slot = 0\n prevVy.clear()\n lastImpact.clear()\n addArena()\n timeScale = 1\n fastForward = false\n walkPlan = null\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Aiming\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const aimO: Vec3 = [0, 0, 0]\n const aimD: Vec3 = [0, 0, -1]\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Avatar and third-person camera. The simulation always sees the first-person camera (the eye: tools, grabs, walks, listener); the shoulder\n // view only moves the camera for the render (`applyCamera`), and the aim ray goes from the eye through the point the camera ray hits.\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const third: Required<ThirdPersonOptions> = { ...THIRD_PERSON_DEFAULTS, ...options.thirdPerson }\n let avatar: RoomAvatar | null = null\n let cameraMode: CameraMode = options.cameraMode ?? 'first'\n /** Crouched by a player module (`setAvatarState`); the Ctrl key crouches too. */\n let crouchForced = false\n const avatarState: RoomAvatarState = { speed: 0, running: false, crouch: false, down: false, armed: false, pitch: 0 }\n let feetPrev: [number, number] | null = null\n /** `armed` forced by a module (the bench); null follows the tool in hand. */\n let armedForced: boolean | null = null\n let camDistance = Infinity\n const tmpHand = new THREE.Vector3()\n\n const thirdPose = (dt: number): ThirdPersonPose => {\n const pose = thirdPersonPose({ x: player.x, z: player.z, feet: player.feet, yaw: player.yaw, pitch: player.pitch, crouch: avatarState.crouch }, third, (o, d, max) =>\n withoutHeld(() => world.raycast(o, d, max))?.distance ?? null,\n )\n // a wall pulls the camera in at once, the way back is slow (`view.cd`, line 76559 of the team game)\n camDistance = pose.free <= camDistance ? pose.free : dt > 0 ? camDistance + (pose.free - camDistance) * (1 - Math.exp(-dt * third.recover)) : camDistance\n return { ...pose, position: pose.at(camDistance), free: camDistance }\n }\n\n const thirdActive = (): boolean => cameraMode === 'third' && avatar !== null\n const syncAvatarVisible = (): void => {\n if (!avatar) return\n avatar.root.visible = cameraMode === 'third'\n if (avatar.firstPerson) avatar.firstPerson.root.visible = cameraMode === 'first'\n }\n const setCameraMode = (mode: CameraMode): void => {\n if (mode !== 'first' && mode !== 'third') return\n if (mode === cameraMode) return\n cameraMode = mode\n camDistance = Infinity\n syncAvatarVisible()\n action('camera', t('act.camera', { mode: t(`camera.${mode}`) }), { data: { mode, avatar: avatar !== null } })\n fire('camera', mode)\n }\n const setAvatar = (next: RoomAvatar | null): void => {\n if (avatar === next) return\n avatar?.root.removeFromParent()\n avatar?.firstPerson?.root.removeFromParent()\n avatar = next\n feetPrev = null\n if (avatar) {\n scene.add(avatar.root)\n if (avatar.firstPerson) scene.add(avatar.firstPerson.root)\n syncAvatarVisible()\n stepAvatar(0)\n }\n ui?.hud(hudState())\n }\n const stepAvatar = (dt: number): void => {\n if (!avatar) return\n const x = player.x\n const z = player.z\n if (dt > 0 && feetPrev) {\n // a jump of position faster than the player can run is a teleport (`look`, an area opening), not a stride\n const raw = Math.hypot(x - feetPrev[0], z - feetPrev[1]) / dt\n avatarState.speed = raw > MAX_STRIDE_SPEED ? 0 : avatarState.speed + (raw - avatarState.speed) * (1 - Math.exp(-dt * 15))\n if (avatarState.speed < 0.02) avatarState.speed = 0\n }\n feetPrev = [x, z]\n avatarState.running = !player.crouching && (player.keys.has('ShiftLeft') || player.keys.has('ShiftRight'))\n avatarState.crouch = crouchForced || player.crouching\n avatarState.armed = armedForced ?? tool.def.action.kind === 'firearm'\n avatarState.pitch = player.pitch\n avatarState.holding = heldPiece !== null\n avatarState.itemUse = useItemPlayer\n ? { id: useItemName, ...useItemPlayer.pose() }\n : heldPiece && heldTilt > 0.01\n ? { id: 'tilt', position: [0.2, -0.1, -0.38], rotation: [-heldTilt, 0, 0] }\n : null\n avatar.root.position.set(x, player.feet, z)\n avatar.root.rotation.set(0, player.yaw + Math.PI, 0) // the body's front is +z (the three.js way, as the catalogue items), the view looks down -z at yaw 0\n avatar.update(dt, avatarState)\n avatar.root.updateMatrixWorld(true)\n }\n // ----- the first-person arms: where the tool in the hands asks them to be (a module lends it), else the carried item, else nothing\n let handSource: HandTargetSource | null = null\n let carriedHand: HandTargets | null = null\n // a second camera the room can be drawn from without moving the player's: the arms stay where the player's eye puts them\n let debugView: THREE_NS.PerspectiveCamera | null = null\n let lastHand: { stance: string; triggerFinger: number | null; targets: HandTargets | null } = { stance: 'relaxed', triggerFinger: null, targets: null }\n const strikeClips: Readonly<Record<string, string>> = options.strikeClips ?? DEFAULT_STRIKE_CLIPS\n const handStances: Readonly<Record<string, string>> = options.handStances ?? DEFAULT_HAND_STANCES\n const stepFirstPerson = (dt: number): void => {\n const arms = avatar?.firstPerson\n if (!arms) return\n const targets = handSource?.() ?? carriedHand\n const state: RoomFirstPersonState = {\n camera,\n targets,\n stance: handStances[toolId] ?? (targets ? 'hold' : 'relaxed'),\n speed: avatarState.speed,\n running: avatarState.running,\n crouch: avatarState.crouch,\n contact: (origin, direction, maxDistance) => rayWorld(origin, direction, maxDistance)?.distance ?? null,\n triggerFinger: targets?.fingers?.index ?? null,\n }\n lastHand = { stance: state.stance, triggerFinger: state.triggerFinger, targets }\n arms.update(dt, state)\n }\n /** Moves the camera to the shoulder view for the render that follows, and answers the function that puts it back. */\n const applyThirdView = (): (() => void) => {\n if (!thirdActive()) return () => undefined\n const home = camera.position.clone()\n const pose = thirdPose(0)\n camera.position.set(pose.position[0], pose.position[1], pose.position[2])\n camera.updateMatrixWorld(true)\n return () => {\n camera.position.copy(home)\n camera.updateMatrixWorld(true)\n }\n }\n\n const aim = (): void => {\n camera.updateMatrixWorld(true)\n camera.getWorldPosition(tmpV)\n camera.getWorldDirection(tmpV2)\n aimO[0] = tmpV.x\n aimO[1] = tmpV.y\n aimO[2] = tmpV.z\n aimD[0] = tmpV2.x\n aimD[1] = tmpV2.y\n aimD[2] = tmpV2.z\n if (thirdActive()) {\n // shoulder view: the camera ray finds the target, the shot leaves the eye for it (a shot from the camera would cross the player's own back)\n const pose = thirdPose(0)\n const reach = 80\n const hit = withoutHeld(() => world.raycast(pose.position, pose.direction, reach))\n const dist = hit ? hit.distance : reach\n const tx = pose.position[0] + pose.direction[0] * dist - aimO[0]\n const ty = pose.position[1] + pose.direction[1] * dist - aimO[1]\n const tz = pose.position[2] + pose.direction[2] * dist - aimO[2]\n const len = Math.hypot(tx, ty, tz)\n if (len > 0.5 && (tx * pose.direction[0] + ty * pose.direction[1] + tz * pose.direction[2]) / len > 0.5) {\n aimD[0] = tx / len\n aimD[1] = ty / len\n aimD[2] = tz / len\n }\n }\n }\n\n const FAR: Quat = [0, 0, 0, 1]\n /** Run `fn` with the held object moved away, so that rays and bullets do not hit what the player carries. */\n const withoutHeld = <T,>(fn: () => T): T => {\n const e = heldEntry\n if (!e || !world.has(e.so.objectId)) return fn()\n const p = e.so.root.position\n const q = e.so.root.quaternion\n world.setTransform(e.so.objectId, [0, -5000, 0], FAR)\n try {\n return fn()\n } finally {\n world.setTransform(e.so.objectId, [p.x, p.y, p.z], [q.x, q.y, q.z, q.w])\n }\n }\n\n const rayWorld = (o: Vec3, d: Vec3, max: number): RayHit | null => withoutHeld(() => world.raycast(o, d, max))\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Particles helpers and a tiny seeded rng for visuals\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let rng = 12345\n const rnd = (): number => {\n rng = (rng * 1664525 + 1013904223) >>> 0\n return rng / 4294967296\n }\n\n const muzzle = (): Vec3 => {\n aim()\n const e = camera.matrixWorld.elements\n // right = x axis, up = y axis of the camera\n return [\n aimO[0] + aimD[0] * 0.45 + e[0] * 0.16 - e[4] * 0.1,\n aimO[1] + aimD[1] * 0.45 + e[1] * 0.16 - e[5] * 0.1,\n aimO[2] + aimD[2] * 0.45 + e[2] * 0.16 - e[6] * 0.1,\n ]\n }\n\n // tracers\n const tracers: Array<{ line: THREE_NS.Line; life: number }> = []\n const tracerMat = new THREE.LineBasicMaterial({ color: 0xffe9a8, transparent: true, opacity: 0.9 })\n const tracer = (a: Vec3, b: Vec3): void => {\n let tr = tracers.find((x) => x.life <= 0)\n if (!tr) {\n if (tracers.length >= 12) return\n const g = new THREE.BufferGeometry()\n g.setAttribute('position', new THREE.Float32BufferAttribute(6, 3))\n const line = new THREE.Line(g, tracerMat)\n line.frustumCulled = false\n scene.add(line)\n tr = { line, life: 0 }\n tracers.push(tr)\n }\n const attr = tr.line.geometry.getAttribute('position') as THREE_NS.BufferAttribute\n attr.setXYZ(0, a[0], a[1], a[2])\n attr.setXYZ(1, b[0], b[1], b[2])\n attr.needsUpdate = true\n tr.line.visible = true\n tr.life = 0.07\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Fire glue: stains of flammable liquids, fire zones (molotov), dry water near fire\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const fireZones: FireZone[] = []\n const burningStains: BurningStain[] = []\n const stainRadius = (s: StainState): number => {\n let sum = 0\n for (const r of s.front) sum += r\n return s.front.length ? sum / s.front.length : 0.1\n }\n const stainBurning = (s: StainState): boolean => burningStains.some((b) => dist3(b.center, s.center) < 0.05)\n\n function igniteNear(point: Vec3, reach: number): void {\n let lit = false\n let water = false\n for (const s of fluids.stains()) {\n if (s.wetness < 0.05) continue\n if (Math.hypot(s.center[0] - point[0], s.center[2] - point[2]) > reach + stainRadius(s) || Math.abs(s.center[1] - point[1]) > 1.5) continue\n if (fluids.liquids.get(s.liquid)?.flammable) {\n if (stainBurning(s)) continue\n const seconds = Math.max(3, Math.min(20, 4 + s.liters * 30 + stainRadius(s) * 6))\n burningStains.push({ center: [s.center[0], s.center[1], s.center[2]], remaining: seconds, acc: 0 })\n lit = true\n log.add({\n channel: 'event',\n type: 'stain_ignite',\n text: t('ev.stain_ignite', { liquid: fStrings.liquids[s.liquid] ?? s.liquid, x: num(s.center[0], 1), z: num(s.center[2], 1), seconds: num(seconds, 0) }),\n data: { stain: s.id, liquid: s.liquid, seconds },\n })\n } else water = true\n }\n if (water && !lit) {\n fluids.clearStains(point, Math.max(0.5, reach))\n log.coalesce('dry', { channel: 'event', type: 'stain_dried_by_fire', text: t('ev.fire_dries'), data: { point } }, 2)\n }\n }\n\n const hitFireAround = (point: Vec3, radius: number, temperature: number, duration: number): void => {\n for (const id of world.ids()) world.hit(id, { type: 'fire', point, temperature, radius, duration, source: 'fire' })\n }\n\n const updateFires = (dt: number): void => {\n for (let i = fireZones.length - 1; i >= 0; i--) {\n const z = fireZones[i]\n z.remaining -= dt\n z.acc += dt\n if (z.acc >= 0.1) {\n hitFireAround(z.point, z.radius, z.temperature, z.acc)\n igniteNear(z.point, z.radius)\n z.acc = 0\n }\n const a = rnd() * Math.PI * 2\n const r = Math.sqrt(rnd()) * z.radius\n renderer.emit('fire', [z.point[0] + Math.cos(a) * r, z.point[1] + 0.05, z.point[2] + Math.sin(a) * r], [0, 1, 0], 2, 1.5)\n if (z.remaining <= 0) fireZones.splice(i, 1)\n }\n if (burningStains.length) {\n const stains = fluids.stains()\n for (let i = burningStains.length - 1; i >= 0; i--) {\n const b = burningStains[i]\n b.remaining -= dt\n b.acc += dt\n const st = stains.find((s) => dist3(s.center, b.center) < 0.05)\n const r = st ? stainRadius(st) : 0.3\n if (b.acc >= 0.1) {\n hitFireAround([b.center[0], b.center[1] + 0.1, b.center[2]], r + 0.2, 800, b.acc)\n b.acc = 0\n }\n const a = rnd() * Math.PI * 2\n const rr = Math.sqrt(rnd()) * r\n renderer.emit('fire', [b.center[0] + Math.cos(a) * rr, b.center[1] + 0.05, b.center[2] + Math.sin(a) * rr], [0, 1, 0], 3, 1.8)\n if (rnd() < 0.2) renderer.emit('smoke', [b.center[0], b.center[1] + 0.3, b.center[2]], [0, 1, 0], 1, 1)\n if (b.remaining <= 0 || !st) {\n fluids.clearStains(b.center, r + 0.1)\n log.add({ channel: 'event', type: 'stain_burned', text: t('ev.stain_burned'), data: { point: b.center } })\n burningStains.splice(i, 1)\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Tools\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let progress: { label: string; value: number; at: number } | null = null\n let statusLine = ''\n let statusAt = 0\n const say = (msg: string): void => {\n statusLine = msg\n statusAt = simTime\n ui?.toast(msg)\n }\n\n const toolName = (id = toolId): string => arsenal.name(id)\n const hitWhere = (r: RayHit): string => {\n const p = world.part(r.object, r.part)\n return `${nameOf(r.object)} › ${r.part}${p ? ` (${dStrings.materialNames[p.material] ?? p.material})` : ''}`\n }\n\n const pushPiece = (objectId: string, dir: Vec3, momentum: number, point: Vec3): void => {\n if (!rendererPieces.has(objectId)) return\n renderer.impulse(objectId, [dir[0] * momentum, dir[1] * momentum, dir[2] * momentum], point)\n }\n\n const fireShots = (shots: Shot[], recoil: [number, number]): void => {\n if (shots.length === 0) return\n const w = toolName()\n const m = muzzle()\n renderer.emit('flash', m, [aimD[0], aimD[1], aimD[2]], 1, 0)\n renderer.emit('sparks', m, [aimD[0], aimD[1], aimD[2]], 4, 6)\n let hits = 0\n let first: RayHit | null = null\n let energy = 0\n withoutHeld(() => {\n for (const s of shots) {\n energy = Math.max(energy, s.energy)\n const results = world.shoot(s.origin, s.direction, s.energy, s.caliber, 'player', shotExtras(s))\n const r0 = results.find((r) => r.part && r.point)\n let end: Vec3 = [s.origin[0] + s.direction[0] * 40, s.origin[1] + s.direction[1] * 40, s.origin[2] + s.direction[2] * 40]\n if (r0?.point && r0.part) {\n hits++\n end = r0.point\n if (!first) first = { object: r0.object, part: r0.part, point: r0.point, normal: [0, 1, 0], distance: dist3(s.origin, r0.point) }\n const speed = Math.max(80, s.speed)\n pushPiece(r0.object, s.direction, (2 * s.energy) / speed, r0.point)\n }\n if (shots.length <= 3 || rnd() < 0.34) tracer(m, end)\n }\n })\n player.kick(recoil[0], recoil[1])\n const f = first as RayHit | null\n const d = f ? num(f.distance, 1) : ''\n let text: string\n if (shots.length === 1) text = t(f ? 'act.shoot.hit' : 'act.shoot.miss', { weapon: w, energy: num(energy, 0), where: f ? hitWhere(f) : '', dist: d })\n else text = t('act.shoot.pellets', { weapon: w, n: shots.length, energy: num(energy, 0), hits, where: f ? hitWhere(f) : '', dist: d })\n action('shoot', text, {\n objectId: f?.object,\n itemId: f ? entryOf(f.object)?.so.itemId : undefined,\n part: f?.part,\n data: { weapon: toolId, shots: shots.length, hits, energyJ: Math.round(energy), caliberMm: shots[0].caliber, distanceM: f ? Math.round(f.distance * 100) / 100 : null },\n })\n }\n\n const fireRays = (u: { origin: Vec3; direction: Vec3; range: number; cone: boolean; radius: number }): Array<Vec3> => {\n const d = new THREE.Vector3(u.direction[0], u.direction[1], u.direction[2]).normalize()\n const out: Vec3[] = [[d.x, d.y, d.z]]\n if (u.cone) {\n const a = Math.min(0.2, Math.atan2(u.radius, Math.max(0.1, u.range)))\n const right = new THREE.Vector3().crossVectors(d, new THREE.Vector3(0, 1, 0))\n if (right.lengthSq() < 1e-6) right.set(1, 0, 0)\n right.normalize()\n const up = new THREE.Vector3().crossVectors(right, d).normalize()\n for (const [x, y] of [\n [1, 0],\n [-1, 0],\n [0, 1],\n [0, -1],\n ]) {\n const r = d.clone().addScaledVector(right, x * a).addScaledVector(up, y * a).normalize()\n out.push([r.x, r.y, r.z])\n }\n }\n return out\n }\n\n const heatRays = (u: Extract<Use, { kind: 'flame' | 'heat' }>, type: 'fire' | 'heat'): void => {\n const w = toolName()\n const cone = u.kind === 'flame' ? u.cone : false\n const rays = fireRays({ origin: u.origin, direction: u.direction, range: u.range, cone, radius: u.radius })\n let target: RayHit | null = null\n const m = muzzle()\n withoutHeld(() => {\n for (const d of rays) {\n const r = world.raycast(u.origin, d, u.range)\n if (!r) continue\n if (!target) target = r\n world.hit(r.object, { ...useToHit(u, r.point, r.normal)!, type, direction: d, source: 'player' })\n if (type === 'fire') igniteNear(r.point, 0.25)\n else renderer.emit('sparks', r.point, r.normal, 2, 4)\n }\n })\n if (type === 'fire') {\n renderer.emit('fire', m, [u.direction[0], u.direction[1], u.direction[2]], cone ? 5 : 1, Math.max(0.6, u.range * 1.1))\n if (cone) renderer.emit('smoke', m, [u.direction[0], u.direction[1] + 0.3, u.direction[2]], 1, u.range * 0.5)\n // nothing hit: the stain on the ground in front may still catch\n if (!target && u.direction[1] < -0.2) {\n const t0 = (0.05 - u.origin[1]) / u.direction[1]\n if (t0 > 0 && t0 < u.range) igniteNear([u.origin[0] + u.direction[0] * t0, 0.05, u.origin[2] + u.direction[2] * t0], 0.3)\n }\n }\n const tg = target as RayHit | null\n log.coalesce(\n `use:${toolId}`,\n {\n channel: 'action',\n type,\n text: tg ? t(type === 'fire' ? 'act.flame.hit' : 'act.heat.hit', { weapon: w, where: hitWhere(tg), temp: num(u.temperature, 0) }) : t(type === 'fire' ? 'act.flame.air' : 'act.heat.air', { weapon: w }),\n objectId: tg?.object,\n part: tg?.part,\n data: { weapon: toolId, temperatureC: u.temperature },\n },\n 1,\n )\n }\n\n const meleeUse = (u: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const w = toolName(id)\n const r = rayWorld(u.origin, u.direction, u.reach)\n if (!r) {\n action('melee', t('act.melee.miss', { weapon: w }), { data: { weapon: id } })\n return\n }\n world.hitPart(r.object, r.part, { ...useToHit(u, r.point, r.normal)!, source: 'player' })\n pushPiece(r.object, u.direction, (2 * u.energy) / 6, r.point)\n action('melee', t('act.melee.hit', { weapon: w, energy: num(u.energy, 0), where: hitWhere(r), dist: num(r.distance, 1) }), {\n objectId: r.object,\n itemId: entryOf(r.object)?.so.itemId,\n part: r.part,\n data: { weapon: id, damage: u.damage, energyJ: u.energy, distanceM: Math.round(r.distance * 100) / 100 },\n })\n }\n\n /** Strikes that have begun and whose blow has not landed yet: the tool they belong to, the simulated seconds left and what lands. */\n let strikes: Array<{ key: string; remaining: number; land: () => void }> = []\n /**\n * A melee blow. A tool with a strike clip (`strikeClips`) on an avatar that plays it starts the clip, on the arms and on the body, and the blow lands when the clip reaches its\n * impact, with the aim read again then; any other blow lands now.\n */\n const kickLeg = options.kickLeg ?? 'alternate'\n let nextLeg: 'left' | 'right' = 'right'\n const strikeUse = (u: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const clip = strikeClips[id]\n // a kick uses the leg the option says (alternating from the right), whatever the avatar does with it\n const leg = id === 'kick' ? (kickLeg === 'alternate' ? nextLeg : kickLeg) : undefined\n const seconds = clip === undefined ? null : (avatar?.strike?.(clip, leg ? { leg } : undefined) ?? null)\n if (leg && seconds !== null && kickLeg === 'alternate') nextLeg = leg === 'right' ? 'left' : 'right'\n if (clip === undefined || seconds === null) {\n meleeUse(u, id)\n return\n }\n action('strike', t(leg ? 'act.strike.leg' : 'act.strike', { weapon: toolName(id), clip, seconds: num(seconds, 2), leg: leg ? t(`leg.${leg}`) : '' }), { data: { weapon: id, clip, impactIn: seconds, ...(leg ? { leg } : {}) } })\n strikes.push({\n key: id,\n remaining: seconds,\n land: () => {\n aim()\n meleeUse({ ...u, origin: [aimO[0], aimO[1], aimO[2]], direction: [aimD[0], aimD[1], aimD[2]] }, id)\n },\n })\n }\n const stepStrikes = (dt: number): void => {\n if (strikes.length === 0) return\n for (const strike of strikes) strike.remaining -= dt\n const landed = strikes.filter((strike) => strike.remaining <= 0)\n strikes = strikes.filter((strike) => strike.remaining > 0)\n for (const strike of landed) strike.land()\n }\n\n const toolWork = (u: Extract<Use, { kind: 'tool' }>, dt: number): void => {\n const w = toolName()\n const r = rayWorld(u.origin, u.direction, u.reach)\n if (!r) {\n progress = null\n log.coalesce(`use:${toolId}`, { channel: 'action', type: 'tool', text: t('act.tool.none', { weapon: w }), data: { weapon: toolId } }, 1)\n return\n }\n const j: JointState | null = world.nearestJoint(r.object, r.point, 0.45, u.tool as ToolKind)\n if (!j) {\n progress = null\n log.coalesce(`use:${toolId}`, { channel: 'action', type: 'tool', text: t('act.tool.nojoint', { weapon: w, where: hitWhere(r) }), objectId: r.object, part: r.part }, 1)\n return\n }\n const tool_ = u.tool as ToolKind\n const p = world.disassemble(r.object, j.id, tool_, dt)\n const kind = dStrings.jointKinds[j.kind] ?? j.kind\n if (p < 0) {\n const need = JOINT_DEFAULTS[j.kind].tools.map((k) => dStrings.toolKinds[k] ?? k).join(', ') || t('tool.none')\n progress = { label: t('hud.refused', { kind }), value: 0, at: simTime }\n log.coalesce(\n `refuse:${r.object}:${j.id}:${toolId}`,\n {\n channel: 'action',\n type: 'tool_refused',\n text: t('act.tool.refused', { weapon: w, kind, obj: nameOf(r.object), need }),\n objectId: r.object,\n itemId: entryOf(r.object)?.so.itemId,\n data: { weapon: toolId, joint: j.id, kind: j.kind, needs: JOINT_DEFAULTS[j.kind].tools },\n },\n 2,\n )\n return\n }\n progress = { label: `${kind} (${j.id})`, value: p, at: simTime }\n renderer.emit('sparks', r.point, r.normal, 1, 2)\n }\n\n const extinguishUse = (u: Extract<Use, { kind: 'extinguish' }>): void => {\n const w = toolName()\n const rays = fireRays({ origin: u.origin, direction: u.direction, range: u.range, cone: true, radius: 0.6 })\n const m = muzzle()\n renderer.emit('foam', m, [u.direction[0], u.direction[1], u.direction[2]], 8, u.range * 1.2)\n const hit = new Set<string>()\n withoutHeld(() => {\n for (const d of rays) {\n const r = world.raycast(u.origin, d, u.range)\n if (!r) continue\n hit.add(r.object)\n world.extinguish(r.object, undefined, u.coolC * Math.max(u.duration, 0.05) * 6)\n fluids.clearStains(r.point, 0.5)\n for (let i = burningStains.length - 1; i >= 0; i--) if (Math.hypot(burningStains[i].center[0] - r.point[0], burningStains[i].center[2] - r.point[2]) < 1.2) burningStains.splice(i, 1)\n for (let i = fireZones.length - 1; i >= 0; i--) if (Math.hypot(fireZones[i].point[0] - r.point[0], fireZones[i].point[2] - r.point[2]) < 1.5) fireZones.splice(i, 1)\n }\n })\n log.coalesce(\n `use:${toolId}`,\n { channel: 'action', type: 'extinguish', text: hit.size ? t('act.extinguish.hit', { weapon: w, what: [...hit].map(nameOf).join(', ') }) : t('act.extinguish.air', { weapon: w }), data: { objects: [...hit] } },\n 1,\n )\n }\n\n const startFire = (weapon: string, at: Vec3, fire: { temperature: number; radius: number; seconds: number }, impact: boolean): void => {\n fluids.splash('fuel', [at[0], Math.max(at[1], groundAt(at[0], at[2])), at[2]], 0.5)\n fireZones.push({ point: [at[0], Math.max(0.02, groundAt(at[0], at[2])), at[2]], radius: fire.radius, temperature: fire.temperature, remaining: fire.seconds, acc: 0 })\n renderer.emit('fire', at, [0, 1, 0], 24, 3)\n action('molotov_fire', t('act.molotov_fire', { weapon: toolName(weapon), seconds: num(fire.seconds, 0), radius: num(fire.radius, 1) }), { data: { weapon, impact } })\n }\n\n /** The bodies that trip a wire: the player (a column from the ground to the eyes) and every object of the room that is not the arena. */\n function crossingBodies(): { id: string; box: THREE_NS.Box3 }[] {\n const bodies = [...entries.values()].filter((e) => !e.arena).map((e) => ({ id: e.so.objectId, box: new THREE.Box3().setFromObject(e.so.root) }))\n const { x, y, z } = camera.position\n const feet = groundAt(x, z)\n bodies.push({ id: 'player', box: new THREE.Box3(new THREE.Vector3(x - PLAYER_RADIUS, feet, z - PLAYER_RADIUS), new THREE.Vector3(x + PLAYER_RADIUS, y + 0.1, z + PLAYER_RADIUS)) })\n return bodies\n }\n\n // ----- the blast options of the room's explosions (the HUD toggles them), and what the last blast did\n let blastOptions: BlastOptions = { ...options.blast }\n let lastBlast: BlastSummary | undefined\n const blastOn = (key: 'shelter' | 'fragmentHits' | 'confinement'): boolean => Boolean(blastOptions[key])\n const toggleBlast = (key: 'shelter' | 'fragmentHits' | 'confinement'): void => {\n blastOptions = { ...blastOptions, [key]: blastOn(key) ? false : true }\n }\n\n // ----- projectiles (grenades, molotovs, rockets) and charges set down: the room lends the explosives its world, log and host\n const explosives = createExplosives({\n THREE,\n scene,\n camera,\n world,\n renderer,\n effects: vfx.world,\n arsenal,\n objects: () => [...entries.values()].filter((e) => !e.arena).map((e) => e.so.root),\n bodies: crossingBodies,\n toolId: () => toolId,\n toolName,\n withoutHeld,\n groundAt,\n blast: () => blastOptions,\n blasted: (summary) => {\n lastBlast = summary\n },\n translate: t,\n format: num,\n action,\n emitHost,\n startFire,\n say,\n projectileModel: options.projectileModel,\n })\n\n // ----- the trigger\n const useTool = (dt: number, held: boolean): void => {\n aim()\n const cat = tool.def.category\n if (cat === 'hand') {\n if (strikes.some((strike) => strike.key === 'hand' || strike.key === 'fists')) return\n strikeUse({ kind: 'melee', damage: 'blunt', energy: 25, radius: 0.1, reach: 0.8, origin: [aimO[0], aimO[1], aimO[2]], direction: [aimD[0], aimD[1], aimD[2]] }, 'hand')\n return\n }\n if (strikes.some((strike) => strike.key === toolId)) return // the blow of this tool is still on its way\n const res = tool.trigger([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], dt, held, 'player')\n flushEvents(toolId, tool, res.recoil)\n if (res.status === 'empty') {\n if (!tool.reloading && tool.reserve > 0) startReload()\n say(t(tool.reloading ? 'hud.reloading' : 'hud.empty'))\n return\n }\n if (res.status !== 'ok') {\n if (res.status === 'reloading') say(t('hud.reloading'))\n else if (res.status === 'no_fuel') say(t('hud.no_fuel'))\n else if (res.status === 'fault' && res.fault) say(t('hud.fault', { fault: t(`fault.${res.fault}`) }))\n else if (res.status === 'safe') say(t('hud.safe'))\n return\n }\n applyUses(res, dt)\n }\n\n const applyUses = (res: TriggerResult, dt: number): void => {\n if (res.shots.length) fireShots(res.shots, res.recoil)\n for (const u of res.uses) {\n switch (u.kind) {\n case 'melee':\n strikeUse(u)\n break\n case 'flame':\n heatRays(u, 'fire')\n break\n case 'heat':\n heatRays(u, 'heat')\n break\n case 'throw':\n explosives.throwUse(u)\n break\n case 'place':\n explosives.placeUse(u)\n break\n case 'backblast':\n explosives.backblastUse(u)\n break\n case 'tool':\n toolWork(u, dt)\n break\n case 'extinguish':\n extinguishUse(u)\n break\n default:\n break\n }\n }\n }\n\n /** The trigger goes up: a grenade being cooked leaves the hand now, with the fuse that is left (or has already gone off in it). */\n const releaseTrigger = (): void => {\n if (!tool.cooking) {\n tool.release()\n return\n }\n aim()\n const res = tool.release([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]])\n flushEvents(toolId, tool)\n if (res) applyUses(res, 0)\n }\n\n /** The V shortcut: a kick with the `kick` tool, whatever tool is selected (it keeps its own cooldown). */\n const kick = (): void => {\n if (!arsenal.weapons.has('kick') || strikes.some((strike) => strike.key === 'kick')) return\n aim()\n const res = toolState('kick').trigger([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 0, false, 'player')\n if (res.status !== 'ok') return\n for (const u of res.uses) if (u.kind === 'melee') strikeUse(u, 'kick')\n }\n const setTool = (id: string): void => {\n if (!arsenal.weapons.has(id)) throw new Error(`game-test-room: unknown weapon \"${id}\"`)\n releaseTrigger()\n toolId = id\n const i = loadout.indexOf(id)\n if (i >= 0) toolIndex = i\n tool = toolState(id)\n progress = null\n action('tool', t('act.tool', { weapon: toolName(id) }), { data: { weapon: id } })\n fire('tool', id)\n tool.draw()\n flushEvents(id, tool)\n }\n const cycleTool = (dir: 1 | -1): void => {\n if (!loadout.length) return\n toolIndex = (toolIndex + dir + loadout.length) % loadout.length\n setTool(loadout[toolIndex])\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Grabbing, carrying, throwing\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let heldEntry: Entry | null = null\n let heldPiece: Piece | null = null\n let heldName = ''\n let heldYaw = 0\n let heldTilt = 0\n let tiltKey = 0\n const heldLocal = new THREE.Vector3()\n const heldSize = new THREE.Vector3(0.2, 0.2, 0.2)\n let heldRadius = 0.2\n const heldVel: Vec3 = [0, 0, 0]\n let useItemPlayer: ItemUsePlayer | null = null\n let useItemName = ''\n\n const releaseHeld = (): void => {\n if (heldPiece) {\n heldPiece.held = false\n heldPiece.sleeping = false\n heldPiece.velocity = [heldVel[0], heldVel[1], heldVel[2]]\n }\n useItemPlayer?.cancel()\n useItemPlayer = null\n heldEntry = null\n heldPiece = null\n heldTilt = 0\n }\n\n const grab = (): boolean => {\n if (heldPiece) {\n const name = heldName\n releaseHeld()\n action('drop', t('act.drop', { name }))\n fire('grab', { held: false })\n return true\n }\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n if (!r) {\n say(t('hud.nothing_to_grab'))\n return false\n }\n const piece = rendererPieces.get(r.object)\n if (!piece) {\n say(t('hud.cannot_grab', { name: nameOf(r.object) }))\n return false\n }\n const kg = piece.mass\n if (kg > maxCarry) {\n say(t('hud.too_heavy', { name: nameOf(r.object), kg: num(kg, 0) }))\n return false\n }\n heldPiece = piece\n heldEntry = entries.get(r.object) ?? null\n heldName = nameOf(r.object)\n piece.held = true\n piece.sleeping = false\n // centre and unrotated size of the object's bounding box in its own space, to hold it by its middle or cylindrical side\n const savedQ = piece.root.quaternion.clone()\n piece.root.quaternion.identity()\n piece.root.updateMatrixWorld(true)\n const box = new THREE.Box3().setFromObject(piece.root)\n box.getCenter(heldLocal).sub(piece.root.position)\n box.getSize(heldSize)\n piece.root.quaternion.copy(savedQ)\n piece.root.updateMatrixWorld(true)\n heldRadius = heldSize.length() / 3\n heldYaw = 0\n heldTilt = 0\n heldVel[0] = heldVel[1] = heldVel[2] = 0\n action('grab', t('act.grab', { name: heldName, kg: num(kg, 1) }), { objectId: r.object, itemId: entryOf(r.object)?.so.itemId, data: { massKg: Math.round(kg * 10) / 10 } })\n fire('grab', { held: true, objectId: r.object })\n return true\n }\n\n const throwHeld = (speed = 9): boolean => {\n if (!heldPiece) return false\n const piece = heldPiece\n const name = heldName\n const id = piece.objectId\n aim()\n releaseHeld()\n piece.velocity = [0, 0, 0]\n renderer.impulse(id, [aimD[0] * speed * piece.mass, (aimD[1] * speed + 1.2) * piece.mass, aimD[2] * speed * piece.mass])\n action('throw', t('act.throw', { name, speed: num(speed, 1) }), { objectId: id, itemId: entryOf(id)?.so.itemId, data: { speedMs: speed, massKg: piece.mass } })\n fire('throw', { objectId: id, speed })\n return true\n }\n\n /**\n * Where the first-person hands take the carried item: cylindrical cans, bottles and cartons are gripped around their side (and rotated with the item's\n * tilt during drinking, sipping or pouring, with the left hand reaching the cap on `open`/`close`); wide or flat items rest on the palm underneath.\n */\n const carriedTargets = (root: THREE_NS.Object3D, gripQ: THREE_NS.Quaternion): HandTargets => {\n const width = Math.max(heldSize.x, heldSize.z)\n const sideGrip = heldSize.y > width * 1.04 && width <= 0.22\n if (sideGrip) {\n const center = heldLocal.clone().applyQuaternion(root.quaternion).add(root.position)\n const radius = Math.min(heldSize.x, heldSize.z) * 0.5\n const handX = new THREE.Vector3(-0.35, 0, -0.94).normalize().applyQuaternion(gripQ)\n const handY = new THREE.Vector3(0.94, 0, -0.35).normalize().applyQuaternion(gripQ)\n const handZ = new THREE.Vector3().crossVectors(handX, handY).normalize()\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(handX, handY, handZ))\n const up = new THREE.Vector3(0, 1, 0).applyQuaternion(gripQ)\n const palm = center\n .clone()\n .addScaledVector(handY, radius + CARRY_PALM)\n .addScaledVector(handX, -0.022)\n .addScaledVector(up, heldSize.y > 0.16 ? -heldSize.y * 0.08 : -0.005)\n if (useItemName === 'open' || useItemName === 'close') {\n const leftX = new THREE.Vector3(0.35, 0, -0.94).normalize().applyQuaternion(gripQ)\n const leftY = new THREE.Vector3(-0.94, 0, -0.35).normalize().applyQuaternion(gripQ)\n const leftZ = new THREE.Vector3().crossVectors(leftX, leftY).normalize()\n const lq = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(leftX, leftY, leftZ))\n const leftPalm = center\n .clone()\n .addScaledVector(up, heldSize.y * 0.45)\n .addScaledVector(leftY, radius * 0.65 + CARRY_PALM)\n .addScaledVector(leftX, -0.018)\n return {\n R: { position: [palm.x, palm.y, palm.z], quaternion: [q.x, q.y, q.z, q.w] },\n L: { position: [leftPalm.x, leftPalm.y, leftPalm.z], quaternion: [lq.x, lq.y, lq.z, lq.w] },\n grip: 0.85,\n gripL: 0.8,\n }\n }\n return { R: { position: [palm.x, palm.y, palm.z], quaternion: [q.x, q.y, q.z, q.w] }, grip: 0.85 }\n }\n const box = new THREE.Box3().setFromObject(root)\n const center = box.getCenter(new THREE.Vector3())\n const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(gripQ).normalize()\n const back = new THREE.Vector3(0, -1, 0).applyQuaternion(gripQ).normalize()\n const z = new THREE.Vector3().crossVectors(forward, back).normalize()\n const y = new THREE.Vector3().crossVectors(z, forward).normalize()\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(forward, y, z))\n return { R: { position: [center.x, box.min.y - CARRY_PALM, center.z], quaternion: [q.x, q.y, q.z, q.w] }, grip: CARRY_GRIP }\n }\n\n const gripQuat = new THREE.Quaternion()\n const followHeld = (dt: number): void => {\n const piece = heldPiece\n carriedHand = null\n if (!piece) return\n camera.updateMatrixWorld(true)\n const root = piece.root\n let pos: THREE_NS.Vector3\n const targetQ = tmpQ\n const hand = thirdActive() ? avatar?.hand?.('R') : undefined\n const isDrink = useItemName === 'drink' || useItemName === 'sip' || useItemName === 'chug'\n if (hand) {\n // shoulder view: the item rides the avatar's weapon hand, and tilts with `useItemPlayer` or `heldTilt`\n const handWorld = hand.getWorldPosition(tmpHand)\n const yawQ = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw)\n const pose = useItemPlayer?.pose()\n const rx = pose ? (isDrink ? Math.abs(pose.rotation[0]) * 0.9 : pose.rotation[0]) : -heldTilt\n const ry = pose ? pose.rotation[1] : 0\n const rz = pose ? pose.rotation[2] : 0\n gripQuat.copy(yawQ).multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.max(-1.35, Math.min(1.25, rx)), ry, rz, 'XYZ')))\n targetQ.copy(yawQ).multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(rx, ry, rz, 'XYZ')))\n targetQ.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), heldYaw))\n const gripOffset = new THREE.Vector3(-0.02, 0.015, -0.04).applyQuaternion(gripQuat)\n pos = tmpV.copy(handWorld).add(gripOffset)\n } else if (useItemPlayer) {\n const pose = useItemPlayer.pose()\n const frameQ = avatar?.firstPerson ? camera.quaternion : new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw)\n const raise = isDrink ? Math.max(0, Math.min(1, (pose.position[1] + 0.2) / 0.22)) : 0\n const px = pose.position[0] + (isDrink ? 0.02 * raise : 0)\n const py = pose.position[1] - (isDrink ? 0.08 * raise : 0)\n const pz = pose.position[2] - (isDrink ? 0.05 * raise : 0)\n pos = tmpV.set(px, py, pz).applyQuaternion(frameQ).add(camera.position)\n const rx = isDrink ? Math.abs(pose.rotation[0]) * 0.85 : pose.rotation[0]\n const eq = new THREE.Quaternion().setFromEuler(new THREE.Euler(rx, pose.rotation[1], pose.rotation[2], 'XYZ'))\n const wristEq = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.max(-1.35, Math.min(1.25, rx)), pose.rotation[1], pose.rotation[2], 'XYZ'))\n gripQuat.copy(frameQ).multiply(wristEq)\n targetQ.copy(frameQ).multiply(eq)\n targetQ.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), heldYaw))\n } else {\n // with first-person arms, small items sit in the right hand at [0.22, -0.2, -0.42] (matching the start of `ITEM_USES`); large ones stay further out\n const small = heldRadius < 0.22\n const holdX = avatar?.firstPerson ? (small ? 0.22 : 0.08) : 0.05\n const holdY = avatar?.firstPerson ? (small ? -0.2 : -0.26) : -0.28\n const holdZ = avatar?.firstPerson ? (small ? -0.42 : -Math.min(1.15, CARRY_NEAR + heldRadius)) : -1.15\n pos = tmpV.set(holdX, holdY, holdZ).applyMatrix4(camera.matrixWorld)\n const baseQ = avatar?.firstPerson && small ? camera.quaternion : new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw)\n gripQuat.copy(baseQ).multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.max(-1.35, -heldTilt)))\n targetQ.setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw + heldYaw)\n if (avatar?.firstPerson && small && heldTilt <= 1e-4) {\n targetQ.copy(camera.quaternion).multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), heldYaw))\n } else {\n targetQ.multiply(new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -heldTilt))\n }\n }\n const k = Math.min(1, (useItemPlayer ? 30 : 16) * dt)\n const px = root.position.x\n const py = root.position.y\n const pz = root.position.z\n root.quaternion.slerp(targetQ, Math.min(1, k * 0.9))\n // the middle of the carried object follows the target; the offset uses the current rotation so it does not orbit\n const off2 = tmpV2.copy(heldLocal).applyQuaternion(root.quaternion)\n root.position.set(root.position.x + (pos.x - off2.x - root.position.x) * k, root.position.y + (pos.y - off2.y - root.position.y) * k, root.position.z + (pos.z - off2.z - root.position.z) * k)\n if (dt > 0) {\n heldVel[0] = (root.position.x - px) / dt\n heldVel[1] = (root.position.y - py) / dt\n heldVel[2] = (root.position.z - pz) / dt\n }\n root.updateMatrixWorld(true)\n if (avatar?.firstPerson && cameraMode === 'first') carriedHand = carriedTargets(root, gripQuat)\n }\n\n const useItem = (useId: string): boolean => {\n const e = heldEntry\n if (!e?.containerId) return false\n const def = itemUseDefs.find((u) => u.id === useId)\n if (!def) return false\n const c = fluids.container(e.containerId)\n if (!c) return false\n if (def.liquids && def.liquids.length > 0 && (!c.liquid || !def.liquids.includes(c.liquid))) return false\n const consuming = useId === 'drink' || useId === 'sip' || useId === 'chug' || useId === 'pour' || useId === 'pour_out'\n if (consuming && c.liters <= 1e-6) {\n say(t('hud.empty_container', { name: e.name }))\n return false\n }\n if (useItemPlayer && !useItemPlayer.done) return false\n if (consuming && c.closed) fluids.open(e.containerId)\n useItemPlayer = createItemUse(fluids, e.containerId, def)\n useItemName = def.id\n action('use_item', t('act.use_item', { name: e.name, use: S.text[`use.${def.id}`] ?? def.id }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { use: def.id } })\n return true\n }\n\n const updateItemUse = (dt: number): void => {\n if (!useItemPlayer) return\n useItemPlayer.update(dt)\n if (useItemPlayer.done) {\n useItemPlayer = null\n useItemName = ''\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Tap\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const TAP_ID = 'room_tap'\n const TAP_RATE = 0.25\n if (arena.tapSpout) fluids.addTap({ id: TAP_ID, position: arena.tapSpout, liquid: 'water', rate: TAP_RATE, temperature: 16, on: false })\n const isTapOn = (): boolean => fluids.taps().some((x) => x.id === TAP_ID && x.on)\n const toggleTap = (on = !isTapOn()): boolean => {\n fluids.setTap(TAP_ID, on)\n action('tap', t(on ? 'act.tap.on' : 'act.tap.off'))\n return on\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Thrown and falling pieces: damage to what they hit\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const lastImpact = new Map<string, number>()\n /** Landings slower than this (m/s) are not logged (the renderer only treats 3 m/s and up as a hard landing; nothing below 1.5 m/s is ever worth a line). */\n const MIN_LANDING_LOG = 3\n const updateImpacts = (): void => {\n const check = (piece: Piece): void => {\n if (piece.held || piece.sleeping) return\n const v = piece.velocity\n const speed = Math.hypot(v[0], v[1], v[2])\n if (speed < 3.5) return\n if ((lastImpact.get(piece.objectId) ?? -9) > simTime - 0.25) return\n const dir: Vec3 = [v[0] / speed, v[1] / speed, v[2] / speed]\n const c = tmpV.copy(new THREE.Vector3(0, 0, 0))\n void c\n const box = tmpBox.setFromObject(piece.root)\n const centre = box.getCenter(tmpV)\n const size = box.getSize(tmpV2)\n const reach = Math.max(size.x, size.y, size.z) * 0.5\n const origin: Vec3 = [centre.x + dir[0] * (reach + 0.02), centre.y + dir[1] * (reach + 0.02), centre.z + dir[2] * (reach + 0.02)]\n const r = withoutHeld(() => world.raycast(origin, dir, speed * FIXED_DT * 2 + 0.06))\n if (!r || r.object === piece.objectId) return\n const energy = 0.5 * piece.mass * speed * speed\n lastImpact.set(piece.objectId, simTime)\n world.hitPart(r.object, r.part, { type: 'blunt', point: r.point, direction: dir, energy, radius: 0.08, source: 'thrown' })\n if (world.has(piece.objectId)) world.hit(piece.objectId, { type: 'blunt', point: r.point, direction: [-dir[0], -dir[1], -dir[2]], energy: energy * 0.4, radius: 0.08, source: 'thrown' })\n pushPiece(r.object, dir, piece.mass * speed * 0.5, r.point)\n piece.velocity = [-v[0] * 0.25, Math.abs(v[1]) * 0.3 + 0.5, -v[2] * 0.25]\n action('impact', t('act.impact', { name: nameOf(piece.objectId), where: hitWhere(r), energy: num(energy, 0), speed: num(speed, 1) }), {\n objectId: piece.objectId,\n itemId: entryOf(piece.objectId)?.so.itemId,\n data: { energyJ: Math.round(energy), speedMs: Math.round(speed * 10) / 10, target: r.object, targetPart: r.part },\n })\n }\n const land = (piece: Piece): void => {\n const vy = piece.velocity[1]\n const prev = prevVy.get(piece.objectId) ?? 0\n prevVy.set(piece.objectId, vy)\n // the renderer applies the landing damage itself (source 'fall'); here we only describe it in the log\n if (piece.held || prev > -MIN_LANDING_LOG || vy < prev + 2 || !world.has(piece.objectId)) return\n const energy = 0.5 * piece.mass * prev * prev\n action('landing', t('act.landing', { name: nameOf(piece.objectId), speed: num(-prev, 1), energy: num(energy, energy < 100 ? 1 : 0) }), {\n objectId: piece.objectId,\n itemId: entryOf(piece.objectId)?.so.itemId,\n data: { energyJ: Math.round(energy * 10) / 10, speedMs: Math.round(-prev * 10) / 10 },\n })\n }\n for (const e of entries.values()) if (e.piece) { check(e.piece); land(e.piece) }\n for (const p of loose) { check(p); land(p) }\n }\n const prevVy = new Map<string, number>()\n const tmpBox = new THREE.Box3()\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Keys\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const onKey = (code: string, down: boolean, e: KeyboardEvent): void => {\n if (!down) {\n if (code === 'KeyZ') tiltKey = 0\n return\n }\n const digit = /^Digit(\\d)$/.exec(code)\n if (digit && !e.ctrlKey && !e.metaKey) {\n const n = (Number(digit[1]) + 9) % 10\n const page = Math.floor(toolIndex / 10)\n const idx = page * 10 + n\n if (idx < loadout.length) setTool(loadout[idx])\n return\n }\n switch (code) {\n case 'KeyE':\n grab()\n break\n case 'KeyG':\n throwHeld()\n break\n case 'KeyR':\n if (heldPiece) heldYaw += Math.PI / 8\n else {\n startReload()\n say(t('hud.reloading'))\n }\n break\n case 'KeyQ': {\n tool.cycleMode()\n flushEvents(toolId, tool)\n break\n }\n case 'KeyX':\n clearToolFault()\n break\n case 'KeyB':\n toggleSafety()\n break\n case 'KeyZ':\n tiltKey = 1\n break\n case 'KeyF':\n if (heldEntry?.uses[0]) useItem(heldEntry.uses[0])\n break\n case 'KeyC':\n // C crouches by default: the item's second use takes it only when the page moved the crouch to other keys\n if (heldEntry?.uses[1] && !(options.crouch?.keys ?? ['KeyC']).includes('KeyC')) useItem(heldEntry.uses[1])\n break\n case 'KeyV':\n if (heldEntry?.uses[2]) useItem(heldEntry.uses[2])\n else if (avatar && !e.shiftKey) setCameraMode(cameraMode === 'first' ? 'third' : 'first')\n else kick()\n break\n case 'KeyT':\n toggleTap()\n break\n case 'KeyY':\n explosives.detonateCharges()\n break\n case 'KeyH': {\n const w = (heldEntry ?? entryOf(inspectTarget()?.object ?? ''))?.item?.weapon\n if (w) equip(w)\n break\n }\n case 'BracketRight':\n toolIndex = Math.min(loadout.length - 1, (Math.floor(toolIndex / 10) + 1) * 10)\n setTool(loadout[toolIndex])\n break\n case 'BracketLeft':\n toolIndex = Math.max(0, (Math.floor(toolIndex / 10) - 1) * 10)\n setTool(loadout[toolIndex])\n break\n case 'Tab':\n ui?.togglePanels()\n break\n default:\n break\n }\n }\n\n const equip = (weaponId: string): void => {\n if (!arsenal.weapons.has(weaponId)) return\n if (!loadout.includes(weaponId)) loadout.push(weaponId)\n setTool(weaponId)\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Inspector\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const inspectTarget = (): RayHit | null => {\n aim()\n return rayWorld(aimO, aimD, 14)\n }\n\n const inspectInfo = (): InspectInfo | null => {\n const r = inspectTarget()\n if (!r) return null\n const st = world.state(r.object)\n const p = world.part(r.object, r.part)\n if (!st || !p) return null\n const e = entryOf(r.object)\n const joints = st.joints\n .filter((j) => j.a === r.part || j.b === r.part)\n .map((j) => ({\n id: j.id,\n kind: dStrings.jointKinds[j.kind] ?? j.kind,\n tools: JOINT_DEFAULTS[j.kind].tools.map((k) => dStrings.toolKinds[k] ?? k),\n open: j.open,\n progress: j.progress,\n }))\n const ext = p as unknown as { load?: number; stress?: number }\n return {\n object: nameOf(r.object),\n objectId: r.object,\n part: r.part,\n material: S.text[`material.${p.material}`] ?? dStrings.materialNames[p.material] ?? p.material,\n status: dStrings.partStatus[p.status] ?? p.status,\n hp: p.hp,\n maxHp: p.maxHp,\n temperature: p.temperature,\n burning: p.burning,\n char: p.char,\n melt: p.melt,\n liters: p.liters,\n dents: p.dents.length,\n holes: p.holes.length,\n cracks: p.cracks.length,\n mass: p.mass,\n load: ext.load,\n stress: ext.stress,\n joints,\n note: e?.item?.note,\n thumbnail: e?.item?.thumbnail,\n thumbnailCredit: e?.item?.thumbnailCredit,\n distance: r.distance,\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Frame\n // ---------------------------------------------------------------------------------------------------------------------------------------\n let timeScale = 1\n let fastForward = false\n let hudAcc = 1\n let metricsAcc = 0\n // when the room runs its own loop it feeds the counters the unclamped real delta; otherwise update(dt) is the only source\n let ownsLoop = false\n const roomMetricIds: readonly RoomMetricId[] = options.metrics === false ? [] : options.metrics ?? ROOM_METRICS\n const roomMetrics = createRoomMetrics({ gl, destruction: renderer, fluids: fluidView, effects: vfx.world, ids: roomMetricIds, blast: () => lastBlast })\n let qualityName: 'low' | 'medium' | 'high' = quality\n\n const syncContainers = (sdt: number): void => {\n const drinkingHeld = useItemPlayer !== null && (useItemName === 'drink' || useItemName === 'sip' || useItemName === 'chug')\n for (const e of entries.values()) {\n if (!e.containerId) continue\n const host = hostOf(e)\n host.root.updateMatrixWorld(true)\n const q = host.root.getWorldQuaternion(tmpQ)\n const p = tmpV.set(e.fluidOffset[0], e.fluidOffset[1], e.fluidOffset[2]).applyMatrix4(host.root.matrixWorld)\n const vel: Vec3 | undefined = sdt > 0 ? [(p.x - e.last[0]) / sdt, (p.y - e.last[1]) / sdt, (p.z - e.last[2]) / sdt] : undefined\n e.last = [p.x, p.y, p.z]\n // while the player's mouth covers the opening to drink, keep the fluid simulation upright so the drink does not spill onto the floor\n const rot: Quat = drinkingHeld && e === heldEntry ? [0, 0, 0, 1] : [q.x, q.y, q.z, q.w]\n fluids.setTransform(e.containerId, [p.x, p.y, p.z], rot, vel)\n }\n }\n\n const syncLiters = (): void => {\n for (const e of entries.values()) {\n if (!e.containerId || !e.fluidPart) continue\n const c = fluids.container(e.containerId)\n if (!c) continue\n const host = hostOf(e)\n const part = world.part(host.objectId, e.fluidPart)\n if (part && part.liters !== undefined && Math.abs(part.liters - c.liters) > 1e-4) world.setLiters(host.objectId, e.fluidPart, c.liters)\n }\n }\n\n let paused = false\n let walkPlan: { x: number; z: number; remaining: number } | null = null\n const stepWalk = (dt: number): void => {\n if (!walkPlan) return\n const f = walkPlan.remaining <= dt ? 1 : dt / walkPlan.remaining\n player.moveBy((walkPlan.x - camera.position.x) * f, (walkPlan.z - camera.position.z) * f)\n walkPlan.remaining -= dt\n if (walkPlan.remaining <= 1e-9) walkPlan = null\n }\n\n const stepSim = (dt: number): void => {\n if (paused) return\n // `dt` is simulated seconds; real time only drives input\n simTime += dt\n stepWalk(dt)\n stepStrikes(dt)\n const reps = fastForward ? 10 : 1\n updateAnimations(dt)\n updateItemUse(dt)\n explosives.update(dt)\n syncContainers(dt)\n for (let i = 0; i < reps; i++) {\n world.update(dt)\n if (i === 0) updateFires(dt)\n fluids.update(dt)\n }\n syncLiters()\n renderer.update(dt)\n vfx.update(dt)\n craterPatch?.sync()\n updateImpacts()\n fluidView.update(dt)\n filmBridge.update(dt)\n film.update(dt)\n for (const [id, s] of tools) {\n s.update(dt)\n flushEvents(id, s)\n }\n if (audio) {\n // the listener is the camera: where it stands and which way it looks (yaw 0 faces -z)\n const look = camera.getWorldDirection(listenerDirection)\n audio.setListener({ position: [camera.position.x, camera.position.y, camera.position.z], yaw: Math.atan2(-look.x, -look.z) })\n }\n for (const update of frameListeners) update(dt)\n for (const tr of tracers) {\n if (tr.life > 0) {\n tr.life -= dt\n if (tr.life <= 0) tr.line.visible = false\n }\n }\n flush()\n }\n\n const update = (dt: number): void => {\n if (!ownsLoop) roomMetrics.frame(dt)\n player.update(dt)\n stepAvatar(paused ? 0 : dt)\n if (tiltKey || heldTilt > 0) {\n heldTilt = Math.max(0, Math.min(2.4, heldTilt + (tiltKey ? 2.2 : -3) * dt))\n }\n if (useHeld && !paused) {\n if (tool.def.category === 'hand') {\n if (useFirst) grab()\n } else useTool(dt, !useFirst)\n useFirst = false\n }\n if (!paused) followHeld(dt)\n stepSim(dt * timeScale)\n stepFirstPerson(paused ? 0 : dt)\n if (progress && simTime - progress.at > 0.25) progress = null\n hudAcc += dt\n if (hudAcc >= 0.1 && ui) {\n hudAcc = 0\n ui.hud(hudState())\n }\n metricsAcc += dt\n if (metricsAcc >= METRICS_INTERVAL_S && ui) {\n metricsAcc = 0\n if (ui.benchVisible) ui.metrics(metricRows())\n }\n }\n\n const hudState = (): HudState => {\n const page = Math.floor(toolIndex / 10)\n const slots = loadout.slice(page * 10, page * 10 + 10).map((id) => arsenal.name(id))\n const ammo = tool.def.action.kind === 'firearm' ? `${tool.ammo}/${tool.capacity}${tool.reserve ? ` · ${tool.reserve}` : ''}` : tool.def.action.kind === 'hand' ? '' : tool.def.action.kind === 'melee' || tool.def.action.kind === 'tool' ? '' : `${num(tool.ammo, 0)}`\n return {\n toolName: toolName(),\n toolId,\n ammo,\n slots,\n slot: toolIndex - page * 10,\n page: page + 1,\n pages: Math.max(1, Math.ceil(loadout.length / 10)),\n status: simTime - statusAt < 2 ? statusLine : '',\n progress: progress ? { label: progress.label, value: progress.value } : null,\n held: heldEntry || heldPiece ? { name: heldName, uses: (heldEntry?.uses ?? []).map((u, i) => ({ key: ['F', 'C', 'V'][i] ?? '', label: S.text[`use.${u}`] ?? u })), weapon: heldEntry?.item?.weapon ? arsenal.name(heldEntry.item.weapon) : undefined, using: useItemName } : null,\n inspect: inspectInfo(),\n animations: animationsOf(),\n locked: player.locked,\n timeScale,\n fast: fastForward,\n tap: isTapOn(),\n blast: { shelter: blastOn('shelter'), fragmentHits: blastOn('fragmentHits'), confinement: blastOn('confinement') },\n quality: qualityName,\n camera: avatar ? cameraMode : null,\n objects: [...entries.values()].filter((e) => !e.arena).length,\n }\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Item animations (clips of AnimationClipSpec)\n // ---------------------------------------------------------------------------------------------------------------------------------------\n interface Playing {\n entry: Entry\n clip: AnimationClipSpec\n t: number\n fired: number\n targets: Map<string, THREE_NS.Object3D>\n }\n const playing: Playing[] = []\n const restPose = new WeakMap<THREE_NS.Object3D, { p: Vec3; r: Vec3 }>()\n const ZERO: Vec3 = [0, 0, 0]\n const animTarget = (): Entry | undefined => {\n if (heldEntry) return heldEntry\n const r = inspectTarget()\n return r ? entryOf(r.object) : undefined\n }\n const poseAt = (clip: AnimationClipSpec, id: string | null, time: number): { position: Vec3; rotation: Vec3 } => {\n const pick = (k: AnimationClipSpec['keys'][number]): { position?: Vec3; rotation?: Vec3 } | undefined => (id === null ? k : k.parts?.[id])\n const pts = clip.keys.map((k) => ({ t: k.t, position: pick(k)?.position ?? ZERO, rotation: pick(k)?.rotation ?? ZERO }))\n if (pts.length === 0 || pts[0].t > 0) pts.unshift({ t: 0, position: ZERO, rotation: ZERO })\n let a = pts[0]\n let b = pts[pts.length - 1]\n if (time >= b.t) a = b\n else for (let i = 0; i < pts.length - 1; i++) if (time >= pts[i].t && time < pts[i + 1].t) [a, b] = [pts[i], pts[i + 1]]\n const f = a === b || b.t <= a.t ? 0 : (time - a.t) / (b.t - a.t)\n const mix = (x: Vec3, y: Vec3): Vec3 => [x[0] + (y[0] - x[0]) * f, x[1] + (y[1] - x[1]) * f, x[2] + (y[2] - x[2]) * f]\n return { position: mix(a.position, b.position), rotation: mix(a.rotation, b.rotation) }\n }\n const applyClip = (pl: Playing): void => {\n for (const [id, obj] of pl.targets) {\n const rest = restPose.get(obj)\n if (!rest) continue\n const pose = poseAt(pl.clip, id === '' ? null : id, pl.t)\n obj.position.set(rest.p[0] + pose.position[0], rest.p[1] + pose.position[1], rest.p[2] + pose.position[2])\n obj.rotation.set(rest.r[0] + pose.rotation[0], rest.r[1] + pose.rotation[1], rest.r[2] + pose.rotation[2])\n // animations are visual only: move the part's collision/raycast shape to the same pose (spec rest + clip offset)\n const ps = id === '' ? undefined : specs.get(pl.entry.so.objectId)?.parts.find((p) => p.id === id)\n if (ps) {\n const r0 = ps.rotation ?? ZERO\n world.setPartPose(\n pl.entry.so.objectId, id,\n [ps.position[0] + pose.position[0], ps.position[1] + pose.position[1], ps.position[2] + pose.position[2]],\n [r0[0] + pose.rotation[0], r0[1] + pose.rotation[1], r0[2] + pose.rotation[2]],\n )\n }\n }\n }\n const updateAnimations = (dt: number): void => {\n for (let i = playing.length - 1; i >= 0; i--) {\n const pl = playing[i]\n pl.t = Math.min(pl.clip.duration, pl.t + dt)\n applyClip(pl)\n const evs = pl.clip.events ?? []\n while (pl.fired < evs.length && evs[pl.fired].t <= pl.t) {\n const ev = evs[pl.fired++]\n action('animation_event', t('act.anim_event', { name: pl.entry.name, clip: pl.clip.id, type: ev.type }), { objectId: pl.entry.so.objectId, itemId: pl.entry.so.itemId, data: { clip: pl.clip.id, type: ev.type, at: ev.t, ...(ev.data ?? {}) } })\n const key = ev.type === 'sound' ? ev.data?.key : undefined\n if (typeof key === 'string') playSound(key, v3(pl.entry.so.root.getWorldPosition(tmpV)), 1)\n }\n if (pl.t >= pl.clip.duration) {\n playing.splice(i, 1)\n action('animation_end', t('act.anim_end', { name: pl.entry.name, clip: pl.clip.id }), { objectId: pl.entry.so.objectId, itemId: pl.entry.so.itemId, data: { clip: pl.clip.id } })\n }\n }\n }\n const animationsOf = (): AnimationInfo | null => {\n const e = animTarget()\n if (!e || e.arena) return null\n const clips = (e.item?.animations ?? []).map((c) => ({ id: c.id, duration: c.duration }))\n return { objectId: e.so.objectId, itemId: e.so.itemId, name: e.name, clips, playing: playing.find((p) => p.entry === e)?.clip.id ?? null }\n }\n const playAnimation = (clipId: string, objectId?: string): boolean => {\n const e = objectId ? entries.get(objectId) : animTarget()\n const clip = e?.item?.animations?.find((c) => c.id === clipId)\n if (!e || !clip) return false\n for (let i = playing.length - 1; i >= 0; i--) if (playing[i].entry === e && playing[i].clip.id === clipId) playing.splice(i, 1)\n const targets = new Map<string, THREE_NS.Object3D>()\n const ids = new Set<string>()\n for (const k of clip.keys) for (const id of Object.keys(k.parts ?? {})) ids.add(id)\n const grab = (key: string, obj: THREE_NS.Object3D | undefined): void => {\n if (!obj) return\n if (!restPose.has(obj)) restPose.set(obj, { p: [obj.position.x, obj.position.y, obj.position.z], r: [obj.rotation.x, obj.rotation.y, obj.rotation.z] })\n targets.set(key, obj)\n }\n if (clip.keys.some((k) => k.position || k.rotation)) grab('', e.so.root)\n for (const id of ids) grab(id, e.so.root.getObjectByName(id) ?? undefined)\n const pl: Playing = { entry: e, clip, t: 0, fired: 0, targets }\n playing.push(pl)\n applyClip(pl)\n action('animation', t('act.anim_start', { name: e.name, clip: clip.id, seconds: num(clip.duration, 1) }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { clip: clip.id, duration: clip.duration } })\n return true\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // Scenarios and modules\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const extraScenarios: TestRoomScenario[] = [...(options.scenarios ?? [])]\n const moduleCheck = (ok: boolean, text: string, data: Record<string, unknown>, itemId?: string): void => {\n log.add({ channel: 'check', type: ok ? 'pass' : 'fail', text: `${ok ? '✓' : '✗'} ${text}`, itemId, data: { ok, ...data } })\n }\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // What modules get from the room (game-contracts ModuleHost): the scene, the tool events and the frame\n // ---------------------------------------------------------------------------------------------------------------------------------------\n const modules = new Map<string, TestableModule<ScenarioContext>>()\n const detachers = new Map<string, () => void>()\n const benches = new Map<string, BenchStore>()\n let activeBench: string | null = null\n const lastBench = (): string | null => [...benches.keys()].pop() ?? null\n const benchView = (): BenchView | null => {\n const store = activeBench ? benches.get(activeBench) : undefined\n if (!store) return null\n return { title: modules.get(store.moduleId)?.name ?? store.moduleId, controls: store.controls(), layers: store.layers(), sheet: store.sheet() }\n }\n const METRIC_UNAVAILABLE = 'n/a'\n const metricText = (value: number | string | undefined, digits: number, unit?: string): string =>\n typeof value === 'number' ? `${num(value, digits)}${unit ? ` ${unit}` : ''}` : value ?? METRIC_UNAVAILABLE\n const reportedFailures = new Set<string>()\n // a module's failure is told once (not every metrics tick) in the room log\n const reportOnce = (key: string, text: string): void => {\n if (reportedFailures.has(key)) return\n reportedFailures.add(key)\n host.log(text)\n }\n const failureText = (error: unknown): string => (error instanceof Error ? error.message : String(error))\n const moduleMetrics = (): Record<string, number | string> => {\n const store = activeBench ? benches.get(activeBench) : undefined\n const out: Record<string, number | string> = {}\n for (const metric of store?.metrics ?? []) {\n try {\n out[metric.id] = metric.read()\n } catch (error) {\n out[metric.id] = METRIC_UNAVAILABLE\n reportOnce(`${store?.moduleId}:metric:${metric.id}`, t('mod.metric_failed', { name: modules.get(store?.moduleId ?? '')?.name ?? '', metric: metric.id, error: failureText(error) }))\n }\n }\n return out\n }\n const metricRows = (): { room: MetricRow[]; module: MetricRow[] } => {\n const sampled = roomMetrics.sample()\n const room = roomMetricIds.flatMap((id) => {\n const value = sampled[id]\n return value === undefined ? [] : [{ id, name: t(`metric.${id}`), text: num(value, id === 'frame_ms' ? 1 : 0) }]\n })\n const values = moduleMetrics()\n const declared = (activeBench ? benches.get(activeBench)?.metrics : undefined) ?? []\n const module = declared.map((metric) => {\n const value = values[metric.id]\n const ratio = metric.max && typeof value === 'number' ? value / metric.max : undefined\n return { id: metric.id, name: metric.name, text: metricText(value, metric.digits ?? 0, metric.unit), ...(typeof value === 'number' ? { value } : {}), ...(ratio === undefined ? {} : { ratio }) }\n })\n return { room, module }\n }\n const showBench = (): void => {\n if (!ui) return\n ui.bench(benchView())\n ui.metrics(metricRows())\n }\n const hostListeners = new Set<(event: HostEvent) => void>()\n const frameListeners = new Set<(dt: number) => void>()\n const listenerDirection = new THREE.Vector3()\n const environment = options.environment ?? createEnvironmentBus()\n const audioSink = audio ? createAudioSink(audio) : undefined\n function emitHost(event: HostEvent): void {\n for (const listener of hostListeners) listener(event)\n }\n function flushEvents(id: string, state: WeaponState, recoil?: [number, number]): void {\n const phase = state.phase\n for (const event of state.drain()) {\n const hostEvent = toHostEvent(id, event, { ...(recoil ? { recoil } : {}), phase })\n if (hostEvent) emitHost(hostEvent)\n }\n }\n function startReload(): void {\n tool.reload()\n flushEvents(toolId, tool)\n }\n function clearToolFault(): void {\n if (!tool.clearFault()) return\n flushEvents(toolId, tool)\n say(t('hud.clearing'))\n }\n function toggleSafety(): void {\n tool.setSafety(!tool.safety)\n flushEvents(toolId, tool)\n say(t(tool.safety ? 'hud.safety_on' : 'hud.safety_off'))\n }\n function runToolCommand(request: ToolCommand): ToolCommandResult {\n // the room is the bench: every accessory can be fitted here, whatever it needs (a tool, a workbench)\n const work = (done: ReturnType<WeaponState['fit']>): ToolCommandResult => (done.ok ? { ok: true, seconds: done.seconds } : { ok: false, reason: done.reason })\n switch (request.type) {\n case 'fit':\n return work(tool.fit(request.attachment, { install: 'bench', ...(request.mount ? { mount: request.mount as MountKind } : {}) }))\n case 'remove':\n return work(tool.remove(request.attachment, { install: 'bench' }))\n case 'toggle':\n return tool.toggle(request.attachment) === null ? { ok: false, reason: 'not_fitted' } : { ok: true }\n case 'stock':\n return tool.setStock(request.state) ? { ok: true } : { ok: false, reason: 'busy' }\n case 'underbarrel':\n return tool.useUnderbarrel(request.on) ? { ok: true } : { ok: false, reason: 'busy' }\n case 'stance':\n tool.setStance({ ...(request.aiming === undefined ? {} : { aiming: request.aiming }), ...(request.supported === undefined ? {} : { supported: request.supported }) })\n return { ok: true }\n default:\n return { ok: false, reason: 'unknown' }\n }\n }\n const host: ModuleHost = {\n THREE,\n scene,\n camera,\n locale,\n ...(audioSink ? { audio: audioSink } : {}),\n environment,\n groundAt,\n effects: vfx,\n loading,\n ...(options.blastShove ? { blastShove: options.blastShove } : {}),\n tool: () => ({\n weapon: toolId,\n category: tool.def.category,\n ammo: tool.ammo,\n capacity: tool.capacity,\n reserve: tool.reserve,\n reloading: tool.reloading,\n mode: tool.mode,\n ...(tool.fault ? { fault: tool.fault } : {}),\n safety: tool.safety,\n heat: tool.heatLevel,\n attachments: tool.attachments.map((part) => ({ id: part.id, mount: part.mount, ...(part.integral ? { integral: true } : {}), ...(part.on === undefined ? {} : { on: part.on }) })),\n stock: tool.stock,\n suppressed: tool.suppressed,\n underbarrelActive: tool.underbarrelActive,\n mass: tool.mass,\n aimSeconds: tool.aimSeconds,\n }),\n command(request) {\n const result = runToolCommand(request)\n flushEvents(toolId, tool)\n return result\n },\n player: () => ({\n position: player.position,\n yaw: player.yaw,\n pitch: player.pitch,\n crouching: false,\n speed: player.speed,\n running: player.running,\n cameraMode: 'first',\n }),\n configureTool(settings) {\n const condition = settings[SETTING_IDS.condition]\n const ammoQuality = settings[SETTING_IDS.ammoQuality]\n if (condition !== undefined) toolSettings.condition = condition\n if (ammoQuality !== undefined) toolSettings.ammoQuality = ammoQuality\n const fuseMetres = settings[SETTING_IDS.fuseLength] === undefined ? undefined : Number(settings[SETTING_IDS.fuseLength])\n if (fuseMetres !== undefined && fuseMetres > 0) fuseLength = fuseMetres\n for (const state of tools.values()) {\n if (condition !== undefined) state.setCondition(condition)\n if (ammoQuality !== undefined) state.setAmmoQuality(ammoQuality)\n if (fuseMetres !== undefined && fuseMetres > 0) state.setFuseLength(fuseMetres)\n }\n },\n on(listener) {\n hostListeners.add(listener)\n return () => hostListeners.delete(listener)\n },\n onFrame(update) {\n frameListeners.add(update)\n return () => frameListeners.delete(update)\n },\n setHandTargets(source) {\n handSource = source\n return () => {\n if (handSource === source) handSource = null\n }\n },\n log(text, data, type) {\n action(type ?? 'module_note', text, { data })\n },\n addBlocker(blocked) {\n blockers.add(blocked)\n return () => blockers.delete(blocked)\n },\n onClear(listener) {\n clearListeners.add(listener)\n return () => clearListeners.delete(listener)\n },\n }\n let sendingInitial = false\n const lendBench = (store: BenchStore): ModuleBench => ({\n value: store.value,\n layer: store.layer,\n onChange: store.onChange,\n patch: store.patch,\n sheet: store.setSheet,\n // the initial and restored values only set the module's state: they do not move the player's camera (`ModuleArea.view` is how a module asks for a view when its area opens)\n look: (eye, target) => {\n if (!sendingInitial) room.look(eye, target)\n },\n })\n const checkModuleBench = (mod: TestableModule<ScenarioContext>, fail: (problem: string) => void): BenchStore | null => {\n const store = createBenchStore(mod, locale, (error) => reportOnce(`${mod.id}:listener`, t('mod.listener_failed', { name: mod.name, error: failureText(error) })))\n const { controls, layers, metrics } = store.declared\n if (controls.length + layers.length + metrics.length === 0) return null\n const r = checkBench(store.declared)\n const text = r.ok ? t('mod.bench_ok', { name: mod.name, controls: controls.length, layers: layers.length, metrics: metrics.length }) : t('mod.bench_fail', { name: mod.name, problems: r.problems.join('; ') })\n moduleCheck(r.ok, text, { module: mod.id, check: 'bench', problems: r.problems })\n for (const p of r.problems) fail(`bench: ${p}`)\n return r.ok ? store : null\n }\n\n const LIGHTS_CHECK_MS = 250\n\n /** Renders the scene once with throwaway meshes of the materials that decals, effects and liquids make on demand (every light count is another set of programs), so that the first shot does not build them. */\n const warmUp = (): void => {\n const probes = [renderer.warmUpProbes(), vfx.warmUpProbes(), fluidView.warmUpProbes()]\n const groups = probes.map((probe) => probe.group as THREE_NS.Object3D)\n scene.add(...groups)\n gl.render(scene, camera)\n scene.remove(...groups)\n for (const probe of probes) probe.dispose()\n }\n\n /** Draws a throw-away blast and a fire (their particle materials and lights make the materials recompile the first time they appear), then clears them: nothing stays in the world, the log or the sound. */\n const warmUpEffects = (): void => {\n const ids = vfx.catalog?.() ?? []\n const flames = ids.filter((id) => /fire|flame/i.test(id)).slice(0, 1)\n gl.compile(scene, camera)\n const handles = ['m67', ...flames].filter((id) => ids.includes(id)).map((effect) => vfx.play({ effect, point: [0, 0.1, -4], direction: [0, 1, 0], normal: [0, 1, 0] }))\n for (let i = 0; i < 3; i++) {\n vfx.update(0.02)\n gl.render(scene, camera)\n }\n for (const h of handles) if (h !== null) vfx.stop(h)\n vfx.world.clear()\n vfx.update(0)\n gl.render(scene, camera)\n }\n\n const loadModule = (mod: TestableModule<ScenarioContext>): ModuleReport => {\n const report: ModuleReport = { module: mod.id, items: [], scenarios: [], ok: true, problems: [] }\n const fail = (problem: string): void => {\n report.ok = false\n report.problems.push(problem)\n }\n const added = mod.items(locale)\n for (const ti of added) {\n const item: TestRoomItem = {\n id: ti.id,\n name: ti.name,\n group: mod.group,\n build: (T) => ti.build(T) as THREE_NS.Object3D,\n spec: ti.spec as TestRoomItem['spec'],\n movable: ti.movable,\n slow: ti.slow,\n fluid: ti.fluid,\n weapon: ti.weapon,\n impl: ti.impl as TestRoomItem['impl'],\n animations: ti.animations,\n thumbnail: ti.thumbnail,\n thumbnailCredit: ti.thumbnailCredit,\n }\n catalogMap.set(item.id, item)\n const at = catalog.findIndex((c) => c.id === item.id)\n if (at >= 0) catalog[at] = item\n else catalog.push(item)\n report.items.push(item.id)\n // contract checks on a throwaway build of the item (never added to the scene)\n let partIds: string[] = []\n const base = { module: mod.id, item: item.id }\n let checked: THREE_NS.Object3D | undefined\n try {\n const root = (checked = buildRoot(item))\n root.updateMatrixWorld(true)\n if (item.impl) {\n const probe = item.impl(root, `${item.id}_check`)\n const r = checkDestructible(probe, { materials: world.materials.keys() })\n partIds = probe.describe().parts.map((p) => p.id)\n moduleCheck(r.ok, r.ok ? t('mod.destructible_ok', { name: item.name, parts: partIds.length }) : t('mod.destructible_fail', { name: item.name, problems: r.problems.join('; ') }), { ...base, check: 'destructible', problems: r.problems }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n }\n if (!item.impl || item.spec) {\n // the spec is resolved after the build (it may be a function of the root, or derived from the meshes)\n const spec = resolveSpec(item, root).spec\n if (!item.impl) partIds = spec.parts.map((p) => p.id)\n const r = checkSpec(spec, { materials: world.materials.keys() })\n moduleCheck(r.ok, r.ok ? t('mod.spec_ok', { name: item.name, parts: spec.parts.length }) : t('mod.spec_fail', { name: item.name, problems: r.problems.join('; ') }), { ...base, check: 'spec', problems: r.problems, warnings: r.warnings }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n for (const w of r.warnings) log.add({ channel: 'check', type: 'warn', text: `⚠ ${t('mod.spec_warn', { name: item.name, warning: w })}`, itemId: item.id, data: { ok: true, ...base, check: 'spec', warning: w } })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n moduleCheck(false, t('mod.destructible_fail', { name: item.name, problems: msg }), { ...base, check: 'destructible', problems: [msg] }, item.id)\n fail(`${item.id}: ${msg}`)\n }\n if (checked) letGo(checked)\n for (const clip of item.animations ?? []) {\n const r = checkAnimation(clip, partIds)\n moduleCheck(r.ok, r.ok ? t('mod.animation_ok', { name: item.name, clip: clip.id, seconds: num(clip.duration, 1) }) : t('mod.animation_fail', { name: item.name, clip: clip.id, problems: r.problems.join('; ') }), { ...base, check: 'animation', clip: clip.id, problems: r.problems }, item.id)\n for (const p of r.problems) fail(`${item.id}: ${p}`)\n }\n }\n for (const ms of mod.scenarios?.(locale) ?? []) {\n const sc: TestRoomScenario = { id: ms.id, name: ms.name, run: ms.run }\n const at = extraScenarios.findIndex((x) => x.id === sc.id)\n if (at >= 0) extraScenarios[at] = sc\n else extraScenarios.push(sc)\n report.scenarios.push(sc.id)\n }\n action('module', t('act.module_loaded', { name: mod.name, items: report.items.length, scenarios: report.scenarios.length, result: t(report.ok ? 'mod.all_ok' : 'mod.some_failed') }), { data: { module: mod.id, items: report.items, scenarios: report.scenarios, ok: report.ok } })\n const bench = checkModuleBench(mod, fail)\n detachers.get(mod.id)?.()\n detachers.delete(mod.id)\n // a reloaded module keeps its live bench state; the host's state only seeds a module the room has not seen\n const previous = benches.get(mod.id)\n const kept = previous?.encode()\n previous?.dispose()\n benches.delete(mod.id)\n for (const key of [...reportedFailures]) if (key.startsWith(`${mod.id}:`)) reportedFailures.delete(key)\n modules.set(mod.id, mod)\n if (bench) {\n const seed = options.bench?.state?.[mod.id]\n const restored = kept ?? (typeof seed === 'string' ? seed : undefined)\n if (restored !== undefined) bench.restore(restored)\n benches.set(mod.id, bench)\n bench.watch(() => {\n options.bench?.onChange?.(mod.id, bench.encode())\n if (activeBench === mod.id) ui?.bench(benchView())\n })\n if (!activeBench || !benches.has(activeBench)) activeBench = mod.id\n } else if (activeBench === mod.id) activeBench = lastBench()\n if (mod.attach) detachers.set(mod.id, mod.attach(bench ? { ...host, bench: lendBench(bench) } : host))\n sendingInitial = true\n try {\n bench?.sendInitial()\n } finally {\n sendingInitial = false\n }\n showBench()\n ui?.refresh()\n return report\n }\n\n const allScenarios = (): TestRoomScenario[] => [...extraScenarios]\n let scenarioRunning = false\n\n const step = (seconds: number): void => {\n const dt = seconds > 6 ? 1 / 30 : FIXED_DT\n const n = Math.max(1, Math.round(seconds / dt))\n for (let i = 0; i < n; i++) {\n player.update(0)\n followHeld(dt)\n stepSim(dt)\n }\n }\n\n const runScenarios = async (list?: TestRoomScenario[]): Promise<ScenarioReport> => {\n const all = list ?? allScenarios()\n const report: ScenarioReport = { passed: 0, failed: 0, results: [] }\n scenarioRunning = true\n const wasPaused = paused\n paused = false\n try {\n for (const sc of all) {\n hardReset()\n player.look(arena.playerStart, [0, 1.5, arena.wallZ])\n useHeld = false\n const checks: Array<{ label: string; ok: boolean }> = []\n log.add({ channel: 'check', type: 'scenario', text: t('sc.start', { name: sc.name }), data: { id: sc.id } })\n const ctx: ScenarioContext = {\n room,\n step,\n expect(condition, label, data) {\n checks.push({ label, ok: !!condition })\n log.add({ channel: 'check', type: condition ? 'pass' : 'fail', text: `${condition ? '✓' : '✗'} ${label}`, data: { scenario: sc.id, ok: !!condition, ...(data ?? {}) } })\n },\n }\n try {\n await sc.run(ctx)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n ctx.expect(false, t('sc.error', { msg }))\n }\n flush()\n const ok = checks.length > 0 && checks.every((c) => c.ok)\n report.results.push({ id: sc.id, name: sc.name, ok, checks })\n if (ok) report.passed++\n else report.failed++\n log.add({ channel: 'check', type: ok ? 'scenario_pass' : 'scenario_fail', text: t(ok ? 'sc.pass' : 'sc.fail', { name: sc.name }), data: { id: sc.id, ok } })\n await new Promise<void>((res) => setTimeout(res, 0))\n }\n } finally {\n scenarioRunning = false\n paused = wasPaused\n }\n return report\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // The room object\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // lays a module area: things that hold others first, so what goes on them finds their top\n const layArea = (layout: ModuleArea): SpawnedObject[] => {\n // an area may place items of other modules (a kitchen of the household module around a cylinder): the ones this room did not load are left out and said\n const known = layout.placements.filter((p) => {\n if (catalogMap.has(p.item)) return true\n action('area_skip', t('act.area_skip', { item: p.item }), { itemId: p.item })\n return false\n })\n const holders = known.filter((p) => p.surface)\n const rest = known.filter((p) => !p.surface)\n const placed = [...holders, ...rest].map((p) => {\n const so = spawn(p.item, p.position, p.rotationY ?? 0)\n if (p.surface) {\n const [hx, hz] = p.surface.halfSize\n restingTops.push({ objectId: so.objectId, minX: p.position[0] - hx, maxX: p.position[0] + hx, minZ: p.position[2] - hz, maxZ: p.position[2] + hz, top: p.surface.height })\n }\n return { so, asleep: p.asleep === true }\n })\n for (const { so, asleep } of placed) {\n const piece = asleep ? rendererPieces.get(so.objectId) : undefined\n if (piece) piece.sleeping = true\n }\n if (layout.view) room.look(layout.view.eye, layout.view.target)\n return placed.map(({ so }) => so)\n }\n\n /** The name an area is shown with: its module's group, a demo group, or the id. */\n const areaLabel = (area: string): string => {\n const mod = [...modules.values()].find((m) => m.id === area || m.group === area)\n return mod?.group ?? S.groups[area] ?? area\n }\n\n // a test environment per catalogue group, the way the demo site links each area of the index: a loaded module brings its own area,\n // any other group is laid in rows (small things in front, fixed big ones behind)\n const openArea = (area: string): SpawnedObject[] => {\n clear()\n const mod = [...modules.values()].find((m) => m.id === area || m.group === area)\n const label = mod?.group ?? S.groups[area] ?? area\n ui?.showGroup(label)\n activeBench = mod && benches.has(mod.id) ? mod.id : lastBench()\n showBench()\n const layout = mod?.area?.(locale)\n if (layout) return layArea(layout)\n const items = catalog.filter((item) => item.group === label)\n const front = items.filter((item) => item.movable !== false)\n const back = items.filter((item) => item.movable === false)\n const row = (list: TestRoomItem[], gap: number, z: number): SpawnedObject[] => list.map((item, index) => spawn(item.id, [(index - (list.length - 1) / 2) * gap, 0, z], 0))\n return [...row(front, 1.6, 1.5), ...row(back, 4.5, -4)]\n }\n\n const room: TestRoom & {\n tilt(rad: number): void\n toggleTap(on?: boolean): boolean\n blast(): BlastOptions\n setBlast(options: BlastOptions): void\n setSlowMotion(on: boolean): void\n setFastForward(on: boolean): void\n equip(weaponId: string): void\n readonly scenarios: TestRoomScenario[]\n readonly fluidRenderer: FluidRenderer\n inspectInfo(): InspectInfo | null\n } = {\n world,\n renderer,\n scene,\n camera,\n arsenal,\n fluids,\n film: filmBridge,\n vfx: vfx.world,\n fluidRenderer: fluidView,\n audio,\n environment,\n log,\n get tool() {\n return tool\n },\n get scenarios() {\n return allScenarios()\n },\n spawn,\n clear,\n resetAll,\n setTool,\n useItem,\n use(hold = 0) {\n if (tool.def.category === 'hand') {\n grab()\n return\n }\n useTool(FIXED_DT, false)\n flush()\n let t0 = 0\n while (t0 < hold) {\n useTool(FIXED_DT, true)\n stepSim(FIXED_DT)\n t0 += FIXED_DT\n }\n releaseTrigger()\n },\n grab,\n throwHeld,\n look(position, target) {\n player.look(position, target)\n },\n inspect() {\n const r = inspectTarget()\n if (!r) return null\n return { objectId: r.object, partId: r.part, itemId: entryOf(r.object)?.so.itemId ?? '' }\n },\n inspectInfo,\n spawned() {\n return [...entries.values()].filter((e) => !e.arena).map((e) => e.so)\n },\n update,\n waitUntilReady(maxSeconds = 5) {\n let waited = 0\n while (tool.phase && waited < maxSeconds) {\n update(FIXED_DT)\n waited += FIXED_DT\n }\n // the trigger judges a frame by where it starts: one more frame, or the first pull of a fresh draw still answers `drawing`\n update(FIXED_DT)\n return waited + FIXED_DT\n },\n on(type, fn) {\n listeners[type].add(fn)\n return () => listeners[type].delete(fn)\n },\n runScenarios,\n tilt(rad) {\n heldTilt = rad\n },\n toggleTap,\n blast: () => ({ ...blastOptions }),\n setBlast: (next) => {\n blastOptions = { ...blastOptions, ...next }\n },\n pause() {\n paused = true\n },\n resume() {\n paused = false\n },\n get paused() {\n return paused\n },\n walk(to, seconds) {\n walkPlan = seconds > 0 ? { x: to[0], z: to[2], remaining: seconds } : null\n if (!walkPlan) player.moveBy(to[0] - camera.position.x, to[2] - camera.position.z)\n },\n setSlowMotion(on) {\n timeScale = on ? 0.25 : 1\n },\n setFastForward(on) {\n fastForward = on\n },\n equip,\n openArea,\n openAreaAsync: (area) => loading.busy(t('loading.open_area', { area: areaLabel(area) }), () => openArea(area)),\n loading,\n busy: (label, work, busyOptions) => loading.busy(label, work, busyOptions),\n loadModule,\n warmUp: () => {\n warmUp()\n warmUpEffects()\n },\n animations: animationsOf,\n playAnimation,\n bench(moduleId) {\n const id = moduleId ?? activeBench\n return (id ? benches.get(id) : undefined) ?? null\n },\n applyCamera: () => {\n const back = applyThirdView()\n const shake = vfx.applyCamera()\n return () => {\n shake()\n back()\n }\n },\n setAvatar,\n get avatar() {\n return avatar\n },\n setAvatarState(state) {\n if (state.crouch !== undefined) {\n crouchForced = state.crouch\n avatarState.crouch = state.crouch || player.crouching\n }\n if (state.down !== undefined) avatarState.down = state.down\n if (state.armed !== undefined) armedForced = state.armed\n },\n avatarState: () => ({ ...avatarState }),\n handState: () => ({ ...lastHand }),\n setDebugCamera(view) {\n if (!view) {\n debugView = null\n return\n }\n debugView ??= new THREE.PerspectiveCamera(60, camera.aspect, 0.01, 200)\n debugView.fov = view.fov ?? 40\n debugView.aspect = camera.aspect\n debugView.position.set(...view.position)\n debugView.lookAt(...view.target)\n debugView.updateProjectionMatrix()\n debugView.updateMatrixWorld(true)\n },\n setCameraMode,\n get cameraMode() {\n return cameraMode\n },\n metrics() {\n return { room: roomMetrics.sample(), module: moduleMetrics() }\n },\n dispose() {\n destructionSound?.dispose()\n if (ownAudio) audio?.dispose()\n for (const detach of detachers.values()) detach()\n detachers.clear()\n for (const store of benches.values()) store.dispose()\n benches.clear()\n cancelAnimationFrame?.(raf)\n window.removeEventListener('resize', onResize)\n player.dispose()\n ui?.dispose()\n loading.dispose()\n renderer.dispose()\n vfx.dispose()\n craterPatch?.dispose()\n fluidView.dispose()\n filmBridge.dispose()\n film.dispose()\n for (const tr of tracers) tr.line.removeFromParent()\n explosives.clear()\n if (ownRenderer) {\n gl.dispose()\n dom.remove()\n }\n },\n }\n\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // UI and loop\n // ---------------------------------------------------------------------------------------------------------------------------------------\n /** Runs a change of the bench panel: a control the module declares `slow` shows the loading indicator first (and gets its frame to paint), any other runs at once. */\n const slowly = (moduleId: string, controlId: string, run: () => unknown): void => {\n const control = benches.get(moduleId)?.controls().find((c) => c.id === controlId)\n const slow = control?.slow\n if (!slow) {\n run()\n return\n }\n void loading.busy(typeof slow === 'string' ? slow : control.name, run).catch((error: unknown) => {\n action('bench_failed', t('act.bench_failed', { name: control.name, error: error instanceof Error ? error.message : String(error) }), { data: { module: moduleId, control: controlId } })\n })\n }\n let ui: RoomUi | null = null\n if (options.ui !== false) {\n const groups = (): Map<string, TestRoomItem[]> => {\n const m = new Map<string, TestRoomItem[]>()\n for (const i of catalog) {\n const g = m.get(i.group) ?? []\n g.push(i)\n m.set(i.group, g)\n }\n return m\n }\n ui = createUi({\n container,\n strings: S,\n t,\n log,\n groups,\n loadout: () => loadout.map((id) => ({ id, name: arsenal.name(id) })),\n onSpawn: (id) => {\n const item = catalogMap.get(id)\n // an item that declares itself slow (a vehicle: its first build takes most of a second) spawns behind the loading indicator\n if (item?.slow) void loading.busy(typeof item.slow === 'string' ? item.slow : t('loading.spawn', { name: item.name }), () => spawn(id))\n else spawn(id)\n },\n onEquip: (itemId) => {\n const w = catalogMap.get(itemId)?.weapon\n if (w) equip(w)\n },\n onClear: clear,\n onResetAll: resetAll,\n onSlow: (on) => room.setSlowMotion(on),\n onFast: (on) => room.setFastForward(on),\n onQuality: (q) => {\n qualityName = q\n if (ownRenderer) {\n gl.shadowMap.enabled = q !== 'low'\n gl.setPixelRatio(q === 'low' ? 1 : Math.min(typeof devicePixelRatio === 'number' ? devicePixelRatio : 1, 2))\n arena.sun.shadow.mapSize.set(q === 'high' ? 2048 : 1024, q === 'high' ? 2048 : 1024)\n arena.sun.shadow.map?.dispose()\n arena.sun.shadow.map = null\n resize()\n }\n },\n quality: qualityName,\n scenarios: allScenarios,\n onRun: async (sc) => {\n await runScenarios([sc])\n },\n onRunAll: async () => {\n await runScenarios()\n },\n onTool: (index) => {\n toolIndex = index\n setTool(loadout[index])\n },\n onTap: () => toggleTap(),\n onBlast: (key) => toggleBlast(key),\n onPlay: (objectId, clipId) => {\n playAnimation(clipId, objectId)\n },\n onResize: resize,\n onControl: (id, value) => {\n if (activeBench) slowly(activeBench, id, () => benches.get(activeBench as string)?.set(id, value))\n },\n onLayer: (id, on) => {\n if (activeBench) benches.get(activeBench)?.setLayer(id, on)\n },\n onAction: (id) => {\n if (activeBench) slowly(activeBench, id, () => benches.get(activeBench as string)?.act(id))\n },\n })\n ui.hud(hudState())\n showBench()\n }\n\n let raf = 0\n if (ownRenderer && typeof requestAnimationFrame === 'function') {\n let last = performance.now()\n ownsLoop = true\n let nextLightsCheck = 0\n let warmedLights = ''\n // modules add lights after the first frame, and each light count is another set of programs: warm again when the lights change\n const lightsKey = (): string => {\n let key = ''\n scene.traverseVisible((object) => {\n if ((object as THREE_NS.Light).isLight) key += `${object.type[0]}${object.castShadow ? 's' : ''}`\n })\n return key\n }\n const loop = (now: number): void => {\n raf = requestAnimationFrame(loop)\n if (now >= nextLightsCheck) {\n nextLightsCheck = now + LIGHTS_CHECK_MS\n const key = lightsKey()\n if (key !== warmedLights) {\n warmedLights = key\n warmUp()\n }\n }\n const realDelta = (now - last) / 1000\n roomMetrics.frame(realDelta)\n const dt = Math.min(0.05, realDelta)\n last = now\n if (!scenarioRunning) update(dt)\n const restoreCamera = room.applyCamera()\n gl.render(scene, debugView ?? camera)\n restoreCamera()\n roomMetrics.rendered()\n }\n raf = requestAnimationFrame(loop)\n }\n\n if (options.initial) {\n for (const [i, id] of options.initial.entries()) spawn(id, [(i - (options.initial.length - 1) / 2) * 1.3, 0, 0.5])\n }\n if (options.avatar) setAvatar(options.avatar)\n if (options.area) openArea(options.area)\n\n return room\n}\n\nfunction structuredCloneSpec(spec: DestructibleSpec): DestructibleSpec {\n return JSON.parse(JSON.stringify(spec)) as DestructibleSpec\n}\n","import type { DestructibleSpec, JointSpec, PartSpec, Vec3 } from '@adatechnology/game-destruction'\n\nconst box = (id: string, material: string, size: Vec3, position: Vec3, extra: Partial<Omit<PartSpec, 'id' | 'material' | 'shape' | 'position'>> = {}): PartSpec => ({ id, material, shape: { kind: 'box', size }, position, ...extra })\nconst joint = (a: string, b: string, kind: JointSpec['kind'], extra: Partial<JointSpec> = {}): JointSpec => ({ a, b, kind, ...extra })\n\n/** Spec of the brick target wall: `cols` x `rows` brick panels, the bottom row anchored, mortar joints between neighbours. */\nexport function brickWallSpec(cols = 8, rows = 6, panel: Vec3 = [1.25, 0.5, 0.2]): DestructibleSpec {\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n const id = (c: number, r: number): string => `brick_${r}_${c}`\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n parts.push(box(id(c, r), 'brick', panel, [(c - (cols - 1) / 2) * panel[0], panel[1] / 2 + r * panel[1], 0], { anchored: r === 0 }))\n if (c > 0) joints.push(joint(id(c - 1, r), id(c, r), 'mortar'))\n if (r > 0) joints.push(joint(id(c, r - 1), id(c, r), 'mortar'))\n }\n }\n return { name: 'brick wall', parts, joints, tags: ['structure'] }\n}\n","import type * as THREE_NS from 'three'\nimport type { DestructibleSpec, JointSpec, PartSpec, Vec3 } from '@adatechnology/game-destruction'\nimport type { SurfaceSpec } from '@adatechnology/game-fluids'\nimport { brickWallSpec } from './items'\nimport type { SceneryObject, SceneryTap } from './types'\n\nexport interface ArenaObject {\n id: string\n spec: DestructibleSpec\n position: Vec3\n rotationY: number\n colors?: Record<string, number>\n build?: SceneryObject['build']\n label?: string\n top?: SceneryObject['top']\n spout?: SceneryObject['spout']\n}\n\n/** A top that loose things rest on while its part stands: the footprint in world space and the height of the upper face. */\nexport interface ArenaTop {\n /** Id of the arena object the top belongs to, and of its part. */\n id: string\n topPart: string\n minX: number\n maxX: number\n minZ: number\n maxZ: number\n top: number\n}\n\n/** The static part of the room: lights, floor, grid, ruler and the destructible scenery. */\nexport interface Arena {\n group: THREE_NS.Group\n /** Objects to register in the world (by default the target wall, the table and the shelf). */\n objects: ArenaObject[]\n surfaces: SurfaceSpec[]\n /** `[minX, minZ, maxX, maxZ]` boxes the player cannot walk into. */\n colliders: Array<[number, number, number, number]>\n playerStart: Vec3\n wallZ: number\n /** Tops of the scenery (pieces rest on them while their part stands). */\n tops: ArenaTop[]\n /** Where the tap pours: over the top of the `table` object; null when the room has no table with a top. */\n tapSpout: Vec3 | null\n sun: THREE_NS.DirectionalLight\n}\n\n/** Box of a spec in world space, ignoring the parts that lie flat on the floor (a plinth, a ground slab: the player walks over them). */\nexport interface SpecBounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n minZ: number\n maxZ: number\n}\n\nconst sizeOf = (shape: PartSpec['shape']): Vec3 => (shape.kind === 'box' ? shape.size : shape.kind === 'cylinder' ? [shape.radius * 2, shape.height, shape.radius * 2] : [shape.radius * 2, shape.radius * 2, shape.radius * 2])\n\n/**\n * Bounds of a spec turned `rotationY` about the vertical axis and moved to `position`: the corners of every part (after its own rotation).\n * `onlyPart` limits it to one part; `minHeight` leaves out the parts whose upper face is lower than that (default 0: all).\n */\nexport function specBounds(THREE: typeof THREE_NS, spec: DestructibleSpec, position: Vec3, rotationY: number, options: { onlyPart?: string; minHeight?: number } = {}): SpecBounds | null {\n const out: SpecBounds = { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity, minZ: Infinity, maxZ: -Infinity }\n const q = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, rotationY, 0))\n const v = new THREE.Vector3()\n const e = new THREE.Euler()\n const pq = new THREE.Quaternion()\n let any = false\n for (const p of spec.parts) {\n if (options.onlyPart !== undefined && p.id !== options.onlyPart) continue\n const [sx, sy, sz] = sizeOf(p.shape)\n pq.setFromEuler(e.set(p.rotation?.[0] ?? 0, p.rotation?.[1] ?? 0, p.rotation?.[2] ?? 0, 'XYZ'))\n const corners: Vec3[] = []\n let top = -Infinity\n for (const cx of [-0.5, 0.5]) for (const cy of [-0.5, 0.5]) for (const cz of [-0.5, 0.5]) {\n v.set(cx * sx, cy * sy, cz * sz).applyQuaternion(pq)\n const c: Vec3 = [v.x + p.position[0], v.y + p.position[1], v.z + p.position[2]]\n top = Math.max(top, c[1])\n corners.push(c)\n }\n if (top < (options.minHeight ?? 0)) continue\n any = true\n for (const c of corners) {\n v.set(c[0], c[1], c[2]).applyQuaternion(q)\n out.minX = Math.min(out.minX, v.x + position[0])\n out.maxX = Math.max(out.maxX, v.x + position[0])\n out.minY = Math.min(out.minY, v.y + position[1])\n out.maxY = Math.max(out.maxY, v.y + position[1])\n out.minZ = Math.min(out.minZ, v.z + position[2])\n out.maxZ = Math.max(out.maxZ, v.z + position[2])\n }\n }\n return any ? out : null\n}\n\nconst tableSpec = (): DestructibleSpec => {\n const parts: PartSpec[] = [{ id: 'top', material: 'wood_hard', shape: { kind: 'box', size: [1.6, 0.05, 0.8] }, position: [0, 0.755, 0] }]\n const joints: JointSpec[] = []\n for (const [i, [x, z]] of [\n [-0.72, -0.32],\n [0.72, -0.32],\n [-0.72, 0.32],\n [0.72, 0.32],\n ].entries()) {\n parts.push({ id: `leg_${i + 1}`, material: 'wood_hard', shape: { kind: 'box', size: [0.06, 0.73, 0.06] }, position: [x, 0.365, z], anchored: true })\n joints.push({ a: `leg_${i + 1}`, b: 'top', kind: 'screw' })\n }\n return { name: 'table', parts, joints, tags: ['furniture'] }\n}\n\nconst shelfSpec = (): DestructibleSpec => {\n const parts: PartSpec[] = []\n const joints: JointSpec[] = []\n for (const [i, x] of [-0.6, 0.6].entries()) {\n parts.push({ id: `upright_${i + 1}`, material: 'wood_hard', shape: { kind: 'box', size: [0.04, 1.7, 0.4] }, position: [x, 0.85, 0], anchored: true })\n }\n for (const [i, y] of [0.4, 0.9, 1.4].entries()) {\n parts.push({ id: `board_${i + 1}`, material: 'wood_soft', shape: { kind: 'box', size: [1.2, 0.03, 0.4] }, position: [0, y, 0] })\n joints.push({ a: `board_${i + 1}`, b: 'upright_1', kind: 'screw' }, { a: `board_${i + 1}`, b: 'upright_2', kind: 'screw' })\n }\n return { name: 'shelf', parts, joints, tags: ['furniture'] }\n}\n\n/** The scenery a bare room has: the brick target wall, the table (the tap stands beside it) and the shelf. */\nexport const defaultScenery = (wallZ: number): Record<string, SceneryObject> => ({\n target_wall: { spec: brickWallSpec(), position: [0, 0, wallZ], colors: { brick: 0xa5472e } },\n table: { spec: tableSpec(), position: [3.5, 0, 0], top: { part: 'top', y: 0.78 } },\n shelf: { spec: shelfSpec(), position: [-3.5, 0, 0], colors: { wood_soft: 0xc79a62 } },\n})\n\nconst DEFAULT_WALL_Z = -11\nconst WALL_ID = 'target_wall'\nconst TABLE_ID = 'table'\n\n/** The scenery of the room: the defaults with the host's `scenery` applied (replace by id, `null` removes, a new id adds). */\nexport function resolveScenery(scenery: Record<string, SceneryObject | null> | undefined): ArenaObject[] {\n const merged = new Map<string, SceneryObject>(Object.entries(defaultScenery(DEFAULT_WALL_Z)))\n for (const [id, obj] of Object.entries(scenery ?? {})) {\n if (obj === null) {\n merged.delete(id)\n continue\n }\n const old = merged.get(id)\n const position = obj.position ?? old?.position\n if (!position) throw new Error(`game-test-room: scenery \"${id}\" is new, so it needs a position`)\n merged.set(id, { ...obj, position })\n }\n return [...merged.entries()].map(([id, o]) => ({ id, spec: o.spec, position: o.position as Vec3, rotationY: o.rotationY ?? 0, colors: o.colors, build: o.build, label: o.label, top: o.top, spout: o.spout }))\n}\n\nexport function createArena(THREE: typeof THREE_NS, size: number, scene: THREE_NS.Scene, scenery?: Record<string, SceneryObject | null>, tapOption?: SceneryTap | null): Arena {\n const group = new THREE.Group()\n group.name = 'test-room-arena'\n scene.background = new THREE.Color(0x9fb4c8)\n\n group.add(new THREE.HemisphereLight(0xcfe3ff, 0x6b6257, 0.75))\n const sun = new THREE.DirectionalLight(0xffffff, 2.1)\n sun.position.set(7, 13, 8)\n sun.castShadow = true\n sun.shadow.mapSize.set(1024, 1024)\n const sc = sun.shadow.camera\n sc.left = -16\n sc.right = 16\n sc.top = 16\n sc.bottom = -16\n sc.near = 1\n sc.far = 40\n sun.shadow.bias = -0.0006\n group.add(sun)\n\n const floor = new THREE.Mesh(new THREE.PlaneGeometry(size * 2, size * 2), new THREE.MeshStandardMaterial({ color: 0x8e8e8a, roughness: 0.95 }))\n floor.rotation.x = -Math.PI / 2\n floor.receiveShadow = true\n floor.name = 'floor'\n group.add(floor)\n\n const grid = new THREE.GridHelper(size * 2, size * 2, 0x4c4c52, 0x77777b)\n grid.position.y = 0.004\n group.add(grid)\n\n const sceneryObjects = resolveScenery(scenery)\n const wallObject = sceneryObjects.find((o) => o.id === WALL_ID)\n const wallZ = wallObject ? wallObject.position[2] : DEFAULT_WALL_Z\n const playerStart: Vec3 = [0, 1.7, 5]\n\n // distance ruler along the left of the lane: a tick every metre (taller every 5 m) and a label every 5 m\n const pts: number[] = []\n const rx = -1.6\n for (let z = Math.round(playerStart[2]); z >= wallZ; z--) {\n const d = playerStart[2] - z\n const len = d % 5 === 0 ? 0.5 : 0.2\n pts.push(rx, 0.01, z, rx + len, 0.01, z)\n }\n pts.push(rx, 0.01, playerStart[2], rx, 0.01, wallZ)\n const rg = new THREE.BufferGeometry()\n rg.setAttribute('position', new THREE.Float32BufferAttribute(pts, 3))\n group.add(new THREE.LineSegments(rg, new THREE.LineBasicMaterial({ color: 0xffd23f })))\n for (let d = 5; playerStart[2] - d >= wallZ; d += 5) {\n try {\n const canvas = document.createElement('canvas')\n canvas.width = 128\n canvas.height = 64\n const ctx = canvas.getContext('2d')\n if (!ctx) break\n ctx.fillStyle = '#ffd23f'\n ctx.font = 'bold 44px sans-serif'\n ctx.textAlign = 'center'\n ctx.fillText(`${d} m`, 64, 48)\n const sprite = new THREE.Sprite(new THREE.SpriteMaterial({ map: new THREE.CanvasTexture(canvas), transparent: true, depthWrite: false }))\n sprite.scale.set(1.2, 0.6, 1)\n sprite.position.set(rx - 0.8, 0.45, playerStart[2] - d)\n group.add(sprite)\n } catch {\n break\n }\n }\n\n // the tops loose things rest on, and the water surface of each\n const tops: ArenaTop[] = []\n const surfaces: SurfaceSpec[] = [{ id: 'floor', point: [0, 0, 0], normal: [0, 1, 0], halfSize: [size, size], porosity: 0.05 }]\n for (const o of sceneryObjects) {\n if (!o.top) continue\n const b = specBounds(THREE, o.spec, o.position, o.rotationY, { onlyPart: o.top.part })\n if (!b) continue\n const top = o.position[1] + o.top.y\n tops.push({ id: o.id, topPart: o.top.part, minX: b.minX, maxX: b.maxX, minZ: b.minZ, maxZ: b.maxZ, top })\n surfaces.push({ id: o.id, point: [(b.minX + b.maxX) / 2, top, (b.minZ + b.maxZ) / 2], normal: [0, 1, 0], halfSize: [(b.maxX - b.minX) / 2, (b.maxZ - b.minZ) / 2], porosity: 0.3 })\n }\n\n // colliders: the footprint of every object (what lies flat on the floor is walked over); the wall also closes the arena behind it\n const colliders: Array<[number, number, number, number]> = []\n for (const o of sceneryObjects) {\n const b = specBounds(THREE, o.spec, o.position, o.rotationY, { minHeight: 0.1 })\n if (!b) continue\n colliders.push(o.id === WALL_ID ? [-size, b.minZ - 1, size, b.maxZ + 0.1] : [b.minX, b.minZ, b.maxX, b.maxZ])\n }\n\n // the tap: the host's model standing on the table top, or (by default) a post with an arm and a spout beside the table\n let tapSpout: Vec3 | null = null\n const tableTop = tops.find((t) => t.id === TABLE_ID)\n const spouting = sceneryObjects.find((o) => o.spout)\n if (spouting?.spout && tapOption !== null) {\n // a piece of the scenery (a sink, a tub) carries its own tap: the stream pours from its spout\n const s = new THREE.Vector3(spouting.spout[0], spouting.spout[1], spouting.spout[2]).applyAxisAngle(new THREE.Vector3(0, 1, 0), spouting.rotationY)\n tapSpout = [spouting.position[0] + s.x, spouting.position[1] + s.y, spouting.position[2] + s.z]\n } else if (tableTop && tapOption !== null) {\n const cx = (tableTop.minX + tableTop.maxX) / 2\n const cz = (tableTop.minZ + tableTop.maxZ) / 2\n const y = tableTop.top\n if (tapOption) {\n const rot = tapOption.rotationY ?? 0\n const sp = new THREE.Vector3(tapOption.spout[0], tapOption.spout[1], tapOption.spout[2]).applyAxisAngle(new THREE.Vector3(0, 1, 0), rot)\n const at: Vec3 = tapOption.position ?? [cx + 0.3 - sp.x, y, cz - sp.z]\n const model = tapOption.build(THREE)\n model.position.set(at[0], at[1], at[2])\n model.rotation.y = rot\n model.traverse((m) => {\n m.castShadow = true\n })\n group.add(model)\n tapSpout = [at[0] + sp.x, at[1] + sp.y, at[2] + sp.z]\n } else {\n const postX = tableTop.maxX + 0.35\n const tapMat = new THREE.MeshStandardMaterial({ color: 0xb9bec4, metalness: 0.8, roughness: 0.35 })\n const post = new THREE.Mesh(new THREE.CylinderGeometry(0.04, 0.04, 1.4, 10), tapMat)\n post.position.set(postX, 0.7, cz)\n const arm = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, postX - (cx + 0.3), 10), tapMat)\n arm.rotation.z = Math.PI / 2\n arm.position.set((postX + cx + 0.3) / 2, y + 0.6, cz)\n const spoutMesh = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.1, 10), tapMat)\n spoutMesh.position.set(cx + 0.3, y + 0.55, cz)\n for (const m of [post, arm, spoutMesh]) {\n m.castShadow = true\n group.add(m)\n }\n tapSpout = [cx + 0.3, y + 0.5, cz]\n colliders.push([postX - 0.05, cz - 0.1, postX + 0.05, cz + 0.1])\n }\n }\n\n return {\n group,\n objects: sceneryObjects,\n surfaces,\n colliders,\n playerStart,\n wallZ,\n tops,\n tapSpout,\n sun,\n }\n}\n","import type { BenchChange, BenchSheet, ControlPatch, ControlValue, ModuleControl, ModuleLayer, ModuleMetric, TestableModule } from '@adatechnology/game-contracts'\nimport type { BenchControl, BenchHandle, BenchLayer } from './types'\n\n/** What the room keeps per module bench: the declarations, the module's patches, the values and the layers. Pure: no DOM, no three.js. */\nexport interface BenchStore extends BenchHandle {\n readonly moduleId: string\n readonly metrics: readonly ModuleMetric[]\n readonly declared: { readonly controls: readonly ModuleControl[]; readonly layers: readonly ModuleLayer[]; readonly metrics: readonly ModuleMetric[] }\n /** Changes for the module (the `ModuleBench.onChange` listeners). */\n onChange(listener: (change: BenchChange) => void): () => void\n /** Any change of state, the module's patches included (the panel and the URL follow it). */\n watch(listener: () => void): () => void\n patch(id: string, patch: ControlPatch): void\n /** The sheet the module put on the panel, if any. */\n sheet(): BenchSheet | null\n setSheet(sheet: BenchSheet | null): void\n /** One change per control (not actions) and per layer, in declaration order. */\n sendInitial(): void\n /** Apply an encoded state without emitting. */\n restore(encoded: string): void\n /** Drops every listener and watcher (the room is gone). */\n dispose(): void\n}\n\ntype ControlState = ModuleControl & { disabled: boolean }\n\nconst snap = (control: Extract<ModuleControl, { kind: 'number' }>, value: number): number => {\n const clamped = Math.min(control.max, Math.max(control.min, value))\n if (!control.step) return clamped\n const stepped = control.min + Math.round((clamped - control.min) / control.step) * control.step\n return Number(Math.min(control.max, stepped).toFixed(10))\n}\n\n/** The value a control takes for `value`, or undefined when it does not fit (wrong type, option not offered, action). */\nfunction fitValue(control: ModuleControl, value: unknown): ControlValue | undefined {\n if (control.kind === 'number') return typeof value === 'number' && Number.isFinite(value) ? snap(control, value) : undefined\n if (control.kind === 'boolean') return typeof value === 'boolean' ? value : undefined\n if (control.kind === 'choice') return typeof value === 'string' && control.options.some((option) => option.id === value) ? value : undefined\n return undefined\n}\n\nconst fromText = (control: ModuleControl, text: string): unknown => {\n if (control.kind === 'number') return text.trim() === '' ? Number.NaN : Number(text)\n if (control.kind === 'boolean') return text === '1' ? true : text === '0' ? false : undefined\n return text\n}\n\nconst toText = (value: ControlValue): string => (typeof value === 'boolean' ? (value ? '1' : '0') : String(value))\n\n/** `id=value;id=value`, values with `encodeURIComponent`, booleans and layers as `1` / `0`. */\nexport function encodeBenchState(controls: readonly BenchControl[], layers: readonly BenchLayer[]): string {\n const pairs: string[] = []\n for (const control of controls) if (control.value !== undefined) pairs.push(`${control.id}=${encodeURIComponent(toText(control.value))}`)\n for (const layer of layers) pairs.push(`${layer.id}=${layer.on ? '1' : '0'}`)\n return pairs.join(';')\n}\n\n/** Reads an encoded state as hostile input: unknown ids, NaN, options not offered and malformed pairs are dropped; numbers are clamped. */\nexport function decodeBenchState(encoded: string, controls: readonly ModuleControl[], layers: readonly ModuleLayer[]): Map<string, ControlValue> {\n const out = new Map<string, ControlValue>()\n for (const pair of encoded.split(';')) {\n const at = pair.indexOf('=')\n if (at <= 0) continue\n const id = pair.slice(0, at)\n let text: string\n try {\n text = decodeURIComponent(pair.slice(at + 1))\n } catch {\n continue\n }\n const control = controls.find((c) => c.id === id)\n if (control) {\n const value = fitValue(control, fromText(control, text))\n if (value !== undefined) out.set(id, value)\n continue\n }\n if (layers.some((layer) => layer.id === id) && (text === '1' || text === '0')) out.set(id, text === '1')\n }\n return out\n}\n\nexport function createBenchStore(module: TestableModule<unknown>, locale: string, onListenerError?: (error: unknown) => void): BenchStore {\n const declared = { controls: module.controls?.(locale) ?? [], layers: module.layers?.(locale) ?? [], metrics: module.metrics?.(locale) ?? [] }\n const controls: ControlState[] = declared.controls.map((control) => ({ ...control, disabled: false }))\n const values = new Map<string, ControlValue>()\n for (const control of controls) if (control.kind !== 'action') values.set(control.id, control.default)\n const layers = new Map<string, boolean>(declared.layers.map((layer) => [layer.id, layer.default !== false]))\n const listeners = new Set<(change: BenchChange) => void>()\n const watchers = new Set<() => void>()\n const emit = (change: BenchChange): void => {\n for (const listener of listeners) {\n try {\n listener(change)\n } catch (error) {\n onListenerError?.(error)\n }\n }\n }\n const changed = (): void => {\n for (const watcher of watchers) watcher()\n }\n let sheet: BenchSheet | null = null\n const controlOf = (id: string): ControlState | undefined => controls.find((control) => control.id === id)\n\n const store: BenchStore = {\n moduleId: module.id,\n metrics: declared.metrics,\n declared,\n controls: () => controls.map((control) => ({ ...control, value: values.get(control.id) })),\n layers: () => declared.layers.map((layer) => ({ ...layer, on: layers.get(layer.id) === true })),\n value: (id) => values.get(id),\n layer: (id) => layers.get(id) === true,\n set(id, value) {\n const control = controlOf(id)\n if (!control || control.disabled) return false\n const fitted = fitValue(control, value)\n if (fitted === undefined) return false\n values.set(id, fitted)\n emit({ kind: 'control', id, value: fitted })\n changed()\n return true\n },\n setLayer(id, on) {\n if (!layers.has(id)) return false\n layers.set(id, on)\n emit({ kind: 'layer', id, on })\n changed()\n return true\n },\n act(id) {\n const control = controlOf(id)\n if (!control || control.kind !== 'action' || control.disabled) return false\n emit({ kind: 'action', id })\n return true\n },\n encode: () => encodeBenchState(store.controls(), store.layers()),\n onChange(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n watch(listener) {\n watchers.add(listener)\n return () => watchers.delete(listener)\n },\n sheet: () => sheet,\n setSheet(next) {\n sheet = next\n changed()\n },\n patch(id, patch) {\n const index = controls.findIndex((control) => control.id === id)\n if (index < 0) return\n let control = controls[index]\n if (patch.hidden !== undefined) control = { ...control, hidden: patch.hidden }\n if (patch.disabled !== undefined) control = { ...control, disabled: patch.disabled }\n if (patch.options && control.kind === 'choice' && patch.options.length > 0) {\n control = { ...control, options: [...patch.options] }\n const offered = control.options\n if (!offered.some((option) => option.id === values.get(id))) values.set(id, offered[0].id)\n }\n controls[index] = control\n if (patch.value !== undefined) {\n const fitted = fitValue(control, patch.value)\n if (fitted !== undefined) values.set(id, fitted)\n }\n changed()\n },\n sendInitial() {\n for (const control of controls) {\n const value = values.get(control.id)\n if (value !== undefined) emit({ kind: 'control', id: control.id, value })\n }\n for (const layer of declared.layers) emit({ kind: 'layer', id: layer.id, on: layers.get(layer.id) === true })\n changed()\n },\n restore(encoded) {\n for (const [id, value] of decodeBenchState(encoded, controls, declared.layers)) {\n if (typeof value === 'boolean' && layers.has(id)) layers.set(id, value)\n else values.set(id, value)\n }\n },\n dispose() {\n listeners.clear()\n watchers.clear()\n },\n }\n return store\n}\n","import type * as THREE_NS from 'three'\nimport type { DestructibleSpec, PartSpec } from '@adatechnology/game-destruction'\n\n/** Default look of each built-in destruction material (`0xRRGGBB`). */\nexport const MATERIAL_COLORS: Record<string, number> = {\n steel: 0x8d949c,\n cast_iron: 0x4a4d52,\n aluminium: 0xc4c9ce,\n copper: 0xb8733a,\n wood_soft: 0xb9854f,\n wood_hard: 0x7a4a26,\n plywood: 0xc9a46a,\n mdf: 0xa88b64,\n glass: 0x9cd6e6,\n tempered_glass: 0x9cd6e6,\n ceramic: 0xe9e4da,\n concrete: 0x9a9a96,\n brick: 0xa5472e,\n plaster: 0xe6e1d4,\n stone: 0x77746f,\n plastic: 0x3b78c4,\n rubber: 0x1f1f22,\n fabric: 0x8a4b5e,\n foam: 0xe3c458,\n leather: 0x5b3a26,\n paper: 0xeeeadf,\n foliage: 0x3f8f3a,\n green_wood: 0x6b4a2b,\n cactus: 0x3e7d4a,\n flesh_fruit: 0xd24b32,\n wax: 0xefe2b5,\n soil: 0x4a3322,\n}\n\nexport interface BuildFromSpecOptions {\n /** Colour per part id, then per material id (falls back to `MATERIAL_COLORS`, then grey). */\n colors?: Record<string, number>\n /** Segments of cylinders and spheres (default 12: low poly on purpose). */\n segments?: number\n /** Cast and receive shadows (default true). */\n shadows?: boolean\n}\n\nconst TRANSPARENT: Record<string, number> = { glass: 0.38, tempered_glass: 0.38 }\n\n/**\n * Draw any `DestructibleSpec` as plain meshes: one mesh per part (box, cylinder or sphere) with `name` and `userData.destructionPart` set to the\n * part id and `userData.destructionMaterial` to its material, so `renderer.bind` and `specFromObject3D` find them. Useful for teams that describe\n * objects as specs and want something to look at while they tune them.\n */\nexport function buildFromSpec(THREE: typeof THREE_NS, spec: DestructibleSpec, options: BuildFromSpecOptions = {}): THREE_NS.Group {\n const root = new THREE.Group()\n root.name = spec.name ?? 'object'\n const seg = options.segments ?? 12\n const shadows = options.shadows !== false\n const mats = new Map<string, THREE_NS.Material>()\n const materialFor = (p: PartSpec): THREE_NS.Material => {\n const color = options.colors?.[p.id] ?? options.colors?.[p.material] ?? MATERIAL_COLORS[p.material] ?? 0x888888\n const key = `${p.material}:${color}`\n let m = mats.get(key)\n if (!m) {\n const alpha = TRANSPARENT[p.material]\n const metal = p.material === 'steel' || p.material === 'aluminium' || p.material === 'copper' || p.material === 'cast_iron'\n m = new THREE.MeshStandardMaterial({\n color,\n roughness: alpha ? 0.1 : metal ? 0.45 : 0.85,\n metalness: metal ? 0.7 : 0,\n transparent: !!alpha,\n opacity: alpha ?? 1,\n depthWrite: !alpha,\n })\n mats.set(key, m)\n }\n return m\n }\n for (const p of spec.parts) {\n let geo: THREE_NS.BufferGeometry\n const s = p.shape\n if (s.kind === 'box') geo = new THREE.BoxGeometry(s.size[0], s.size[1], s.size[2])\n else if (s.kind === 'cylinder') geo = new THREE.CylinderGeometry(s.radius, s.radius, s.height, seg)\n else geo = new THREE.SphereGeometry(s.radius, seg, Math.max(6, seg - 4))\n const mesh = new THREE.Mesh(geo, materialFor(p))\n mesh.name = p.id\n mesh.userData.destructionPart = p.id\n mesh.userData.destructionMaterial = p.material\n mesh.position.set(p.position[0], p.position[1], p.position[2])\n if (p.rotation) mesh.rotation.set(p.rotation[0], p.rotation[1], p.rotation[2], 'XYZ')\n mesh.castShadow = shadows && !TRANSPARENT[p.material]\n mesh.receiveShadow = shadows\n root.add(mesh)\n }\n return root\n}\n","import type * as THREE_NS from 'three'\nimport type { BlastOptions, DestructionWorld, HitResult, Vec3 } from '@adatechnology/game-destruction'\nimport type { DestructionRenderer } from '@adatechnology/game-destruction-three'\nimport type { VfxWorld } from '@adatechnology/game-vfx'\nimport { backblastEffect, blastEffect, createExplosiveBody, tripwireSegment } from '@adatechnology/game-weapons'\nimport type { Arsenal, Detonation, ExplosiveBody, SurfaceProbe, Use } from '@adatechnology/game-weapons'\nimport type { HostEvent } from '@adatechnology/game-contracts'\n\nimport { segmentTouchesBox } from './segment-box'\nimport type { ProjectileModel, ProjectileQuery } from './types'\n\ntype Vars = Record<string, string | number>\ntype Fire = { temperature: number; radius: number; seconds: number }\n\n/** Radius of the blast a cone gives to each object inside it: the blast is the object's own, not the area around it. */\nconst CONE_BLAST_RADIUS = 0.5\n\ninterface Projectile {\n mesh: THREE_NS.Object3D\n pos: THREE_NS.Vector3\n vel: THREE_NS.Vector3\n weapon: string\n fuse: number\n burstOnImpact: boolean\n energy: number\n radius: number\n fire?: Fire | undefined\n age: number\n /** The explosive that flies or waits (`game-weapons`): when set, it decides the flight and the blast. */\n body?: ExplosiveBody | undefined\n /** Points along its velocity (a rocket). */\n aligned?: boolean\n /** The axis of the mesh that points along its velocity (default +y). */\n axis?: THREE_NS.Vector3\n /** Set down where it was used: waits for its trigger instead of flying. */\n placed?: boolean\n /** The wire of a charge that waits for a body to cross it, and the bodies already touching it when it was set (they are let out first). */\n wire?: { from: Vec3; to: Vec3; letThrough: Set<string> }\n /** What shows where it was set down (marker and wire), taken away with it. */\n attached?: THREE_NS.Object3D[]\n}\n\n/** What a blast did, summed over everything it reached: the share that got to the most sheltered target (0..1), the pressure multiplier, the fragment hits. */\nexport type BlastSummary = { readonly shelter: number; readonly confinement: number; readonly fragmentHits: number; readonly targets: number }\n\nexport const summarizeBlast = (results: readonly HitResult[]): BlastSummary | undefined => {\n const reports = results.flatMap((r) => (r.blast ? [r.blast] : []))\n if (reports.length === 0) return undefined\n return {\n shelter: Math.min(...reports.map((r) => r.shelter)),\n confinement: reports[0]!.confinement,\n fragmentHits: reports.reduce((n, r) => n + r.fragmentHits, 0),\n targets: reports.length,\n }\n}\n\n/** A body that can set off a trip wire: the player, a physics object, or anything a module brings. */\nexport type CrossingBody = { readonly id: string; readonly box: THREE_NS.Box3 }\n\n/** What the explosives need from the room: the world to blast, the renderer to draw it, the log and the host to tell, and the few room rules (ground, held object, fire). */\nexport type ExplosivesContext = {\n readonly THREE: typeof THREE_NS\n readonly scene: THREE_NS.Scene\n readonly camera: THREE_NS.Camera\n readonly world: Pick<DestructionWorld, 'raycast' | 'explode'>\n readonly renderer: Pick<DestructionRenderer, 'emit' | 'explode'>\n /** The effects world that draws the blast of an explosive by its id; the renderer keeps the shove on pieces and the sound. */\n readonly effects: Pick<VfxWorld, 'explosion'>\n readonly arsenal: Pick<Arsenal, 'explosives' | 'rules'>\n /** The roots of the objects a blast can reach (the arena is not one). */\n readonly objects: () => readonly THREE_NS.Object3D[]\n /** The bodies that set off a trip wire when they cross it: their world boxes, now. */\n readonly bodies: () => readonly CrossingBody[]\n readonly toolId: () => string\n readonly toolName: (id?: string) => string\n readonly withoutHeld: <TResult>(run: () => TResult) => TResult\n readonly groundAt: (x: number, z: number) => number\n /** The blast options every explosion starts with (the room's toggles). */\n readonly blast: () => BlastOptions\n /** What the last blast did, once it carried a report (shelter, confinement, fragment hits). */\n readonly blasted: (summary: BlastSummary) => void\n readonly translate: (key: string, vars?: Vars) => string\n readonly format: (value: number, digits?: number) => string\n readonly action: (type: string, text: string, extra?: { data?: Record<string, unknown> }) => void\n readonly emitHost: (event: HostEvent) => void\n readonly startFire: (weapon: string, at: Vec3, fire: Fire, isImpact: boolean) => void\n readonly say: (message: string) => void\n /** The host's model for a projectile or a charge; without it, or when it answers nothing, the room draws a primitive. */\n readonly projectileModel?: ((query: ProjectileQuery) => ProjectileModel | null | undefined) | undefined\n}\n\nexport type Explosives = {\n throwUse: (use: Extract<Use, { kind: 'throw' }>) => void\n placeUse: (use: Extract<Use, { kind: 'place' }>) => void\n backblastUse: (use: Extract<Use, { kind: 'backblast' }>) => void\n /** Sets off the charges set down that wait for the remote detonator; returns how many went off. A trip wire charge goes off by itself, when a body crosses the wire. */\n detonateCharges: () => number\n update: (dt: number) => void\n /** Removes every projectile and charge, and their meshes. */\n clear: () => void\n}\n\nconst toArray = (vector: THREE_NS.Vector3): Vec3 => [vector.x, vector.y, vector.z]\n\n/** The projectiles (grenades, molotovs, rockets) and charges set down: an `ExplosiveBody` of game-weapons flies or waits, the room only draws it and applies the blast. */\nexport function createExplosives(context: ExplosivesContext): Explosives {\n const { THREE, scene, camera, world, renderer, arsenal, translate, format, action } = context\n const projectiles: Projectile[] = []\n const meshes: THREE_NS.Object3D[] = []\n const up = new THREE.Vector3(0, 1, 0)\n\n const clear = (): void => {\n projectiles.length = 0\n for (const mesh of meshes) mesh.removeFromParent()\n meshes.length = 0\n }\n\n const addMesh = (geometry: THREE_NS.BufferGeometry, color: number, metalness: number, at: Vec3): THREE_NS.Mesh => {\n const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color, roughness: 0.6, metalness }))\n mesh.castShadow = true\n mesh.position.set(at[0], at[1], at[2])\n scene.add(mesh)\n meshes.push(mesh)\n return mesh\n }\n\n /** Puts the host's model of a projectile in the scene, or undefined when the host has none. */\n const addModel = (query: ProjectileQuery, at: Vec3): { mesh: THREE_NS.Object3D; axis?: THREE_NS.Vector3 } | undefined => {\n const custom = context.projectileModel?.(query)\n if (!custom) return undefined\n custom.model.position.set(at[0], at[1], at[2])\n custom.model.traverse((child) => {\n child.castShadow = true\n })\n scene.add(custom.model)\n meshes.push(custom.model)\n return { mesh: custom.model, ...(custom.axis ? { axis: new THREE.Vector3(custom.axis[0], custom.axis[1], custom.axis[2]).normalize() } : {}) }\n }\n\n const remove = (projectile: Projectile): void => {\n for (const extra of projectile.attached ?? []) {\n extra.removeFromParent()\n const extraAt = meshes.indexOf(extra)\n if (extraAt >= 0) meshes.splice(extraAt, 1)\n }\n projectile.mesh.removeFromParent()\n const meshAt = meshes.indexOf(projectile.mesh)\n if (meshAt >= 0) meshes.splice(meshAt, 1)\n const at = projectiles.indexOf(projectile)\n if (at >= 0) projectiles.splice(at, 1)\n }\n\n const throwUse = (use: Extract<Use, { kind: 'throw' }>): void => {\n const isMolotov = !!use.fire\n const isRocket = use.trigger === 'impact' && (use.armDistance ?? 0) > 0\n const modeled = addModel({ weapon: context.toolId(), ...(use.explosive !== undefined ? { explosive: use.explosive } : {}), kind: isRocket ? 'rocket' : isMolotov ? 'molotov' : 'grenade' }, use.origin)\n const mesh = modeled?.mesh ?? addMesh(isRocket ? new THREE.CylinderGeometry(0.04, 0.04, 0.5, 8) : isMolotov ? new THREE.CylinderGeometry(0.035, 0.04, 0.2, 8) : new THREE.SphereGeometry(0.045, 8, 6), isMolotov ? 0x3b7a3b : isRocket ? 0x6b705c : 0x4b5320, isMolotov ? 0 : 0.4, use.origin)\n projectiles.push({\n mesh,\n ...(modeled?.axis ? { axis: modeled.axis } : {}),\n pos: new THREE.Vector3(use.origin[0], use.origin[1], use.origin[2]),\n vel: new THREE.Vector3(use.velocity[0], use.velocity[1], use.velocity[2]),\n weapon: context.toolId(),\n fuse: use.fuse,\n burstOnImpact: isMolotov && use.fuse <= 0,\n energy: use.energy,\n radius: use.radius,\n fire: use.fire,\n age: 0,\n ...(use.explosive !== undefined ? { body: createExplosiveBody(use, arsenal.explosives, arsenal.rules.explosives), aligned: isRocket } : {}),\n })\n const key = isRocket ? 'act.launch' : isMolotov ? 'act.throw.molotov' : 'act.throw.grenade'\n action(isRocket ? 'launch_projectile' : 'throw_projectile', translate(key, { weapon: context.toolName(), fuse: format(use.fuse, 1), arm: format(use.armDistance ?? 0, 0) }), {\n data: { weapon: context.toolId(), fuse: use.fuse, explosive: use.explosive },\n })\n }\n\n /** A charge goes where the player aims, on the first surface within reach, else on the floor 2 m ahead. */\n const placementPoint = (use: Extract<Use, { kind: 'place' }>): Vec3 => {\n const hit = context.withoutHeld(() => world.raycast(use.origin, use.direction, 3))\n if (hit) return [hit.point[0] + hit.normal[0] * 0.03, hit.point[1] + hit.normal[1] * 0.03, hit.point[2] + hit.normal[2] * 0.03]\n const x = use.origin[0] + use.direction[0] * 2\n const z = use.origin[2] + use.direction[2] * 2\n return [x, context.groundAt(x, z) + 0.03, z]\n }\n\n /** The marker that shows where a charge was set down: a stake with a flag, so it can be found (and avoided). */\n const markerAt = (at: Vec3): THREE_NS.Group => {\n const marker = new THREE.Group()\n marker.name = 'charge_marker'\n const stake = new THREE.Mesh(new THREE.CylinderGeometry(0.01, 0.01, 0.4, 6), new THREE.MeshStandardMaterial({ color: 0x8b6b3d, roughness: 0.8 }))\n stake.position.y = 0.2\n const flag = new THREE.Mesh(new THREE.ConeGeometry(0.06, 0.12, 4), new THREE.MeshStandardMaterial({ color: 0xff6a00, emissive: 0xff3300, emissiveIntensity: 0.4 }))\n flag.position.y = 0.46\n marker.add(stake, flag)\n marker.position.set(at[0] + 0.12, at[1] - 0.03, at[2])\n scene.add(marker)\n meshes.push(marker)\n return marker\n }\n\n const wireLine = (from: Vec3, to: Vec3): THREE_NS.Line => {\n const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(...from), new THREE.Vector3(...to)])\n const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xe8e4c8 }))\n line.name = 'charge_wire'\n scene.add(line)\n meshes.push(line)\n return line\n }\n\n /** The bodies whose box the wire touches right now. */\n const touching = (wire: NonNullable<Projectile['wire']>): string[] =>\n context\n .bodies()\n .filter((body) => segmentTouchesBox(wire.from, wire.to, toArray(body.box.min), toArray(body.box.max)))\n .map((body) => body.id)\n\n const placeUse = (use: Extract<Use, { kind: 'place' }>): void => {\n const at = placementPoint(use)\n const placed = { ...use, origin: at }\n const body = createExplosiveBody(placed, arsenal.explosives, arsenal.rules.explosives)\n if (!body) return\n const modeled = addModel({ weapon: context.toolId(), explosive: use.explosive, kind: 'charge' }, at)\n const mesh = modeled?.mesh ?? addMesh(new THREE.BoxGeometry(0.18, 0.06, 0.1), use.explosive === 'claymore' ? 0x556b2f : 0xc2a878, 0.1, at)\n mesh.rotation.y = Math.atan2(use.direction[0], use.direction[2])\n const attached: THREE_NS.Object3D[] = [markerAt(at)]\n const segment = tripwireSegment(placed)\n const projectile: Projectile = { mesh, pos: new THREE.Vector3(at[0], at[1], at[2]), vel: new THREE.Vector3(), weapon: context.toolId(), fuse: 0, burstOnImpact: false, energy: use.energy, radius: use.radius, age: 0, body, placed: true, attached }\n if (segment) {\n const wire = { from: segment.from, to: segment.to, letThrough: new Set<string>() }\n for (const id of touching(wire)) wire.letThrough.add(id)\n attached.push(wireLine(segment.from, segment.to))\n projectile.wire = wire\n }\n projectiles.push(projectile)\n action('place_charge', translate('act.place', { weapon: context.toolName(), triggers: use.triggers.join('/') || '-' }), { data: { weapon: context.toolId(), explosive: use.explosive, triggers: [...use.triggers], point: at, ...(segment ? { wire: segment } : {}) } })\n }\n\n /** The blast behind a launcher: a puff of dust in the cone and what lies inside it, counted. */\n const backblastUse = (use: Extract<Use, { kind: 'backblast' }>): void => {\n renderer.emit('smoke', use.origin, use.direction, 14, use.radius)\n let reached = 0\n for (const object of context.objects()) if (backblastEffect(use, toArray(object.position)) > 0) reached++\n const onPlayer = backblastEffect(use, toArray(camera.position))\n action('backblast', translate('act.backblast', { weapon: context.toolName(), radius: format(use.radius, 0), n: reached, player: format(onPlayer, 2) }), {\n data: { weapon: context.toolId(), radius: use.radius, halfAngleDeg: use.halfAngleDeg, objects: reached, onPlayer },\n })\n }\n\n const surfaceProbe: SurfaceProbe = (from, to) => {\n const dx = to[0] - from[0]\n const dy = to[1] - from[1]\n const dz = to[2] - from[2]\n const length = Math.hypot(dx, dy, dz)\n if (length < 1e-6) return null\n const direction: Vec3 = [dx / length, dy / length, dz / length]\n const ray = context.withoutHeld(() => world.raycast(from, direction, length + 0.03))\n let best: { point: Vec3; normal: Vec3; ground: boolean; at: number } | null = ray && ray.distance <= length + 0.03 ? { point: ray.point, normal: ray.normal, ground: ray.normal[1] > 0.7, at: ray.distance } : null\n const floor = context.groundAt(to[0], to[2]) + 0.045\n if (to[1] < floor) {\n const point: Vec3 = [to[0], floor, to[2]]\n const at = Math.hypot(point[0] - from[0], point[1] - from[1], point[2] - from[2])\n if (!best || at < best.at) best = { point, normal: [0, 1, 0], ground: true, at }\n }\n return best ? { point: best.point, normal: best.normal, ground: best.ground } : null\n }\n\n /** The point of the object's box (its center, its corners, the closest to the charge) that takes the most of the blast, or undefined when none is inside the cone. */\n const mostExposedPoint = (box: THREE_NS.Box3, detonation: Detonation): Vec3 | undefined => {\n const { min, max } = box\n const candidates: Vec3[] = [toArray(box.getCenter(new THREE.Vector3())), toArray(box.clampPoint(new THREE.Vector3(...detonation.point), new THREE.Vector3()))]\n for (const x of [min.x, max.x]) for (const y of [min.y, max.y]) for (const z of [min.z, max.z]) candidates.push([x, y, z])\n let best: { point: Vec3; falloff: number } | undefined\n for (const point of candidates) {\n const effect = blastEffect(detonation, point)\n if (effect.zone !== 'none' && (!best || effect.falloff > best.falloff)) best = { point, falloff: effect.falloff }\n }\n return best?.point\n }\n\n /** A directional charge only reaches what is inside its cone: each object whose box has a point in reach takes a blast of its own there, scaled by how close that point is. */\n const coneBlast = (detonation: Detonation): number => {\n let reached = 0\n for (const object of context.objects()) {\n const box = new THREE.Box3().setFromObject(object)\n if (box.isEmpty()) box.expandByPoint(object.position)\n const at = mostExposedPoint(box, detonation)\n if (!at) continue\n const results = world.explode(at, detonation.energy * blastEffect(detonation, at).falloff, CONE_BLAST_RADIUS, 'player', context.blast())\n reached += results.length\n told(results)\n }\n return reached\n }\n\n /** Tells the room what a blast with a report did (for its metrics and its log). */\n const told = (results: readonly HitResult[]): void => {\n const summary = summarizeBlast(results)\n if (!summary) return\n context.blasted(summary)\n action('blast_report', translate('act.blast_report', { shelter: format(summary.shelter * 100, 0), confinement: format(summary.confinement, 2), fragments: summary.fragmentHits, n: summary.targets }), { data: { ...summary } })\n }\n\n /** The only place a blast is applied: the world, the drawing, the log, the player's share, the host event and the fire. */\n const detonate = (projectile: Projectile, detonation: Detonation): void => {\n const weaponName = context.toolName(projectile.weapon)\n const reach = Math.max(detonation.injuryRadius, detonation.lethalRadius)\n const results = detonation.energy <= 0 || detonation.cone ? [] : world.explode(detonation.point, detonation.energy, reach, 'player', context.blast())\n const reached = detonation.energy <= 0 ? 0 : detonation.cone ? coneBlast(detonation) : results.length\n if (!detonation.cone) told(results)\n if (detonation.energy > 0) {\n const isPlayed = context.effects.explosion(detonation.explosive, detonation.point, { direction: detonation.direction }) !== null\n renderer.explode(detonation.point, detonation.energy, reach, { visual: !isPlayed, report: results })\n }\n if (detonation.stunSeconds !== undefined) renderer.emit('flash', detonation.point, [0, 1, 0], 1, 1)\n const onPlayer = blastEffect(detonation, toArray(camera.position))\n action('explode', translate('act.explode', { weapon: weaponName, energy: format(detonation.energy, 0), radius: format(reach, 1), n: reached }), {\n data: { weapon: projectile.weapon, explosive: detonation.explosive, cause: detonation.cause, energyJ: detonation.energy, radius: reach, point: detonation.point, player: onPlayer.zone, stunSeconds: onPlayer.stunSeconds },\n })\n if (onPlayer.zone !== 'none') {\n action('blast_player', translate('act.blast_player', { weapon: weaponName, zone: translate(`blast.zone.${onPlayer.zone}`), distance: format(onPlayer.distance, 1), stun: format(onPlayer.stunSeconds, 1) }), { data: { ...onPlayer } })\n }\n context.emitHost({ type: 'explosion', source: projectile.weapon, point: detonation.point, energy: detonation.energy, radius: reach, cause: detonation.cause, explosive: detonation.explosive })\n if (detonation.fire) context.startFire(projectile.weapon, detonation.point, detonation.fire, detonation.cause === 'impact')\n }\n\n /** A projectile with no `ExplosiveBody` (a use that names no explosive) blasts a sphere of its own radius, with the same effects as any other. */\n const detonateBare = (projectile: Projectile, isImpact: boolean): void => {\n detonate(projectile, {\n explosive: projectile.weapon,\n cause: isImpact ? 'impact' : 'timer',\n point: toArray(projectile.pos),\n direction: [0, 1, 0],\n at: projectile.age,\n energy: projectile.energy,\n lethalRadius: 0,\n injuryRadius: projectile.radius,\n noise: 0,\n destructionLevel: 0,\n ...(projectile.fire ? { fire: projectile.fire } : {}),\n })\n }\n\n const detonateCharges = (): number => {\n let count = 0\n for (const projectile of [...projectiles]) {\n if (!projectile.placed || !projectile.body) continue\n const event = projectile.body.trigger('remote')\n if (event?.type !== 'detonate') continue\n detonate(projectile, event.detonation)\n remove(projectile)\n count++\n }\n if (count === 0) context.say(translate('hud.no_charges'))\n return count\n }\n\n const stepBody = (projectile: Projectile, body: ExplosiveBody, dt: number): void => {\n const events = body.step(dt, surfaceProbe)\n projectile.pos.set(body.position[0], body.position[1], body.position[2])\n projectile.mesh.position.copy(projectile.pos)\n if (projectile.aligned && body.velocity[0] ** 2 + body.velocity[1] ** 2 + body.velocity[2] ** 2 > 1e-6) {\n projectile.mesh.quaternion.setFromUnitVectors(projectile.axis ?? up, new THREE.Vector3(body.velocity[0], body.velocity[1], body.velocity[2]).normalize())\n } else if (!projectile.placed) projectile.mesh.rotation.x += dt * 8\n for (const event of events) {\n if (event.type === 'dud') action('dud', translate('act.dud', { weapon: context.toolName(projectile.weapon), distance: format(body.travelled, 1) }), { data: { weapon: projectile.weapon, point: event.point } })\n else if (event.type === 'detonate') detonate(projectile, event.detonation)\n }\n }\n\n /** Moves a bare projectile one step (gravity, bounce on the first surface or the ground); true when it bursts on impact. */\n const flyBare = (projectile: Projectile, dt: number): boolean => {\n const { gravity } = arsenal.rules.explosives\n let isBurst = false\n projectile.vel.y -= gravity * dt\n const speed = projectile.vel.length()\n const step = speed * dt\n if (step > 1e-6) {\n const direction: Vec3 = [projectile.vel.x / speed, projectile.vel.y / speed, projectile.vel.z / speed]\n const hit = context.withoutHeld(() => world.raycast(toArray(projectile.pos), direction, step + 0.05))\n if (hit && hit.distance <= step + 0.04) {\n projectile.pos.set(hit.point[0] - direction[0] * 0.03, hit.point[1] - direction[1] * 0.03, hit.point[2] - direction[2] * 0.03)\n if (projectile.burstOnImpact) isBurst = true\n else {\n const normal = hit.normal\n const normalSpeed = projectile.vel.x * normal[0] + projectile.vel.y * normal[1] + projectile.vel.z * normal[2]\n projectile.vel.x = (projectile.vel.x - 2 * normalSpeed * normal[0]) * 0.35\n projectile.vel.y = (projectile.vel.y - 2 * normalSpeed * normal[1]) * 0.35\n projectile.vel.z = (projectile.vel.z - 2 * normalSpeed * normal[2]) * 0.35\n }\n } else projectile.pos.addScaledVector(projectile.vel, dt)\n }\n const ground = context.groundAt(projectile.pos.x, projectile.pos.z) + 0.045\n if (projectile.pos.y < ground) {\n projectile.pos.y = ground\n if (projectile.burstOnImpact) isBurst = true\n else {\n projectile.vel.y = Math.abs(projectile.vel.y) * 0.35\n projectile.vel.x *= 0.7\n projectile.vel.z *= 0.7\n }\n }\n return isBurst\n }\n\n /** A body crossed the wire: the charge goes off. Bodies already on the wire when it was set are let through until they step off it. */\n const checkWire = (projectile: Projectile, body: ExplosiveBody): void => {\n const wire = projectile.wire\n if (!wire) return\n const crossing = touching(wire)\n for (const id of [...wire.letThrough]) if (!crossing.includes(id)) wire.letThrough.delete(id)\n const crosser = crossing.find((id) => !wire.letThrough.has(id))\n if (crosser === undefined) return\n const event = body.trigger('wire')\n if (event?.type !== 'detonate') return\n action('tripwire', translate('act.tripwire', { weapon: context.toolName(projectile.weapon), who: crosser }), { data: { weapon: projectile.weapon, body: crosser } })\n detonate(projectile, event.detonation)\n }\n\n const update = (dt: number): void => {\n for (let index = projectiles.length - 1; index >= 0; index--) {\n const projectile = projectiles[index]\n if (!projectile) continue\n projectile.age += dt\n if (projectile.body) {\n if (projectile.wire && !projectile.body.done) checkWire(projectile, projectile.body)\n stepBody(projectile, projectile.body, dt)\n if (projectile.body.done || (!projectile.placed && projectile.age > 60)) remove(projectile)\n continue\n }\n const isBurst = flyBare(projectile, dt)\n projectile.mesh.position.copy(projectile.pos)\n projectile.mesh.rotation.x += dt * 8\n projectile.fuse -= dt\n if (isBurst || (!projectile.burstOnImpact && projectile.fuse <= 0) || projectile.age > 30) {\n detonateBare(projectile, isBurst)\n remove(projectile)\n }\n }\n }\n\n return { throwUse, placeUse, backblastUse, detonateCharges, update, clear }\n}\n","import type { Vec3 } from '@adatechnology/game-destruction'\n\n/** Whether the segment `from` to `to` touches the axis-aligned box `min` to `max` (slab test): the check of \"a body crossed the wire\". */\nexport const segmentTouchesBox = (from: Vec3, to: Vec3, min: Vec3, max: Vec3): boolean => {\n let near = 0\n let far = 1\n for (let axis = 0; axis < 3; axis++) {\n const start = from[axis] as number\n const delta = (to[axis] as number) - start\n const low = min[axis] as number\n const high = max[axis] as number\n if (Math.abs(delta) < 1e-12) {\n if (start < low || start > high) return false\n continue\n }\n const entering = (low - start) / delta\n const leaving = (high - start) / delta\n near = Math.max(near, Math.min(entering, leaving))\n far = Math.min(far, Math.max(entering, leaving))\n if (near > far) return false\n }\n return true\n}\n","import type { HostEvent } from '@adatechnology/game-contracts'\nimport type { WeaponEvent, WeaponPhase } from '@adatechnology/game-weapons'\n\nconst NO_RECOIL: [number, number] = [0, 0]\n\nexport interface HostEventOptions {\n recoil?: [number, number]\n /** What the weapon is busy with when the event is drained: the start of a phase takes its duration from it. */\n phase?: WeaponPhase | null\n}\n\nconst durationOf = (phase: WeaponPhase | null | undefined, id: WeaponPhase['id']): { duration?: number } => (phase?.id === id ? { duration: Math.round((phase.end - phase.start) * 1e6) / 1e6 } : {})\n\n/** What the host tells a module about a weapon event: the whole cycle, with the seconds the rule gave each phase. */\nexport const toHostEvent = (weapon: string, event: WeaponEvent, options: HostEventOptions = {}): HostEvent | null => {\n const { recoil = NO_RECOIL, phase } = options\n switch (event.type) {\n case 'draw':\n return event.phase === 'start' ? { type: 'tool', weapon, ...durationOf(phase, 'draw') } : null\n // a launcher spends a round and throws one projectile: the weapon counts none because it is a throw, a host counts the one that leaves\n case 'shot':\n return { type: 'shot', weapon, shots: Math.max(1, event.shots), recoil, rounds: event.rounds, mode: event.mode, ...(event.suppressed ? { suppressed: true } : {}) }\n case 'misfire':\n return { type: 'misfire', weapon }\n case 'reload':\n return { type: 'reload', weapon, phase: event.phase, ...(event.phase === 'start' ? { kind: event.kind, ...durationOf(phase, 'reload') } : {}) }\n case 'reload_stage':\n return { type: 'stage', weapon, stage: event.stage }\n case 'feed':\n return { type: 'feed', weapon }\n case 'cycle':\n return { type: 'cycle', weapon, phase: event.phase, ...(event.phase === 'start' ? durationOf(phase, 'cycle') : {}) }\n case 'empty':\n return { type: 'empty', weapon }\n case 'mode':\n return { type: 'mode', weapon, mode: event.mode }\n case 'fault':\n return { type: 'fault', weapon, fault: event.fault }\n case 'clear':\n return { type: 'clear', weapon, fault: event.fault, phase: event.phase, ...(event.phase === 'start' ? durationOf(phase, 'clear') : {}) }\n case 'safety':\n return { type: 'safety', weapon, on: event.on }\n case 'cook':\n return { type: 'cook', weapon, phase: event.phase, fuse: event.fuse }\n case 'attachment':\n return { type: 'attachment', weapon, action: event.action, attachment: event.id, mount: event.mount, ...(event.action === 'break' ? {} : durationOf(phase, 'fit')) }\n case 'toggle':\n return { type: 'toggle', weapon, attachment: event.id, on: event.on }\n case 'stock':\n return { type: 'stock', weapon, state: event.state, kind: event.kind, ...durationOf(phase, 'stock') }\n case 'underbarrel':\n return { type: 'underbarrel', weapon, on: event.on, ...durationOf(phase, 'switch') }\n default:\n return null\n }\n}\n","/**\n * The look of the loading indicator, with no dependency: a card with a title, a bar and a line of text over a dim backdrop. The room draws it (`createLoading`), and a page that must show it before any\n * script has run (the default test room's first frame) writes the same markup and styles from `loadingMarkup` and `LOADING_CSS`, so the screen the page starts with and the one the room shows later are one.\n */\nexport const LOADING_CLASS = 'tr-loading'\n\nexport const LOADING_CSS = [\n '.tr-loading{position:absolute;inset:0;z-index:2147483000;display:flex;align-items:center;justify-content:center;background:rgba(16,19,26,.72);color:#e8eaee;font:15px/1.4 system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;transition:opacity .25s;pointer-events:auto}',\n '.tr-loading.tr-loading-fixed{position:fixed}',\n '.tr-loading.tr-loading-solid{background:#10131a}',\n '.tr-loading.tr-loading-hidden{opacity:0;pointer-events:none}',\n '.tr-loading-card{width:min(440px,86vw);text-align:center}',\n '.tr-loading-title{font-size:18px;font-weight:600;margin-bottom:18px}',\n '.tr-loading-spin{display:inline-block;width:16px;height:16px;margin-right:10px;vertical-align:-2px;border:2px solid #3a3f4a;border-top-color:#ffd23f;border-radius:50%;animation:tr-loading-turn .8s linear infinite}',\n '.tr-loading-bar{position:relative;height:8px;border-radius:4px;background:#2a2e36;overflow:hidden}',\n '.tr-loading-bar i{display:block;height:100%;width:0;background:#ffd23f;transition:width .15s}',\n '.tr-loading-bar.tr-loading-indeterminate i{position:absolute;width:35%;animation:tr-loading-sweep 1.1s ease-in-out infinite}',\n '.tr-loading-step{margin-top:12px;color:#9aa3b2;min-height:1.4em}',\n '@keyframes tr-loading-turn{to{transform:rotate(360deg)}}',\n '@keyframes tr-loading-sweep{0%{left:-35%}100%{left:100%}}',\n '@media (prefers-reduced-motion:reduce){.tr-loading-spin,.tr-loading-bar.tr-loading-indeterminate i{animation-duration:3s}}',\n].join('')\n\nconst escape = (text: string): string => text.replace(/[&<>\"]/g, (c) => (c === '&' ? '&' : c === '<' ? '<' : c === '>' ? '>' : '"'))\n\n/** The markup of the indicator as a string, for a page that writes it into its HTML. `solid` is the opaque backdrop of a first screen, `fixed` covers the window instead of the room. */\nexport function loadingMarkup(options: { title: string; step?: string; solid?: boolean; fixed?: boolean; id?: string }): string {\n const classes = [LOADING_CLASS, options.solid ? 'tr-loading-solid' : '', options.fixed ? 'tr-loading-fixed' : ''].filter(Boolean).join(' ')\n const id = options.id ? ` id=\"${escape(options.id)}\"` : ''\n return `<div${id} class=\"${classes}\" role=\"status\" aria-live=\"polite\"><div class=\"tr-loading-card\"><div class=\"tr-loading-title\"><span class=\"tr-loading-spin\"></span><span class=\"tr-loading-label\">${escape(options.title)}</span></div><div class=\"tr-loading-bar tr-loading-indeterminate\"><i></i></div><div class=\"tr-loading-step\">${escape(options.step ?? '')}</div></div></div>`\n}\n","import type { BusyOptions, BusySink, BusyTask } from '@adatechnology/game-contracts'\n\nimport { LOADING_CLASS, LOADING_CSS } from './loading-view'\n\n/** What the indicator shows now: the label of the task on top, its line of text, and how far it is (the bar) when it knows. */\nexport interface LoadingState {\n readonly label: string\n readonly text: string\n readonly done: number\n readonly total: number | undefined\n /** The task hides what is behind the indicator. */\n readonly opaque: boolean\n /** Tasks open at once (an area that builds a house inside a slow action counts two). */\n readonly depth: number\n}\n\n/**\n * The loading indicator of the room: an overlay with a spinner or a bar and a line of text, shown for any slow job so that the page never looks frozen. `begin` shows it at once, `busy` also waits for the\n * paint before it runs the work (the only way to show a bar before a heavy synchronous job), and the last task to end takes it down. The room lends it to modules as `ModuleHost.loading`.\n */\nexport interface RoomLoading extends BusySink {\n /** True while a task is open. */\n readonly active: boolean\n /** Resolves once no task is open (at once when none is): a scenario or test awaits it after a change that rebuilds behind the indicator, instead of sleeping. */\n idle(): Promise<void>\n /** What it shows now, or undefined when nothing is open. */\n state(): LoadingState | undefined\n /** Follows it: called whenever a task opens, steps or ends, with `undefined` once none is left. Returns the function that stops following. */\n on(listener: (state: LoadingState | undefined) => void): () => void\n /** The overlay element (undefined in a room with `ui: false`, where the page draws its own from `on`). */\n readonly element: HTMLElement | undefined\n dispose(): void\n}\n\nexport interface LoadingOptions {\n /** The room's container: the overlay covers it. */\n readonly container: HTMLElement\n /** False for a room with `ui: false`: the state is kept and told through `on`, nothing is drawn. Default true. */\n readonly draw?: boolean\n /** Text of a task that has none yet (already translated). */\n readonly working: string\n}\n\ninterface Task {\n label: string\n text: string\n done: number\n total: number | undefined\n opaque: boolean\n ended: boolean\n}\n\nconst PAINT_FALLBACK_MS = 100\nlet styled = false\n\nconst ensureStyle = (document: Document): void => {\n if (styled && document.getElementById('tr-loading-style')) return\n const style = document.createElement('style')\n style.id = 'tr-loading-style'\n style.textContent = LOADING_CSS\n document.head.appendChild(style)\n styled = true\n}\n\n/** Resolves once the browser has painted a frame (a frame callback, then a timer), or after a short wait when frames are not running (a hidden tab, a test). */\nexport const nextPaint = (): Promise<void> =>\n new Promise((resolve) => {\n let done = false\n const finish = (): void => {\n if (!done) {\n done = true\n resolve()\n }\n }\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(() => setTimeout(finish, 0))\n setTimeout(finish, PAINT_FALLBACK_MS)\n })\n\nexport function createLoading(options: LoadingOptions): RoomLoading {\n const draw = options.draw !== false && typeof document !== 'undefined'\n const tasks: Task[] = []\n const listeners = new Set<(state: LoadingState | undefined) => void>()\n let element: HTMLElement | undefined\n let labelNode: HTMLElement | null = null\n let stepNode: HTMLElement | null = null\n let barNode: HTMLElement | null = null\n let fillNode: HTMLElement | null = null\n let hideTimer: ReturnType<typeof setTimeout> | undefined\n const idlers: Array<() => void> = []\n\n const current = (): Task | undefined => tasks[tasks.length - 1]\n const state = (): LoadingState | undefined => {\n const task = current()\n return task ? { label: task.label, text: task.text, done: task.done, total: task.total, opaque: task.opaque, depth: tasks.length } : undefined\n }\n\n const build = (): HTMLElement => {\n ensureStyle(options.container.ownerDocument)\n const root = document.createElement('div')\n root.className = `${LOADING_CLASS} tr-loading-hidden`\n root.setAttribute('role', 'status')\n root.setAttribute('aria-live', 'polite')\n root.innerHTML =\n '<div class=\"tr-loading-card\"><div class=\"tr-loading-title\"><span class=\"tr-loading-spin\"></span><span class=\"tr-loading-label\"></span></div><div class=\"tr-loading-bar tr-loading-indeterminate\"><i></i></div><div class=\"tr-loading-step\"></div></div>'\n labelNode = root.querySelector('.tr-loading-label')\n stepNode = root.querySelector('.tr-loading-step')\n barNode = root.querySelector('.tr-loading-bar')\n fillNode = root.querySelector('.tr-loading-bar i')\n options.container.appendChild(root)\n return root\n }\n\n const render = (): void => {\n const now = state()\n for (const listener of listeners) listener(now)\n if (!now) for (const wake of idlers.splice(0)) wake()\n if (!draw) return\n if (!now) {\n if (element) {\n element.classList.add('tr-loading-hidden')\n // the card fades out, then stops being laid out\n hideTimer = setTimeout(() => element?.style.setProperty('display', 'none'), 300)\n }\n return\n }\n if (hideTimer !== undefined) clearTimeout(hideTimer)\n element ??= build()\n element.style.removeProperty('display')\n element.classList.remove('tr-loading-hidden')\n element.classList.toggle('tr-loading-solid', now.opaque)\n if (labelNode) labelNode.textContent = now.label\n if (stepNode) stepNode.textContent = now.text\n const determinate = now.total !== undefined && now.total > 0\n barNode?.classList.toggle('tr-loading-indeterminate', !determinate)\n if (fillNode) fillNode.style.width = determinate ? `${Math.max(0, Math.min(1, now.done / (now.total as number))) * 100}%` : ''\n }\n\n const begin = (label: string, taskOptions: BusyOptions = {}): BusyTask => {\n const task: Task = { label, text: options.working, done: 0, total: taskOptions.total, opaque: taskOptions.opaque === true, ended: false }\n tasks.push(task)\n render()\n return {\n step(text, done) {\n if (task.ended) return\n if (text !== undefined) task.text = text\n if (done !== undefined) task.done = done\n render()\n },\n paint: nextPaint,\n end() {\n if (task.ended) return\n task.ended = true\n const at = tasks.indexOf(task)\n if (at >= 0) tasks.splice(at, 1)\n render()\n },\n }\n }\n\n return {\n get active() {\n return tasks.length > 0\n },\n get element() {\n return element\n },\n state,\n idle: () => (tasks.length === 0 ? Promise.resolve() : new Promise<void>((resolve) => idlers.push(resolve))),\n on(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n begin,\n async busy<T>(label: string, work: (task: BusyTask) => T | Promise<T>, taskOptions?: BusyOptions): Promise<T> {\n const task = begin(label, taskOptions)\n try {\n await task.paint()\n return await work(task)\n } finally {\n task.end()\n }\n },\n dispose() {\n if (hideTimer !== undefined) clearTimeout(hideTimer)\n tasks.length = 0\n for (const wake of idlers.splice(0)) wake()\n listeners.clear()\n element?.remove()\n element = undefined\n },\n }\n}\n","import type { LogEntry, NewLogEntry, TestRoomLog } from './types'\n\nexport type NewEntry = NewLogEntry\n\n/** The log the room writes to (a `TestRoomLog` plus the write side). */\nexport interface WritableLog extends TestRoomLog {\n /** Called before every read, so pending work (the room batches events per frame) is flushed first. */\n setBeforeRead(fn: (() => void) | null): void\n setClock(fn: () => number): void\n}\n\nconst MAX_ENTRIES = 5000\n\nconst pad = (n: number, w = 2): string => String(n).padStart(w, '0')\n\n/** `00:03.21` style clock for the text export. */\nexport const formatTime = (t: number): string => {\n const m = Math.floor(t / 60)\n const s = t - m * 60\n return `${pad(m)}:${s.toFixed(2).padStart(5, '0')}`\n}\n\n/** Minimal shape of the `downloads` capability a claude.ai Artifact page gets from `claude.use('downloads')`. */\ninterface DownloadsApi {\n save(request: { filename: string; data: string }): Promise<unknown>\n}\n\nexport interface LogOptions {\n /** Text of the `action` line written when the viewer declines (or fails) an export from an Artifact page. */\n exportCancelled?: () => string\n}\n\nexport function createLog(options: LogOptions = {}): WritableLog {\n // In a claude.ai Artifact the page cannot use <a download> / blob links: it asks the host for the `downloads` capability. The promise is\n // created once, never awaited here (`use` may take up to 10 s and resolve null); `download` awaits it when somebody actually exports.\n const host = (globalThis as { claude?: { use?: (name: string) => Promise<unknown> } }).claude\n let downloadsP: Promise<DownloadsApi | null> | null = null\n if (host && typeof host.use === 'function') {\n try {\n downloadsP = Promise.resolve(host.use('downloads')).then((d) => (d as DownloadsApi | null) ?? null, () => null)\n } catch {\n downloadsP = null\n }\n }\n let list: LogEntry[] = []\n let seq = 0\n let clock = (): number => 0\n let beforeRead: (() => void) | null = null\n const listeners = new Set<(entry: LogEntry, updated: boolean) => void>()\n const keyed = new Map<string, { entry: LogEntry; last: number; count: number }>()\n\n const read = (): LogEntry[] => {\n beforeRead?.()\n return list\n }\n const emit = (e: LogEntry, updated: boolean): void => {\n for (const fn of listeners) {\n try {\n fn(e, updated)\n } catch {\n // a broken listener must not break the room\n }\n }\n }\n\n const add = (entry: NewEntry): LogEntry => {\n const { t, ...rest } = entry\n const e: LogEntry = { seq: seq++, t: Math.round((t ?? clock()) * 1000) / 1000, ...rest }\n list.push(e)\n if (list.length > MAX_ENTRIES) list = list.slice(list.length - MAX_ENTRIES)\n emit(e, false)\n return e\n }\n\n const log: WritableLog = {\n add,\n coalesce(key, entry, windowS = 1) {\n const now = entry.t ?? clock()\n const k = keyed.get(key)\n if (k && now - k.last <= windowS && list.includes(k.entry)) {\n const { t: _t, ...rest } = entry\n k.count++\n Object.assign(k.entry, rest)\n k.entry.data = { ...(rest.data ?? {}), updates: k.count }\n k.last = now\n emit(k.entry, true)\n return k.entry\n }\n const e = add(entry)\n keyed.set(key, { entry: e, last: now, count: 1 })\n return e\n },\n setBeforeRead(fn) {\n beforeRead = fn\n },\n setClock(fn) {\n clock = fn\n },\n entries(filter) {\n const all = read()\n if (!filter) return all.slice()\n return all.filter(\n (e) =>\n (!filter.channel || e.channel === filter.channel) && (!filter.type || e.type === filter.type) && (!filter.objectId || e.objectId === filter.objectId),\n )\n },\n clear() {\n beforeRead?.()\n list = []\n keyed.clear()\n },\n toJSON: () => JSON.stringify(read(), null, 2),\n toNDJSON: () => read().map((e) => JSON.stringify(e)).join('\\n') + (list.length ? '\\n' : ''),\n toText: () => read().map((e) => `[${formatTime(e.t)}] ${e.channel.padEnd(6)} ${e.text}`).join('\\n'),\n async download(format = 'ndjson') {\n const body = format === 'json' ? log.toJSON() : format === 'txt' ? log.toText() : log.toNDJSON()\n const downloads = downloadsP ? await downloadsP : null\n if (downloads) {\n // the Artifact allowlist has no `.ndjson`: it goes out as text\n const filename = format === 'ndjson' ? 'test-room-log.ndjson.txt' : `test-room-log.${format}`\n try {\n await downloads.save({ filename, data: body })\n } catch (err) {\n const code = (err as { code?: unknown } | null)?.code\n log.add({ channel: 'action', type: 'export_cancelled', text: options.exportCancelled?.() ?? 'export cancelled', data: { format, ...(typeof code === 'string' ? { code } : {}) } })\n }\n return\n }\n if (typeof document === 'undefined' || typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) return\n const mime = format === 'json' ? 'application/json' : 'text/plain'\n const url = URL.createObjectURL(new Blob([body], { type: mime }))\n const a = document.createElement('a')\n a.href = url\n a.download = `test-room-log.${format}`\n document.body.appendChild(a)\n a.click()\n a.remove()\n setTimeout(() => URL.revokeObjectURL(url), 1000)\n },\n summary() {\n const byType: Record<string, number> = {}\n const byMaterial: Record<string, number> = {}\n const objects = new Set<string>()\n let destroyed = 0\n for (const e of read()) {\n byType[e.type] = (byType[e.type] ?? 0) + 1\n if (e.material) byMaterial[e.material] = (byMaterial[e.material] ?? 0) + 1\n if (e.objectId) objects.add(e.objectId)\n if (e.type === 'destroyed') destroyed++\n }\n return { byType, byMaterial, objects: objects.size, destroyed }\n },\n on(fn) {\n listeners.add(fn)\n return () => listeners.delete(fn)\n },\n }\n return log\n}\n","import type { RoomMetricId } from './types'\n\nexport const ROOM_METRICS: readonly RoomMetricId[] = ['fps', 'frame_ms', 'draw_calls', 'triangles', 'objects', 'fragments', 'particles', 'decals', 'blast_shelter', 'blast_confinement', 'blast_fragments']\n\nconst WINDOW_S = 0.5\n\ninterface RenderInfo {\n info?: { render?: { calls: number; triangles: number } }\n}\n\nexport interface RoomMetricsSources {\n readonly gl: unknown\n readonly destruction: { stats(): { fragments: number; particles: number; pieces: number; decals: number } }\n readonly fluids: { stats(): { particles: number; stains: number } }\n readonly effects: { stats(): { puffs: number; sparks: number; glows: number; chunks: number } }\n readonly ids: readonly RoomMetricId[]\n /** What the last blast with a report did (none until one). */\n readonly blast?: () => { shelter: number; confinement: number; fragmentHits: number } | undefined\n}\n\nexport interface RoomMetrics {\n /** Every frame with the real `dt`, before the time scale. */\n frame(dt: number): void\n /** Right after the room renders (only when it owns the loop). */\n rendered(): void\n sample(): Partial<Record<RoomMetricId, number>>\n}\n\nexport function createRoomMetrics(sources: RoomMetricsSources): RoomMetrics {\n const wanted = new Set(sources.ids)\n const gl = sources.gl as RenderInfo\n let windowS = 0\n let frames = 0\n let fps: number | undefined\n let frameMs: number | undefined\n let calls: number | undefined\n let triangles: number | undefined\n let ownsRender = false\n return {\n frame(dt) {\n frames++\n windowS += dt\n if (windowS < WINDOW_S) return\n fps = frames / windowS\n frameMs = (windowS / frames) * 1000\n frames = 0\n windowS = 0\n },\n rendered() {\n ownsRender = true\n calls = gl.info?.render?.calls\n triangles = gl.info?.render?.triangles\n },\n sample() {\n const out: Partial<Record<RoomMetricId, number>> = {}\n const put = (id: RoomMetricId, value: number | undefined): void => {\n if (wanted.has(id) && value !== undefined) out[id] = value\n }\n put('fps', fps)\n put('frame_ms', frameMs)\n const render = ownsRender ? { calls, triangles } : gl.info?.render\n put('draw_calls', render?.calls)\n put('triangles', render?.triangles)\n const blast = sources.blast?.()\n if (blast) {\n put('blast_shelter', blast.shelter * 100)\n put('blast_confinement', blast.confinement)\n put('blast_fragments', blast.fragmentHits)\n }\n if (!['objects', 'fragments', 'particles', 'decals'].some((id) => wanted.has(id as RoomMetricId))) return out\n const destruction = sources.destruction.stats()\n const fluids = sources.fluids.stats()\n const effects = sources.effects.stats()\n put('objects', destruction.pieces)\n put('fragments', destruction.fragments)\n put('particles', destruction.particles + fluids.particles + effects.puffs + effects.sparks + effects.glows + effects.chunks)\n put('decals', destruction.decals + fluids.stains)\n return out\n },\n }\n}\n","import type { DestructionEvent, DestructionWorld, PartState, ToolKind } from '@adatechnology/game-destruction'\nimport type { FluidEvent, FluidWorld } from '@adatechnology/game-fluids'\nimport type { WritableLog } from './log'\nimport type { LogEntry } from './types'\n\ntype Vars = Record<string, string | number>\n\n/** What the narrator needs to know about the room. */\nexport interface NarrateContext {\n world: DestructionWorld\n fluids: FluidWorld\n log: WritableLog\n /** Current room time in seconds. */\n now: () => number\n t: (key: string, vars?: Vars) => string\n /** Locale number: `1.5` -> `1,5` in pt-BR. */\n num: (n: number, digits?: number) => string\n /** Item display name of an object id (also loose pieces). */\n nameOf: (objectId: string) => string\n itemIdOf: (objectId: string) => string | undefined\n materialName: (id: string) => string\n liquidName: (id: string) => string\n jointKind: (kind: string) => string\n toolName: (tool: string) => string\n /** Display name of the item that carries a fluid container. */\n containerName: (containerId: string) => { name: string; objectId?: string; itemId?: string } | undefined\n /** Where a part lives now: its object, or the loose piece it broke off into. */\n locatePart?: (objectId: string, partId: string) => { objectId: string; part: PartState } | null\n}\n\nconst SKIP_DAMAGE: ReadonlySet<string> = new Set(['fire', 'heat'])\n\n/**\n * Turns destruction and fluid events into plain log lines in the room locale. Events of one frame arrive as a batch: a `damage` event is merged\n * into the dent, hole or crack it caused, a `leak` event into the hole that opened it, and the noisy ones (melt, drip, disassembly) become one\n * line that is updated while it goes on.\n */\nexport function createNarrator(c: NarrateContext) {\n const { t, num } = c\n\n /** Materials seen per `object|part`, so a line about a part that already broke off its object still names the material. */\n const materialMemo = new Map<string, string>()\n const findPart = (objectId: string, partId: string): PartState | null => {\n const p = c.world.part(objectId, partId) ?? c.locatePart?.(objectId, partId)?.part ?? null\n if (p) materialMemo.set(`${objectId}|${partId}`, p.material)\n return p\n }\n const plural = (key: string, n: number): string => t(`${key}.${n === 1 ? 'one' : 'other'}`, { n })\n const pieces = (n: number): string => plural('count.piece', n)\n const joints = (n: number): string => plural('count.joint', n)\n const xz = (x: number, z: number): string => t('coords', { x: num(x, 1), z: num(z, 1) })\n\n const where = (objectId: string, partId: string): string => {\n const p = findPart(objectId, partId)\n const m = p?.material ?? materialMemo.get(`${objectId}|${partId}`)\n return `${c.nameOf(objectId)} › ${partId}${m ? ` (${c.materialName(m)})` : ''}`\n }\n\n const stateOf = (objectId: string, partId: string): LogEntry['state'] => {\n const p = findPart(objectId, partId)\n if (!p) return undefined\n const s: Record<string, number | string | boolean> = {\n status: p.status,\n hp: Math.round(p.hp * 10) / 10,\n maxHp: Math.round(p.maxHp * 10) / 10,\n temperature: Math.round(p.temperature),\n char: Math.round(p.char * 100) / 100,\n melt: Math.round(p.melt * 100) / 100,\n }\n if (p.liters !== undefined) s.liters = Math.round(p.liters * 1000) / 1000\n return s\n }\n\n const base = (ev: DestructionEvent, part?: string): Pick<LogEntry, 'channel' | 'objectId' | 'itemId' | 'part' | 'material' | 'state'> => ({\n channel: 'event',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n part,\n material: part ? (findPart(ev.object, part)?.material ?? materialMemo.get(`${ev.object}|${part}`)) : undefined,\n state: part ? stateOf(ev.object, part) : undefined,\n })\n\n const hpText = (obj: string, part: string): string => {\n const p = findPart(obj, part)\n return p ? `hp ${num(p.hp, 0)}/${num(p.maxHp, 0)}` : ''\n }\n\n const isLost = (obj: string, part: string): boolean => {\n const st = findPart(obj, part)?.status\n return st === 'broken' || st === 'melted' || st === 'ashes'\n }\n\n /** Per-part running totals for lines that repeat while something goes on (cracks under load, overload damage). */\n const crackAcc = new Map<string, { n: number; cm: number; last: number }>()\n const damageAcc = new Map<string, { total: number; last: number }>()\n const stressAt = new Map<string, number>()\n const leakAt = new Map<string, number>()\n const list = (names: string[]): string => (names.length > 6 ? `${names.slice(0, 6).join(', ')}…` : names.join(', '))\n\n const events = (batch: DestructionEvent[]): void => {\n const now = c.now()\n const damage = new Map<string, { amount: number; type: string }>()\n const holes = new Map<string, LogEntry>()\n const dents = new Map<string, LogEntry>()\n for (const ev of batch) {\n if (ev.type !== 'damage') continue\n const k = `${ev.object}|${ev.part}`\n const prev = damage.get(k)\n damage.set(k, { amount: (prev?.amount ?? 0) + ev.amount, type: ev.damageType })\n }\n\n // A part that breaks, melts or burns away opens every joint it had: those `detach` events become part of ONE line about the part\n // (appended to its fracture or burnout line, or standing alone), instead of one line per joint.\n const lostJoints = new Map<string, { obj: string; part: string; joints: number; groups: number; merged: boolean }>()\n // Joints that open for another reason (a blow, a tool) are counted per object.\n const openJoints = new Map<string, { obj: string; by: string; list: Array<{ joint: string; a: string; b: string }>; groups: number; done: boolean }>()\n // Several parts of one object catching fire or being put out at once are one line.\n const fireParts = new Map<string, { obj: string; parts: string[]; temp: number; done: boolean }>()\n const outParts = new Map<string, { obj: string; parts: string[]; done: boolean }>()\n for (const ev of batch) {\n if (ev.type === 'detach') {\n if (ev.by === 'part_lost') {\n const [a, b] = ev.parts\n const lost = isLost(ev.object, a) && !isLost(ev.object, b) ? a : isLost(ev.object, b) && !isLost(ev.object, a) ? b : isLost(ev.object, a) ? a : b\n const key = `${ev.object}|${lost}`\n const g = lostJoints.get(key) ?? { obj: ev.object, part: lost, joints: 0, groups: 0, merged: false }\n g.joints++\n g.groups = ev.groups.length\n lostJoints.set(key, g)\n } else {\n const key = `${ev.object}|${ev.by}`\n const g = openJoints.get(key) ?? { obj: ev.object, by: ev.by, list: [], groups: 0, done: false }\n const [a, b] = ev.parts\n g.list.push({ joint: ev.joint, a, b })\n g.groups = ev.groups.length\n openJoints.set(key, g)\n }\n } else if (ev.type === 'ignite') {\n const g = fireParts.get(ev.object) ?? { obj: ev.object, parts: [], temp: 0, done: false }\n g.parts.push(ev.part)\n g.temp = Math.max(g.temp, findPart(ev.object, ev.part)?.temperature ?? 0)\n fireParts.set(ev.object, g)\n } else if (ev.type === 'extinguish') {\n const g = outParts.get(ev.object) ?? { obj: ev.object, parts: [], done: false }\n g.parts.push(ev.part)\n outParts.set(ev.object, g)\n }\n }\n const lostTail = (key: string): string => {\n const g = lostJoints.get(key)\n if (!g) return ''\n g.merged = true\n return t('ev.lost.tail', { joints: joints(g.joints), pieces: pieces(g.groups) })\n }\n const lostData = (key: string): Record<string, unknown> => {\n const g = lostJoints.get(key)\n return g ? { jointsOpened: g.joints, pieces: g.groups } : {}\n }\n\n for (const ev of batch) {\n switch (ev.type) {\n case 'damage':\n break\n case 'dent': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n const mm = ev.dent.depth * 1000\n const prev = dents.get(k)\n if (prev) {\n const n = Number(prev.data?.count ?? 1) + 1\n const deepest = Math.max(Number(prev.data?.depthMm ?? 0), mm)\n prev.text = t('ev.dents', { where: where(ev.object, ev.part), n, mm: num(deepest, 0), hp: hpText(ev.object, ev.part) })\n prev.data = { ...prev.data, count: n, depthMm: Math.round(deepest * 10) / 10 }\n break\n }\n dents.set(\n k,\n c.log.add({\n ...base(ev, ev.part),\n type: 'dent',\n text: t('ev.dent', { where: where(ev.object, ev.part), mm: num(mm, 0), hp: hpText(ev.object, ev.part) }),\n data: { count: 1, depthMm: Math.round(mm * 10) / 10, radius: ev.dent.radius, damage: d?.amount, point: ev.worldPoint, source: ev.source },\n }),\n )\n break\n }\n case 'hole': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n const mm = ev.hole.diameter * 1000\n const prev = holes.get(k)\n if (prev) {\n const n = Number(prev.data?.count ?? 1) + 1\n const through = Number(prev.data?.throughCount ?? 0) + (ev.hole.through ? 1 : 0)\n prev.text = t('ev.holes', { where: where(ev.object, ev.part), n, mm: num(mm, 0), thr: through, hp: hpText(ev.object, ev.part) })\n prev.data = { ...prev.data, count: n, throughCount: through, through: through > 0 }\n break\n }\n holes.set(\n k,\n c.log.add({\n ...base(ev, ev.part),\n type: 'hole',\n text: t(ev.hole.through ? 'ev.hole.through' : 'ev.hole.stuck', { where: where(ev.object, ev.part), mm: num(mm, 0), hp: hpText(ev.object, ev.part) }),\n data: { count: 1, throughCount: ev.hole.through ? 1 : 0, diameterMm: Math.round(mm * 10) / 10, through: ev.hole.through, damage: d?.amount, point: ev.worldPoint, source: ev.source },\n }),\n )\n break\n }\n case 'crack': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n // a part under load cracks again and again: that is one line that counts them (a cracking shot or blow stays its own line)\n const loaded = (findPart(ev.object, ev.part)?.stress ?? 0) > 0.8 && ev.source === undefined\n const cm = ev.crack.length * 100\n if (loaded) {\n const acc = crackAcc.get(k)\n const n = acc && now - acc.last <= 1 ? acc.n + 1 : 1\n const longest = acc && n > 1 ? Math.max(acc.cm, cm) : cm\n crackAcc.set(k, { n, cm: longest, last: now })\n c.log.coalesce(\n `crack:${k}`,\n {\n ...base(ev, ev.part),\n type: 'crack',\n text: t('ev.cracks', { where: where(ev.object, ev.part), n, cm: num(longest, 0), hp: hpText(ev.object, ev.part) }),\n data: { rays: ev.crack.rays, lengthM: ev.crack.length, count: n, underLoad: true },\n },\n 1,\n )\n break\n }\n c.log.add({\n ...base(ev, ev.part),\n type: 'crack',\n text: t('ev.crack', { where: where(ev.object, ev.part), rays: ev.crack.rays, cm: num(cm, 0), hp: hpText(ev.object, ev.part) }),\n data: { rays: ev.crack.rays, lengthM: ev.crack.length, damage: d?.amount, source: ev.source },\n })\n break\n }\n case 'ricochet':\n c.log.add({\n ...base(ev, ev.part),\n type: 'ricochet',\n text: t('ev.ricochet', { where: where(ev.object, ev.part), energy: num(ev.energy, 0) }),\n data: { energy: ev.energy, direction: ev.direction },\n })\n break\n case 'leak': {\n const k = `${ev.object}|${ev.part}`\n const liquid = c.liquidName(ev.fluid)\n const hole = holes.get(k)\n const rate = num(ev.rate, 2)\n leakAt.set(ev.object, now)\n if (hole) {\n hole.text += t('ev.leak.tail', { liquid, rate })\n hole.data = { ...hole.data, leak: { fluid: ev.fluid, ratePerS: ev.rate, pressurized: ev.pressurized } }\n } else {\n c.log.add({ ...base(ev, ev.part), type: 'leak', text: t('ev.leak.alone', { where: where(ev.object, ev.part), liquid, rate }), data: { fluid: ev.fluid, ratePerS: ev.rate } })\n }\n break\n }\n case 'fracture': {\n const k = `${ev.object}|${ev.part}`\n const d = damage.get(k)\n damage.delete(k)\n c.log.add({\n ...base(ev, ev.part),\n type: 'fracture',\n text: t(`ev.fracture.${ev.style}`, { where: where(ev.object, ev.part), n: ev.fragments.length }) + lostTail(k),\n data: { style: ev.style, fragments: ev.fragments.length, damage: d?.amount, point: ev.point, source: ev.source, ...lostData(k) },\n })\n break\n }\n case 'detach': {\n if (ev.by === 'part_lost') {\n // the part's own line (fracture, burnout) already says it; with none in this batch, say it here, once\n const [a, b] = ev.parts\n const lost = isLost(ev.object, a) && !isLost(ev.object, b) ? a : isLost(ev.object, b) && !isLost(ev.object, a) ? b : isLost(ev.object, a) ? a : b\n const key = `${ev.object}|${lost}`\n const g = lostJoints.get(key)\n if (!g || g.merged) break\n const hasOwnLine = batch.some((e) => (e.type === 'fracture' || e.type === 'burnout') && e.object === ev.object && e.part === lost)\n if (hasOwnLine) break\n g.merged = true\n const status = findPart(ev.object, lost)?.status\n const verb = t(`lost.${status === 'ashes' ? 'ashes' : status === 'melted' ? 'melted' : 'broken'}`)\n c.log.add({\n ...base(ev, lost),\n type: 'detach',\n text: t('ev.lost.alone', { where: where(ev.object, lost), verb, joints: joints(g.joints), pieces: pieces(g.groups) }),\n data: { parts: [a, b], by: ev.by, ...lostData(key) },\n })\n break\n }\n const key = `${ev.object}|${ev.by}`\n const g = openJoints.get(key)\n if (!g || g.done) break\n g.done = true\n const [a, b] = ev.parts\n const many = g.list.length > 1\n c.log.add({\n channel: 'event',\n type: 'detach',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: many\n ? t(`ev.detach.many.${ev.by === 'tool' ? 'tool' : 'break'}`, { obj: c.nameOf(ev.object), joints: joints(g.list.length), pieces: pieces(g.groups) })\n : t('ev.detach', { obj: c.nameOf(ev.object), a, b, by: t(`by.${ev.by}`), pieces: pieces(g.groups) }),\n data: { joint: ev.joint, joints: g.list.map((j) => j.joint), parts: ev.parts, by: ev.by, groups: g.groups },\n })\n break\n }\n case 'disassemble_progress': {\n const pct = Math.round(ev.progress * 100)\n const kind = kindOf(ev.object, ev.joint)\n const [a, b] = ev.joint.split('~')\n c.log.coalesce(\n `dis:${ev.object}:${ev.joint}`,\n {\n channel: 'event',\n type: 'disassemble_progress',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.disassemble', { obj: c.nameOf(ev.object), a: a ?? ev.joint, b: b ?? '', kind: kind ? c.jointKind(kind) : t('joint.generic'), tool: c.toolName(ev.tool as ToolKind), pct }),\n data: { joint: ev.joint, tool: ev.tool, progress: ev.progress },\n },\n 1.5,\n )\n break\n }\n case 'ignite': {\n const g = fireParts.get(ev.object)\n if (g && g.parts.length >= 3) {\n if (g.done) break\n g.done = true\n c.log.add({\n channel: 'event',\n type: 'ignite',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.ignite.many', { obj: c.nameOf(ev.object), n: g.parts.length, temp: num(g.temp, 0), parts: list(g.parts) }),\n data: { parts: g.parts, temperature: Math.round(g.temp) },\n })\n break\n }\n c.log.add({ ...base(ev, ev.part), type: 'ignite', text: t('ev.ignite', { where: where(ev.object, ev.part), temp: num(findPart(ev.object, ev.part)?.temperature ?? 0, 0) }) })\n break\n }\n case 'extinguish': {\n const g = outParts.get(ev.object)\n if (g && g.parts.length >= 3) {\n if (g.done) break\n g.done = true\n c.log.add({\n channel: 'event',\n type: 'extinguish',\n objectId: ev.object,\n itemId: c.itemIdOf(ev.object),\n text: t('ev.extinguish.many', { obj: c.nameOf(ev.object), n: g.parts.length, parts: list(g.parts) }),\n data: { parts: g.parts },\n })\n break\n }\n c.log.add({ ...base(ev, ev.part), type: 'extinguish', text: t('ev.extinguish', { where: where(ev.object, ev.part) }) })\n break\n }\n case 'burnout': {\n const k = `${ev.object}|${ev.part}`\n c.log.add({ ...base(ev, ev.part), type: 'burnout', text: t('ev.burnout', { where: where(ev.object, ev.part) }) + lostTail(k), data: lostData(k) })\n break\n }\n case 'melt':\n c.log.coalesce(\n `melt:${ev.object}:${ev.part}`,\n { ...base(ev, ev.part), type: 'melt', text: t('ev.melt', { where: where(ev.object, ev.part), pct: Math.round(ev.melt * 100) }), data: { melt: ev.melt } },\n 2,\n )\n break\n case 'drip':\n c.log.coalesce(`drip:${ev.object}:${ev.part}`, { ...base(ev, ev.part), type: 'drip', text: t('ev.drip', { where: where(ev.object, ev.part) }), data: { point: ev.point } }, 2)\n break\n case 'explode':\n c.log.add({\n ...base(ev, ev.part),\n type: 'explode',\n text: t('ev.explode', { where: where(ev.object, ev.part), energy: num(ev.energy, 0), radius: num(ev.radius, 1) }),\n data: { energy: ev.energy, radius: ev.radius, point: ev.point },\n })\n break\n case 'destroyed':\n c.log.add({ channel: 'event', type: 'destroyed', objectId: ev.object, itemId: c.itemIdOf(ev.object), text: t('ev.destroyed', { obj: c.nameOf(ev.object) }) })\n break\n default: {\n // structural events (`stress`, `collapse`) come from newer versions of the core\n const x = ev as unknown as Record<string, unknown> & { type: string; object: string; time: number }\n if (x.type === 'stress') {\n const part = String(x.part ?? '')\n stressAt.set(`${x.object}|${part}`, now)\n c.log.coalesce(\n `stress:${x.object}:${part}`,\n {\n ...base(ev, part),\n type: 'stress',\n text: t('ev.stress', { where: where(x.object, part), stress: num(Number(x.stress ?? 0) * 100, 0), load: num(Number(x.load ?? 0), 0) }),\n data: { stress: x.stress, load: x.load },\n },\n 1,\n )\n } else if (x.type === 'collapse') {\n const parts = Array.isArray(x.parts) ? (x.parts as unknown[]).map(String) : []\n c.log.add({\n channel: 'event',\n type: 'collapse',\n objectId: x.object,\n itemId: c.itemIdOf(x.object),\n text: t('ev.collapse', { obj: c.nameOf(x.object), pieces: pieces(parts.length), mass: num(Number(x.mass ?? 0), 0), parts: list(parts) }),\n data: { parts: parts.length, partIds: parts, massKg: x.mass, cause: x.cause },\n })\n }\n }\n }\n }\n // damage that no dent, hole, crack or fracture explained (blunt thuds, blast, absorbed bullets, a structure carrying too much)\n for (const [k, d] of damage) {\n if (SKIP_DAMAGE.has(d.type) || d.amount < 0.5) continue\n const [obj, part] = k.split('|')\n const overload = d.type === 'blunt' && now - (stressAt.get(k) ?? -99) <= 3\n const entry = {\n channel: 'event' as const,\n type: 'damage',\n objectId: obj,\n itemId: c.itemIdOf(obj),\n part,\n material: findPart(obj, part)?.material ?? materialMemo.get(k),\n state: stateOf(obj, part),\n }\n if (!overload) {\n c.log.add({ ...entry, text: t('ev.damage', { where: where(obj, part), type: t(`dmg.${d.type}`), amount: num(d.amount, 0), hp: hpText(obj, part) }), data: { amount: d.amount, damageType: d.type } })\n continue\n }\n // a structure carrying too much loses hit points every tick: one line with the running total\n const acc = damageAcc.get(k)\n const total = acc && now - acc.last <= 1 ? acc.total + d.amount : d.amount\n damageAcc.set(k, { total, last: now })\n c.log.coalesce(\n `damage:${k}`,\n { ...entry, text: t('ev.damage.overload', { where: where(obj, part), amount: num(total, 0), hp: hpText(obj, part) }), data: { amount: total, damageType: d.type, overload: true } },\n 1,\n )\n }\n }\n\n const kindMemo = new Map<string, string>()\n const kindOf = (objectId: string, jointId: string): string => {\n const key = `${objectId}|${jointId}`\n const own = c.world.state(objectId)?.joints.find((j) => j.id === jointId)?.kind\n if (own) {\n kindMemo.set(key, own)\n return own\n }\n const known = kindMemo.get(key)\n if (known) return known\n for (const id of c.world.ids()) {\n const k = c.world.state(id)?.joints.find((j) => j.id === jointId)?.kind\n if (k) return k\n }\n return ''\n }\n\n const stainInfo = new Map<string, { liquid: string; surface: string; x: number; z: number }>()\n const stainAcc = new Map<string, { n: number; last: number }>()\n const driedAcc = new Map<string, { n: number; last: number }>()\n const drinkAcc = new Map<string, { liters: number; thirst: number; burn: boolean; effects: Set<string>; last: number; start: number }>()\n const fluid = (ev: FluidEvent): void => {\n const who = (id: string): string => c.containerName(id)?.name ?? id\n const meta = (id: string): { objectId?: string; itemId?: string } => {\n const m = c.containerName(id)\n return { objectId: m?.objectId, itemId: m?.itemId }\n }\n const f = 'fluid.'\n switch (ev.type) {\n case 'fill':\n c.log.coalesce(`fill:${ev.container}`, { channel: 'event', type: f + 'fill', ...meta(ev.container), text: t('fl.fill', { who: who(ev.container), liquid: c.liquidName(ev.liquid), liters: num(ev.liters, 2) }), data: { liters: ev.liters } }, 1.5)\n break\n case 'pour':\n c.log.coalesce(`pour:${ev.container}`, { channel: 'event', type: f + 'pour', ...meta(ev.container), text: t('fl.pour', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, 2) }), data: { rate: ev.rate } }, 2)\n break\n case 'spill':\n c.log.coalesce(`spill:${ev.container}`, { channel: 'event', type: f + 'spill', ...meta(ev.container), text: t('fl.spill', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, 2) }), data: { rate: ev.rate } }, 2)\n break\n case 'leak': {\n // the hole line of the destruction event already says the object is leaking\n const owner = meta(ev.container).objectId\n if (owner && c.now() - (leakAt.get(owner) ?? -99) <= 2) break\n c.log.coalesce(`fleak:${ev.container}`, { channel: 'event', type: f + 'leak', ...meta(ev.container), text: t('fl.leak', { who: who(ev.container), liquid: c.liquidName(ev.liquid), rate: num(ev.rate, ev.rate < 0.01 ? 3 : 2) }), data: { rate: ev.rate, point: ev.point } }, 2)\n break\n }\n case 'drink': {\n // a sip arrives as many small drink events: one line per sip, updated while it goes on\n const now = c.now()\n let acc = drinkAcc.get(ev.container)\n if (!acc || now - acc.last > 0.5) acc = { liters: 0, thirst: 0, burn: false, effects: new Set<string>(), last: now, start: now }\n acc.liters += ev.liters\n acc.thirst += ev.thirst\n acc.burn = acc.burn || ev.burn\n for (const e of ev.effects) acc.effects.add(e)\n acc.last = now\n drinkAcc.set(ev.container, acc)\n const effects = [...acc.effects].map((e) => t(`effect.${e}`)).join(', ')\n c.log.coalesce(\n `drink:${ev.container}:${acc.start}`,\n {\n channel: 'event',\n type: f + 'drink',\n ...meta(ev.container),\n text:\n t('fl.drink', { who: who(ev.container), liters: num(acc.liters, 2), thirst: num(acc.thirst, 0) }) +\n (effects ? `, ${effects}` : '') +\n (acc.burn ? `, ${t('fl.burn')}` : ''),\n data: { liters: acc.liters, temperature: ev.temperature, thirst: acc.thirst, effects: [...acc.effects], burn: acc.burn },\n },\n 0.5,\n )\n break\n }\n case 'empty':\n c.log.add({ channel: 'event', type: f + 'empty', ...meta(ev.container), text: t('fl.empty', { who: who(ev.container) }) })\n break\n case 'splash':\n c.log.coalesce(`splash:${ev.liquid}`, { channel: 'event', type: f + 'splash', text: t('fl.splash', { liquid: c.liquidName(ev.liquid) }), data: { point: ev.point, intensity: ev.intensity } }, 1)\n break\n case 'stain': {\n const surface = t(`surface.${ev.surface}`)\n const liquid = c.liquidName(ev.liquid)\n stainInfo.set(ev.stain, { liquid: ev.liquid, surface, x: ev.point[0], z: ev.point[2] })\n // a leak or a spill makes several stains in a row: one line that counts them\n const key = `stain:${ev.liquid}:${ev.surface}`\n const acc = stainAcc.get(key)\n const n = acc && c.now() - acc.last <= 1 ? acc.n + 1 : 1\n stainAcc.set(key, { n, last: c.now() })\n c.log.coalesce(\n key,\n {\n channel: 'event',\n type: f + 'stain',\n text: n > 1 ? t('fl.stains', { n, liquid, surface, where: xz(ev.point[0], ev.point[2]) }) : t('fl.stain', { liquid, surface, where: xz(ev.point[0], ev.point[2]) }),\n data: { stain: ev.stain, surface: ev.surface, liquid: ev.liquid, point: ev.point, count: n },\n },\n 1,\n )\n break\n }\n case 'dried': {\n const info = stainInfo.get(ev.stain)\n const key = `dried:${info?.liquid ?? '?'}:${ev.mark}`\n const acc = driedAcc.get(key)\n const n = acc && c.now() - acc.last <= 1.5 ? acc.n + 1 : 1\n driedAcc.set(key, { n, last: c.now() })\n const vars = { liquid: info ? c.liquidName(info.liquid) : '', surface: info?.surface ?? '', where: info ? xz(info.x, info.z) : '', n }\n const text = !info\n ? t(ev.mark ? 'fl.dried.mark' : 'fl.dried')\n : n > 1\n ? t(ev.mark ? 'fl.dried.many.mark' : 'fl.dried.many', vars)\n : t(ev.mark ? 'fl.dried.known.mark' : 'fl.dried.known', vars)\n c.log.coalesce(key, { channel: 'event', type: f + 'dried', text, data: { stain: ev.stain, mark: ev.mark, count: n } }, 1.5)\n break\n }\n case 'mix':\n c.log.add({ channel: 'event', type: f + 'mix', ...meta(ev.container), text: t('fl.mix', { who: who(ev.container), from: c.liquidName(ev.from), into: c.liquidName(ev.into) }) })\n break\n default:\n break\n }\n }\n\n return { events, fluid }\n}\n","import type * as THREE_NS from 'three'\nimport type { Vec3 } from '@adatechnology/game-destruction'\n\nexport interface PlayerHooks {\n /** Primary button pressed / released (use the tool). `click` is a press without a drag, for the no-pointer-lock fallback. */\n primaryDown(): void\n primaryUp(): void\n secondary(): void\n key(code: string, down: boolean, event: KeyboardEvent): void\n wheel(direction: 1 | -1): void\n}\n\nexport interface PlayerOptions {\n camera: THREE_NS.PerspectiveCamera\n dom: HTMLElement\n /** `[minX, minZ, maxX, maxZ]` boxes to stay out of. */\n colliders: Array<[number, number, number, number]>\n /** Extra places to stay out of, asked on every step (a module's walls): `(x, z, radius) => blocked`. The set may change while the player walks. */\n blockers?: ReadonlySet<(x: number, z: number, radius: number) => boolean>\n /** Half size of the arena. */\n limit: number\n start: Vec3\n hooks: PlayerHooks\n /** `KeyboardEvent.code`s that crouch while held (default `['KeyC']`). Ctrl is not one by default: Ctrl+W closes the tab and no page can stop it. */\n crouchKeys?: readonly string[]\n}\n\nexport interface Player {\n readonly yaw: number\n readonly pitch: number\n readonly locked: boolean\n /** Where the feet are: x and z on the floor, y above it (a jump lifts it). The eye is `EYE` above, the camera sits there. */\n readonly x: number\n readonly z: number\n readonly feet: number\n /** Feet position. */\n readonly position: Vec3\n /** Horizontal metres per second walked in the last update. */\n readonly speed: number\n readonly running: boolean\n /** Whether the player is crouched (a crouch key held): the eye sinks and the walk slows. */\n readonly crouching: boolean\n /** Held keys, by `KeyboardEvent.code`. */\n keys: ReadonlySet<string>\n update(dt: number): void\n setPose(position: Vec3, yaw: number, pitch: number): void\n /** Put the eye at `position` looking at `target`. */\n look(position: Vec3, target: Vec3): void\n /** Camera kick in degrees. */\n kick(pitchDeg: number, yawDeg: number): void\n /** Move the player by a world offset on the floor plane, stopped by the colliders and the arena limit (scripted walks). */\n moveBy(dx: number, dz: number): void\n /** Walk by hand (tests): moves the player `forward` and `right` metres along its facing. */\n walk(forward: number, right: number): void\n dispose(): void\n}\n\nconst EYE = 1.7\n/** Horizontal radius of the player, metres: what the colliders and a trip wire see. */\nexport const PLAYER_RADIUS = 0.3\nconst WALK = 3.4\n/** How far (m) the eye sinks when crouched, the speed of a crouched walk, and how fast the eye goes down and up (per second). */\nexport const CROUCH_DROP = 0.55\nconst CROUCH_WALK = 1.7\nconst CROUCH_RATE = 9\nconst RUN = 6.2\nconst JUMP = 4.6\nconst GRAVITY = 13\nconst LOOK = 0.0022\n\n/**\n * First-person controller: WASD, Shift, Space, mouse look with pointer lock, and a drag-to-look fallback for pages where the lock is not\n * available (iframes, headless browsers, touch). In the fallback a press that does not move is a click (tool use), a drag looks around.\n */\nexport function createPlayer(THREE: typeof THREE_NS, o: PlayerOptions): Player {\n const cam = o.camera\n let yaw = 0\n let pitch = 0\n let y = 0\n let eye = EYE\n let crouch = 0\n let vy = 0\n let walked = 0\n let running = false\n const px = { x: o.start[0], z: o.start[2] }\n let locked = false\n const keys = new Set<string>()\n const crouchKeys = o.crouchKeys ?? ['KeyC']\n const isCrouchHeld = (): boolean => crouchKeys.some((code) => keys.has(code))\n const euler = new THREE.Euler(0, 0, 0, 'YXZ')\n\n const apply = (): void => {\n euler.set(pitch, yaw, 0, 'YXZ')\n cam.quaternion.setFromEuler(euler)\n cam.position.set(px.x, eye + y - CROUCH_DROP * crouch, px.z)\n cam.updateMatrixWorld(true)\n }\n apply()\n\n const blocked = (x: number, z: number): boolean => {\n if (Math.abs(x) > o.limit - PLAYER_RADIUS || Math.abs(z) > o.limit - PLAYER_RADIUS) return true\n for (const c of o.colliders) if (x > c[0] - PLAYER_RADIUS && x < c[2] + PLAYER_RADIUS && z > c[1] - PLAYER_RADIUS && z < c[3] + PLAYER_RADIUS) return true\n if (o.blockers) for (const blocked of o.blockers) if (blocked(x, z, PLAYER_RADIUS)) return true\n return false\n }\n const move = (dx: number, dz: number): void => {\n if (!blocked(px.x + dx, px.z)) px.x += dx\n if (!blocked(px.x, px.z + dz)) px.z += dz\n }\n\n let dragging = false\n let moved = 0\n let downAt = 0\n let useStarted = false\n let holdTimer: ReturnType<typeof setTimeout> | null = null\n\n const look = (dx: number, dy: number): void => {\n yaw -= dx * LOOK\n pitch = Math.max(-1.5, Math.min(1.5, pitch - dy * LOOK))\n }\n const onLockChange = (): void => {\n locked = document.pointerLockElement === o.dom\n if (locked) {\n try {\n const nav = (typeof navigator !== 'undefined' ? navigator : null) as unknown as { keyboard?: { lock?(keys?: string[]): Promise<void> } } | null\n nav?.keyboard?.lock?.().catch(() => {})\n } catch {\n // ignore if not supported\n }\n } else {\n try {\n const nav = (typeof navigator !== 'undefined' ? navigator : null) as unknown as { keyboard?: { unlock?(): void } } | null\n nav?.keyboard?.unlock?.()\n } catch {\n // ignore\n }\n }\n }\n const onMouseDown = (e: MouseEvent): void => {\n o.dom.focus?.()\n if (e.button === 2) {\n e.preventDefault()\n o.hooks.secondary()\n return\n }\n if (e.button !== 0) return\n if (!locked) {\n try {\n const r = (o.dom.requestPointerLock as unknown as (() => Promise<void> | void) | undefined)?.call(o.dom)\n if (r && typeof (r as Promise<void>).catch === 'function') (r as Promise<void>).catch(() => undefined)\n } catch {\n // no pointer lock here: drag to look\n }\n dragging = true\n moved = 0\n downAt = performance.now()\n useStarted = false\n holdTimer = setTimeout(() => {\n if (dragging && moved < 4 && !useStarted) {\n useStarted = true\n o.hooks.primaryDown()\n }\n }, 220)\n return\n }\n useStarted = true\n o.hooks.primaryDown()\n }\n const onMouseUp = (e: MouseEvent): void => {\n if (e.button !== 0) return\n if (holdTimer) clearTimeout(holdTimer)\n if (dragging) {\n dragging = false\n if (!useStarted && moved < 4 && performance.now() - downAt < 400) {\n o.hooks.primaryDown()\n o.hooks.primaryUp()\n } else if (useStarted) o.hooks.primaryUp()\n useStarted = false\n return\n }\n if (useStarted) o.hooks.primaryUp()\n useStarted = false\n }\n const onMouseMove = (e: MouseEvent): void => {\n if (locked) look(e.movementX, e.movementY)\n else if (dragging) {\n moved += Math.abs(e.movementX) + Math.abs(e.movementY)\n if (moved >= 4) {\n if (useStarted) {\n useStarted = false\n o.hooks.primaryUp()\n }\n look(e.movementX, e.movementY)\n }\n }\n }\n const onWheel = (e: WheelEvent): void => {\n e.preventDefault()\n o.hooks.wheel(e.deltaY > 0 ? 1 : -1)\n }\n const typing = (e: Event): boolean => {\n const t = e.target as HTMLElement | null\n return !!t && (t.tagName === 'INPUT' || t.tagName === 'SELECT' || t.tagName === 'TEXTAREA')\n }\n const onKeyDown = (e: KeyboardEvent): void => {\n if (typing(e)) return\n if (e.code === 'Space' || e.code === 'Tab') e.preventDefault()\n // Ctrl/Meta/Alt chords are game input while playing (crouch + key); only F keys stay with the browser\n const isControlHeld = e.ctrlKey || e.metaKey || keys.has('ControlLeft') || keys.has('ControlRight')\n if (isControlHeld || (e.altKey && locked)) {\n if (!/^F\\d+$/.test(e.code)) e.preventDefault()\n }\n if (!e.repeat) keys.add(e.code)\n o.hooks.key(e.code, true, e)\n }\n const onKeyUp = (e: KeyboardEvent): void => {\n keys.delete(e.code)\n if (typing(e)) return\n o.hooks.key(e.code, false, e)\n }\n const onContext = (e: Event): void => e.preventDefault()\n const onBlur = (): void => keys.clear()\n const onBeforeUnload = (e: BeforeUnloadEvent): void => {\n if (!locked && !keys.has('ControlLeft') && !keys.has('ControlRight')) return\n e.preventDefault()\n e.returnValue = ''\n }\n\n o.dom.addEventListener('mousedown', onMouseDown)\n window.addEventListener('mouseup', onMouseUp)\n window.addEventListener('mousemove', onMouseMove)\n o.dom.addEventListener('wheel', onWheel, { passive: false })\n o.dom.addEventListener('contextmenu', onContext)\n document.addEventListener('pointerlockchange', onLockChange)\n window.addEventListener('keydown', onKeyDown)\n window.addEventListener('keyup', onKeyUp)\n window.addEventListener('blur', onBlur)\n window.addEventListener('beforeunload', onBeforeUnload)\n\n return {\n get yaw() {\n return yaw\n },\n get pitch() {\n return pitch\n },\n get locked() {\n return locked\n },\n get x() {\n return px.x\n },\n get z() {\n return px.z\n },\n get feet() {\n return y\n },\n get position() {\n return [px.x, y, px.z] as Vec3\n },\n get speed() {\n return walked\n },\n get running() {\n return running\n },\n get crouching() {\n return isCrouchHeld()\n },\n keys,\n update(dt) {\n const crouched = isCrouchHeld()\n crouch += ((crouched ? 1 : 0) - crouch) * Math.min(1, dt * CROUCH_RATE)\n if (!crouched && crouch < 1e-3) crouch = 0\n const run = !crouched && (keys.has('ShiftLeft') || keys.has('ShiftRight'))\n const fromX = px.x\n const fromZ = px.z\n const speed = crouched ? CROUCH_WALK : run ? RUN : WALK\n let f = 0\n let r = 0\n if (keys.has('KeyW') || keys.has('ArrowUp')) f += 1\n if (keys.has('KeyS') || keys.has('ArrowDown')) f -= 1\n if (keys.has('KeyD') || keys.has('ArrowRight')) r += 1\n if (keys.has('KeyA') || keys.has('ArrowLeft')) r -= 1\n if ((f || r || keys.has('Space')) && eye !== EYE) eye = EYE\n if (f || r) {\n const len = Math.hypot(f, r)\n const fx = -Math.sin(yaw)\n const fz = -Math.cos(yaw)\n const rx = Math.cos(yaw)\n const rz = -Math.sin(yaw)\n move(((fx * f + rx * r) / len) * speed * dt, ((fz * f + rz * r) / len) * speed * dt)\n }\n walked = dt > 0 ? Math.hypot(px.x - fromX, px.z - fromZ) / dt : 0\n running = run && walked > 0\n if (y <= 0 && keys.has('Space')) vy = JUMP\n if (y > 0 || vy > 0) {\n vy -= GRAVITY * dt\n y += vy * dt\n if (y <= 0) {\n y = 0\n vy = 0\n }\n }\n apply()\n },\n setPose(position, yw, pt) {\n px.x = position[0]\n px.z = position[2]\n eye = position[1]\n y = 0\n vy = 0\n yaw = yw\n pitch = pt\n apply()\n },\n look(position, target) {\n px.x = position[0]\n px.z = position[2]\n eye = position[1]\n y = 0\n vy = 0\n const dx = target[0] - position[0]\n const dy = target[1] - position[1]\n const dz = target[2] - position[2]\n yaw = Math.atan2(-dx, -dz)\n pitch = Math.atan2(dy, Math.hypot(dx, dz))\n apply()\n },\n kick(pitchDeg, yawDeg) {\n pitch = Math.max(-1.5, Math.min(1.5, pitch + (pitchDeg * Math.PI) / 180))\n yaw += (yawDeg * Math.PI) / 180\n apply()\n },\n moveBy(dx, dz) {\n move(dx, dz)\n apply()\n },\n walk(forward, right) {\n move(-Math.sin(yaw) * forward + Math.cos(yaw) * right, -Math.cos(yaw) * forward - Math.sin(yaw) * right)\n apply()\n },\n dispose() {\n if (holdTimer) clearTimeout(holdTimer)\n o.dom.removeEventListener('mousedown', onMouseDown)\n window.removeEventListener('mouseup', onMouseUp)\n window.removeEventListener('mousemove', onMouseMove)\n o.dom.removeEventListener('wheel', onWheel)\n o.dom.removeEventListener('contextmenu', onContext)\n document.removeEventListener('pointerlockchange', onLockChange)\n window.removeEventListener('keydown', onKeyDown)\n window.removeEventListener('keyup', onKeyUp)\n window.removeEventListener('blur', onBlur)\n window.removeEventListener('beforeunload', onBeforeUnload)\n if (document.pointerLockElement === o.dom) document.exitPointerLock?.()\n },\n }\n}\n","/**\n * The player's body in the room and the third-person camera. Generic: the room knows an avatar only by this interface (a body from any package\n * that fits it, such as `createPlayerAvatar` of `@adatechnology/game-characters-three`), and no character code is imported here.\n */\nimport type * as THREE_NS from 'three'\nimport type { Vec3 } from '@adatechnology/game-destruction'\nimport type { HandTargets } from '@adatechnology/game-contracts'\n\nexport interface RoomAvatarItemUse {\n readonly id: string\n readonly position: readonly [number, number, number]\n readonly rotation: readonly [number, number, number]\n}\n\n/** What the room tells the avatar every frame. */\nexport interface RoomAvatarState {\n /** Ground speed of the player, m/s (from the movement of the feet, jumps ignored). */\n speed: number\n /** Shift held. */\n running: boolean\n crouch: boolean\n down: boolean\n /** A firearm is the tool in hand. */\n armed: boolean\n /** Camera pitch, radians, positive looking up (the room's own convention). */\n pitch: number\n /** Whether the player is carrying an item in hand. */\n holding?: boolean\n /** Active scripted item use (`drink`, `sip`, `chug`, `pour`, `open`, `close`, `tilt`). */\n itemUse?: RoomAvatarItemUse | null\n}\n\n/** What the room tells the first-person arms every frame, after the modules have placed the tool in the hands. */\nexport interface RoomFirstPersonState {\n /** The player's eye: the arms are drawn in its space. */\n camera: THREE_NS.Object3D\n /** Where the tool in the hands asks them to be (world space): the module's, else the carried item's, else null. */\n targets: HandTargets | null\n /** `hold` when something is held (targets), else the rest stance of the tool in hand (`relaxed`, `fists`...; `RoomOptions.handStances`). */\n stance: string\n /** How far the index finger of the shooting hand is curled, 0 extended along the frame to 1 pulled on the trigger; null when no tool asks for it. */\n triggerFinger: number | null\n speed: number\n running: boolean\n crouch: boolean\n /** The distance along a ray (world space) to the first thing in the room, or null: what the arms use to stop at a wall or a wardrobe. */\n contact(origin: [number, number, number], direction: [number, number, number], maxDistance: number): number | null\n}\n\n/** A body the room can show. The room puts `root` at the player's feet turned to where the player looks: the body's front is +z (as the catalogue items'), so `rotation.y` is the player's yaw plus pi. */\nexport interface RoomAvatar {\n root: THREE_NS.Object3D\n update(dt: number, state: RoomAvatarState): void\n /** A socket at a hand: the carried item follows `hand('R')` in third person. */\n hand?(side: 'R' | 'L'): THREE_NS.Object3D\n /**\n * The arms of the first-person view. The room shows `root` only in first person (the body only in third), updates it every frame after the modules'\n * frame hooks (so the tool in the hands is already placed) and before the render.\n */\n firstPerson?: { root: THREE_NS.Object3D; update(dt: number, state: RoomFirstPersonState): void }\n /**\n * Plays the strike `clipId` (on the body and on the arms) and answers the seconds until its impact, or null when this avatar has no such clip. The room then waits that long\n * before the blow lands (`strikeClips`); an avatar without `strike`, or one that answers null, gets the blow at the click.\n */\n strike?(clipId: string, options?: { leg?: 'left' | 'right' }): number | null\n}\n\n/** Which leg a kick uses: `alternate` swaps at each kick (right first). */\nexport type KickLeg = 'alternate' | 'left' | 'right'\n\nexport type CameraMode = 'first' | 'third'\n\n/** Which clip a melee tool plays before its blow lands (`TestRoomOptions.strikeClips`). */\nexport const DEFAULT_STRIKE_CLIPS: Readonly<Record<string, string>> = { hand: 'punch_right', fists: 'punch_right', shove: 'shove_two_hands', kick: 'front_kick' }\n/** The first-person stance of the tools that choose one (`TestRoomOptions.handStances`). */\nexport const DEFAULT_HAND_STANCES: Readonly<Record<string, string>> = { fists: 'fists' }\n\n/**\n * The over-the-shoulder view, metres. Defaults are the numbers of the team game's shoulder camera\n * (`site/pages/jogo/zombiada-modo-livre.html`, `cameraUpdate`, line 76546): `view.cb` 3.8 back, `view.cs` 0.9 to the side, `view.cu` 1.95 high\n * (1.4 crouched), the `+ 0.1` lift of the camera at line 76551, and three probe rays (centre and +-0.2 m, line 76557) that pull the camera in\n * 0.3 m short of a wall (`h.t - 0.3`, never closer than 0.2 m) and let it out again slowly (`dt * 4`, line 76558).\n */\nexport interface ThirdPersonOptions {\n /** Distance behind the pivot. Default 3.8. */\n back?: number\n /** Pivot offset to the right of the player (negative: left shoulder). Default 0.9. */\n side?: number\n /** Pivot height above the feet. Default 1.95. */\n up?: number\n /** Pivot height above the feet while crouched. Default 1.4. */\n crouchUp?: number\n /** Extra height of the camera over the line from the pivot. Default 0.1. */\n lift?: number\n /** How far short of a wall the camera stops. Default 0.3. */\n margin?: number\n /** Closest the camera comes to the pivot. Default 0.2. */\n minDistance?: number\n /** Sideways offsets of the probe rays. Default `[0, 0.2, -0.2]`. */\n probes?: readonly number[]\n /** Per second rate at which the camera returns after a wall is gone. Default 4. */\n recover?: number\n}\n\nexport const THIRD_PERSON_DEFAULTS: Required<ThirdPersonOptions> = {\n back: 3.8,\n side: 0.9,\n up: 1.95,\n crouchUp: 1.4,\n lift: 0.1,\n margin: 0.3,\n minDistance: 0.2,\n probes: [0, 0.2, -0.2],\n recover: 4,\n}\n\n/** First blocking distance along a ray from `origin` (unit `direction`) within `max`, or null. */\nexport type FreeProbe = (origin: Vec3, direction: Vec3, max: number) => number | null\n\nexport interface ThirdPersonInput {\n x: number\n z: number\n feet: number\n yaw: number\n pitch: number\n crouch: boolean\n}\n\nexport interface ThirdPersonPose {\n /** Where the camera stands (pulled in to `free`). */\n position: Vec3\n /** Where the camera would stand `distance` metres from the pivot along the same line. */\n at(distance: number): Vec3\n /** The point it looks past (the shoulder pivot). */\n pivot: Vec3\n /** Unit view direction, the same as the first-person one. */\n direction: Vec3\n /** The distance from pivot the view asks for, and how far a wall lets it go. */\n wanted: number\n free: number\n}\n\n/** The camera of the shoulder view: behind and beside the player along the view direction, pulled in against walls. */\nexport function thirdPersonPose(input: ThirdPersonInput, options: Required<ThirdPersonOptions>, probe: FreeProbe): ThirdPersonPose {\n const cy = Math.cos(input.pitch)\n const d: Vec3 = [-Math.sin(input.yaw) * cy, Math.sin(input.pitch), -Math.cos(input.yaw) * cy]\n const rx = Math.cos(input.yaw)\n const rz = -Math.sin(input.yaw)\n const pivot: Vec3 = [input.x + rx * options.side, input.feet + (input.crouch ? options.crouchUp : options.up), input.z + rz * options.side]\n const dx = -d[0] * options.back\n const dy = -d[1] * options.back + options.lift\n const dz = -d[2] * options.back\n const wanted = Math.hypot(dx, dy, dz)\n const dir: Vec3 = [dx / wanted, dy / wanted, dz / wanted]\n let free = wanted\n for (const o of options.probes) {\n const hit = probe([pivot[0] + rx * o, pivot[1], pivot[2] + rz * o], dir, wanted)\n if (hit !== null) free = Math.min(free, Math.max(options.minDistance, hit - options.margin))\n }\n const at = (distance: number): Vec3 => [pivot[0] + dir[0] * distance, Math.max(0.1, pivot[1] + dir[1] * distance), pivot[2] + dir[2] * distance]\n return { position: at(free), at, pivot, direction: d, wanted, free }\n}\n","/** Locales shipped with the package. Unknown locales fall back to `en`. */\nexport type TestRoomLocale = 'en' | 'pt-BR'\n\nexport interface RoomStrings {\n /** Display name per item id the room itself names (none: the items come from the modules). */\n items: Record<string, string>\n /** Display name per demo catalogue group. */\n groups: Record<string, string>\n /** Every other text: UI, log lines, scenario names and checks. `{name}` placeholders are replaced. */\n text: Record<string, string>\n}\n\nconst en: RoomStrings = {\n items: {},\n groups: { furniture: 'Furniture', structure: 'Structure', vehicles: 'Vehicles', plants: 'Plants', items: 'Items', containers: 'Containers' },\n text: {\n 'locale.decimal': '.',\n yes: 'yes',\n no: 'no',\n piece: 'piece',\n coords: 'x {x} · z {z}',\n 'count.piece.one': '1 piece',\n 'count.piece.other': '{n} pieces',\n 'count.joint.one': '1 joint',\n 'count.joint.other': '{n} joints',\n 'count.dent.one': '1 dent',\n 'count.dent.other': '{n} dents',\n 'count.hole.one': '1 hole',\n 'count.hole.other': '{n} holes',\n 'count.crack.one': '1 crack',\n 'count.crack.other': '{n} cracks',\n 'joint.generic': 'joint',\n 'lost.broken': 'broke',\n 'lost.melted': 'melted away',\n 'lost.ashes': 'burned to ash',\n 'tool.none': 'by hand only',\n 'arena.target_wall': 'Target wall',\n 'arena.table': 'Table',\n 'arena.shelf': 'Shelf',\n 'surface.floor': 'on the floor',\n 'surface.ground': 'on the floor',\n 'surface.table': 'on the table',\n 'by.break': 'broken loose',\n 'by.tool': 'undone with a tool',\n 'by.part_lost': 'the part next to it was lost',\n 'dmg.ballistic': 'ballistic',\n 'dmg.blunt': 'blunt',\n 'dmg.slash': 'slash',\n 'dmg.explosive': 'blast',\n 'dmg.fire': 'fire',\n 'dmg.heat': 'heat',\n 'effect.caffeine': 'caffeine',\n 'effect.alcohol': 'alcohol',\n 'effect.poison': 'poison',\n 'effect.disgust': 'disgust',\n\n 'ev.dent': '{where}: dent of {mm} mm, {hp}',\n 'ev.hole.through': '{where}: {mm} mm hole went through, {hp}',\n 'ev.hole.stuck': '{where}: {mm} mm hole, did not go through, {hp}',\n 'ev.dents': '{where}: {n} dents, deepest {mm} mm, {hp}',\n 'ev.holes': '{where}: {n} holes of {mm} mm, {thr} went through, {hp}',\n 'ev.leak.tail': ', leaking {liquid} at {rate} l/s',\n 'ev.leak.alone': '{where}: leaking {liquid} at {rate} l/s',\n 'ev.crack': '{where}: cracked, {rays} rays up to {cm} cm, {hp}',\n 'ev.ricochet': '{where}: bullet ricocheted, {energy} J left',\n 'ev.fracture.shatter': '{where}: shattered into {n} shards',\n 'ev.fracture.crumble': '{where}: crumbled into {n} chunks',\n 'ev.fracture.splinter': '{where}: splintered into {n} pieces',\n 'ev.fracture.tear': '{where}: torn into {n} scraps',\n 'ev.fracture.snap': '{where}: snapped into {n} pieces',\n 'ev.fracture.none': '{where}: broke into {n} pieces',\n 'ev.detach': '{obj}: {a} came off {b} ({by}); the object now has {pieces}',\n 'ev.detach.many.break': '{obj}: {joints} broke loose; the object now has {pieces}',\n 'ev.detach.many.tool': '{obj}: {joints} undone with a tool; the object now has {pieces}',\n 'ev.lost.tail': ' and came loose from {joints}; the object now has {pieces}',\n 'ev.lost.alone': '{where}: {verb} and came loose from {joints}; the object now has {pieces}',\n 'ev.cracks': '{where}: cracking under the load, {n} cracks so far, longest {cm} cm, {hp}',\n 'ev.disassemble': '{obj}: undoing the {kind} between {a} and {b} with {tool}: {pct}%',\n 'ev.ignite': '{where}: caught fire at {temp} °C',\n 'ev.ignite.many': '{obj}: {n} parts caught fire at {temp} °C ({parts})',\n 'ev.extinguish': '{where}: fire put out',\n 'ev.extinguish.many': '{obj}: fire put out on {n} parts ({parts})',\n 'ev.burnout': '{where}: burned to ash',\n 'ev.melt': '{where}: melting, {pct}% melted away',\n 'ev.drip': '{where}: dripping molten material',\n 'ev.explode': '{where}: exploded, {energy} J within {radius} m',\n 'ev.destroyed': '{obj}: destroyed',\n 'ev.damage': '{where}: {type} damage {amount}, {hp}',\n 'ev.damage.overload': '{where}: crushed by the weight it carries, lost {amount} hp so far, {hp}',\n 'ev.stress': '{where}: overloaded at {stress}% of its capacity, carrying {load} kg',\n 'ev.collapse': '{obj}: collapsed, {pieces} fell ({mass} kg): {parts}',\n 'ev.stain_ignite': 'The {liquid} stain at x {x} · z {z} caught fire and will burn for about {seconds} s',\n 'ev.stain_burned': 'The burning stain burned itself out',\n 'ev.fire_dries': 'Fire dried the wet stains nearby',\n\n 'fl.fill': '{who}: filled with {liquid} (+{liters} l)',\n 'fl.pour': '{who}: pouring {liquid} at {rate} l/s',\n 'fl.spill': '{who}: spilled {liquid} over the lip at {rate} l/s',\n 'fl.leak': '{who}: leaking {liquid} at {rate} l/s',\n 'fl.drink': '{who}: drank {liters} l, thirst +{thirst}',\n 'fl.burn': 'too hot: burned the mouth',\n 'fl.empty': '{who}: empty',\n 'fl.splash': 'Splash of {liquid}',\n 'fl.stain': 'Stain of {liquid} {surface} at {where}',\n 'fl.stains': '{n} stains of {liquid} {surface}, the latest at {where}',\n 'fl.dried': 'A stain dried up',\n 'fl.dried.mark': 'A stain dried and left a mark',\n 'fl.dried.known': 'The {liquid} stain {surface} at {where} dried up',\n 'fl.dried.known.mark': 'The {liquid} stain {surface} at {where} dried and left a mark',\n 'fl.dried.many': '{n} {liquid} stains dried up',\n 'fl.dried.many.mark': '{n} {liquid} stains dried and left marks',\n 'fl.mix': '{who}: {from} mixed into {into}',\n\n 'act.anim_start': '{name}: animation \"{clip}\" ({seconds} s)',\n 'act.anim_event': '{name}: \"{clip}\" event {type}',\n 'act.anim_end': '{name}: animation \"{clip}\" finished',\n 'act.area_skip': 'Area item \"{item}\" is not loaded in this room: left out',\n 'act.module_loaded': 'Module \"{name}\" loaded: {items} item(s), {scenarios} scenario(s), contract checks: {result}',\n 'mod.all_ok': 'all passed',\n 'mod.some_failed': 'some FAILED',\n 'mod.destructible_ok': '{name}: destructible contract ok ({parts} parts, hit and state well-formed)',\n 'mod.destructible_fail': '{name}: destructible contract broken: {problems}',\n 'mod.animation_ok': '{name}: animation \"{clip}\" ok ({seconds} s)',\n 'mod.spec_ok': '{name}: spec ok ({parts} parts)',\n 'mod.spec_fail': '{name}: spec broken: {problems}',\n 'mod.spec_warn': '{name}: spec warning: {warning}',\n 'mod.animation_fail': '{name}: animation \"{clip}\" broken: {problems}',\n 'ui.animations': 'Animations',\n 'ui.animations_aim': 'Aim at an item or hold it to see its animations.',\n 'ui.animations_none': 'This item brings no animations.',\n 'mod.bench_ok': '{name}: bench ok ({controls} controls, {layers} layers, {metrics} metrics)',\n 'mod.bench_fail': '{name}: bench broken: {problems}',\n 'mod.metric_failed': '{name}: metric \"{metric}\" threw and shows n/a: {error}',\n 'mod.listener_failed': '{name}: a bench listener threw: {error}',\n 'ui.bench': 'Bench',\n 'ui.layers': 'Layers',\n 'ui.metrics': 'Counters',\n 'metric.fps': 'FPS',\n 'metric.frame_ms': 'ms/frame',\n 'metric.draw_calls': 'Draw calls',\n 'metric.triangles': 'Triangles',\n 'metric.objects': 'Objects',\n 'metric.fragments': 'Fragments',\n 'metric.particles': 'Particles',\n 'metric.decals': 'Decals',\n 'act.spawn': 'Spawned {name} at x {x} · z {z}',\n 'act.clear': 'Cleared the room',\n 'act.reset': 'Repaired every object',\n 'act.tool': 'Equipped {weapon}',\n 'act.shoot.hit': '{weapon}: shot, {energy} J, hit {where} at {dist} m',\n 'act.shoot.miss': '{weapon}: shot, {energy} J, hit nothing',\n 'act.shoot.pellets': '{weapon}: shot, {n} projectiles of up to {energy} J, {hits} hit {where} at {dist} m',\n 'act.melee.hit': '{weapon}: strike, {energy} J, hit {where} at {dist} m',\n 'act.melee.miss': '{weapon}: struck the air',\n 'act.strike': '{weapon}: {clip} begins, impact in {seconds} s',\n 'act.strike.leg': '{weapon}: {clip} with the {leg} leg begins, impact in {seconds} s',\n 'leg.left': 'left',\n 'leg.right': 'right',\n 'act.flame.hit': '{weapon}: flame at {temp} °C on {where}',\n 'act.flame.air': '{weapon}: flame, nothing in range',\n 'act.heat.hit': '{weapon}: heating {where} at {temp} °C',\n 'act.heat.air': '{weapon}: nothing in range',\n 'act.throw.grenade': '{weapon}: thrown, fuse {fuse} s',\n 'act.throw.molotov': '{weapon}: thrown, breaks on impact',\n 'act.launch': '{weapon}: launched, arms after {arm} m',\n 'act.place': '{weapon}: charge set down, waits for {triggers}',\n 'act.tripwire': '{weapon}: {who} crossed the trip wire',\n 'act.dud': '{weapon}: hit before arming ({distance} m), did not explode',\n 'act.backblast': '{weapon}: blast behind the tube, {radius} m, {n} objects in the cone, {player} on the shooter',\n 'act.blast_player': '{weapon}: you are in the {zone} zone, {distance} m away (stun {stun} s)',\n 'hud.no_charges': 'No charge set down waits for the remote detonator',\n 'blast.zone.lethal': 'lethal',\n 'blast.zone.injury': 'injury',\n 'act.explode': '{weapon}: exploded, {energy} J within {radius} m, {n} objects in range',\n 'act.molotov_fire': '{weapon}: fire on the ground, radius {radius} m for {seconds} s',\n 'act.tool.none': '{weapon}: nothing in reach',\n 'act.tool.nojoint': '{weapon}: no joint near {where}',\n 'act.tool.refused': '{weapon} cannot undo the {kind} of {obj}; it needs: {need}',\n 'act.extinguish.hit': '{weapon}: foam on {what}',\n 'act.extinguish.air': '{weapon}: foam, nothing in range',\n 'act.grab': 'Grabbed {name} ({kg} kg)',\n 'act.drop': 'Dropped {name}',\n 'act.throw': 'Threw {name} at {speed} m/s',\n 'act.landing': '{name} landed at {speed} m/s: {energy} J',\n 'act.bench_failed': '{name} failed: {error}',\n 'loading.working': 'Working…',\n 'loading.open_area': 'Opening {area}…',\n 'loading.spawn': 'Building {name}…',\n 'act.loosened': '{name} was heavy but free: the blast moved it',\n 'act.impact': '{name} hit {where} at {speed} m/s: {energy} J of blunt damage',\n 'act.use_item': '{name}: {use}',\n 'act.tap.on': 'Tap opened',\n 'act.tap.off': 'Tap closed',\n\n 'use.drink': 'drink',\n 'use.sip': 'sip',\n 'use.chug': 'chug',\n 'use.pour': 'pour',\n 'use.pour_out': 'pour out',\n 'use.open': 'open',\n 'use.close': 'close',\n\n 'hud.reloading': 'Reloading...',\n 'hud.empty': 'Empty',\n 'hud.no_fuel': 'Out of fuel',\n 'hud.fault': 'Jammed ({fault}): press X to clear',\n 'hud.safe': 'Safety on: press B',\n 'hud.clearing': 'Clearing the jam...',\n 'hud.safety_on': 'Safety on',\n 'hud.safety_off': 'Safety off',\n 'fault.misfire': 'misfire',\n 'fault.stovepipe': 'stovepipe',\n 'fault.double_feed': 'double feed',\n 'fault.failure_to_extract': 'failure to extract',\n 'hud.nothing_to_grab': 'Nothing to grab here',\n 'hud.cannot_grab': '{name} cannot be picked up',\n 'hud.too_heavy': '{name} is too heavy ({kg} kg)',\n 'hud.empty_container': '{name} is empty',\n 'hud.refused': 'Wrong tool for the {kind}',\n 'hud.drop': 'drop',\n 'hud.rotate': 'rotate',\n 'hud.throw': 'throw',\n 'hud.tilt': 'tilt (hold)',\n 'hud.equip': 'equip {weapon}',\n\n 'ui.help': 'Click: look · WASD: walk · Shift: run · C: crouch · Space: jump · 1-0 / wheel: tool · LMB: use · E: grab/drop · G or RMB: throw · R: reload · Q: fire mode · X: clear a jam · B: safety · Y: detonate charges set down · Tab: panels · Esc: free the mouse',\n 'ui.help.camera': 'V: 1st/3rd person (Shift+V: kick)',\n 'camera.first': '1st person',\n 'camera.third': '3rd person',\n 'act.camera': 'View: {mode}',\n 'ui.log': 'Behaviour log',\n 'ui.filter.action': 'actions',\n 'ui.filter.event': 'events',\n 'ui.filter.check': 'checks',\n 'ui.autoscroll': 'autoscroll',\n 'log.export_cancelled': 'export cancelled',\n 'ui.copy_json': 'Copy JSON',\n 'ui.download_ndjson': 'Download NDJSON',\n 'ui.download_txt': 'Download TXT',\n 'ui.clear_log': 'Clear',\n 'ui.catalog': 'Catalogue',\n 'ui.clear': 'Clear',\n 'ui.reset_all': 'Reset all',\n 'ui.slow': 'Slow motion 0.25×',\n 'ui.fast': 'Time ×10',\n 'ui.tap': 'Tap',\n 'ui.fullscreen': 'Full screen',\n 'ui.fullscreen.hint': 'Full screen opened from here keeps the whole keyboard in the game, Ctrl+W included (F11 does not)',\n 'ui.blast.shelter': 'Shelter',\n 'ui.blast.fragmentHits': 'Fragments',\n 'ui.blast.confinement': 'Confinement',\n 'ui.blast.shelter.hint': 'Blasts: walls and other parts between the blast and the target take their share',\n 'ui.blast.fragmentHits.hint': 'Blasts: the pieces of what breaks fly on and hit what is behind',\n 'ui.blast.confinement.hint': 'Blasts: pressure builds up in an enclosed room',\n 'metric.blast_shelter': 'Blast reaching (%)',\n 'metric.blast_confinement': 'Blast pressure (x)',\n 'metric.blast_fragments': 'Fragment hits',\n 'act.blast_report': 'Blast: {shelter}% reached the most sheltered target, pressure x{confinement}, {fragments} fragment hits, {n} targets',\n 'ui.quality': 'Quality',\n 'ui.quality.low': 'low',\n 'ui.quality.medium': 'medium',\n 'ui.quality.high': 'high',\n 'ui.equip': 'Equip as a tool',\n 'ui.search_items': 'Search items (all groups)',\n 'ui.search_tests': 'Search tests',\n 'ui.no_results': 'Nothing found',\n 'ui.objects': '{n} objects',\n 'ui.tests': 'Tests',\n 'ui.run_all': 'Run all',\n 'ui.running': 'Running...',\n 'ui.report': '{passed} passed, {failed} failed',\n 'ui.panel': 'Panels',\n 'ui.inspector': 'Inspector',\n 'ui.aim_at_something': 'Aim at an object',\n 'ins.material': 'Material',\n 'ins.status': 'Status',\n 'ins.burning': 'burning',\n 'ins.hp': 'Hit points',\n 'ins.temperature': 'Temperature',\n 'ins.char': 'Charred',\n 'ins.melt': 'Melted',\n 'ins.liters': 'Liquid',\n 'ins.damage': 'Marks',\n 'ins.damage_counts': '{dents}, {holes}, {cracks}',\n 'ins.mass': 'Mass',\n 'ins.load': 'Load',\n 'ins.stress': 'Stress',\n 'ins.joints': 'Joints',\n 'ins.open': 'open',\n\n 'sc.start': 'Scenario: {name}',\n 'sc.pass': 'Scenario passed: {name}',\n 'sc.fail': 'Scenario FAILED: {name}',\n 'sc.error': 'the scenario threw an error: {msg}',\n 'leg.still': 'leg_1 still attached',\n 'leg.gone': 'leg_1 came off',\n\n 'roof.standing': 'roof standing',\n 'roof.fell': 'roof fell',\n },\n}\n\nconst ptBR: RoomStrings = {\n items: {},\n groups: { furniture: 'Móveis', structure: 'Estrutura', vehicles: 'Veículos', plants: 'Plantas', items: 'Itens', containers: 'Recipientes' },\n text: {\n 'locale.decimal': ',',\n yes: 'sim',\n no: 'não',\n piece: 'peça',\n coords: 'x {x} · z {z}',\n 'count.piece.one': '1 peça',\n 'count.piece.other': '{n} peças',\n 'count.joint.one': '1 encaixe',\n 'count.joint.other': '{n} encaixes',\n 'count.dent.one': '1 amassado',\n 'count.dent.other': '{n} amassados',\n 'count.hole.one': '1 furo',\n 'count.hole.other': '{n} furos',\n 'count.crack.one': '1 trinca',\n 'count.crack.other': '{n} trincas',\n 'joint.generic': 'junta',\n 'lost.broken': 'quebrou',\n 'lost.melted': 'derreteu',\n 'lost.ashes': 'virou cinza',\n 'tool.none': 'só com a mão',\n 'arena.target_wall': 'Parede de alvo',\n 'arena.table': 'Mesa',\n 'arena.shelf': 'Estante',\n 'surface.floor': 'no chão',\n 'surface.ground': 'no chão',\n 'surface.table': 'na mesa',\n 'by.break': 'arrebentou',\n 'by.tool': 'desmontado com ferramenta',\n 'by.part_lost': 'a peça ao lado se perdeu',\n 'dmg.ballistic': 'de tiro',\n 'dmg.blunt': 'de impacto',\n 'dmg.slash': 'de corte',\n 'dmg.explosive': 'de explosão',\n 'dmg.fire': 'de fogo',\n 'dmg.heat': 'de calor',\n 'effect.caffeine': 'cafeína',\n 'effect.alcohol': 'álcool',\n 'effect.poison': 'veneno',\n 'effect.disgust': 'nojo',\n\n 'ev.dent': '{where}: amassado de {mm} mm, {hp}',\n 'ev.hole.through': '{where}: furo de {mm} mm atravessou, {hp}',\n 'ev.hole.stuck': '{where}: furo de {mm} mm não atravessou, {hp}',\n 'ev.dents': '{where}: {n} amassados, o mais fundo com {mm} mm, {hp}',\n 'ev.holes': '{where}: {n} furos de {mm} mm, {thr} atravessaram, {hp}',\n 'ev.leak.tail': ', vazando {liquid} a {rate} l/s',\n 'ev.leak.alone': '{where}: vazando {liquid} a {rate} l/s',\n 'ev.crack': '{where}: trincou, {rays} raios de até {cm} cm, {hp}',\n 'ev.ricochet': '{where}: a bala ricocheteou, sobraram {energy} J',\n 'ev.fracture.shatter': '{where}: estilhaçou em {n} cacos',\n 'ev.fracture.crumble': '{where}: esfarelou em {n} pedaços',\n 'ev.fracture.splinter': '{where}: lascou em {n} pedaços',\n 'ev.fracture.tear': '{where}: rasgou em {n} retalhos',\n 'ev.fracture.snap': '{where}: partiu em {n} pedaços',\n 'ev.fracture.none': '{where}: quebrou em {n} pedaços',\n 'ev.detach': '{obj}: {a} soltou de {b} ({by}); o objeto agora tem {pieces}',\n 'ev.detach.many.break': '{obj}: {joints} arrebentaram; o objeto agora tem {pieces}',\n 'ev.detach.many.tool': '{obj}: {joints} soltos com ferramenta; o objeto agora tem {pieces}',\n 'ev.lost.tail': ' e se soltou de {joints}; o objeto agora tem {pieces}',\n 'ev.lost.alone': '{where}: {verb} e se soltou de {joints}; o objeto agora tem {pieces}',\n 'ev.cracks': '{where}: rachando sob o peso, {n} trincas até agora, a maior com {cm} cm, {hp}',\n 'ev.disassemble': '{obj}: soltando {kind} entre {a} e {b} com {tool}: {pct}%',\n 'ev.ignite': '{where}: pegou fogo a {temp} °C',\n 'ev.ignite.many': '{obj}: {n} peças pegaram fogo a {temp} °C ({parts})',\n 'ev.extinguish': '{where}: fogo apagado',\n 'ev.extinguish.many': '{obj}: fogo apagado em {n} peças ({parts})',\n 'ev.burnout': '{where}: virou cinza',\n 'ev.melt': '{where}: derretendo, {pct}% já derreteu',\n 'ev.drip': '{where}: pingando material derretido',\n 'ev.explode': '{where}: explodiu, {energy} J em {radius} m',\n 'ev.destroyed': '{obj}: destruído',\n 'ev.damage': '{where}: dano {type} de {amount}, {hp}',\n 'ev.damage.overload': '{where}: esmagado pelo peso que sustenta, perdeu {amount} hp até agora, {hp}',\n 'ev.stress': '{where}: sobrecarregado a {stress}% da capacidade, sustentando {load} kg',\n 'ev.collapse': '{obj}: desabou, caíram {pieces} ({mass} kg): {parts}',\n 'ev.stain_ignite': 'A mancha de {liquid} em x {x} · z {z} pegou fogo e vai queimar por uns {seconds} s',\n 'ev.stain_burned': 'A mancha em chamas se consumiu',\n 'ev.fire_dries': 'O fogo secou as manchas molhadas por perto',\n\n 'fl.fill': '{who}: encheu de {liquid} (+{liters} l)',\n 'fl.pour': '{who}: despejando {liquid} a {rate} l/s',\n 'fl.spill': '{who}: derramou {liquid} pela borda a {rate} l/s',\n 'fl.leak': '{who}: vazando {liquid} a {rate} l/s',\n 'fl.drink': '{who}: bebeu {liters} l, sede +{thirst}',\n 'fl.burn': 'quente demais: queimou a boca',\n 'fl.empty': '{who}: vazio',\n 'fl.splash': 'Respingo de {liquid}',\n 'fl.stain': 'Mancha de {liquid} {surface} em {where}',\n 'fl.stains': '{n} manchas de {liquid} {surface}, a última em {where}',\n 'fl.dried': 'Uma mancha secou',\n 'fl.dried.mark': 'Uma mancha secou e deixou marca',\n 'fl.dried.known': 'A mancha de {liquid} {surface} em {where} secou',\n 'fl.dried.known.mark': 'A mancha de {liquid} {surface} em {where} secou e deixou marca',\n 'fl.dried.many': '{n} manchas de {liquid} secaram',\n 'fl.dried.many.mark': '{n} manchas de {liquid} secaram e deixaram marca',\n 'fl.mix': '{who}: {from} misturou em {into}',\n\n 'act.anim_start': '{name}: animação \"{clip}\" ({seconds} s)',\n 'act.anim_event': '{name}: \"{clip}\" evento {type}',\n 'act.anim_end': '{name}: animação \"{clip}\" terminou',\n 'act.area_skip': 'Item \"{item}\" da área não está carregado nesta sala: ficou de fora',\n 'act.module_loaded': 'Módulo \"{name}\" carregado: {items} item(ns), {scenarios} cenário(s), verificações do contrato: {result}',\n 'mod.all_ok': 'todas passaram',\n 'mod.some_failed': 'algumas FALHARAM',\n 'mod.destructible_ok': '{name}: contrato de destruição ok ({parts} peças, golpe e estado bem formados)',\n 'mod.destructible_fail': '{name}: contrato de destruição quebrado: {problems}',\n 'mod.animation_ok': '{name}: animação \"{clip}\" ok ({seconds} s)',\n 'mod.spec_ok': '{name}: spec ok ({parts} peças)',\n 'mod.spec_fail': '{name}: spec quebrada: {problems}',\n 'mod.spec_warn': '{name}: aviso na spec: {warning}',\n 'mod.animation_fail': '{name}: animação \"{clip}\" quebrada: {problems}',\n 'ui.animations': 'Animações',\n 'ui.animations_aim': 'Mire num item ou segure-o para ver as animações.',\n 'ui.animations_none': 'Este item não traz animações.',\n 'mod.bench_ok': '{name}: bancada ok ({controls} controles, {layers} camadas, {metrics} contadores)',\n 'mod.bench_fail': '{name}: bancada quebrada: {problems}',\n 'mod.metric_failed': '{name}: o contador \"{metric}\" lançou erro e mostra n/a: {error}',\n 'mod.listener_failed': '{name}: um ouvinte da bancada lançou erro: {error}',\n 'ui.bench': 'Bancada',\n 'ui.layers': 'Camadas',\n 'ui.metrics': 'Contadores',\n 'metric.fps': 'FPS',\n 'metric.frame_ms': 'ms/quadro',\n 'metric.draw_calls': 'Chamadas de desenho',\n 'metric.triangles': 'Triângulos',\n 'metric.objects': 'Objetos',\n 'metric.fragments': 'Fragmentos',\n 'metric.particles': 'Partículas',\n 'metric.decals': 'Decalques',\n 'act.spawn': 'Criou {name} em x {x} · z {z}',\n 'act.clear': 'Limpou a sala',\n 'act.reset': 'Consertou todos os objetos',\n 'act.tool': 'Equipou {weapon}',\n 'act.shoot.hit': '{weapon}: disparo, {energy} J, acertou {where} a {dist} m',\n 'act.shoot.miss': '{weapon}: disparo, {energy} J, não acertou nada',\n 'act.shoot.pellets': '{weapon}: disparo, {n} projéteis de até {energy} J, {hits} acertaram {where} a {dist} m',\n 'act.melee.hit': '{weapon}: golpe, {energy} J, acertou {where} a {dist} m',\n 'act.melee.miss': '{weapon}: golpe no ar',\n 'act.strike': '{weapon}: {clip} começa, impacto em {seconds} s',\n 'act.strike.leg': '{weapon}: {clip} com a perna {leg} começa, impacto em {seconds} s',\n 'leg.left': 'esquerda',\n 'leg.right': 'direita',\n 'act.flame.hit': '{weapon}: chama a {temp} °C em {where}',\n 'act.flame.air': '{weapon}: chama, nada ao alcance',\n 'act.heat.hit': '{weapon}: esquentando {where} a {temp} °C',\n 'act.heat.air': '{weapon}: nada ao alcance',\n 'act.throw.grenade': '{weapon}: arremessada, pavio de {fuse} s',\n 'act.throw.molotov': '{weapon}: arremessado, quebra no impacto',\n 'act.launch': '{weapon}: disparado, arma depois de {arm} m',\n 'act.place': '{weapon}: carga posta, espera {triggers}',\n 'act.tripwire': '{weapon}: {who} cruzou o fio',\n 'act.dud': '{weapon}: bateu antes de armar ({distance} m), não explodiu',\n 'act.backblast': '{weapon}: sopro atrás do tubo, {radius} m, {n} objetos no cone, {player} no atirador',\n 'act.blast_player': '{weapon}: você está na zona {zone}, a {distance} m (atordoado {stun} s)',\n 'hud.no_charges': 'Nenhuma carga posta espera o detonador',\n 'blast.zone.lethal': 'letal',\n 'blast.zone.injury': 'de ferimento',\n 'act.explode': '{weapon}: explodiu, {energy} J em {radius} m, {n} objetos ao alcance',\n 'act.molotov_fire': '{weapon}: fogo no chão, raio de {radius} m por {seconds} s',\n 'act.tool.none': '{weapon}: nada ao alcance',\n 'act.tool.nojoint': '{weapon}: nenhuma junta perto de {where}',\n 'act.tool.refused': '{weapon} não solta {kind} de {obj}; precisa de: {need}',\n 'act.extinguish.hit': '{weapon}: espuma em {what}',\n 'act.extinguish.air': '{weapon}: espuma, nada ao alcance',\n 'act.grab': 'Pegou {name} ({kg} kg)',\n 'act.drop': 'Soltou {name}',\n 'act.throw': 'Arremessou {name} a {speed} m/s',\n 'act.landing': '{name} caiu a {speed} m/s: {energy} J',\n 'act.bench_failed': '{name} falhou: {error}',\n 'loading.working': 'Trabalhando…',\n 'loading.open_area': 'Abrindo {area}…',\n 'loading.spawn': 'Montando {name}…',\n 'act.loosened': '{name} é pesado mas estava solto: a explosão o moveu',\n 'act.impact': '{name} bateu em {where} a {speed} m/s: {energy} J de dano de impacto',\n 'act.use_item': '{name}: {use}',\n 'act.tap.on': 'Abriu a torneira',\n 'act.tap.off': 'Fechou a torneira',\n\n 'use.drink': 'beber',\n 'use.sip': 'golinho',\n 'use.chug': 'virar',\n 'use.pour': 'despejar',\n 'use.pour_out': 'esvaziar',\n 'use.open': 'abrir',\n 'use.close': 'fechar',\n\n 'hud.reloading': 'Recarregando...',\n 'hud.empty': 'Sem munição',\n 'hud.no_fuel': 'Sem combustível',\n 'hud.fault': 'Travou ({fault}): aperte X para destravar',\n 'hud.safe': 'Trava ligada: aperte B',\n 'hud.clearing': 'Destravando...',\n 'hud.safety_on': 'Trava ligada',\n 'hud.safety_off': 'Trava desligada',\n 'fault.misfire': 'nega',\n 'fault.stovepipe': 'chaminé',\n 'fault.double_feed': 'dupla alimentação',\n 'fault.failure_to_extract': 'falha de extração',\n 'hud.nothing_to_grab': 'Nada para pegar aqui',\n 'hud.cannot_grab': '{name} não dá para pegar',\n 'hud.too_heavy': '{name} é pesado demais ({kg} kg)',\n 'hud.empty_container': '{name} está vazio',\n 'hud.refused': 'Ferramenta errada para {kind}',\n 'hud.drop': 'soltar',\n 'hud.rotate': 'girar',\n 'hud.throw': 'arremessar',\n 'hud.tilt': 'inclinar (segurar)',\n 'hud.equip': 'equipar {weapon}',\n\n 'ui.help': 'Clique: olhar · WASD: andar · Shift: correr · C: agachar · Espaço: pular · 1-0 / roda: ferramenta · botão esquerdo: usar · E: pegar/soltar · G ou botão direito: arremessar · R: recarregar · Q: modo de tiro · X: destravar · B: trava · Y: detonar cargas postas · Tab: painéis · Esc: soltar o mouse',\n 'ui.help.camera': 'V: 1ª/3ª pessoa (Shift+V: chute)',\n 'camera.first': '1ª pessoa',\n 'camera.third': '3ª pessoa',\n 'act.camera': 'Câmera: {mode}',\n 'ui.log': 'Registro de comportamento',\n 'ui.filter.action': 'ações',\n 'ui.filter.event': 'eventos',\n 'ui.filter.check': 'testes',\n 'ui.autoscroll': 'rolar sozinho',\n 'log.export_cancelled': 'exportação cancelada',\n 'ui.copy_json': 'Copiar JSON',\n 'ui.download_ndjson': 'Baixar NDJSON',\n 'ui.download_txt': 'Baixar TXT',\n 'ui.clear_log': 'Limpar',\n 'ui.catalog': 'Catálogo',\n 'ui.clear': 'Limpar',\n 'ui.reset_all': 'Consertar tudo',\n 'ui.slow': 'Câmera lenta 0,25×',\n 'ui.fast': 'Tempo ×10',\n 'ui.tap': 'Torneira',\n 'ui.fullscreen': 'Tela cheia',\n 'ui.fullscreen.hint': 'A tela cheia aberta por aqui segura o teclado todo no jogo, inclusive Ctrl+W (o F11 não)',\n 'ui.blast.shelter': 'Abrigo',\n 'ui.blast.fragmentHits': 'Estilhaços',\n 'ui.blast.confinement': 'Confinamento',\n 'ui.blast.shelter.hint': 'Explosões: paredes e outras partes entre a explosão e o alvo ficam com a sua parte',\n 'ui.blast.fragmentHits.hint': 'Explosões: os pedaços do que quebra voam e acertam o que está atrás',\n 'ui.blast.confinement.hint': 'Explosões: a pressão sobe num ambiente fechado',\n 'metric.blast_shelter': 'Explosão que chegou (%)',\n 'metric.blast_confinement': 'Pressão da explosão (x)',\n 'metric.blast_fragments': 'Estilhaços que acertaram',\n 'act.blast_report': 'Explosão: {shelter}% chegou ao alvo mais abrigado, pressão x{confinement}, {fragments} estilhaços acertaram, {n} alvos',\n 'ui.quality': 'Qualidade',\n 'ui.quality.low': 'baixa',\n 'ui.quality.medium': 'média',\n 'ui.quality.high': 'alta',\n 'ui.equip': 'Equipar como ferramenta',\n 'ui.search_items': 'Buscar item (todas as abas)',\n 'ui.search_tests': 'Buscar teste',\n 'ui.no_results': 'Nada encontrado',\n 'ui.objects': '{n} objetos',\n 'ui.tests': 'Testes',\n 'ui.run_all': 'Rodar todos',\n 'ui.running': 'Rodando...',\n 'ui.report': '{passed} passaram, {failed} falharam',\n 'ui.panel': 'Painéis',\n 'ui.inspector': 'Inspetor',\n 'ui.aim_at_something': 'Mire em um objeto',\n 'ins.material': 'Material',\n 'ins.status': 'Estado',\n 'ins.burning': 'em chamas',\n 'ins.hp': 'Pontos de vida',\n 'ins.temperature': 'Temperatura',\n 'ins.char': 'Carbonizado',\n 'ins.melt': 'Derretido',\n 'ins.liters': 'Líquido',\n 'ins.damage': 'Marcas',\n 'ins.damage_counts': '{dents}, {holes}, {cracks}',\n 'ins.mass': 'Massa',\n 'ins.load': 'Carga',\n 'ins.stress': 'Tensão',\n 'ins.joints': 'Juntas',\n 'ins.open': 'aberta',\n\n 'sc.start': 'Cenário: {name}',\n 'sc.pass': 'Cenário passou: {name}',\n 'sc.fail': 'Cenário FALHOU: {name}',\n 'sc.error': 'o cenário lançou um erro: {msg}',\n 'leg.still': 'leg_1 continua presa',\n 'leg.gone': 'leg_1 soltou',\n\n 'roof.standing': 'laje de pé',\n 'roof.fell': 'laje caiu',\n },\n}\n\nexport const locales: Record<TestRoomLocale, RoomStrings> = { en, 'pt-BR': ptBR }\n\nexport const resolveStrings = (locale: string | undefined): RoomStrings => locales[(locale as TestRoomLocale) ?? 'en'] ?? locales.en\n","import type { BenchSheet, ControlValue } from '@adatechnology/game-contracts'\nimport type { BenchControl, BenchLayer } from './types'\n\n/** What the bench panel shows: the active module's bench, or only the room counters. */\nexport interface BenchView {\n readonly title: string\n readonly controls: readonly BenchControl[]\n readonly layers: readonly BenchLayer[]\n readonly sheet?: BenchSheet | null\n}\n\nexport interface MetricRow {\n readonly id: string\n readonly name: string\n readonly text: string\n /** The number behind `text`, when the metric reads one (a sheet's playhead follows it). */\n readonly value?: number\n /** Value over the budget, when the metric has one. */\n readonly ratio?: number\n}\n\nexport interface BenchPanelOptions {\n t: (key: string, vars?: Record<string, string | number>) => string\n num: (n: number, digits?: number) => string\n onControl: (id: string, value: ControlValue) => void\n onLayer: (id: string, on: boolean) => void\n onAction: (id: string) => void\n}\n\nexport interface BenchPanel {\n readonly element: HTMLElement\n show(view: BenchView | null): void\n metrics(rows: { room: readonly MetricRow[]; module: readonly MetricRow[] }): void\n readonly visible: boolean\n}\n\nconst SEGMENTED_MAX = 4\n\nconst mk = <K extends keyof HTMLElementTagNameMap>(tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] => {\n const e = document.createElement(tag)\n if (cls) e.className = cls\n if (text !== undefined) e.textContent = text\n return e\n}\n\n// the shape of the panel without the values: when it is unchanged the values are updated in place (a range being dragged keeps its focus)\nconst shapeOf = (view: BenchView): string =>\n JSON.stringify([view.title, view.controls.map((c) => ({ ...c, value: undefined })), view.layers.map((l) => [l.id, l.name]), view.sheet ?? null])\n\nexport function createBenchPanel(o: BenchPanelOptions): BenchPanel {\n const { t } = o\n const element = mk('div', 'tr-panel tr-bench')\n element.style.display = 'none'\n element.addEventListener('keydown', (e) => e.stopPropagation())\n const roomLine = mk('div', 'sub tr-bench-room')\n const body = mk('div')\n const metricTitle = mk('div', 'sub', t('ui.metrics'))\n metricTitle.style.display = 'none'\n const metricList = mk('dl', 'tr-metrics')\n element.append(mk('h3', undefined, t('ui.bench')), roomLine, body, metricTitle, metricList)\n\n let shape = ''\n let hasRoom = false\n let hasBench = false\n const refreshers: Array<(view: BenchView) => void> = []\n const metricNodes = new Map<string, { text: HTMLElement; bar: HTMLElement | null }>()\n let metricKey = ''\n\n const syncDisplay = (): void => {\n element.style.display = hasRoom || hasBench ? '' : 'none'\n }\n\n const numberControl = (control: Extract<BenchControl, { kind: 'number' }>): HTMLElement => {\n const wrap = mk('label', 'tr-ctl')\n const input = mk('input')\n input.type = 'range'\n input.min = String(control.min)\n input.max = String(control.max)\n input.step = control.step ? String(control.step) : 'any'\n input.disabled = control.disabled\n const reading = mk('output')\n input.oninput = () => o.onControl(control.id, Number(input.value))\n wrap.append(mk('span', undefined, control.name), input, reading)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n if (typeof value !== 'number') return\n if (Number(input.value) !== value) input.value = String(value)\n reading.textContent = `${o.num(value, control.step && control.step >= 1 ? 0 : 2)}${control.unit ? ` ${control.unit}` : ''}`\n })\n return wrap\n }\n\n const booleanControl = (control: BenchControl): HTMLElement => {\n const wrap = mk('label', 'tr-ctl')\n const box = mk('input')\n box.type = 'checkbox'\n box.disabled = control.disabled\n box.onchange = () => o.onControl(control.id, box.checked)\n wrap.append(box, document.createTextNode(` ${control.name}`))\n refreshers.push((view) => {\n box.checked = view.controls.find((c) => c.id === control.id)?.value === true\n })\n return wrap\n }\n\n const choiceControl = (control: Extract<BenchControl, { kind: 'choice' }>): HTMLElement => {\n const wrap = mk('div', 'tr-ctl')\n wrap.appendChild(mk('span', undefined, control.name))\n const grouped = control.options.some((option) => option.group !== undefined)\n if (control.options.length <= SEGMENTED_MAX && !grouped) {\n const group = mk('div', 'tr-seg')\n group.setAttribute('role', 'group')\n const buttons = control.options.map((option) => {\n const b = mk('button', 'tr-btn', option.name)\n b.type = 'button'\n b.disabled = control.disabled\n b.onclick = () => o.onControl(control.id, option.id)\n group.appendChild(b)\n return { b, id: option.id }\n })\n wrap.appendChild(group)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n for (const { b, id } of buttons) {\n b.setAttribute('aria-pressed', String(id === value))\n b.classList.toggle('on', id === value)\n }\n })\n return wrap\n }\n const select = mk('select')\n select.disabled = control.disabled\n let heading: string | undefined\n let section: HTMLElement = select\n for (const option of control.options) {\n if (option.group !== heading) {\n heading = option.group\n section = select\n if (heading !== undefined) {\n const optgroup = mk('optgroup')\n optgroup.label = heading\n select.appendChild(optgroup)\n section = optgroup\n }\n }\n const op = mk('option', undefined, option.name)\n op.value = option.id\n section.appendChild(op)\n }\n select.onchange = () => o.onControl(control.id, select.value)\n wrap.appendChild(select)\n refreshers.push((view) => {\n const value = view.controls.find((c) => c.id === control.id)?.value\n if (typeof value === 'string') select.value = value\n })\n return wrap\n }\n\n const actionControl = (control: BenchControl): HTMLElement => {\n const b = mk('button', 'tr-btn', control.name)\n b.type = 'button'\n b.disabled = control.disabled\n b.onclick = () => o.onAction(control.id)\n return b\n }\n\n const controlElement = (control: BenchControl): HTMLElement => {\n const el = control.kind === 'number' ? numberControl(control) : control.kind === 'boolean' ? booleanControl(control) : control.kind === 'choice' ? choiceControl(control) : actionControl(control)\n if (control.hint) el.title = control.hint\n return el\n }\n\n const layerList = (layers: readonly BenchLayer[]): HTMLElement => {\n const wrap = mk('div', 'tr-layers')\n wrap.appendChild(mk('div', 'sub', t('ui.layers')))\n for (const layer of layers) {\n const label = mk('label', 'tr-ctl')\n const box = mk('input')\n box.type = 'checkbox'\n box.onchange = () => o.onLayer(layer.id, box.checked)\n label.append(box, document.createTextNode(` ${layer.name}`))\n wrap.appendChild(label)\n refreshers.push((view) => {\n box.checked = view.layers.find((l) => l.id === layer.id)?.on === true\n })\n }\n return wrap\n }\n\n let playhead: { node: HTMLElement; metric: string; end: number } | null = null\n\n const sheetCard = (sheet: BenchSheet): HTMLElement => {\n const card = mk('div', 'tr-sheet')\n if (sheet.kicker) card.appendChild(mk('div', 'sub', sheet.kicker))\n card.appendChild(mk('h4', undefined, sheet.title))\n if (sheet.body) card.appendChild(mk('p', undefined, sheet.body))\n if (sheet.facts?.length) {\n const facts = mk('dl', 'tr-facts')\n for (const fact of sheet.facts) facts.append(mk('dt', undefined, fact.label), mk('dd', undefined, fact.value))\n card.appendChild(facts)\n }\n if (sheet.steps?.length) {\n const steps = mk('ol', 'tr-steps')\n for (const step of sheet.steps) {\n const li = mk('li')\n li.append(mk('b', undefined, step.at), document.createTextNode(` ${step.text}`))\n steps.appendChild(li)\n }\n card.appendChild(steps)\n }\n if (sheet.swatches?.length) {\n const row = mk('div', 'tr-swatches')\n for (const swatch of sheet.swatches) {\n const chip = mk('span', 'tr-swatch')\n const dot = mk('i')\n dot.style.background = swatch.color\n chip.append(dot, document.createTextNode(swatch.name))\n row.appendChild(chip)\n }\n card.appendChild(row)\n }\n if (sheet.timeline) {\n const { segments, ticks, metric } = sheet.timeline\n const end = Math.max(0.001, ...segments.map((segment) => segment.end), ...ticks)\n const strip = mk('div', 'tr-timeline')\n for (const segment of segments) {\n const bar = mk('div', 'tr-segment', segment.name)\n bar.style.left = `${(segment.start / end) * 100}%`\n bar.style.width = `${((segment.end - segment.start) / end) * 100}%`\n bar.style.background = segment.color\n strip.appendChild(bar)\n }\n for (const tick of ticks) {\n const mark = mk('u', 'tr-tick')\n mark.style.left = `${(tick / end) * 100}%`\n strip.appendChild(mark)\n }\n const head = mk('s', 'tr-playhead')\n strip.appendChild(head)\n playhead = { node: head, metric, end }\n card.appendChild(strip)\n }\n if (sheet.note) card.appendChild(mk('p', 'sub', sheet.note))\n return card\n }\n\n const rebuild = (view: BenchView): void => {\n playhead = null\n body.textContent = ''\n refreshers.length = 0\n body.appendChild(mk('div', 'sub', view.title))\n const list = mk('div', 'tr-ctls')\n for (const control of view.controls) if (!control.hidden) list.appendChild(controlElement(control))\n body.appendChild(list)\n if (view.layers.length) body.appendChild(layerList(view.layers))\n if (view.sheet) body.appendChild(sheetCard(view.sheet))\n }\n\n const renderMetrics = (rows: readonly MetricRow[]): void => {\n metricList.textContent = ''\n metricNodes.clear()\n metricTitle.style.display = rows.length ? '' : 'none'\n for (const row of rows) {\n const dd = mk('dd')\n const text = mk('span', undefined, row.text)\n dd.appendChild(text)\n let bar: HTMLElement | null = null\n if (row.ratio !== undefined) {\n bar = mk('div', 'tr-bar')\n bar.appendChild(mk('i'))\n dd.appendChild(bar)\n }\n metricList.append(mk('dt', undefined, row.name), dd)\n metricNodes.set(row.id, { text, bar })\n }\n }\n\n const fillBar = (bar: HTMLElement, ratio: number): void => {\n bar.className = `tr-bar${ratio > 1 ? ' bad' : ratio >= 0.8 ? ' warn' : ''}`\n const fill = bar.firstElementChild as HTMLElement\n fill.style.width = `${Math.round(Math.max(0, Math.min(1, ratio)) * 100)}%`\n }\n\n return {\n element,\n show(view) {\n hasBench = view !== null\n syncDisplay()\n if (!view) {\n playhead = null\n shape = ''\n body.textContent = ''\n refreshers.length = 0\n renderMetrics([])\n metricKey = ''\n return\n }\n const next = shapeOf(view)\n if (next !== shape) {\n shape = next\n rebuild(view)\n }\n for (const refresh of refreshers) refresh(view)\n },\n metrics(rows) {\n hasRoom = rows.room.length > 0\n syncDisplay()\n roomLine.textContent = rows.room.map((row) => `${row.name} ${row.text}`).join(' · ')\n const key = rows.module.map((row) => `${row.id}:${row.ratio !== undefined}`).join('|')\n if (key !== metricKey) {\n metricKey = key\n renderMetrics(rows.module)\n }\n for (const row of rows.module) {\n const node = metricNodes.get(row.id)\n if (!node) continue\n node.text.textContent = row.text\n if (node.bar && row.ratio !== undefined) fillBar(node.bar, row.ratio)\n }\n if (playhead) {\n const at = rows.module.find((row) => row.id === playhead?.metric)?.value\n playhead.node.style.left = `${Math.max(0, Math.min(1, (at ?? 0) / playhead.end)) * 100}%`\n }\n },\n get visible() {\n if (element.style.display === 'none') return false\n const parent = element.parentElement\n return !parent || getComputedStyle(parent).display !== 'none'\n },\n }\n}\n","import type { ControlValue } from '@adatechnology/game-contracts'\nimport { createBenchPanel } from './bench-panel'\nimport type { BenchView, MetricRow } from './bench-panel'\nimport type { WritableLog } from './log'\nimport type { RoomStrings } from './locale'\nimport type { AnimationInfo, LogEntry, ScenarioReport, TestRoomItem, TestRoomScenario } from './types'\n\nexport interface InspectInfo {\n object: string\n objectId: string\n part: string\n material: string\n status: string\n hp: number\n maxHp: number\n temperature: number\n burning: boolean\n char: number\n melt: number\n liters?: number\n dents: number\n holes: number\n cracks: number\n mass: number\n /** Structural load in kg and stress (load / capacity) when the core reports them. */\n load?: number\n stress?: number\n joints: Array<{ id: string; kind: string; tools: string[]; open: boolean; progress: number }>\n note?: string\n /** Thumbnail of the aimed item (`TestRoomItem.thumbnail`). */\n thumbnail?: string\n /** Author and licence of the thumbnail (`TestRoomItem.thumbnailCredit`). */\n thumbnailCredit?: string\n distance: number\n}\n\nexport interface HudState {\n toolName: string\n toolId: string\n ammo: string\n slots: string[]\n slot: number\n page: number\n pages: number\n status: string\n progress: { label: string; value: number } | null\n held: { name: string; uses: Array<{ key: string; label: string }>; weapon?: string; using: string } | null\n inspect: InspectInfo | null\n /** Animations of the aimed or held item. */\n animations: AnimationInfo | null\n locked: boolean\n timeScale: number\n fast: boolean\n tap: boolean\n /** The room's blast options that are on. */\n blast: { shelter: boolean; fragmentHits: boolean; confinement: boolean }\n quality: string\n objects: number\n /** The view when the room has a body (`null`: no body, no shortcut). */\n camera: 'first' | 'third' | null\n}\n\nexport interface UiOptions {\n container: HTMLElement\n strings: RoomStrings\n t: (key: string, vars?: Record<string, string | number>) => string\n log: WritableLog\n groups: () => Map<string, TestRoomItem[]>\n loadout: () => Array<{ id: string; name: string }>\n onSpawn: (itemId: string) => void\n onEquip: (itemId: string) => void\n onClear: () => void\n onResetAll: () => void\n onSlow: (on: boolean) => void\n onFast: (on: boolean) => void\n onQuality: (q: 'low' | 'medium' | 'high') => void\n quality: 'low' | 'medium' | 'high'\n scenarios: () => TestRoomScenario[]\n onRun: (s: TestRoomScenario) => Promise<ScenarioReport | void>\n onRunAll: () => Promise<ScenarioReport | void>\n onTool: (index: number) => void\n onTap: () => void\n onBlast: (key: 'shelter' | 'fragmentHits' | 'confinement') => void\n onPlay: (objectId: string, clipId: string) => void\n onResize: () => void\n onControl: (id: string, value: ControlValue) => void\n onLayer: (id: string, on: boolean) => void\n onAction: (id: string) => void\n}\n\nexport interface RoomUi {\n hud(state: HudState): void\n toast(text: string): void\n /** Re-read the catalogue and the scenarios (after `loadModule`). */\n refresh(): void\n /** Open the catalogue on a group tab (its translated name), clearing the search. */\n showGroup(group: string): void\n togglePanels(): void\n /** The active module's bench (null: none). */\n bench(view: BenchView | null): void\n /** Room counters and the active module's metrics, text only. */\n metrics(rows: { room: readonly MetricRow[]; module: readonly MetricRow[] }): void\n /** The bench panel has something to show and is on screen (the room samples its counters only then). */\n readonly benchVisible: boolean\n dispose(): void\n}\n\nconst CSS = `\n.tr-root{position:absolute;inset:0;pointer-events:none;font:12px/1.35 system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;color:#e8eaee;overflow:hidden}\n.tr-root *{box-sizing:border-box}\n.tr-root button,.tr-root select,.tr-root label,.tr-root input{pointer-events:auto}\n.tr-search{width:100%;margin:0 0 6px;padding:5px 8px;border-radius:5px;border:1px solid #3a404c;background:#0f1116;color:#e8eaee;font:inherit}\n.tr-search::placeholder{color:#7d8594}\n.tr-item small{color:#7d8594;margin-left:4px}\n.tr-thumb{display:block;width:100%;height:26px;background:currentColor;-webkit-mask:var(--tr-thumb) center/contain no-repeat;mask:var(--tr-thumb) center/contain no-repeat}\n.tr-item{min-width:0}\n.tr-item .tr-btn.has-thumb{display:flex;flex-direction:column;gap:3px;min-width:0}.tr-item .tr-btn.has-thumb .tr-name{overflow:hidden;text-overflow:ellipsis}\n.tr-insp .tr-thumb{width:140px;height:28px;margin-bottom:3px}\n.tr-empty{color:#9aa3b2;padding:4px 2px;grid-column:1/-1}\n.tr-cross{position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-9px 0 0 -9px}\n.tr-cross:before,.tr-cross:after{content:\"\";position:absolute;background:#fff;opacity:.85;box-shadow:0 0 2px #000}\n.tr-cross:before{left:8px;top:0;width:2px;height:18px}.tr-cross:after{top:8px;left:0;height:2px;width:18px}\n.tr-cross i{position:absolute;left:6px;top:6px;width:6px;height:6px;background:#0b0c0e;border-radius:50%;z-index:1}\n.tr-top{position:absolute;top:8px;left:50%;transform:translateX(-50%);text-align:center;max-width:46vw}\n.tr-tool{display:inline-block;background:rgba(10,12,16,.72);padding:4px 12px;border-radius:6px;font-size:14px;font-weight:600}\n.tr-tool small{font-weight:400;opacity:.8;margin-left:8px}\n.tr-status{margin-top:4px;min-height:16px;color:#ffd23f;text-shadow:0 1px 2px #000}\n.tr-prog{margin:4px auto 0;width:260px;background:rgba(10,12,16,.72);border-radius:6px;padding:4px 8px;display:none}\n.tr-prog b{display:block;font-weight:500;margin-bottom:3px}\n.tr-sheet{margin-top:8px;padding:8px;border:1px solid #2a2e36;border-radius:6px;font-size:12px;line-height:1.4}\n.tr-sheet h4{margin:2px 0 4px;font-size:13px}.tr-sheet p{margin:4px 0}\n.tr-facts{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;margin:4px 0}.tr-facts dt{opacity:.7}.tr-facts dd{margin:0}\n.tr-steps{margin:4px 0;padding-left:16px}.tr-swatches{display:flex;flex-wrap:wrap;gap:6px}.tr-swatch i{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:4px}\n.tr-timeline{position:relative;height:22px;margin:8px 0;background:#1b1e24;border-radius:4px;overflow:hidden}\n.tr-segment{position:absolute;top:0;height:100%;font-size:10px;overflow:hidden;white-space:nowrap;opacity:.85;padding:0 3px;box-sizing:border-box;color:#000}\n.tr-tick{position:absolute;top:0;bottom:0;width:1px;background:#fff6;text-decoration:none}.tr-playhead{position:absolute;top:0;bottom:0;width:2px;background:#fff;text-decoration:none}\n.tr-bar{height:7px;background:#2a2e36;border-radius:4px;overflow:hidden}\n.tr-bar i{display:block;height:100%;background:#4fc3f7;width:0}\n.tr-bar.hp i{background:#66bb6a}.tr-bar.warn i{background:#ffb300}.tr-bar.bad i{background:#ef5350}\n.tr-bottom{position:absolute;bottom:8px;left:50%;transform:translateX(-50%);text-align:center;max-width:56vw}\n.tr-held{margin-bottom:6px;background:rgba(10,12,16,.72);padding:4px 10px;border-radius:6px;display:none}\n.tr-held kbd,.tr-help kbd{background:#2a2e36;border:1px solid #4a505c;border-radius:3px;padding:0 4px;font:inherit;font-weight:700}\n.tr-hotbar{display:inline-flex;gap:3px;flex-wrap:wrap;justify-content:center}\n.tr-slot{pointer-events:auto;min-width:64px;max-width:92px;padding:3px 5px;background:rgba(10,12,16,.68);border:1px solid #3a404c;border-radius:5px;color:#cfd3da;cursor:pointer;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-slot b{color:#ffd23f;margin-right:3px}\n.tr-slot.on{border-color:#ffd23f;color:#fff;background:rgba(60,50,10,.8)}\n.tr-help{position:absolute;left:8px;bottom:8px;max-width:360px;opacity:.75;font-size:11px;background:rgba(10,12,16,.55);padding:4px 8px;border-radius:6px}\n.tr-left{position:absolute;top:8px;left:8px;bottom:70px;width:min(400px,36vw);display:flex;flex-direction:column;gap:8px}\n.tr-right{position:absolute;top:8px;right:8px;bottom:8px;width:min(310px,34vw);display:flex;flex-direction:column;gap:8px}\n.tr-panel{background:rgba(12,14,19,.82);border:1px solid #2c313b;border-radius:8px;padding:8px;pointer-events:auto;overflow:auto}\n.tr-panel h3{margin:0 0 6px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#9aa3b2;font-weight:600}\n.tr-insp{flex:0 0 auto;max-height:46%;min-height:60px}\n.tr-insp .r{display:flex;justify-content:space-between;gap:8px}.tr-insp .r span:first-child{color:#9aa3b2}\n.tr-insp .t{font-weight:600;font-size:13px;margin-bottom:3px}\n.tr-log{flex:1 1 auto;display:flex;flex-direction:column;min-height:120px;overflow:hidden}\n.tr-logbar{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:5px;align-items:center}\n.tr-logbody{flex:1;overflow:auto;font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;background:#090a0d;border-radius:5px;padding:4px 6px}\n.tr-logbody div{white-space:pre-wrap;word-break:break-word;border-bottom:1px solid #15171c}\n.tr-logbody .action{color:#8fd3ff}.tr-logbody .event{color:#dfe3ea}.tr-logbody .check{color:#c8e6c9}.tr-logbody .check.fail{color:#ff8a80;font-weight:700}.tr-logbody .check.pass{color:#9be59f}\n.tr-logbody time{color:#6b7280;margin-right:6px}\n.tr-btn,.tr-root button.tr-btn{background:#232831;border:1px solid #3a404c;color:#e8eaee;border-radius:5px;padding:3px 8px;cursor:pointer;font:inherit}\n.tr-btn:hover{background:#2d3440}.tr-btn.on{background:#3b3a14;border-color:#ffd23f;color:#fff}\n.tr-btn.pass{border-color:#4caf50}.tr-btn.fail{border-color:#ef5350;background:#3a1d1d}\n.tr-tabs{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:6px}\n.tr-items{display:grid;grid-template-columns:1fr 1fr;gap:4px}\n.tr-item{display:flex;gap:2px}.tr-item .tr-btn:first-child{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-cat{flex:0 1 auto;max-height:40%}\n.tr-anim{flex:0 0 auto;max-height:18%}\n.tr-anim .list{display:flex;flex-wrap:wrap;gap:4px}.tr-anim .sub{color:#9aa3b2;margin-bottom:4px}\n.tr-bench{flex:0 1 auto;max-height:34%}\n.tr-bench .sub{color:#9aa3b2;margin-bottom:4px}\n.tr-ctls{display:flex;flex-direction:column;gap:5px}\n.tr-ctl{display:flex;flex-wrap:wrap;align-items:center;gap:6px}.tr-ctl input[type=range]{flex:1;min-width:90px}.tr-ctl output{min-width:48px;text-align:right;color:#cfd3da}\n.tr-seg{display:inline-flex;flex-wrap:wrap;gap:2px}\n.tr-layers{margin-top:6px;display:flex;flex-direction:column;gap:2px}\n.tr-metrics{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;margin:6px 0 0}.tr-metrics dt{color:#9aa3b2}.tr-metrics dd{margin:0}\n.tr-tests{flex:1 1 auto;min-height:100px}\n.tr-tests .list{display:flex;flex-direction:column;gap:3px;margin-top:6px}.tr-tests .list .tr-btn{text-align:left}\n.tr-row{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;align-items:center}\n.tr-toggle{position:absolute;top:8px;right:8px;display:none}\n.tr-summary{margin-top:6px;color:#9aa3b2}\n@media (max-width:980px){.tr-left,.tr-right{display:none}.tr-root.open .tr-left,.tr-root.open .tr-right{display:flex}.tr-toggle{display:block;pointer-events:auto}.tr-root.open .tr-toggle{right:min(310px,34vw)}.tr-left{width:min(400px,46vw)}.tr-help{display:none}}\n`\n\n// accents are dropped on both sides of a search, so \"gas\" finds \"gás\"\nconst fold = (text: string): string => text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase()\n\nconst mk = <K extends keyof HTMLElementTagNameMap>(tag: K, cls?: string, text?: string): HTMLElementTagNameMap[K] => {\n const e = document.createElement(tag)\n if (cls) e.className = cls\n if (text !== undefined) e.textContent = text\n return e\n}\n\n// An SVG given as markup becomes a data URI; either way the picture is a mask over the text colour, so a one-colour silhouette follows the theme.\nconst thumbSource = (thumbnail: string): string => {\n const source = thumbnail.trim().startsWith('<') ? `data:image/svg+xml,${encodeURIComponent(thumbnail.trim())}` : thumbnail.trim()\n return source.replace(/[\"\\\\\\n\\r]/g, (char) => encodeURIComponent(char))\n}\nconst thumb = (thumbnail: string, credit?: string): HTMLElement => {\n const e = mk('span', 'tr-thumb')\n if (credit) e.title = credit\n else e.setAttribute('aria-hidden', 'true')\n e.style.setProperty('--tr-thumb', `url(\"${thumbSource(thumbnail)}\")`)\n return e\n}\n\ntype KeyboardLock = { lock?: () => Promise<void>; unlock?: () => void }\n\nasync function toggleFullscreen(): Promise<void> {\n const keyboard = (navigator as Navigator & { keyboard?: KeyboardLock }).keyboard\n try {\n if (document.fullscreenElement) {\n keyboard?.unlock?.()\n await document.exitFullscreen()\n return\n }\n await document.documentElement.requestFullscreen()\n await keyboard?.lock?.()\n } catch {\n // refused by the browser (no gesture, unsupported): the page just stays as it was\n }\n}\n\nexport function createUi(o: UiOptions): RoomUi {\n const { t } = o\n const style = mk('style')\n style.textContent = CSS\n const root = mk('div', 'tr-root')\n const pos = getComputedStyle?.(o.container)?.position\n if (!pos || pos === 'static') o.container.style.position = 'relative'\n root.appendChild(style)\n o.container.appendChild(root)\n\n // crosshair, top bar\n const cross = mk('div', 'tr-cross')\n cross.appendChild(mk('i'))\n const top = mk('div', 'tr-top')\n const toolBox = mk('div', 'tr-tool')\n const status = mk('div', 'tr-status')\n const prog = mk('div', 'tr-prog')\n const progLabel = mk('b')\n const progBar = mk('div', 'tr-bar')\n const progFill = mk('i')\n progBar.appendChild(progFill)\n prog.append(progLabel, progBar)\n top.append(toolBox, status, prog)\n\n // bottom: held hint and hotbar\n const bottom = mk('div', 'tr-bottom')\n const held = mk('div', 'tr-held')\n const hotbar = mk('div', 'tr-hotbar')\n bottom.append(held, hotbar)\n const help = mk('div', 'tr-help')\n help.textContent = t('ui.help')\n\n // left: inspector + log\n const left = mk('div', 'tr-left')\n const insp = mk('div', 'tr-panel tr-insp')\n const logPanel = mk('div', 'tr-panel tr-log')\n left.append(insp, logPanel)\n\n // log panel\n const logTitle = mk('h3', undefined, t('ui.log'))\n const logBar = mk('div', 'tr-logbar')\n const logBody = mk('div', 'tr-logbody')\n const filters: Record<LogEntry['channel'], boolean> = { action: true, event: true, check: true }\n const filterBtns: HTMLButtonElement[] = []\n for (const ch of ['action', 'event', 'check'] as const) {\n const b = mk('button', 'tr-btn on', t(`ui.filter.${ch}`))\n b.type = 'button'\n b.onclick = () => {\n filters[ch] = !filters[ch]\n b.classList.toggle('on', filters[ch])\n rebuildLog()\n }\n filterBtns.push(b)\n logBar.appendChild(b)\n }\n let autoscroll = true\n const asLabel = mk('label')\n const asBox = mk('input')\n asBox.type = 'checkbox'\n asBox.checked = true\n asBox.onchange = () => {\n autoscroll = asBox.checked\n }\n asLabel.append(asBox, document.createTextNode(' ' + t('ui.autoscroll')))\n logBar.appendChild(asLabel)\n const logBtn = (label: string, fn: () => void): void => {\n const b = mk('button', 'tr-btn', label)\n b.type = 'button'\n b.onclick = fn\n logBar.appendChild(b)\n }\n logBtn(t('ui.copy_json'), () => {\n const text = o.log.toJSON()\n // no clipboard API (an Artifact iframe, file://): select the text in a textarea and ask the browser to copy it, leaving it selected\n const select = (): void => {\n const ta = mk('textarea')\n ta.value = text\n ta.setAttribute('readonly', '')\n ta.style.cssText = 'position:fixed;left:8px;bottom:8px;width:min(480px,80vw);height:120px;z-index:99999'\n document.body.appendChild(ta)\n ta.focus()\n ta.select()\n let copied = false\n try {\n copied = !!document.execCommand?.('copy')\n } catch {\n copied = false\n }\n if (copied) ta.remove()\n else ta.onblur = () => ta.remove()\n }\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) navigator.clipboard.writeText(text).catch(select)\n else select()\n })\n logBtn(t('ui.download_ndjson'), () => o.log.download('ndjson'))\n logBtn(t('ui.download_txt'), () => o.log.download('txt'))\n logBtn(t('ui.clear_log'), () => {\n o.log.clear()\n logBody.textContent = ''\n nodes.clear()\n })\n logPanel.append(logTitle, logBar, logBody)\n\n const MAX_LINES = 200\n const nodes = new Map<number, HTMLElement>()\n const fmtTime = (s: number): string => `${Math.floor(s / 60)\n .toString()\n .padStart(2, '0')}:${(s % 60).toFixed(1).padStart(4, '0')}`\n const lineClass = (e: LogEntry): string => `${e.channel}${e.type === 'fail' || e.type === 'scenario_fail' ? ' fail' : e.type === 'pass' || e.type === 'scenario_pass' ? ' pass' : ''}`\n const fill = (n: HTMLElement, e: LogEntry): void => {\n n.className = lineClass(e)\n n.textContent = ''\n const tm = mk('time', undefined, fmtTime(e.t))\n n.append(tm, document.createTextNode(e.text))\n }\n const addNode = (e: LogEntry): void => {\n if (!filters[e.channel]) return\n const n = mk('div')\n fill(n, e)\n nodes.set(e.seq, n)\n logBody.appendChild(n)\n while (logBody.childElementCount > MAX_LINES) {\n const first = logBody.firstElementChild as HTMLElement\n for (const [k, v] of nodes) if (v === first) nodes.delete(k)\n first.remove()\n }\n if (autoscroll) logBody.scrollTop = logBody.scrollHeight\n }\n function rebuildLog(): void {\n logBody.textContent = ''\n nodes.clear()\n for (const e of o.log.entries().slice(-MAX_LINES * 3)) addNode(e)\n }\n const offLog = o.log.on((e, updated) => {\n if (updated) {\n const n = nodes.get(e.seq)\n if (n) fill(n, e)\n } else addNode(e)\n })\n\n // right: catalogue and tests\n const right = mk('div', 'tr-right')\n const cat = mk('div', 'tr-panel tr-cat')\n const anim = mk('div', 'tr-panel tr-anim')\n const tests = mk('div', 'tr-panel tr-tests')\n const benchPanel = createBenchPanel({ t, num: (n, d) => num(n, d), onControl: o.onControl, onLayer: o.onLayer, onAction: o.onAction })\n right.append(cat, anim, benchPanel.element, tests)\n\n cat.appendChild(mk('h3', undefined, t('ui.catalog')))\n const itemSearch = mk('input', 'tr-search')\n itemSearch.type = 'search'\n itemSearch.placeholder = t('ui.search_items')\n const tabs = mk('div', 'tr-tabs')\n const items = mk('div', 'tr-items')\n cat.append(itemSearch, tabs, items)\n let activeGroup = ''\n // a search looks in every group, so an item is found without knowing its tab\n const visibleItems = (): Array<{ item: TestRoomItem; group: string }> => {\n const term = fold(itemSearch.value.trim())\n if (!term) return (o.groups().get(activeGroup) ?? []).map((item) => ({ item, group: activeGroup }))\n return [...o.groups()].flatMap(([group, list]) => list.filter((item) => fold(`${item.name} ${item.id} ${group}`).includes(term)).map((item) => ({ item, group })))\n }\n const renderItems = (): void => {\n items.textContent = ''\n const searching = itemSearch.value.trim() !== ''\n const found = visibleItems()\n if (!found.length) items.appendChild(mk('div', 'tr-empty', t('ui.no_results')))\n for (const { item: it, group } of found) {\n const wrap = mk('div', 'tr-item')\n const b = mk('button', it.thumbnail ? 'tr-btn has-thumb' : 'tr-btn', it.thumbnail ? undefined : it.name)\n if (it.thumbnail) b.append(thumb(it.thumbnail), mk('span', 'tr-name', it.name))\n if (searching) b.appendChild(mk('small', undefined, group))\n b.type = 'button'\n b.title = it.note ?? it.name\n b.onclick = () => o.onSpawn(it.id)\n wrap.appendChild(b)\n if (it.weapon) {\n const w = mk('button', 'tr-btn', '⚔')\n w.type = 'button'\n w.title = t('ui.equip')\n w.onclick = () => o.onEquip(it.id)\n wrap.appendChild(w)\n }\n items.appendChild(wrap)\n }\n }\n const renderTabs = (): void => {\n tabs.textContent = ''\n const groupNames = [...o.groups().keys()]\n if (!groupNames.includes(activeGroup)) activeGroup = groupNames[0] ?? ''\n for (const g of groupNames) {\n const b = mk('button', g === activeGroup ? 'tr-btn on' : 'tr-btn', g)\n b.type = 'button'\n b.onclick = () => {\n activeGroup = g\n renderTabs()\n }\n tabs.appendChild(b)\n }\n renderItems()\n }\n renderTabs()\n itemSearch.oninput = renderItems\n // typing in a search box must not move the player or switch tools\n for (const box of [itemSearch]) box.addEventListener('keydown', (e) => e.stopPropagation())\n\n const controls = mk('div', 'tr-row')\n const ctl = (label: string, fn: (b: HTMLButtonElement) => void): HTMLButtonElement => {\n const b = mk('button', 'tr-btn', label)\n b.type = 'button'\n b.onclick = () => fn(b)\n controls.appendChild(b)\n return b\n }\n ctl(t('ui.clear'), () => o.onClear())\n ctl(t('ui.reset_all'), () => o.onResetAll())\n let slow = false\n ctl(t('ui.slow'), (b) => {\n slow = !slow\n b.classList.toggle('on', slow)\n o.onSlow(slow)\n })\n let fast = false\n ctl(t('ui.fast'), (b) => {\n fast = !fast\n b.classList.toggle('on', fast)\n o.onFast(fast)\n })\n const tapBtn = ctl(t('ui.tap'), () => o.onTap())\n const fullscreenBtn = ctl(t('ui.fullscreen'), () => void toggleFullscreen())\n fullscreenBtn.title = t('ui.fullscreen.hint')\n const blastBtns = (['shelter', 'fragmentHits', 'confinement'] as const).map((key) => ({ key, b: ctl(t(`ui.blast.${key}`), () => o.onBlast(key)) }))\n for (const { key, b } of blastBtns) b.title = t(`ui.blast.${key}.hint`)\n const qSel = mk('select')\n for (const q of ['low', 'medium', 'high'] as const) {\n const op = mk('option', undefined, t(`ui.quality.${q}`))\n op.value = q\n qSel.appendChild(op)\n }\n qSel.value = o.quality\n qSel.onchange = () => o.onQuality(qSel.value as 'low' | 'medium' | 'high')\n const qLabel = mk('label', undefined, t('ui.quality') + ' ')\n qLabel.appendChild(qSel)\n controls.appendChild(qLabel)\n const count = mk('span')\n controls.appendChild(count)\n cat.appendChild(controls)\n\n // tests\n tests.appendChild(mk('h3', undefined, t('ui.tests')))\n const runAll = mk('button', 'tr-btn', t('ui.run_all'))\n runAll.type = 'button'\n const summary = mk('div', 'tr-summary')\n const testSearch = mk('input', 'tr-search')\n testSearch.type = 'search'\n testSearch.placeholder = t('ui.search_tests')\n testSearch.addEventListener('keydown', (e) => e.stopPropagation())\n const list = mk('div', 'list')\n tests.append(runAll, summary, testSearch, list)\n testSearch.oninput = () => {\n const term = fold(testSearch.value.trim())\n for (const b of scBtns.values()) b.style.display = !term || fold(b.textContent ?? '').includes(term) ? '' : 'none'\n }\n const scBtns = new Map<string, HTMLButtonElement>()\n let busy = false\n const mark = (rep: ScenarioReport | void): void => {\n if (!rep) return\n for (const r of rep.results) {\n const b = scBtns.get(r.id)\n if (!b) continue\n b.classList.remove('pass', 'fail')\n b.classList.add(r.ok ? 'pass' : 'fail')\n b.textContent = `${r.ok ? '✓' : '✗'} ${r.name}`\n }\n summary.textContent = t('ui.report', { passed: rep.passed, failed: rep.failed })\n }\n const renderScenarios = (): void => {\n list.textContent = ''\n scBtns.clear()\n for (const s of o.scenarios()) {\n const b = mk('button', 'tr-btn', s.name)\n b.type = 'button'\n b.onclick = async () => {\n if (busy) return\n busy = true\n try {\n mark(await o.onRun(s))\n } finally {\n busy = false\n }\n }\n scBtns.set(s.id, b)\n list.appendChild(b)\n }\n }\n renderScenarios()\n runAll.onclick = async () => {\n if (busy) return\n busy = true\n summary.textContent = t('ui.running')\n try {\n mark(await o.onRunAll())\n } finally {\n busy = false\n }\n }\n\n const toggle = mk('button', 'tr-btn tr-toggle', t('ui.panel'))\n toggle.type = 'button'\n const togglePanels = (): void => {\n root.classList.toggle('open')\n o.onResize()\n }\n toggle.onclick = togglePanels\n\n root.append(cross, top, bottom, help, left, right, toggle)\n\n // inspector\n const bar = (value: number, max: number, cls: string): HTMLElement => {\n const b = mk('div', `tr-bar ${cls}`)\n const i = mk('i')\n i.style.width = `${Math.max(0, Math.min(100, (value / Math.max(1e-9, max)) * 100))}%`\n b.appendChild(i)\n return b\n }\n const row = (k: string, v: string): HTMLElement => {\n const r = mk('div', 'r')\n r.append(mk('span', undefined, k), mk('span', undefined, v))\n return r\n }\n const num = (n: number, d = 1): string => {\n const s = (Math.round(n * 10 ** d) / 10 ** d).toFixed(d)\n return t('locale.decimal') === ',' ? s.replace('.', ',') : s\n }\n const renderInspector = (i: InspectInfo | null): void => {\n insp.textContent = ''\n insp.appendChild(mk('h3', undefined, t('ui.inspector')))\n if (!i) {\n insp.appendChild(mk('div', undefined, t('ui.aim_at_something')))\n return\n }\n if (i.thumbnail) insp.appendChild(thumb(i.thumbnail, i.thumbnailCredit))\n insp.appendChild(mk('div', 't', `${i.object} › ${i.part}`))\n insp.appendChild(row(t('ins.material'), i.material))\n insp.appendChild(row(t('ins.status'), i.status + (i.burning ? ` · ${t('ins.burning')}` : '')))\n insp.appendChild(row(t('ins.hp'), `${num(i.hp, 0)} / ${num(i.maxHp, 0)}`))\n const frac = i.hp / Math.max(1e-9, i.maxHp)\n insp.appendChild(bar(i.hp, i.maxHp, frac < 0.25 ? 'bad' : frac < 0.6 ? 'warn' : 'hp'))\n insp.appendChild(row(t('ins.temperature'), `${num(i.temperature, 0)} °C`))\n if (i.char > 0.01) insp.appendChild(row(t('ins.char'), `${num(i.char * 100, 0)} %`))\n if (i.melt > 0.01) insp.appendChild(row(t('ins.melt'), `${num(i.melt * 100, 0)} %`))\n if (i.liters !== undefined) insp.appendChild(row(t('ins.liters'), `${num(i.liters, 2)} l`))\n const cn = (what: string, n: number): string => t(`count.${what}.${n === 1 ? 'one' : 'other'}`, { n })\n insp.appendChild(row(t('ins.damage'), t('ins.damage_counts', { dents: cn('dent', i.dents), holes: cn('hole', i.holes), cracks: cn('crack', i.cracks) })))\n insp.appendChild(row(t('ins.mass'), `${num(i.mass, 1)} kg`))\n if (i.load !== undefined) insp.appendChild(row(t('ins.load'), `${num(i.load, 0)} kg`))\n if (i.stress !== undefined) {\n insp.appendChild(row(t('ins.stress'), `${num(i.stress * 100, 0)} %`))\n insp.appendChild(bar(Math.min(i.stress, 1.2), 1.2, i.stress > 1 ? 'bad' : i.stress > 0.7 ? 'warn' : 'hp'))\n }\n if (i.joints.length) {\n insp.appendChild(mk('div', undefined, t('ins.joints') + ':'))\n for (const j of i.joints) {\n const tools = j.tools.length ? j.tools.join(', ') : t('tool.none')\n insp.appendChild(mk('div', undefined, `• ${j.kind} (${j.id})${j.open ? ` · ${t('ins.open')}` : ` → ${tools}`}`))\n }\n }\n if (i.note) insp.appendChild(mk('div', undefined, i.note))\n }\n\n let lastAnim = ''\n const renderAnimations = (a: AnimationInfo | null): void => {\n anim.textContent = ''\n anim.appendChild(mk('h3', undefined, t('ui.animations')))\n if (!a) {\n anim.appendChild(mk('div', 'sub', t('ui.animations_aim')))\n return\n }\n anim.appendChild(mk('div', 'sub', a.name))\n if (a.clips.length === 0) {\n anim.appendChild(mk('div', 'sub', t('ui.animations_none')))\n return\n }\n const l = mk('div', 'list')\n for (const c of a.clips) {\n const b = mk('button', a.playing === c.id ? 'tr-btn on' : 'tr-btn', `▶ ${t(`anim.${c.id}`) === `anim.${c.id}` ? c.id : t(`anim.${c.id}`)} (${num(c.duration, 1)} s)`)\n b.type = 'button'\n b.onclick = () => o.onPlay(a.objectId, c.id)\n l.appendChild(b)\n }\n anim.appendChild(l)\n }\n renderAnimations(null)\n\n let toastTimer: ReturnType<typeof setTimeout> | null = null\n const slotsEl: HTMLButtonElement[] = []\n let lastSlotsKey = ''\n let lastInspect = ''\n let hudPage = 0\n\n const api: RoomUi = {\n hud(s) {\n toolBox.textContent = ''\n toolBox.append(document.createTextNode(s.toolName))\n if (s.ammo) toolBox.append(mk('small', undefined, s.ammo))\n if (s.camera) toolBox.append(mk('small', undefined, t(`camera.${s.camera}`)))\n const helpText = s.camera ? `${t('ui.help')} · ${t('ui.help.camera')}` : t('ui.help')\n if (help.textContent !== helpText) help.textContent = helpText\n if (s.status) status.textContent = s.status\n else if (!toastTimer) status.textContent = ''\n if (s.progress) {\n prog.style.display = 'block'\n progLabel.textContent = s.progress.label\n progFill.style.width = `${Math.round(s.progress.value * 100)}%`\n } else prog.style.display = 'none'\n if (s.held) {\n held.style.display = 'block'\n held.textContent = ''\n held.append(document.createTextNode(`${s.held.name} · `))\n const keys: Array<[string, string]> = [\n ['E', t('hud.drop')],\n ['R', t('hud.rotate')],\n ['G', t('hud.throw')],\n ['Z', t('hud.tilt')],\n ...s.held.uses.map((u) => [u.key, u.label] as [string, string]),\n ]\n if (s.held.weapon) keys.push(['H', t('hud.equip', { weapon: s.held.weapon })])\n for (const [k, label] of keys) {\n held.append(mk('kbd', undefined, k), document.createTextNode(` ${label} `))\n }\n } else held.style.display = 'none'\n const key = s.slots.join('|') + s.page\n if (key !== lastSlotsKey) {\n lastSlotsKey = key\n hotbar.textContent = ''\n slotsEl.length = 0\n hudPage = s.page - 1\n s.slots.forEach((name, i) => {\n const b = mk('button', 'tr-slot')\n b.type = 'button'\n b.append(mk('b', undefined, String((i + 1) % 10)), document.createTextNode(name))\n b.title = name\n b.onclick = () => o.onTool(hudPage * 10 + i)\n hotbar.appendChild(b)\n slotsEl.push(b)\n })\n }\n slotsEl.forEach((b, i) => b.classList.toggle('on', i === s.slot))\n tapBtn.classList.toggle('on', s.tap)\n for (const { key, b } of blastBtns) b.classList.toggle('on', s.blast[key])\n count.textContent = t('ui.objects', { n: s.objects })\n const ak = JSON.stringify(s.animations)\n if (ak !== lastAnim) {\n lastAnim = ak\n renderAnimations(s.animations)\n }\n const ik = JSON.stringify(s.inspect)\n if (ik !== lastInspect) {\n lastInspect = ik\n renderInspector(s.inspect)\n }\n },\n toast(text) {\n status.textContent = text\n if (toastTimer) clearTimeout(toastTimer)\n toastTimer = setTimeout(() => {\n toastTimer = null\n }, 2000)\n },\n refresh() {\n renderTabs()\n renderScenarios()\n },\n showGroup(group) {\n activeGroup = group\n itemSearch.value = ''\n renderTabs()\n },\n togglePanels,\n bench: benchPanel.show,\n metrics: benchPanel.metrics,\n get benchVisible() {\n return benchPanel.visible\n },\n dispose() {\n offLog()\n if (toastTimer) clearTimeout(toastTimer)\n root.remove()\n },\n }\n rebuildLog()\n return api\n}\n"],"mappings":"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","names":["control","box","document","a","b","key","g","blocked","box","mk","list","box","key","t","host","box","fire","width","center","q","px","py","pz","update","grab","room"]}
|