@adatechnology/game-test-room 0.24.0 → 0.25.1
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/dist/index.d.ts +3 -1
- package/dist/index.global.js +188 -25
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +73 -11
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/room.ts","../src/body-sounds.ts","../src/arena.ts","../src/items.ts","../src/hand-sounds.ts","../src/bench.ts","../src/build-from-spec.ts","../src/explosives.ts","../src/segment-box.ts","../src/test-table.ts","../src/host-events.ts","../src/loading-view.ts","../src/loading.ts","../src/graphics.ts","../src/log.ts","../src/metrics.ts","../src/memory-watch.ts","../src/narrate.ts","../src/player.ts","../src/furniture-push.ts","../src/seating.ts","../src/door-open.ts","../src/avatar.ts","../src/locale.ts","../src/bench-panel.ts","../src/test-table-panel.ts","../src/ui.ts","../src/module-views.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, loadKitSamples, loadUserSamples } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { createDestructionRenderer, createDestructionSound, dragSoundKey, impactKey, impactSoundKeys, specFromObject3D } from '@adatechnology/game-destruction-three'\nimport type { SoundDetail } from '@adatechnology/game-destruction-three'\nimport { bodyMass, KNOCK_CHEST, knockOf, surfaceOfMaterial } from '@adatechnology/game-contracts'\nimport type { GaitId, SurfaceId } from '@adatechnology/game-contracts'\nimport { blowOfTool, createBodySounds, createStrideCounter, swingLead } from './body-sounds'\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 { SPRITE_KINDS, createVfx, patchSpriteKinds } from '@adatechnology/game-vfx'\nimport { createVfxRenderer } from '@adatechnology/game-vfx-three'\nimport { createFramePacer, createGeometryPool, createLightBudget, createMaterialPool, createProgramWarmup, createStaticBatcher, spriteProbes } from '@adatechnology/game-render-three'\nimport type { EffectWarmup, RenderPools, StaticBatcher, WarmupProbe } from '@adatechnology/game-render-three'\nimport type { FluidRenderer } from '@adatechnology/game-fluids-three'\nimport { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, checkAnimation, checkBench, checkDestructible, checkSpec, createEnvironmentBus, sealBlock, sealOpener, shotExtras, twistStroke, TWIST_LIFT, useToHit } from '@adatechnology/game-contracts'\nimport type { AnimationClipSpec, HandPose, HandTargetSource, HandTargets, HostEvent, ItemUseDef, TwistStroke, ModuleArea, ModuleBench, ModuleHost, TestableModule, ToolCommand, ToolCommandResult } from '@adatechnology/game-contracts'\nimport { createScheduler, startLoop } from '@adatechnology/game-runtime'\nimport { createArena } from './arena'\nimport { leafFoleyOf, openSoundOf, pickupSoundOf, USE_SOUND_EVERY, useSoundOf } from './hand-sounds'\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 { createTestTable } from './test-table'\nimport type { BlastSummary } from './explosives'\nimport { toHostEvent } from './host-events'\nimport { createLoading } from './loading'\nimport { createRoomGraphics } from './graphics'\nimport type { RoomGraphics } from './graphics'\nimport { createLog } from './log'\nimport { createRoomMetrics, heapMB, ROOM_METRICS } from './metrics'\nimport { createMemoryWatch } from './memory-watch'\nimport { createNarrator } from './narrate'\nimport { createPlayer, PLAYER_RADIUS } from './player'\nimport type { PlayerSlam } from './player'\nimport { createRoomPush, PUSH_REACH } from './furniture-push'\nimport type { RoomPushTarget } from './furniture-push'\nimport { createSeating } from './seating'\nimport type { SeatHolder } from './seating'\nimport { createRoomDoors, DOOR_REACH } from './door-open'\nimport type { RoomLeaf } from './door-open'\nimport { releaseObject3D } from '@adatechnology/game-shapes-three'\nimport { createTerrain, createTerrainImpl, DEFAULT_PROFILE, type TerrainBlowResult } from '@adatechnology/game-terrain'\nimport { createTerrainRenderer, terrainProfileName } from '@adatechnology/game-terrain-three'\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 { createModuleViews } from './module-views'\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 UseStatus,\n} from './types'\n\ntype Vars = Record<string, string | number>\n\ninterface Entry {\n so: SpawnedObject\n /** What draws the object's own damage on it (`SceneryObject.follow`). */\n follower?: { restore?(): void; dispose?(): void; update?(): void } | null\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 /** A sealed item (`TestRoomItem.seal`) was opened. */\n opened?: boolean\n /** Litres the container started with, and litres the player ate or drank out of it: the rest of a loss is a leak. */\n fluidStart?: number\n fluidUsed?: number\n /** Litres a sealed item had lost when it was opened (`sealLoss`). */\n sealLoss?: number\n /** Leaning on it pushes it. */\n pushable?: 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\n/** The effect ids of the explosives of the arsenal (the profiles of `game-vfx`) the room draws at load. */\nconst EXPLOSIVE_EFFECT_IDS = ['m67', 'molotov', 'pipe_bomb', 'm79_40mm', 'm72_66mm', 'at4_84mm', 'dynamite', 'c4', 'claymore'] as const\n/** The fog the scene may be in while the room runs: none, the weather's linear fog and its exponential one (the weather module comes in after the load). */\n/** The most loose bodies (casings, magazines) the room lets its modules keep alive at once: the cap the weapons viewmodel had on its own. */\nconst DEFAULT_PARTICLE_LIMIT = 900\nconst WARMED_FOG_STATES = ['none', 'linear', 'exp2'] as const\n/** Slots of the room's LightBudget: the default 16 point and 4 spot (perf.mjs on a real GPU: p50 and p99 of every phase the same as with 13 and 3, and the fixed cost of the light loop is lost in the noise). */\nconst ROOM_LIGHT_SIZES = { point: 16, spot: 4, pointShadows: 0, hemisphere: 1 } as const\n/** Widest scenery footprint (m) the renderer's drawn boxes stand for (as its own limit for fixed meshes); a wider one keeps its collider. */\nconst SOLID_SPAN = 3\n/** Meshes an object needs before the room draws its still ones in batches (a bookcase, a shelf of books): fewer cost less than the batch check. */\nconst BATCH_MIN_MESHES = 8\n/** Milliseconds a frame the batches of a new object may take to be made. */\nconst BATCH_BUDGET_MS = 1\n/** Owners that draw their own batches or move every frame (a vehicle batches itself; people and animals are posed each frame). */\nconst UNBATCHED_OWNERS = /vehicles|characters|animals|crowd/\n/** Highest top (m above the feet) the player steps onto: low debris; higher stops the walk. */\nconst STEP_UP = 0.45\n/** Height of the walking body (m): what starts above it is walked under. */\nconst BODY_HEIGHT = 1.75\n/** Pieces lighter than this (kg) are kicked out of the way instead of stepped on or stopping the player; how high above the feet they still are. */\nconst KICK_MASS = 6\nconst KICK_HEIGHT = 0.6\n/** Object id of the floor in the destruction world. */\nconst GROUND_ID = 'room_ground'\nconst TERRAIN_CELL = 0.1\n/** A huge arena gets coarser cells, not more memory. */\nconst TERRAIN_MAX_CELLS = 1000\nconst GROUND_BURST_MAX = 28\nconst GROUND_BURST_PER_METRE = 30\nconst GROUND_DUST_RADIUS = 0.2\nconst GROUND_FIRE_EVERY = 0.3\n\n/** Speed (m/s) the rounds of one trigger pull must give a free-standing object to move it: a shotgun moves a bookcase, a pistol does not. */\nconst SHOVE_SPEED = 0.04\nconst METRICS_INTERVAL_S = 0.25\n/** How far the palm sits off the part of a carried item it holds (m). */\nconst CARRY_PALM = 0.012\n/** Metres a screw cap rises off its thread at the end of an opening use, which the hand on it follows. */\nconst CAP_RISE = 0.03\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 */\n/**\n * The sound key of a vehicle's door, hood or trunk lid (`vehicle_door_shut`...): a car leaf has its own sounds, not those of its sheet metal. The part's\n * role tag (`door`, `hood`, `lid`, from game-vehicles) says which; an untagged leaf counts as a door.\n */\nconst vehicleLeafKey = (spec: DestructibleSpec, part: string, moment: 'open' | 'shut'): string => {\n const tags = spec.parts.find((p) => p.id === part)?.tags ?? []\n const leaf = tags.includes('hood') ? 'hood' : tags.includes('lid') || tags.includes('trunk') ? 'trunk' : 'door'\n return `vehicle_${leaf}_${moment}`\n}\n\n/** The destruction events that already play the impact of a blow (a mark, a break): a blow without any of them plays its contact sound itself. */\nconst MARK_EVENTS: ReadonlySet<string> = new Set(['dent', 'hole', 'crack', 'chip', 'stage', 'fracture'])\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 // the extra views (mirrors, reversing cameras) and the main-view takeover that modules ask for\n const moduleViews = createModuleViews(THREE, gl)\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 // the player's graphics settings (game-graphics): only on a renderer the room owns, and only when the page asks (the example page does; tests keep the fixed look)\n const graphics: RoomGraphics | null =\n ownRenderer && options.graphics\n ? createRoomGraphics({\n gl,\n camera,\n sun: arena.sun,\n container,\n locale,\n loading,\n label: t('loading.graphics'),\n ui: options.ui !== false,\n options: options.graphics === true ? {} : options.graphics,\n })\n : null\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 partStands = (object: string, part: string): boolean => {\n const p = world.part(object, part)\n return !!p && p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes' && !renderer.piece(object)\n }\n const topOk = (t: ArenaTop): boolean => (t.boards ? t.boards.some((b) => partStands(t.id, b.part)) : partStands(t.id, t.topPart))\n /** Whether the top holds what is at (x, z): the board there, on a top of boards. */\n const topHolds = (t: ArenaTop, x: number, z: number): boolean => (t.boards ? t.boards.some((b) => x > b.minX && x < b.maxX && z > b.minZ && z < b.maxZ && partStands(t.id, b.part)) : topOk(t))\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 && topHolds(t, x, z)) top = t.top\n return top\n }\n // the floor is the terrain: 0 was the height of a flat floor, now a hole goes under it and a heap over it; a top (a table, a counter) answers only where there is one\n const defaultGround = options.ground ?? { surface: DEFAULT_PROFILE }\n const terrain = createTerrain({ bounds: [-arenaSize, -arenaSize, arenaSize, arenaSize], cellSize: Math.max(TERRAIN_CELL, (2 * arenaSize) / TERRAIN_MAX_CELLS), layout: defaultGround, ...(options.terrainBudget ? { budget: options.terrainBudget } : {}) })\n const terrainView = createTerrainRenderer(THREE, { terrain })\n arena.group.add(terrainView.group)\n const groundAt = (x: number, z: number): number => {\n const top = Math.max(sceneryTopAt(x, z), restingTopAt(x, z))\n const floor = terrain.heightAt(x, z)\n return top > 0 ? Math.max(top, floor) : floor\n }\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({ deferredStart: {} }))\n const destructionSound = audio ? createDestructionSound(audio) : null\n // the kit's recorded files (game-audio assets/sfx), served next to the page: each recipe of the same id plays until its takes load, and stays where they cannot be fetched\n if (audio && options.samplesBaseUrl !== null) {\n void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? './sfx/' }).then(async (bank) => {\n // the owner's own sounds after the kit's, so each one the kit has keeps the kit's recording in front\n if (options.userSamplesBaseUrl !== null) {\n const own = await loadUserSamples(audio, { baseUrl: options.userSamplesBaseUrl ?? './sfx-local/' })\n if (own) log.add({ channel: 'event', type: 'user_sounds', text: `sons do dono: ${own.playing.length} tocando, ${own.behindKit.length} atrás do SDK`, data: { playing: own.playing, behindKit: own.behindKit } })\n }\n if (!bank || typeof window === 'undefined') return\n // the hand's sounds (a door, an item taken) load on the first key or click, when the page may make its AudioContext, so even the first one is the recording\n const preload = (): void => {\n window.removeEventListener('keydown', preload, true)\n window.removeEventListener('pointerdown', preload, true)\n void audio.loadSamples(['latch', 'creak_wood', 'shut_wood', 'rattle', 'grab_hard', 'grab_soft']).catch(() => undefined)\n }\n window.addEventListener('keydown', preload, true)\n window.addEventListener('pointerdown', preload, true)\n })\n }\n // the body's own sounds (jump, landing, the swing and the knuckles, sole or blade of a blow); the footsteps are the player module's, on the footfalls the room sends\n const bodySounds = createBodySounds(audio)\n const playSound = (key: string, point: Vec3, volume: number, detail?: SoundDetail): void => {\n destructionSound?.onSound(key, point, volume, detail)\n if (detail) options.onSound?.(key, point, volume, detail)\n else options.onSound?.(key, point, volume)\n }\n\n // the one owner of the point and spot lights: its size is what the clients of the room ask of it (T4.4 raises it client by client)\n const lights = createLightBudget(THREE, scene, { ...ROOM_LIGHT_SIZES, ...options.lightSizes })\n // what the effects of the room and of its modules ask for instead of making their own; the warmup's anchors keep the programs of the materials that are given back\n const warmup = createProgramWarmup(THREE)\n const pools: RenderPools = { geometries: createGeometryPool(), materials: createMaterialPool({ anchors: warmup.anchors, renderer: gl }) }\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 vfx = createVfxRenderer(THREE, {\n scene,\n lights,\n camera,\n overlay: container,\n quality,\n pointScale,\n vfx: createVfx({\n profile: quality,\n ...(options.debris?.particles ? { sprites: { kinds: patchSpriteKinds(SPRITE_KINDS, options.debris.particles) } } : {}),\n groundAt,\n }),\n })\n const renderer = createDestructionRenderer(THREE, {\n scene,\n world,\n vfx: vfx.world,\n quality,\n groundAt,\n pointScale,\n ...(options.debris?.fragmentLife !== undefined ? { fragmentLife: options.debris.fragmentLife } : {}),\n ...(options.debris?.maxFragments !== undefined ? { maxFragments: options.debris.maxFragments } : {}),\n eventBudgetMs: options.debris?.eventBudgetMs ?? 8,\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, cause) => {\n const e = entries.get(objectId)\n if (!e) return\n e.piece = piece\n leaveFootprint(objectId)\n rendererPieces.set(objectId, piece)\n action('loosened', t(cause === 'blast' ? 'act.loosened' : 'act.came_apart', { 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\n // the ground is an object of the world: shots, blows, blasts and flames reach it like anything else\n const showGroundBlow = (result: TerrainBlowResult): void => {\n const material = terrain.material(result.removed[0]?.material ?? result.exposed)\n const def = world.materials.get(material.id)\n const size = Math.min(GROUND_BURST_MAX, Math.ceil(result.radius * GROUND_BURST_PER_METRE))\n renderer.emit(material.debris === 'clods' ? 'dust' : material.debris, result.point as Vec3, [0, 1, 0], Math.max(2, size), Math.min(4, 1 + result.radius * 4))\n if (result.radius > GROUND_DUST_RADIUS) renderer.emit('dust', result.point as Vec3, [0, 1, 0], size, 1.4)\n playSound(impactKey(def), result.point as Vec3, Math.min(1, 0.25 + result.radius), impactSoundKeys(material.id, def))\n }\n terrain.onDeform((region) => renderer.wakeRegion(region.x, region.z, region.radius))\n const groundImpl = createTerrainImpl(terrain, { id: GROUND_ID, name: t('ground.name'), onBlow: showGroundBlow })\n const registerGround = (): void => {\n if (!world.has(GROUND_ID)) world.register(groundImpl, { id: GROUND_ID })\n }\n registerGround()\n let groundFireClock = 0\n const showGroundFire = (dt: number): void => {\n groundFireClock += dt\n if (groundFireClock < GROUND_FIRE_EVERY) return\n groundFireClock = 0\n for (const [x, z] of terrain.burningPoints()) {\n const y = terrain.heightAt(x, z)\n renderer.emit('fire', [x, y + 0.05, z], [0, 1, 0], 3, 1.6)\n if (rnd() < 0.25) renderer.emit('smoke', [x, y + 0.2, z], [0, 1, 0], 1, 1)\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(), footfall: 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 // the scenery the renderer draws stops the player by what is drawn now (a fallen bookcase is walked onto, not its old footprint); what is\n // too wide for the renderer's boxes (the wall closing the arena) and the tap's post keep their footprint\n const drawnScenery = (i: number): boolean => {\n const c = arena.colliders[i]\n return arena.colliderIds[i] !== null && c[2] - c[0] <= SOLID_SPAN && c[3] - c[1] <= SOLID_SPAN\n }\n // the footprints that still hold: the player and the push read this same list\n const standingColliders: Array<[number, number, number, number]> = []\n const standingIds: Array<string | null> = []\n /** Scenery too wide for the renderer's boxes that came loose: the body stops the player from then on (`inTheWay`), wherever it goes. */\n const footprintsWithBody = new Set<string>()\n /** Every piece of the scenery back where it stands. */\n const standFootprints = (): void => {\n standingColliders.length = 0\n standingIds.length = 0\n footprintsWithBody.clear()\n arena.colliders.forEach((collider, i) => {\n if (drawnScenery(i)) return\n standingColliders.push(collider)\n standingIds.push(arena.colliderIds[i] ?? null)\n })\n }\n standFootprints()\n /** The object is a body now: the footprint it had where it stood no longer means anything. */\n const leaveFootprint = (objectId: string): void => {\n const i = standingIds.indexOf(objectId)\n if (i < 0) return\n standingIds.splice(i, 1)\n standingColliders.splice(i, 1)\n footprintsWithBody.add(objectId)\n }\n /**\n * The footing of the player at (x, z) with the feet at `feet`: what is drawn there and not lighter than `KICK_MASS` (that is kicked, see\n * `kickLight`) is stepped onto when its top is within `STEP_UP` of the feet and stops the player when it is taller and reaches the body.\n */\n const footing = (x: number, z: number, radius: number, feet: number): { floor: number; blocked: boolean } => {\n let floor = -Infinity\n let blocked = false\n for (const s of renderer.solidsNear(x, z, radius)) {\n if ((s.piece?.mass ?? s.loose?.mass ?? Infinity) < KICK_MASS) continue\n const dx = Math.max(s.min[0] - x, 0, x - s.max[0])\n const dz = Math.max(s.min[2] - z, 0, z - s.max[2])\n if (dx * dx + dz * dz > radius * radius) continue\n if (s.max[1] <= feet + STEP_UP) floor = Math.max(floor, s.max[1])\n else if (s.min[1] < feet + BODY_HEIGHT) blocked = true\n }\n return { floor, blocked }\n }\n /** Light pieces at the player's feet (books, boards) are kicked along: away from the player at a little more than the walking speed. */\n const kickFrom = { x: 0, z: 0 }\n const kickLight = (dt: number): void => {\n const x = player.x\n const z = player.z\n // walked by the keys or by a scripted walk: the distance since the last frame\n const speed = dt > 0 ? Math.hypot(x - kickFrom.x, z - kickFrom.z) / dt : 0\n kickFrom.x = x\n kickFrom.z = z\n if (speed < 0.2 || speed > 20) return\n const kicked = new Set<object>()\n for (const s of renderer.solidsNear(x, z, PLAYER_RADIUS)) {\n const pc = s.piece\n const body = pc ?? s.loose\n if (!body || body.mass >= KICK_MASS || kicked.has(body) || s.min[1] > player.feet + KICK_HEIGHT) continue\n kicked.add(body)\n const cx = (s.min[0] + s.max[0]) / 2 - x\n const cz = (s.min[2] + s.max[2]) / 2 - z\n const d = Math.hypot(cx, cz) || 1\n const v = speed * 1.2\n if (!pc) {\n s.loose?.push((cx / d) * v, (cz / d) * v)\n continue\n }\n if (pc.velocity[0] * cx + pc.velocity[2] * cz >= v * d) continue\n pc.velocity = [(cx / d) * v, Math.max(pc.velocity[1], 0.6), (cz / d) * v]\n pc.sleeping = false\n }\n }\n const player = createPlayer(THREE, {\n camera,\n dom,\n colliders: standingColliders,\n footing: (x, z, radius, feet) => footing(x, z, radius, feet),\n blockers,\n limit: arenaSize,\n floorAt: terrain.heightAt,\n start: arena.playerStart,\n crouchKeys: options.crouch?.keys,\n onSlam: (event) => slamPlayer(event),\n onFeet: (event) => {\n const at = player.position\n if (event.type === 'jump') bodySounds.jump(at)\n else {\n bodySounds.land(surfaceUnderFeet(), event.speed, at)\n action('landing_player', t('act.player_land', { speed: num(event.speed, 1) }), { data: { speedMs: Math.round(event.speed * 100) / 100, surface: surfaceUnderFeet() } })\n }\n },\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 /** How far from straight ahead (cosine) something can be and still be what the player leans on. */\n const PUSH_AHEAD = 0.6\n const heaviestMaterial = (id: string): string | undefined => {\n let best: { mass: number; material: string } | undefined\n for (const p of world.state(id)?.parts ?? []) if (p.status !== 'broken' && (!best || p.mass > best.mass)) best = { mass: p.mass, material: p.material }\n return best?.material\n }\n /** What the player stands against when the aim is not on it (from the shoulder the aim of something low falls on the floor beside it): the closest thing ahead within arm's reach. */\n const leanedOn = (): RoomPushTarget | null => {\n const fx = -Math.sin(player.yaw)\n const fz = -Math.cos(player.yaw)\n let best: Entry | null = null\n let bestDistance = PUSH_REACH\n for (const e of entries.values()) {\n if (!e.pushable || (!e.piece && !e.free)) continue\n const b = bodyBox(e)\n if (!b) continue\n const dx = Math.max(b.minX, Math.min(b.maxX, player.x)) - player.x\n const dz = Math.max(b.minZ, Math.min(b.maxZ, player.z)) - player.z\n const distance = Math.hypot(dx, dz)\n if (distance >= bestDistance || (distance > 1e-3 && (dx * fx + dz * fz) / distance < PUSH_AHEAD)) continue\n best = e\n bestDistance = distance\n }\n return best ? { objectId: best.so.objectId, root: best.so.root, name: nameOf(best.so.objectId), piece: best.piece ?? null } : null\n }\n const push = createRoomPush({\n THREE,\n player,\n world,\n arena: { limit: arenaSize, colliders: standingColliders },\n blockers,\n ...(options.push ? { rules: options.push } : {}),\n pick: () => {\n if (heldPiece || (tool.def.category !== 'hand' && toolId !== 'fists')) return null\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n const aimed = r ? (rendererPieces.get(r.object)?.root ?? (entries.get(r.object)?.free ? entries.get(r.object)?.so.root : undefined)) : undefined\n // the eye on something that is not pushed (a can on the floor) is the eye on what the hand takes, even against a sofa\n if (r && aimed) return entries.get(r.object)?.pushable ? { objectId: r.object, root: aimed, name: nameOf(r.object), piece: rendererPieces.get(r.object) ?? null } : null\n return leanedOn()\n },\n massOf: (objectId) => massOfObject(objectId),\n materialOf: heaviestMaterial,\n makePiece: (objectId) => {\n const piece = renderer.makePiece(objectId, { mass: Math.max(0.2, massOfObject(objectId)) })\n const e = entries.get(objectId)\n if (e) e.piece = piece\n rendererPieces.set(objectId, piece)\n leaveFootprint(objectId)\n return piece\n },\n dragSound: (objectId, point, volume) => playSound(dragSoundKey(world.materials.get(heaviestMaterial(objectId) ?? '')), point, volume),\n hitSound: (objectId, point) => {\n const material = heaviestMaterial(objectId) ?? ''\n const def = world.materials.get(material)\n playSound(impactKey(def), point, 0.5, impactSoundKeys(material, def, 'blunt'))\n },\n onEvent: (ev) => {\n const vars = { name: ev.name, kg: num(ev.massKg, 0) }\n action(`push_${ev.type}`, t(`act.push_${ev.type}`, vars), { objectId: ev.objectId, itemId: entryOf(ev.objectId)?.so.itemId, data: { massKg: Math.round(ev.massKg * 10) / 10 } })\n fire('push', ev)\n if (ev.type === 'engaged') say(t('hud.push_on', vars))\n else if (ev.type === 'too_heavy') say(t('hud.push_too_heavy', vars))\n else if (ev.type === 'obstacle') say(t('hud.push_blocked', vars))\n },\n ring: (value) => ui?.holdRing(value),\n hasBody: () => !!avatar?.eye,\n })\n const seatHolder = (objectId: string): SeatHolder | null => {\n const e = entries.get(objectId)\n const seats = e?.item?.seats\n if (!e || !seats?.length || !world.has(objectId)) return null\n return { objectId, root: rendererPieces.get(objectId)?.root ?? e.so.root, seats }\n }\n const seating = createSeating({\n THREE,\n player,\n pick: () => {\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n return r ? seatHolder(r.object) : null\n },\n find: seatHolder,\n hasBody: () => !!avatar?.eye,\n groundAt: (x, z) => groundAt(x, z),\n onSit: (seat) => action('sit', t(seat.pose === 'lie' ? 'act.lie' : 'act.sit', { name: nameOf(seat.objectId) }), { objectId: seat.objectId, itemId: entryOf(seat.objectId)?.so.itemId, data: { seat: seat.seatId, pose: seat.pose } }),\n onStand: (seat) => action('stand', t('act.stand', { name: nameOf(seat.objectId) }), { objectId: seat.objectId, itemId: entryOf(seat.objectId)?.so.itemId, data: { seat: seat.seatId } }),\n })\n /** E was pressed on something that can be pushed, not by a script: letting the key go is letting the piece go. */\n let pushByKey = false\n\n // ----- doors, lids and drawers worked by hand: a tap of E on a leaf (a part an `open_*` clip of the item moves) opens or closes it\n const leafCache = new WeakMap<object, RoomLeaf[]>()\n /** The leaves of an item: each part its `open_*` clips move, with the clip that opens it (a clip of its own wins over one that opens several together). */\n const leavesOf = (objectId: string): RoomLeaf[] => {\n const item = entries.get(objectId)?.item\n if (!item?.animations?.length) return []\n const cached = leafCache.get(item)\n if (cached) return cached\n const byPart = new Map<string, { clip: AnimationClipSpec; n: number }>()\n for (const clip of item.animations) {\n if (!clip.id.startsWith('open_')) continue\n const parts = new Set<string>()\n for (const k of clip.keys) for (const id of Object.keys(k.parts ?? {})) parts.add(id)\n for (const part of parts) {\n const had = byPart.get(part)\n if (!had || parts.size < had.n) byPart.set(part, { clip, n: parts.size })\n }\n }\n const leaves = [...byPart].map(([part, v]) => ({ part, clip: v.clip }))\n leafCache.set(item, leaves)\n return leaves\n }\n /** Locked leaves: `objectId\\0part`, or `objectId\\0*` for every leaf of the object. */\n const lockedLeaves = new Set<string>()\n const doors = createRoomDoors({\n THREE,\n player,\n world,\n camera,\n arena: { limit: arenaSize, colliders: standingColliders, ids: standingIds },\n ...(options.doors ? { rules: options.doors } : {}),\n pick: () => {\n if (heldPiece) return []\n aim()\n const hits: Array<{ objectId: string; part: string; point: Vec3 }> = []\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], DOOR_REACH)\n if (r) hits.push({ objectId: r.object, part: r.part, point: r.point as Vec3 })\n // over the shoulder the crosshair can pass by a handle the body hides: what the eye itself faces comes next\n if (thirdActive()) {\n camera.getWorldDirection(tmpV2)\n const e = rayWorld([aimO[0], aimO[1], aimO[2]], [tmpV2.x, tmpV2.y, tmpV2.z], DOOR_REACH)\n if (e) hits.push({ objectId: e.object, part: e.part, point: e.point as Vec3 })\n }\n return hits\n },\n leaves: leavesOf,\n objectOf: (objectId, part) => entries.get(objectId)?.so.root.getObjectByName(part) ?? null,\n pose: (objectId, part, clip, fraction) => {\n const e = entries.get(objectId)\n const obj = e?.so.root.getObjectByName(part)\n if (!e || !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 const rest = restPose.get(obj)!\n const pose = poseAt(clip, part, Math.max(0, Math.min(1, fraction)) * clip.duration)\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 followPart(e, part, obj, rest)\n },\n isLocked: (objectId, part) => lockedLeaves.has(`${objectId}\\0*`) || lockedLeaves.has(`${objectId}\\0${part}`),\n nameOf,\n impactKey: (objectId, part) => impactKey(world.materials.get(world.part(objectId, part)?.material ?? heaviestMaterial(objectId) ?? '')),\n leafSound: (objectId, part, moment) => {\n const spec = specs.get(objectId)\n return spec?.tags?.includes('vehicle') ? vehicleLeafKey(spec, part, moment) : undefined\n },\n sound: playSound,\n // a vehicle's doors, hood and lid have their own sounds in the vehicle bank (game-vehicles-three), not those of the house\n leafFoley: (objectId, part, slides) =>\n specs.get(objectId)?.tags?.includes('vehicle') ? null : leafFoleyOf(entryOf(objectId)?.item?.sounds, part, impactKey(world.materials.get(world.part(objectId, part)?.material ?? heaviestMaterial(objectId) ?? '')), slides),\n onEvent: (ev) => {\n const vars = { name: ev.name, percent: Math.round(ev.opening * 100) }\n action(`door_${ev.type}`, t(`act.door_${ev.type}`, vars), { objectId: ev.objectId, itemId: entryOf(ev.objectId)?.so.itemId, part: ev.part, data: { opening: Math.round(ev.opening * 1000) / 1000, ...(ev.by ? { by: ev.by } : {}) } })\n fire('door', ev)\n if (ev.type === 'locked') say(t('hud.door_locked', vars))\n else if (ev.type === 'blocked') say(t('hud.door_blocked', vars))\n },\n })\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 // the still meshes of an object draw in one batch per material; a mesh that is hit, moved or swung draws on its own again (createStaticBatcher)\n const batchers = new Map<string, StaticBatcher>()\n const batchObject = (objectId: string, root: THREE_NS.Object3D): void => {\n let meshes = 0\n let unbatched = false\n // the owner mark may sit on an inner node (a wrapper around the vehicle's own root)\n root.traverse((object) => {\n if ((object as THREE_NS.Mesh).isMesh) meshes++\n if (UNBATCHED_OWNERS.test((object.userData.kitOrigin as { owner?: string } | undefined)?.owner ?? '')) unbatched = true\n })\n if (!unbatched && meshes >= BATCH_MIN_MESHES) batchers.set(objectId, createStaticBatcher(THREE, root, { budgetMs: BATCH_BUDGET_MS }))\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 batchObject(objectId, root)\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 e.fluidStart = f.container.liters\n e.fluidUsed = 0\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 const e = registerEntry(o.id, o.id, root, o.spec, o.label ?? S.text[`arena.${o.id}`] ?? o.id, undefined, undefined, true, false)\n if (o.free) e.free = true\n if (o.pushable) e.pushable = true\n e.follower = o.follow?.(root, world, o.id) || null\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 // eslint-disable-next-line kit/no-bare-remove -- the inner object belongs to the module that built it, which shows it again; removeEntry frees it when it goes\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 /** The items modules put in the world as scenery (`ModuleHost.addObject`): kept through `clear`; the scenarios run without them (each starts from the seeded room) and they come back after. */\n const sceneryObjects = new Map<string, { item: TestRoomItem; position: Vec3; rotationY: number }>()\n const placeScenery = (objectId: string, item: TestRoomItem, position: Vec3, rotationY: number): Entry => {\n const root = buildRoot(item)\n root.position.set(position[0], position[1], position[2])\n root.rotation.y = rotationY\n root.name = item.id\n scene.add(root)\n root.updateMatrixWorld(true)\n const own = item.impl?.(root, objectId)\n const { spec, parts } = own ? { spec: structuredCloneSpec(own.describe()), parts: undefined } : resolveSpec(item, root)\n root.updateMatrixWorld(true)\n const q = root.getWorldQuaternion(tmpQ)\n if (own) world.register(own, { id: objectId, position, rotation: [q.x, q.y, q.z, q.w] })\n else world.add(spec, { id: objectId, position, rotation: [q.x, q.y, q.z, q.w] })\n const e = registerEntry(objectId, item.id, root, spec, item.name, parts, item, true, false)\n fire('spawn', e.so)\n return e\n }\n const restoreScenery = (): void => {\n for (const [objectId, o] of sceneryObjects) if (!entries.has(objectId)) placeScenery(objectId, o.item, o.position, o.rotationY)\n }\n const addScenery = (itemId: string, position: Vec3, rotationY = 0): { objectId: string; root: unknown; remove(): void } | null => {\n const item = catalogMap.get(itemId)\n if (!item) return null\n const objectId = `${item.id}_scenery_${sceneryObjects.size + 1}`\n sceneryObjects.set(objectId, { item, position: [position[0], position[1], position[2]], rotationY })\n const e = placeScenery(objectId, item, position, rotationY)\n action('spawn', t('act.spawn', { name: item.name, x: num(position[0], 1), z: num(position[2], 1) }), { objectId, itemId: item.id, data: { position, movable: false, scenery: true } })\n return {\n objectId,\n get root() {\n return entries.get(objectId)?.so.root ?? e.so.root\n },\n remove() {\n sceneryObjects.delete(objectId)\n removeEntry(objectId)\n },\n }\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 // (a drawing with no mesh has an empty box: it stays where it was asked, instead of going to minus infinity)\n const box = new THREE.Box3().setFromObject(root)\n const base = Math.max(pos[1], groundAt(pos[0], pos[2]))\n if (!box.isEmpty()) 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 if (item.pushable) e.pushable = 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\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // The player against the objects: what stands on the floor blocks the walk, and the walk pushes what is light enough to slide\n // ---------------------------------------------------------------------------------------------------------------------------------------\n /** Objects lower than this (m) the player steps onto (a can, a concrete block): they do not block, the feet scuff them along. */\n const STEP_OVER = STEP_UP\n /** Things that hang higher than this (m) above the feet pass over the head. */\n const HEADROOM = 1.9\n /**\n * Horizontal force (N) a walking and a running player puts into what is in the way, and the floor's friction coefficient the push has to beat: a 3 kg bin slides off,\n * a 12 kg nightstand moves, a 70 kg fridge only blocks (it would take 0.5 x 70 x 9.8 = 343 N, a shove with the shoulder).\n */\n const PUSH_WALK_N = 250\n const PUSH_RUN_N = 450\n const FLOOR_FRICTION = 0.5\n interface BodyBox { minX: number; maxX: number; minZ: number; maxZ: number; base: number; top: number; stamp: number }\n const bodyBoxes = new Map<string, BodyBox>()\n const bodyBounds = new THREE.Box3()\n let frameStamp = 0\n /** World box of an object the player can bump into, kept until the object moves (a piece that is awake is measured again each frame). */\n const bodyBox = (e: Entry): BodyBox | null => {\n const id = e.so.objectId\n const known = bodyBoxes.get(id)\n if (known && (known.stamp === frameStamp || !e.piece || e.piece.sleeping)) return known\n if (!e.so.root.parent || world.state(id)?.destroyed) {\n bodyBoxes.delete(id)\n return null\n }\n bodyBounds.setFromObject(e.so.root)\n if (bodyBounds.isEmpty()) return null\n const box = { minX: bodyBounds.min.x, maxX: bodyBounds.max.x, minZ: bodyBounds.min.z, maxZ: bodyBounds.max.z, base: bodyBounds.min.y, top: bodyBounds.max.y, stamp: frameStamp }\n bodyBoxes.set(id, box)\n return box\n }\n const footPos = new THREE.Vector3()\n /**\n * Whether `e` stands in the player's way at the floor point (x, z): the arena has its own colliders, a held thing and a low one do not block. A piece that declares its\n * own footprint in `root.userData.collider` (a plant: the trunk as a cylinder, or null for grass the feet walk through) is tested against that instead of its whole box.\n */\n const inTheWay = (e: Entry, x: number, z: number, r: number): BodyBox | null => {\n if ((e.arena && !footprintsWithBody.has(e.so.objectId)) || (e.piece && e.piece.held)) return null\n const ud = e.so.root.userData as { collider?: { kind?: string; radius?: number; height?: number } | null }\n if ('collider' in ud && !ud.collider?.kind) return null\n const b = bodyBox(e)\n if (!b || b.base > player.feet + HEADROOM) return null\n const c = ud.collider\n if (c?.kind === 'cylinder' && c.radius != null) {\n e.so.root.getWorldPosition(footPos)\n const reach = c.radius + r\n return (x - footPos.x) ** 2 + (z - footPos.z) ** 2 < reach * reach ? { ...b, top: Math.min(b.top, footPos.y + (c.height ?? b.top - footPos.y)) } : null\n }\n return x > b.minX - r && x < b.maxX + r && z > b.minZ - r && z < b.maxZ + r ? b : null\n }\n blockers.add((x, z, r) => {\n for (const e of entries.values()) {\n const b = inTheWay(e, x, z, r)\n if (b && b.top - b.base >= STEP_OVER) return true\n }\n return false\n })\n /**\n * The walk pushes what it runs into, by the force of a person leaning on it against the floor's grip: the push brings the object up to the walking speed at most, at the\n * middle of where the body touches it (a waist-high bin slides, a tall light thing can tip), and a low thing the feet step over is scuffed along.\n */\n const pushByPlayer = (dt: number): void => {\n const [wx, wz] = player.takeWish()\n const len = Math.hypot(wx, wz)\n if (dt <= 0 || len < 1e-6) return\n const dx = wx / len\n const dz = wz / len\n const speed = len / dt\n const force = player.running ? PUSH_RUN_N : PUSH_WALK_N\n // where the step tried to go (and a hair more), so what the blocked step stopped against is found\n const ax = player.x + dx * (Math.min(len, 0.5) + 0.03)\n const az = player.z + dz * (Math.min(len, 0.5) + 0.03)\n for (const e of entries.values()) {\n const piece = e.piece\n if (!piece) continue\n const b = inTheWay(e, ax, az, PLAYER_RADIUS)\n if (!b) continue\n const grip = FLOOR_FRICTION * piece.mass * 9.81\n if (force <= grip) continue\n const along = piece.velocity[0] * dx + piece.velocity[2] * dz\n const impulse = Math.min(piece.mass * Math.max(0, speed - along), (force - grip) * dt)\n if (impulse <= 1e-4) continue\n // the body touches it from the floor up to the chest (or its top): the push acts at the middle of that span\n const y = (b.base + Math.max(b.base, Math.min(b.top, player.feet + 1.4))) / 2\n const point: Vec3 = [Math.max(b.minX, Math.min(b.maxX, player.x)), y, Math.max(b.minZ, Math.min(b.maxZ, player.z))]\n piece.sleeping = false\n renderer.impulse(e.so.objectId, [dx * impulse, 0, dz * impulse], point)\n log.coalesce(`bump:${e.so.objectId}`, { channel: 'action', type: 'bump', text: t('act.bump', { name: e.name, kg: num(piece.mass, 1) }), objectId: e.so.objectId, itemId: e.so.itemId, data: { massKg: Math.round(piece.mass * 10) / 10, pushN: force } }, 1)\n }\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 // A removed tree's geometries, materials and textures stay on the GPU (and in three.js's caches) until disposed: everything the room takes out of the scene\n // goes through `dropTree`, released at once or, inside `releasingTogether`, in one pass at its end (one walk of the scene for what is still drawn).\n let releaseBatch: THREE_NS.Object3D[] | null = null\n const dropTree = (root: THREE_NS.Object3D | undefined): void => {\n if (!root) return\n if (releaseBatch) releaseBatch.push(root)\n else releaseObject3D(root, { keep: scene })\n }\n const releasingTogether = (fn: () => void): void => {\n if (releaseBatch) return fn()\n releaseBatch = []\n try {\n fn()\n } finally {\n const roots = releaseBatch\n releaseBatch = null\n releaseObject3D(roots, { keep: scene })\n }\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 e.follower?.dispose?.()\n if (world.has(id)) world.remove(id)\n e.so.root.removeFromParent()\n const inner = wrapped.get(e.so.root)\n letGo(e.so.root)\n // after the renderer let go of it (its restore puts the original meshes back), so the tree released is the one that was drawn\n dropTree(e.so.root)\n dropTree(inner)\n entries.delete(id)\n batchers.get(id)?.dispose()\n batchers.delete(id)\n doors.forget(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 dropTree(p?.root)\n rendererPieces.delete(id)\n splitOf.delete(id)\n }\n loose.length = 0\n }\n\n const clearEverything = (): void => releasingTogether(clearEverythingNow)\n const clearEverythingNow = (): 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 // every fire sound goes with the fires (the renderer's parts are cleared below without their burn_end)\n destructionSound?.reset()\n terrain.setLayout(defaultGround)\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 e.follower?.restore?.()\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 resetListeners = 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 e.follower?.restore?.()\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 seating.release()\n pushByKey = false\n push.end()\n releasingTogether(() => {\n clearEverythingNow()\n for (const id of [...entries.keys()]) removeEntry(id)\n })\n renderer.reset()\n for (const listener of [...resetListeners]) listener()\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 registerGround()\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 filmRandom.seed = 1\n groundFireClock = 0\n counter = 0\n slot = 0\n prevVy.clear()\n lastImpact.clear()\n addArena()\n standFootprints()\n scheduler.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 crouch keys crouch too. */\n let crouchForced = false\n /** Down by a player module (`setAvatarState`: knocked by a zombie, dead); a blast that knocks the player off its feet puts the body down too. */\n let downForced = false\n /** Mass of the player's body for the shove of a blast (kg). */\n const playerMass = options.playerMass ?? bodyMass(1.75)\n /**\n * A blast shoves the player the way it shoves the people of the modules (`knockOf`, the host's `blastShove`), cut by the cover between the centre and the chest: strong\n * enough, it takes the player off its feet, and the body lies a while and gets up.\n */\n /** How far ahead of the body (m, from its axis) a wall it slammed into is looked for, and the height of the shoulder that takes it. */\n const SLAM_REACH = PLAYER_RADIUS + 0.35\n const SLAM_SHOULDER = 1.3\n /**\n * A body thrown into something firm: what it hit takes the blow of its weight (`½ m v²`, blunt, across the shoulder) and answers as its material does (drywall or a board\n * cracks or breaks, brick holds); the body falls with a thud and, when it was hard, cries out.\n */\n const slamPlayer = (event: PlayerSlam): void => {\n const [x, feet, z] = player.position\n const energy = 0.5 * playerMass * event.speed * event.speed\n let hit: RayHit | null = null\n if (event.against === 'obstacle') {\n const from: Vec3 = [x, feet + ((player.knocked?.lying ?? 0) > 0.5 ? 0.3 : SLAM_SHOULDER), z]\n hit = rayWorld(from, event.direction, SLAM_REACH)\n if (hit) world.hitPart(hit.object, hit.part, { type: 'blunt', point: hit.point, direction: event.direction, energy, radius: 0.2, ...(hit.normal ? { normal: hit.normal } : {}) })\n }\n bodySounds.slam(event.speed, [x, feet + 0.5, z])\n action('player_slammed', t(event.against === 'obstacle' ? 'act.player_slammed' : 'act.player_fell', { speed: num(event.speed, 1), what: hit ? nameOf(hit.object) : '' }), {\n ...(hit ? { objectId: hit.object, part: hit.part } : {}),\n data: { against: event.against, speed: event.speed, energy, ...(hit ? { object: hit.object, part: hit.part } : {}) },\n })\n }\n const knockPlayer = (event: { readonly point: Vec3; readonly energy: number; readonly radius: number; readonly source: string }): void => {\n if (seating.seat) return\n const feet: Vec3 = [player.x, player.feet, player.z]\n const reach = world.blastReach(event.point, [feet[0], feet[1] + KNOCK_CHEST, feet[2]], event.source ? { ignore: [event.source] } : {})\n const knock = knockOf({ point: event.point, energy: event.energy, radius: event.radius, reach }, feet, playerMass, options.blastShove)\n if (!knock) return\n player.knock(knock)\n const speed = Math.hypot(knock.velocity[0], knock.velocity[1], knock.velocity[2])\n action(knock.down ? 'player_knocked_down' : 'player_shoved', t(knock.down ? 'act.knocked_down' : 'act.player_shoved', { speed: num(speed, 1), reach: num(reach * 100, 0) }), {\n data: { speed, reach, down: knock.down, source: event.source },\n })\n }\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 // one body for both views: in first person the camera sits at its eyes and only the head is kept out of that camera\n avatar.root.visible = cameraMode === 'third' || !!avatar.eye\n avatar.setView?.(cameraMode, camera)\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?.setView?.('third', null)\n // eslint-disable-next-line kit/no-bare-remove -- the avatar belongs to the host that set it (the player module), which may set it again or dispose it\n avatar?.root.removeFromParent()\n avatar = next\n feetPrev = null\n if (avatar) {\n // the weapon's contact and laser rays leave from the eye, inside the body: they must not stop at the chest\n avatar.root.userData.viewmodel = true\n scene.add(avatar.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 || push.isBent\n avatarState.down = downForced || Boolean(player.knocked?.down || (player.knocked?.lying ?? 0) > 0.5)\n // a blast falls the body the way it pushed it; a module's own knock-down keeps the avatar's pick\n avatarState.fallForward = downForced ? undefined : player.knockedForward\n avatarState.armed = armedForced ?? tool.def.action.kind === 'firearm'\n avatarState.pitch = player.pitch\n avatarState.holding = heldPiece !== null\n avatarState.push = push.avatarState\n const seat = seating.seat\n avatarState.seat = seat ? { pose: seat.pose, hip: seat.hips[1] - player.feet } : null\n avatarState.door = doors.avatarState\n avatarState.itemUse = useItemPlayer\n ? { id: useItemName, ...useItemPlayer.pose(), ...(twistHand?.gripL !== undefined ? { gripL: twistHand.gripL } : {}) }\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 placeEye()\n }\n /**\n * A view a script asked for (`room.look`: scenarios, the test table, the view an area opens on) is kept exactly until the player moves: the body's eye stands ahead and at the\n * body's own height, and a scripted aim (an axe on a trunk, a punch at a can on the table) is measured from the point it asked for.\n */\n let scriptedAt: [number, number] | null = null\n const lookAt = (eye: Vec3, target: Vec3): void => {\n player.look(eye, target)\n scriptedAt = [player.x, player.z]\n }\n /** How far short of what stands between the player's middle and the body's eyes (a wall, a wardrobe) the eye stops, metres. */\n const EYE_CLEARANCE = 0.1\n const eyeAt = new THREE.Vector3()\n /**\n * The body's eyes are the camera of the first-person view and where the room aims, shoots and reaches from in both views; they are ahead of the player's middle (0.2 m standing,\n * more crouched or down), so they are pulled back toward it out of whatever stands in between.\n */\n const placeEye = (): void => {\n if (!avatar?.eye) return\n if (scriptedAt) {\n const [walkX, walkZ] = player.walkIntent\n if (!walkX && !walkZ && Math.hypot(player.x - scriptedAt[0], player.z - scriptedAt[1]) < 1e-6) return\n scriptedAt = null\n }\n avatar.eye(eyeAt)\n const dx = eyeAt.x - player.x\n const dz = eyeAt.z - player.z\n const ahead = Math.hypot(dx, dz)\n if (ahead > 1e-4) {\n const dir: Vec3 = [dx / ahead, 0, dz / ahead]\n const hit = rayWorld([player.x, eyeAt.y, player.z], dir, ahead + EYE_CLEARANCE)\n if (hit) {\n const keep = Math.max(0, hit.distance - EYE_CLEARANCE)\n eyeAt.set(player.x + dir[0] * keep, eyeAt.y, player.z + dir[2] * keep)\n }\n }\n camera.position.copy(eyeAt)\n camera.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 // 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 /** The body's hands go to the tool the module placed (a carried piece follows the hand instead, a push poses the hands itself, and a door's hand goes to the handle through the same reach). */\n /** How far inside the right shoulder joint, toward the middle of the chest, the pocket a stock rests in sits (m). */\n const SHOULDER_POCKET_IN = 0.1\n const pocketAt = new THREE.Vector3()\n const aimTurn = new THREE.Quaternion()\n const aimEuler = new THREE.Euler(0, 0, 0, 'YXZ')\n /** The pocket of the body's right shoulder, turned to the aim, in both views (`ModuleHost.holdFrame`); null for no body or a body that names no shoulder. */\n const bodyHoldFrame = (): HandPose | null => {\n const shoulder = avatar?.shoulder?.('R')\n if (!shoulder) return null\n shoulder.getWorldPosition(pocketAt)\n // the view's right at this yaw is (cos, 0, -sin): the pocket is that much inside the joint\n pocketAt.x -= Math.cos(player.yaw) * SHOULDER_POCKET_IN\n pocketAt.z += Math.sin(player.yaw) * SHOULDER_POCKET_IN\n aimTurn.setFromEuler(aimEuler.set(player.pitch, player.yaw, 0, 'YXZ'))\n return { position: [pocketAt.x, pocketAt.y, pocketAt.z], quaternion: [aimTurn.x, aimTurn.y, aimTurn.z, aimTurn.w] }\n }\n const reachAvatar = (): void => {\n const doorHand = doors.handTargets()\n const targets = push.active ? null : (doorHand ?? (heldPiece ? twistHand : (handSource?.() ?? null)))\n lastHand = {\n stance: push.active || doorHand ? 'hold' : (handStances[toolId] ?? (targets ? 'hold' : 'relaxed')),\n triggerFinger: targets?.fingers?.index ?? null,\n targets: push.handTargets() ?? targets,\n }\n if (!avatar?.reach) return\n // the camera is the eye here in both views (the shoulder view only moves it for the render): the same reach in both, so switching views moves no hand\n avatar.reach(targets, { camera, keepOutside: { contact: (origin, direction, maxDistance) => rayWorld(origin, direction, maxDistance)?.distance ?? null } })\n }\n /** Moves the camera to the shoulder view for the render that follows, and answers the function that puts it back. */\n const thirdEuler = new THREE.Euler(0, 0, 0, 'YXZ')\n const applyThirdView = (): (() => void) => {\n if (!thirdActive()) return () => undefined\n const home = camera.position.clone()\n const turn = camera.quaternion.clone()\n const pose = thirdPose(0)\n camera.position.set(pose.position[0], pose.position[1], pose.position[2])\n // the view of a body on the floor (turned up, rolled) is the first person's: the camera behind the body keeps the player's own look\n if (player.knocked) camera.quaternion.setFromEuler(thirdEuler.set(player.pitch, player.yaw, 0, 'YXZ'))\n camera.updateMatrixWorld(true)\n return () => {\n camera.position.copy(home)\n camera.quaternion.copy(turn)\n camera.updateMatrixWorld(true)\n }\n }\n\n /** Height of the hip above the feet (m): where a kick leaves from; and how far (rad) below the look it goes, so a level look kicks at the height of a chair seat. */\n const KICK_HIP = 0.9\n const KICK_DROP = 0.35\n /**\n * A kick leaves the hip, not the eye: along the facing, 20 degrees below the look and kept between 50 degrees down (a stomp on what lies on the floor) and 6 up, so a kick\n * at a bin or a chair in front of the feet lands on it, as the leg reaches it, instead of on what the eye ray would find beyond the leg's reach.\n */\n const legAim = (): void => {\n aim()\n // never above the eye: a player low on the ground kicks from where it is, along its look\n const low = aimO[1] < player.feet + KICK_HIP\n const pitch = Math.max(-0.9, Math.min(0.1, player.pitch - (low ? 0 : KICK_DROP)))\n aimO[0] = player.x\n aimO[1] = Math.min(player.feet + KICK_HIP, aimO[1])\n aimO[2] = player.z\n aimD[0] = -Math.sin(player.yaw) * Math.cos(pitch)\n aimD[1] = Math.sin(pitch)\n aimD[2] = -Math.cos(player.yaw) * Math.cos(pitch)\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 /** What the feet stand on, by its sound: the part right under them (a heap of boards, a car roof) or the ground's top layer (a slab, turf, a crater's soil). */\n const surfaceUnderFeet = (): SurfaceId => {\n const [x, feet, z] = player.position\n const under = rayWorld([x, feet + 0.15, z], [0, -1, 0], 0.5)\n if (under && under.object !== GROUND_ID) {\n const material = world.state(under.object)?.parts.find((p) => p.id === under.part)?.material\n if (material) return surfaceOfMaterial(material)\n }\n return surfaceOfMaterial(terrain.columnAt(x, z).material)\n }\n\n // footfalls: the body's walk says when a heel is down; with no body (or one that does not say) the room counts strides along the ground walked\n const strides = createStrideCounter()\n let feetAt: [number, number] | null = null\n const stepFeet = (dt: number): void => {\n const [x, , z] = player.position\n const moved = feetAt && dt > 0 ? Math.hypot(x - feetAt[0], z - feetAt[1]) : 0\n feetAt = [x, z]\n if (dt <= 0 || seating.seat) return\n const gait: GaitId = player.running ? 'run' : 'walk'\n const foot = avatar?.footfall ? avatar.footfall() : moved / dt > MAX_STRIDE_SPEED ? null : strides.advance(moved, gait)\n if (!foot || !player.grounded) return\n emitHost({ type: 'footfall', foot, surface: surfaceUnderFeet(), gait, position: player.position })\n fire('footfall', { foot, gait, time: simTime })\n }\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 // a pool of fuel burning (a molotov's zone, a fuel stain on fire): the fire sound of a liquid, from when it lights to when it goes out\n const poolFire = (point: Vec3, burning: boolean): void => playSound(burning ? 'burn_loop' : 'burn_end', point, 0.5, { fuel: 'liquid' })\n const dropZone = (i: number): void => {\n const [zone] = fireZones.splice(i, 1)\n if (zone) poolFire(zone.point, false)\n }\n const dropStain = (i: number): void => {\n const [stain] = burningStains.splice(i, 1)\n if (stain) poolFire(stain.center, false)\n }\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 poolFire([s.center[0], s.center[1], s.center[2]], true)\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) dropZone(i)\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 dropStain(i)\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 toolDef = (id: string): { readonly category: string } | undefined => arsenal.weapons.get(id)\n /** What a blow met, for its sound: a body (a head apart) or anything else. */\n const blowTarget = (r: RayHit): 'body' | 'head' | 'object' => {\n const part = world.state(r.object)?.parts.find((p) => p.id === r.part)\n if (!part || !(world.materials.get(part.material)?.tags ?? []).includes('body')) return 'object'\n return /head|face|jaw|skull|neck/.test(r.part) ? 'head' : 'body'\n }\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 shotRay = new THREE.Raycaster()\n // batched meshes leave the camera layer (createStaticBatcher), not the world: rays still find them\n shotRay.layers.enableAll()\n /** Metres of water a pistol round crosses to lose 1/e of its speed (a full can takes about a fifth of it in its 6 cm). */\n const LIQUID_SLOWING = 0.25\n /** Share of the momentum along the surface a round leaves in a wall it meets at a slant (the rest goes on with it). */\n const SHOT_GRIP = 0.3\n /**\n * The push a round gives what it hits, at the point of the drawn surface it meets (not the box the world sees): the momentum the round lost there (all of it when\n * it stopped; through a thin shell, only what the wall and the liquid inside took), along the inward normal of that surface plus a little along it. So a round on the\n * right of a can pushes it away and to the left and spins it, as a real one does.\n */\n const shotPush = (s: Shot, objectId: string, results: readonly { readonly object: string; readonly penetrated: boolean; readonly exitEnergy: number }[], fallback: Vec3): { impulse: Vec3; point: Vec3 } => {\n const e = entries.get(objectId)\n const speed = Math.max(80, s.speed)\n const onIt = results.filter((r) => r.object === objectId)\n const last = onIt[onIt.length - 1]\n let kept = last && last.penetrated ? Math.sqrt(Math.max(0, Math.min(1, last.exitEnergy / Math.max(s.energy, 1e-6)))) : 0\n let point = fallback\n let inward: Vec3 = [s.direction[0], s.direction[1], s.direction[2]]\n if (e) {\n shotRay.set(new THREE.Vector3(...s.origin), new THREE.Vector3(...s.direction).normalize())\n shotRay.far = 60\n // sprites (labels, effects) under the object raycast against the camera\n shotRay.camera = camera\n const hit = shotRay.intersectObject(e.so.root, true).find((h) => (h.object as THREE_NS.Mesh).isMesh && !h.object.userData.destructionDebris && h.face)\n if (hit?.face) {\n point = [hit.point.x, hit.point.y, hit.point.z]\n const n = hit.face.normal.clone().transformDirection(hit.object.matrixWorld)\n if (n.x * s.direction[0] + n.y * s.direction[1] + n.z * s.direction[2] > 0) n.negate()\n inward = [-n.x, -n.y, -n.z]\n }\n // the liquid inside slows the round down along the chord it crosses\n const c = kept > 0 && e.containerId ? fluids.container(e.containerId) : null\n if (c && c.liters > 1e-4) {\n const size = new THREE.Box3().setFromObject(e.so.root).getSize(new THREE.Vector3())\n kept *= Math.exp(-(Math.min(size.x, size.z) * 0.9) / LIQUID_SLOWING)\n }\n }\n const momentum = ((2 * s.energy) / speed) * (1 - kept)\n // the momentum of the round, split along the inward normal (all of it) and along the surface (a share)\n const along = s.direction[0] * inward[0] + s.direction[1] * inward[1] + s.direction[2] * inward[2]\n const impulse: Vec3 = [0, 1, 2].map((k) => momentum * (along * inward[k]! + SHOT_GRIP * (s.direction[k]! - along * inward[k]!))) as unknown as Vec3\n return { impulse, point }\n }\n\n /**\n * The push of one trigger pull on what stands free (`free`) and is not a piece yet: when the momentum of every round that hit it is enough to move\n * its mass (`SHOVE_SPEED`: a shotgun's load into a bookcase, not a pistol round), it becomes a piece and takes the push.\n */\n const shoveFree = (pushes: Map<string, { impulse: Vec3; point: Vec3 }>): void => {\n for (const [objectId, push] of pushes) {\n const e = entries.get(objectId)\n if (!e || e.piece || !e.free) continue\n const mass = Math.max(0.2, massOfObject(objectId))\n if (Math.hypot(...push.impulse) / mass < SHOVE_SPEED) continue\n const piece = renderer.makePiece(objectId, { mass })\n e.piece = piece\n rendererPieces.set(objectId, piece)\n leaveFootprint(objectId)\n action('loosened', t('act.shoved', { name: e.name }), { objectId, itemId: e.so.itemId })\n renderer.impulse(objectId, push.impulse, push.point)\n }\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 const pushes = new Map<string, { impulse: Vec3; point: Vec3 }>()\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 blow = shotPush(s, r0.object, results, r0.point)\n if (rendererPieces.has(r0.object)) renderer.impulse(r0.object, blow.impulse, blow.point)\n const push = pushes.get(r0.object) ?? { impulse: [0, 0, 0] as Vec3, point: blow.point }\n for (let k = 0; k < 3; k++) push.impulse[k] += blow.impulse[k]!\n pushes.set(r0.object, push)\n }\n if (shots.length <= 3 || rnd() < 0.34) tracer(m, end)\n }\n })\n shoveFree(pushes)\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 /**\n * A kick leaves the leg, not the eye: level, the way the player faces, at the heights of `kickHeights` above the feet (shin, knee, hip), it finds the nearest\n * thing standing low in front (a chair, a door, a crate) within the tool's reach; when none of those rays finds anything the eye's aim decides, as for any other blow.\n */\n const kickHeights = options.kickHeights ?? [0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85]\n const footRay = (u: Extract<Use, { kind: 'melee' }>): Extract<Use, { kind: 'melee' }> => {\n const flat = Math.hypot(u.direction[0], u.direction[2])\n const direction: Vec3 = flat > 1e-6 ? [u.direction[0] / flat, 0, u.direction[2] / flat] : [-Math.sin(player.yaw), 0, -Math.cos(player.yaw)]\n const feet = player.position\n let best: { origin: Vec3; distance: number } | null = null\n for (const height of kickHeights) {\n const origin: Vec3 = [feet[0], feet[1] + height, feet[2]]\n const hit = rayWorld(origin, direction, u.reach)\n if (hit && (!best || hit.distance < best.distance)) best = { origin, distance: hit.distance }\n }\n return best ? { ...u, origin: best.origin, direction } : u\n }\n const meleeUse = (use: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const w = toolName(id)\n const u = id === 'kick' ? footRay(use) : use\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 const hit = useToHit(u, r.point, r.normal)!\n const result = world.hitPart(r.object, r.part, { ...hit, source: 'player' })\n // a blow that leaves no mark (a punch on solid wood, a kick on the ground) still meets the surface: its impact sounds, by material and blow\n if (!result.events.some((e) => MARK_EVENTS.has(e.type))) {\n const material = world.part(r.object, r.part)?.material ?? heaviestMaterial(r.object) ?? ''\n const def = world.materials.get(material)\n playSound(impactKey(def), r.point, Math.min(0.8, 0.25 + u.energy / 400), impactSoundKeys(material, def, hit.type))\n }\n const blow = blowOfTool(id, toolDef(id)?.category ?? '')\n if (blow) bodySounds.hit(blow, blowTarget(r), r.point as Vec3, u.energy)\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; swing?: () => void; lead?: number }> = []\n /**\n * A melee blow. A tool with a strike clip (`strikeClips`) on an avatar that plays it starts the clip on the body, in both views, 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 punchHand = options.punchHand ?? 'alternate'\n const punchTools = new Set(options.punchTools ?? ['hand', 'fists'])\n let nextHand: 'left' | 'right' = 'right'\n // the combo (an ability the page gives, `strikeCombo`): while it is on, each blow of its tools is its next step, and a pause longer than `reset` starts it over\n const combo = options.strikeCombo\n let comboOn = !!combo && options.strikeComboOn === true\n let comboNext = 0\n let comboAt = -Infinity\n const setStrikeCombo = (on: boolean): void => {\n if (!combo || on === comboOn) return\n comboOn = on\n comboNext = 0\n const name = combo.name?.[locale] ?? combo.id\n action('combo', t(on ? 'act.combo.on' : 'act.combo.off', { name }), { data: { combo: combo.id, on } })\n say(t(on ? 'act.combo.on' : 'act.combo.off', { name }))\n }\n const strikeUse = (u: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const stepIndex = comboOn && combo?.tools.includes(id) && combo.steps.length > 0 ? (simTime - comboAt > combo.reset ? 0 : comboNext) : null\n const step = stepIndex === null ? undefined : combo!.steps[stepIndex]\n const clip = step ? step.clip : strikeClips[id]\n // a kick uses the leg the option says (alternating from the right), a punch the hand (the same way) or the one of its combo step, whatever the avatar does with them\n const leg = id === 'kick' ? (kickLeg === 'alternate' ? nextLeg : kickLeg) : undefined\n const hand = step ? step.hand : punchTools.has(id) ? (punchHand === 'alternate' ? nextHand : punchHand) : undefined\n const side = leg ? { leg } : hand ? { hand } : undefined\n const seconds = clip === undefined ? null : (avatar?.strike?.(clip, side) ?? null)\n if (leg && seconds !== null && kickLeg === 'alternate') nextLeg = leg === 'right' ? 'left' : 'right'\n if (!step && hand && seconds !== null && punchHand === 'alternate') nextHand = hand === 'right' ? 'left' : 'right'\n if (step && stepIndex !== null) {\n comboNext = (stepIndex + 1) % combo!.steps.length\n comboAt = simTime\n }\n const blow = blowOfTool(id, toolDef(id)?.category ?? '')\n // the swing's loudest part meets the contact: it starts `swingLead` before the clip's impact (counted in the room's time, so slow motion keeps it), or now\n const lead = blow ? swingLead(blow) : 0\n const swing = blow ? (): void => bodySounds.swing(blow, player.position) : undefined\n if (swing && (seconds === null || seconds <= lead)) swing()\n if (clip === undefined || seconds === null) {\n if (leg) {\n legAim()\n meleeUse({ ...u, origin: [aimO[0], aimO[1], aimO[2]], direction: [aimD[0], aimD[1], aimD[2]] }, id)\n } else meleeUse(u, id)\n return\n }\n const text = leg ? 'act.strike.leg' : hand ? 'act.strike.hand' : 'act.strike'\n action('strike', t(text, { weapon: toolName(id), clip, seconds: num(seconds, 2), leg: leg ? t(`leg.${leg}`) : '', hand: hand ? t(`hand.${hand}`) : '' }), {\n data: { weapon: id, clip, impactIn: seconds, ...(leg ? { leg } : {}), ...(hand ? { hand } : {}), ...(step ? { combo: combo!.id, step: stepIndex } : {}) },\n })\n strikes.push({\n key: id,\n remaining: seconds,\n ...(swing && seconds > lead ? { swing, lead } : {}),\n land: () => {\n if (leg) legAim()\n else 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) {\n strike.remaining -= dt\n if (strike.swing && strike.remaining <= (strike.lead ?? 0)) {\n strike.swing()\n delete strike.swing\n }\n }\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) dropStain(i)\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) dropZone(i)\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 const zone: FireZone = { 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 fireZones.push(zone)\n poolFire(zone.point, true)\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 /** Pulls the trigger of the tool in hand; answers what the trigger said (`drawing` while the draw is not over yet, `ok` when it did something). */\n const useTool = (dt: number, held: boolean): UseStatus => {\n aim()\n const cat = tool.def.category\n if (cat === 'hand') {\n if (strikes.some((strike) => strike.key === 'hand' || strike.key === 'fists')) return 'cooldown'\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 'ok'\n }\n if (strikes.some((strike) => strike.key === toolId)) return 'cooldown' // 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 res.status\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 res.status\n }\n applyUses(res, dt)\n return res.status\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 kick key (K, Shift+V) and the kick button: a kick with the `kick` tool, whatever tool is selected (it keeps its own cooldown). False when there is no kick or it is not ready. */\n const kick = (): boolean => {\n if (!arsenal.weapons.has('kick') || strikes.some((strike) => strike.key === 'kick')) return false\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 false\n for (const u of res.uses) if (u.kind === 'melee') strikeUse(u, 'kick')\n return true\n }\n const kickKeys = options.kick?.keys ?? ['KeyK']\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 const heldVel: Vec3 = [0, 0, 0]\n let useItemPlayer: ItemUsePlayer | null = null\n let useItemName = ''\n /** The use asked for while the seal's opening use (`ModuleItemSeal.openUse`) plays: it starts once the item is open. */\n let afterOpening: string | null = null\n /** The other hand turning the seal's part during the opening use: the stroke and how far the part is off (0..1). */\n let twisting: { stroke: TwistStroke; lift: number } | null = null\n /** The left hand on the part being turned, world space, set by `followHeld` while `twisting`. */\n let twistHand: HandTargets | null = null\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 afterOpening = null\n twisting = null\n twistHand = null\n heldEntry = null\n heldPiece = null\n heldTilt = 0\n }\n\n /**\n * The click with bare hands: a punch (`strikeClips.hand`, the clip plays on the body and the blow lands at its impact). With something in the hands the\n * click lets it go; E grabs and drops, the right button grabs or throws.\n */\n const handUse = (): UseStatus => {\n if (!heldPiece) return useTool(FIXED_DT, false)\n grab()\n return 'ok'\n }\n const grab = (): boolean => {\n if (push.active) return false\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 heldYaw = 0\n heldTilt = 0\n heldVel[0] = heldVel[1] = heldVel[2] = 0\n playSound(pickupSoundOf(heldEntry?.item?.sounds, world.materials.get(heaviestMaterial(r.object) ?? '')), r.point as Vec3, Math.min(1, 0.45 + kg * 0.1))\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 // the hand closing on it: the sound starts as the hold does (criterion C1)\n playSound(impactKey(world.materials.get(heaviestMaterial(r.object) ?? '')).replace('impact_', 'grab_'), v3(piece.root.getWorldPosition(tmpV)), 0.8)\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 playSound('item_throw', [piece.root.position.x, piece.root.position.y, piece.root.position.z], Math.min(1, 0.3 + speed * 0.04))\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 * The left hand on the top of the held item while `twisting`: palm down on the part, the fingers round it, the wrist turned by the stroke about the item's\n * axis and lifted with the part as it comes off. The same pose for the first-person arms and the body.\n */\n const twistTargets = (root: THREE_NS.Object3D, gripQ: THREE_NS.Quaternion): HandTargets | null => {\n if (!twisting) return null\n const { stroke, lift } = twisting\n const up = new THREE.Vector3(0, 1, 0).applyQuaternion(root.quaternion)\n const top = heldLocal\n .clone()\n .applyQuaternion(root.quaternion)\n .add(root.position)\n .addScaledVector(up, heldSize.y * 0.5 + lift * CAP_RISE + stroke.lift * TWIST_LIFT + CARRY_PALM)\n // the fingers point to the right and away from the body (the forearm comes in from the left, not in front of the item), then the wrist turns with the stroke (a cap comes off turning to the left seen from above)\n const knuckles = new THREE.Vector3(0.85, 0, -0.5).normalize().applyQuaternion(gripQ)\n knuckles.addScaledVector(up, -knuckles.dot(up)).normalize().applyAxisAngle(up, stroke.angle)\n const side = new THREE.Vector3().crossVectors(knuckles, up).normalize()\n // the palm sits over the middle of the part, so the middle of the hand is a little back toward the wrist\n const palm = top.addScaledVector(knuckles, -0.025)\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(knuckles, up, side))\n return { L: { position: [palm.x, palm.y, palm.z], quaternion: [q.x, q.y, q.z, q.w] }, gripL: 0.35 + 0.5 * stroke.grip }\n }\n\n const gripQuat = new THREE.Quaternion()\n const followHeld = (dt: number): void => {\n const piece = heldPiece\n twistHand = 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 = avatar?.hand?.('R')\n const isDrink = useItemName === 'drink' || useItemName === 'sip' || useItemName === 'chug'\n if (hand) {\n // with a body the item rides its weapon hand in both views, 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 = 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 // no body to hold it: the item floats in front of the eye\n pos = tmpV.set(0.05, -0.28, -1.15).applyMatrix4(camera.matrixWorld)\n gripQuat.setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw).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 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 twistHand = twistTargets(root, gripQuat)\n }\n\n /** How far (m) from the player an item on the table still counts as at hand (a can opener next to the tin). */\n const TOOL_REACH = 1.6\n /** Ids of what the player could open a seal with: the weapons of the loadout and the items within `TOOL_REACH` (catalogue and item ids). */\n const toolsAtHand = (): string[] => {\n const here = player.position\n const near: string[] = [...loadout]\n for (const other of entries.values()) {\n if (other === heldEntry || other.arena) continue\n const p = other.so.root.position\n if (Math.hypot(p.x - here[0], p.z - here[2]) <= TOOL_REACH) near.push(other.so.itemId)\n }\n return near\n }\n /** Litres a sealed item lost that nobody ate or drank; once it is open, only what it had lost before (a spill from the open mouth spoils nothing). */\n const sealLoss = (e: Entry): number => {\n if (e.sealLoss !== undefined) return e.sealLoss\n const c = e.containerId ? fluids.container(e.containerId) : undefined\n return c && e.fluidStart !== undefined ? Math.max(0, e.fluidStart - c.liters - (e.fluidUsed ?? 0)) : 0\n }\n /** The seal state of an item: opened, holed through (any part) or leaking (it lost contents while sealed). */\n const sealState = (e: Entry): { opened: boolean; breached: boolean; leaked: boolean } => {\n const breached = world.state(e.so.objectId)?.parts.some((p) => p.holes.some((h) => h.through && !h.vent)) ?? false\n const leaked = e.fluidStart !== undefined && sealLoss(e) > Math.max(0.002, e.fluidStart * 0.02)\n return { opened: !!e.opened, breached, leaked }\n }\n /** Opens a sealed item: the container opens, the model is drawn open and the room says with what. False when it needs a tool that is not at hand. */\n const openSeal = (e: Entry): boolean => {\n const seal = e.item?.seal\n if (!seal || e.opened) return true\n const opener = sealOpener(seal, toolsAtHand())\n if (!opener.ok) {\n // the names of the catalogue's items; the arsenal's names only when the catalogue has none of them\n const listed = (seal.openWith ?? []).map((id) => catalogMap.get(id)?.name).filter((n): n is string => !!n)\n const names = [...new Set(listed.length ? listed : (seal.openWith ?? []).filter((id) => arsenal.weapons.has(id)).map((id) => toolName(id)))]\n const why = t('hud.needs_opener', { name: e.name, tools: names.join(', ') })\n say(why)\n action('sealed', why, { objectId: e.so.objectId, itemId: e.so.itemId, data: { openWith: [...(seal.openWith ?? [])] } })\n return false\n }\n e.sealLoss = sealLoss(e)\n e.opened = true\n if (e.containerId) fluids.open(e.containerId)\n seal.open?.(wrapped.get(e.so.root) ?? e.so.root)\n playSound(openSoundOf(e.item?.sounds, world.materials.get(heaviestMaterial(e.so.objectId) ?? '')), v3(e.so.root.getWorldPosition(tmpV)), 0.7)\n const tool = opener.tool ? (catalogMap.get(opener.tool)?.name ?? (arsenal.weapons.has(opener.tool) ? toolName(opener.tool) : opener.tool)) : undefined\n action('open_seal', tool ? t('act.open_with', { name: e.name, tool }) : t('act.open_by_hand', { name: e.name }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { tool: opener.tool ?? 'hand' } })\n return true\n }\n\n /** C crouches unless the page moved the crouch to other keys; while it does, an item's second use is on Shift+F instead of C. */\n const crouchOnC = (options.crouch?.keys ?? ['KeyC']).includes('KeyC')\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 eating = useId === 'drink' || useId === 'sip' || useId === 'chug' || useId === 'eat'\n const consuming = eating || useId === 'pour' || useId === 'pour_out'\n if (useItemPlayer && !useItemPlayer.done) return false\n const seal = e.item?.seal\n if (seal && (consuming || useId === 'open')) {\n const state = sealState(e)\n const spoiled = sealBlock(seal, { ...state, opened: true })\n if (eating && spoiled) {\n say(t(spoiled === 'leaked' ? 'hud.spoiled_leak' : 'hud.spoiled_hole', { name: e.name }))\n action('spoiled', t(spoiled === 'leaked' ? 'hud.spoiled_leak' : 'hud.spoiled_hole', { name: e.name }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { reason: spoiled } })\n return false\n }\n if (!e.opened) {\n const opening = seal.byHand && seal.openUse ? itemUseDefs.find((u) => u.id === seal.openUse) : undefined\n if (opening) {\n // the other hand turns it open first; what was asked for follows once it is open\n useItemPlayer = createItemUse(fluids, e.containerId, opening)\n useItemName = opening.id\n afterOpening = useId === 'open' ? null : useId\n return true\n }\n if (!openSeal(e)) return false\n // a tool opens the tin and that is the whole use; a pull tab opens on the way to the mouth\n if (!seal.byHand || useId === 'open') {\n useItemPlayer = createItemUse(fluids, e.containerId, itemUseDefs.find((u) => u.id === 'open') ?? def)\n useItemName = 'open'\n return true\n }\n } else if (useId === 'open') return false\n }\n if (consuming && c.liters <= 1e-6) {\n say(t('hud.empty_container', { name: e.name }))\n return false\n }\n if (consuming && c.closed) fluids.open(e.containerId)\n useItemPlayer = createItemUse(fluids, e.containerId, def)\n useItemName = def.id\n useSoundIn = 0\n if (eating) useLiters = c.liters\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 /** Litres in the container when an eat or drink use began: what it took out is counted as eaten, not leaked. */\n let useLiters: number | null = null\n /** Seconds until the next sound of the use in progress. */\n let useSoundIn = 0\n\n const updateItemUse = (dt: number): void => {\n if (!useItemPlayer) return\n const e = heldEntry\n const c = e?.containerId ? fluids.container(e.containerId) : undefined\n const before = c?.liters\n useItemPlayer.update(dt)\n // a use that lasts repeats its sound (a gulp, a bite chewed) while the container gives something\n const useSound = e && useLiters !== null ? useSoundOf(e.item?.sounds, useItemName) : undefined\n if (useSound && e) {\n useSoundIn -= dt\n const now = e.containerId ? fluids.container(e.containerId)?.liters : undefined\n if (useSoundIn <= 0 && before !== undefined && now !== undefined && now < before) {\n playSound(useSound, v3(e.so.root.getWorldPosition(tmpV)), 0.6)\n useSoundIn = USE_SOUND_EVERY\n }\n }\n const seal = e?.item?.seal\n twisting = null\n if (e && seal?.openUse === useItemName && !e.opened) {\n twisting = openingProgress(useItemPlayer.def, useItemPlayer.time)\n seal.turn?.(wrapped.get(e.so.root) ?? e.so.root, { turned: twisting.stroke.turned, lift: twisting.lift })\n if (twisting.lift >= 1 || useItemPlayer.done) {\n openSeal(e)\n twisting = null\n }\n }\n if (e && useLiters !== null && before !== undefined) {\n const after = (e.containerId ? fluids.container(e.containerId)?.liters : undefined) ?? before\n e.fluidUsed = (e.fluidUsed ?? 0) + Math.max(0, before - after)\n if (e.opened && e.fluidStart) e.item?.seal?.contents?.(wrapped.get(e.so.root) ?? e.so.root, after / e.fluidStart)\n }\n if (useItemPlayer.done) {\n if (e && useLiters !== null && useItemName === 'eat') {\n const left = (e.containerId ? fluids.container(e.containerId)?.liters : undefined) ?? 0\n action('ate', t(left <= 1e-4 ? 'act.ate_all' : 'act.ate', { name: e.name, grams: Math.round((useLiters - left) * 1000) }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { liters: Math.round((useLiters - left) * 1000) / 1000 } })\n }\n useLiters = null\n useItemPlayer = null\n useItemName = ''\n const next = afterOpening\n afterOpening = null\n if (next && e?.opened) useItem(next)\n }\n }\n\n /**\n * Where the opening use (`ModuleItemSeal.openUse`) is at `time`: the hand's stroke over its `turn` keys (`twistStroke`), then the part rising off until its\n * `open` key (or its end).\n */\n const openingProgress = (def: ItemUseDef, time: number): { stroke: TwistStroke; lift: number } => {\n const keys = [...def.keys].sort((a, b) => a.t - b.t)\n const turning = keys.findIndex((k) => k.action === 'turn')\n const lastTurn = keys.map((k) => k.action).lastIndexOf('turn')\n const start = turning >= 0 ? keys[turning]!.t : 0\n const end = lastTurn >= 0 ? (keys[lastTurn + 1]?.t ?? def.duration) : start\n const openAt = keys.find((k) => k.action === 'open')?.t ?? def.duration\n const share = end > start ? (time - start) / (end - start) : 1\n const lift = time <= end ? 0 : openAt > end ? Math.min(1, (time - end) / (openAt - end)) : 1\n return { stroke: twistStroke(share), lift }\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 || r.object === GROUND_ID) 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 strikeGroundWith = (piece: Piece, energy: number): void => {\n const box = tmpBox.setFromObject(piece.root)\n const centre = box.getCenter(tmpV)\n const size = box.getSize(tmpV2)\n if (sceneryTopAt(centre.x, centre.z) > 0 || restingTopAt(centre.x, centre.z) > 0) return\n const result = terrain.strike('blunt', { x: centre.x, z: centre.z, energy, contactRadius: Math.max(size.x, size.z) / 2 })\n if (result.radius > 0) showGroundBlow(result)\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 strikeGroundWith(piece, energy)\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 if (code === 'KeyE' && pushByKey) {\n pushByKey = false\n // a tap on a leaf opens or closes it; a hold pushed the piece\n if (push.end() && !doors.use()) grab()\n }\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 // the kick has a key of its own (K by default); a weapon module that takes the same key first (the laser of a firearm) wins while that weapon is in hand\n if (kickKeys.includes(code) && !e.ctrlKey && !e.metaKey) {\n kick()\n return\n }\n switch (code) {\n case 'KeyE':\n if (e.repeat) break\n // a tap grabs, a hold against something that stands on the floor pushes it\n pushByKey = !heldPiece && push.begin()\n if (!pushByKey && (heldPiece || !doors.use())) 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 // Shift+F is the second use while C crouches\n const use = heldEntry?.uses[e.shiftKey && crouchOnC ? 1 : 0]\n if (use) useItem(use)\n break\n }\n case 'KeyC':\n if (heldEntry?.uses[1] && !crouchOnC) 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 'KeyN':\n setStrikeCombo(!comboOn)\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 // one aim ray per HUD refresh: the inspect line and the animation panel both read what the eye rests on, and a ray that crosses a vehicle\n // tests its drawn triangles (`surfaceRay`); `undefined` outside a refresh\n let hudAimHit: RayHit | null | undefined\n const inspectTarget = (): RayHit | null => {\n if (hudAimHit !== undefined) return hudAimHit\n aim()\n return rayWorld(aimO, aimD, 14)\n }\n\n /** What E does to the leaf in reach the eye rests on (open, close, locked). */\n const leafNote = (distance: number): string | undefined => {\n if (distance > DOOR_REACH) return undefined\n const leaf = doors.aimed()\n if (!leaf) return undefined\n return t(leaf.locked ? 'hud.door_hint_locked' : leaf.open ? 'hud.door_hint_close' : 'hud.door_hint_open')\n }\n\n /** The floor under the aim: the profile and the layer there, read from the terrain at the point the ray reached (the floor of a crater, not the flat top). */\n const groundInspect = (r: RayHit): InspectInfo => {\n const onFloor = terrain.raycast(aimO, aimD, r.distance + 3)\n const [x, , z] = onFloor?.point ?? r.point\n const column = terrain.columnAt(x, z)\n const materialName = S.text[`material.${column.material}`] ?? dStrings.materialNames[column.material] ?? column.material\n return {\n object: t('ground.name'),\n objectId: GROUND_ID,\n part: column.profile,\n material: materialName,\n status: '',\n hp: 0,\n maxHp: 0,\n temperature: 0,\n burning: false,\n char: column.scorch,\n melt: 0,\n dents: 0,\n holes: 0,\n cracks: 0,\n mass: 0,\n joints: [],\n distance: onFloor?.distance ?? r.distance,\n ground: { surface: terrainProfileName(column.profile, locale), material: materialName, dug: column.depth, remaining: column.remaining, scorch: column.scorch },\n }\n }\n\n const inspectInfo = (): InspectInfo | null => {\n const r = inspectTarget()\n if (!r) return null\n if (r.object === GROUND_ID) return groundInspect(r)\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: leafNote(r.distance) ?? 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 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 let moduleFrameCount = 0\n // the room's frame: 0.05 s is the clamp the loop always had, and 8 ms is the biggest budget of the loose queues of today\n // a system that throws: the display loop logs each id once and keeps going; a headless frame (room.update, a scenario step) holds the errors and throws them after the frame, as the loose loops did\n const headlessErrors = new Map<string, unknown>()\n const loggedErrors = new Set<string>()\n let headlessDepth = 0\n const reportFrameError = (error: unknown, system: { id: string; phase: string }): void => {\n if (headlessDepth > 0) {\n if (!headlessErrors.has(system.id)) headlessErrors.set(system.id, error)\n return\n }\n if (loggedErrors.has(system.id)) return\n loggedErrors.add(system.id)\n console.error(`test-room: ${system.id} (${system.phase}) threw`, error)\n }\n const runHeadless = (run: () => void): void => {\n headlessDepth++\n try {\n run()\n } catch (error) {\n headlessErrors.clear()\n throw error\n } finally {\n headlessDepth--\n }\n if (headlessDepth > 0 || headlessErrors.size === 0) return\n const errors = [...headlessErrors.values()]\n headlessErrors.clear()\n throw errors.length === 1 ? errors[0] : new AggregateError(errors, `${errors.length} systems threw in one frame`)\n }\n const scheduler = createScheduler({ maxFrameSeconds: 0.05, budgetMs: options.frameBudgetMs ?? 8, onError: reportFrameError })\n // the deferred queues share the scheduler's budget: the voices of the sound engine and the events of the destruction renderer\n const audioQueue = audio?.deferredQueue?.()\n if (audioQueue) scheduler.budget.register(audioQueue, DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.AUDIO_VOICES])\n scheduler.budget.register(renderer.deferredQueue(), DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS])\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 // CLAUDE.md, \"Memória\": after each clear the GPU counts come back to the scenery; when they keep growing clear after clear the room says so on screen\n const MEMORY_CLEARS = 4\n const memoryWatch = createMemoryWatch({\n clears: MEMORY_CLEARS,\n read: () => {\n const memory = (gl as { info?: { memory?: { geometries: number; textures: number } } }).info?.memory\n const heap = heapMB()\n return memory ? { geometries: memory.geometries, textures: memory.textures, ...(heap === undefined ? {} : { heapMB: heap }) } : undefined\n },\n })\n clearListeners.add(() => {\n const verdict = memoryWatch.cleared(activeBench ?? undefined)\n if (!verdict) return\n if (!verdict.leaking) {\n ui?.alert(null)\n return\n }\n const text = t('memory.leak', { geometries: verdict.grew.geometries, textures: verdict.grew.textures, clears: MEMORY_CLEARS })\n log.add({ channel: 'event', type: 'memory_leak', text, data: { ...verdict.after, grew: verdict.grew } })\n ui?.alert(`⚠ ${text}`)\n })\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 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 // lateSimulate, before the modules' frame callbacks: `dt` is simulated seconds; real time only drives input\n const simulateBeforeModules = (dt: number): void => {\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 destructionSound?.update(dt)\n for (const e of entries.values()) e.follower?.update?.()\n terrainView.sync(camera.position)\n showGroundFire(dt)\n vfx.update(dt)\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 }\n\n // lateSimulate, after the modules' frame callbacks\n const simulateAfterModules = (dt: number): void => {\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 // input: real time, what the player does (the world is paused or slowed without touching it)\n const updateInput = (dt: number, isPaused: boolean): void => {\n if (!ownsLoop) roomMetrics.frame(dt)\n frameStamp++\n seating.update()\n player.update(dt)\n if (pushByKey && !player.keys.has('KeyE')) {\n // the window lost the key without a key up\n pushByKey = false\n push.end()\n }\n push.step(isPaused ? 0 : dt)\n doors.step(isPaused ? 0 : dt)\n if (!isPaused) kickLight(dt)\n if (!isPaused) pushByPlayer(dt)\n else player.takeWish()\n stepAvatar(isPaused ? 0 : dt)\n stepFeet(isPaused ? 0 : dt)\n if (tiltKey || heldTilt > 0) {\n heldTilt = Math.max(0, Math.min(2.4, heldTilt + (tiltKey ? 2.2 : -3) * dt))\n }\n // a click that was pressed and let go between two frames still counts (useFirst stays until a frame reads it)\n if ((useHeld || useFirst) && !isPaused && !push.active) {\n if (tool.def.category === 'hand') {\n if (useFirst) handUse()\n } else if (useHeld) useTool(dt, !useFirst)\n useFirst = false\n }\n if (!isPaused) followHeld(dt)\n }\n\n // present: what the player reads (HUD, progress, log, bench metrics), by real time\n const updatePresent = (dt: number): void => {\n reachAvatar()\n if (progress && simTime - progress.at > 0.25) progress = null\n // the log first: it scrolls before anything of this frame touches the DOM, so reading its height lays nothing out\n ui?.flushLog()\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 hudAimHit = inspectTarget()\n try {\n return readHudState()\n } finally {\n hudAimHit = undefined\n }\n }\n const readHudState = (): 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', crouchOnC ? 'Shift+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: scheduler.timeScale,\n fast: fastForward,\n tap: isTapOn(),\n combo: combo ? comboOn : null,\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\n if (id !== '') followPart(pl.entry, id, obj, rest)\n }\n }\n const fpRest = new THREE.Matrix4()\n const fpNow = new THREE.Matrix4()\n const fpRoot = new THREE.Matrix4()\n const fpPart = new THREE.Matrix4()\n const fpPos = new THREE.Vector3()\n const fpQuat = new THREE.Quaternion()\n const fpScale = new THREE.Vector3()\n const fpEuler = new THREE.Euler()\n /**\n * Moves a part's collision shape the way its drawn group moved from rest: a door group turns on its hinge (its origin), so the shape goes round the hinge with it and does\n * not spin on its own centre into the body next to it.\n */\n const followPart = (e: Entry, id: string, obj: THREE_NS.Object3D, rest: { p: Vec3; r: Vec3 }): void => {\n const ps = specs.get(e.so.objectId)?.parts.find((p) => p.id === id)\n if (!ps || !obj.parent) return\n const root = e.so.root\n root.updateMatrixWorld(true)\n fpRoot.copy(root.matrixWorld).invert()\n fpNow.multiplyMatrices(fpRoot, obj.matrixWorld)\n fpEuler.set(rest.r[0], rest.r[1], rest.r[2])\n fpRest.compose(fpPos.set(rest.p[0], rest.p[1], rest.p[2]), fpQuat.setFromEuler(fpEuler), obj.scale)\n fpRest.premultiply(obj.parent.matrixWorld).premultiply(fpRoot)\n // the move of the group since rest, in the item's frame, carried onto the spec's pose of the part\n fpNow.multiply(fpRest.invert())\n const r0 = ps.rotation ?? ZERO\n fpPart.compose(fpPos.set(ps.position[0], ps.position[1], ps.position[2]), fpQuat.setFromEuler(fpEuler.set(r0[0], r0[1], r0[2])), fpScale.set(1, 1, 1))\n fpPart.premultiply(fpNow).decompose(fpPos, fpQuat, fpScale)\n fpEuler.setFromQuaternion(fpQuat)\n world.setPartPose(e.so.objectId, id, [fpPos.x, fpPos.y, fpPos.z], [fpEuler.x, fpEuler.y, fpEuler.z])\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: MetricRow[] = roomMetricIds.flatMap((id): MetricRow[] => {\n const value = sampled[id]\n return value === undefined ? [] : [{ id, name: t(`metric.${id}`), text: num(value, id === 'frame_ms' ? 1 : 0) }]\n })\n // stays on the counters line until a clear finds the memory back down\n const leak = memoryWatch.last\n if (leak?.leaking) room.push({ id: 'memory_leak', name: '⚠', text: t('memory.leak_short', { geometries: leak.grew.geometries, textures: leak.grew.textures, clears: MEMORY_CLEARS }) })\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 listenerDirection = new THREE.Vector3()\n const environment = options.environment ?? createEnvironmentBus()\n const audioSink = audio ? createAudioSink(audio) : undefined\n function emitHost(event: HostEvent): void {\n if (event.type === 'explosion') knockPlayer(event)\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 ...(graphics ? { graphics: graphics.host } : {}),\n ...(audioSink ? { audio: audioSink } : {}),\n environment,\n groundAt,\n // the terrain's material where the floor is the top; a table or a counter answers undefined (the module's default)\n surfaceAt: (x, z) => (Math.max(sceneryTopAt(x, z), restingTopAt(x, z)) > terrain.heightAt(x, z) ? undefined : terrain.columnAt(x, z).material),\n effects: vfx,\n particleLimit: () => options.debris?.particleLimit ?? DEFAULT_PARTICLE_LIMIT,\n lights,\n pools,\n loading,\n addView: (view) => moduleViews.add(view),\n setViewCamera: (view) => moduleViews.setMain((view as THREE_NS.Camera | null) ?? null),\n holdPlayer: (held) => player.setWalkHeld(held),\n ...(options.blastShove ? { blastShove: options.blastShove } : {}),\n blastReach: (point, target, ignore) => world.blastReach(point, target, ignore ? { ignore } : {}),\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 defer: (queue, queueOptions) => scheduler.budget.register(queue, queueOptions),\n onFrame(update, frameOptions) {\n return scheduler.add((ctx) => update(ctx.dt), { phase: frameOptions?.phase ?? 'lateSimulate', order: frameOptions?.order ?? 0, id: `module.frame#${moduleFrameCount++}` })\n },\n holdFrame: () => bodyHoldFrame(),\n reachFor(reach) {\n if (!avatar) {\n reach.onGrip?.()\n return\n }\n doors.reachFor(reach)\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 onReset(listener) {\n resetListeners.add(listener)\n return () => resetListeners.delete(listener)\n },\n addObject(itemId, place) {\n return addScenery(itemId, place.position, place.rotationY)\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 /** Every material a probe group draws: they go to the warmup's anchors, which keep them alive (a program is freed when the last material that uses it is disposed). */\n const materialsOf = (group: THREE_NS.Object3D): THREE_NS.Material[] => {\n const found = new Set<THREE_NS.Material>()\n group.traverse((object) => {\n const material = (object as THREE_NS.Mesh).material as THREE_NS.Material | THREE_NS.Material[] | undefined\n for (const each of Array.isArray(material) ? material : material ? [material] : []) found.add(each)\n })\n return [...found]\n }\n // the materials that decals, effects and liquids make on demand: each adapter's probes are drawn once at load (every light count is another set of programs), and their materials stay as anchors\n const probeOf = (id: string, adapter: { warmUpProbes(): { readonly group: unknown; dispose(): void } }): WarmupProbe => ({\n id,\n build() {\n const probe = adapter.warmUpProbes()\n const group = probe.group as THREE_NS.Object3D\n return { group, materials: materialsOf(group), dispose: () => probe.dispose() }\n },\n })\n warmup.register(probeOf('destruction', renderer))\n warmup.register(probeOf('vfx', vfx))\n warmup.register(probeOf('fluids', fluidView))\n warmup.register(spriteProbes(THREE))\n // a blast of every explosive and a flame, drawn a few frames at load: their programs link and their buffers reach the GPU before the first one goes off; nothing stays in the world, the log or the sound\n const warmedEffect = (id: string): EffectWarmup => {\n let handle: number | null = null\n return {\n id: `vfx:${id}`,\n play() {\n handle = vfx.play({ effect: id, point: [0, 0.1, -4], direction: [0, 1, 0], normal: [0, 1, 0] })\n },\n step: (dt) => vfx.update(dt),\n stop() {\n if (handle !== null) vfx.stop(handle)\n vfx.world.clear()\n vfx.update(0)\n },\n }\n }\n const catalogIds = vfx.catalog?.() ?? []\n for (const id of [...EXPLOSIVE_EFFECT_IDS, ...catalogIds.filter((id) => /fire|flame/i.test(id)).slice(0, 1)]) if (catalogIds.includes(id)) warmup.registerEffect(warmedEffect(id))\n let warmedUp = false\n const warmUp = (): void => {\n warmup.warmUp(gl, scene, camera, { lights, fogStates: WARMED_FOG_STATES, materials: pools.materials.registeredMaterials?.() ?? [] })\n warmedUp = true\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 pushable: ti.pushable,\n slow: ti.slow,\n fluid: ti.fluid,\n seal: ti.seal,\n weapon: ti.weapon,\n impl: ti.impl as TestRoomItem['impl'],\n animations: ti.animations,\n seats: ti.seats,\n sounds: ti.sounds,\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 let reportedState = bench.encode()\n bench.watch(() => {\n const encoded = bench.encode()\n if (encoded !== reportedState) {\n reportedState = encoded\n options.bench?.onChange?.(mod.id, encoded)\n }\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 // a scenario steps the world through the scheduler: input and present know they are scripted (ctx.scripted) and keep to what the step always did\n const step = (seconds: number): void => runHeadless(() => scheduler.advance(seconds, { dt: seconds > 6 ? 1 / 30 : FIXED_DT }))\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 = scheduler.paused\n scheduler.resume()\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 if (wasPaused) scheduler.pause()\n restoreScenery()\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 if (mod?.ground) terrain.setLayout(mod.ground)\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 // ----- the test table: a group of the catalogue laid on the `test_table` piece a page at a time, and the trials on one of its items\n const catalogGroups = (): 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 const tableOptions = options.testTable === false ? {} : (options.testTable ?? {})\n const tableScenery = tableOptions.scenery ?? 'test_table'\n const measured = new Map<string, { w: number; d: number }>()\n const testTable = createTestTable(\n {\n groups: catalogGroups,\n top: () => {\n const top = arena.tops.find((x) => x.id === tableScenery)\n return top && topOk(top) ? top : null\n },\n measure: (itemId) => {\n let size = measured.get(itemId)\n if (!size) {\n const item = catalogMap.get(itemId)\n const box = item ? new THREE.Box3().setFromObject(buildRoot(item)) : null\n size = box && !box.isEmpty() ? { w: box.max.x - box.min.x, d: box.max.z - box.min.z } : { w: 0.3, d: 0.3 }\n measured.set(itemId, size)\n }\n return size\n },\n spawn: (itemId, position) => spawn(itemId, position, 0),\n clear,\n resetAll,\n box: (objectId) => {\n const e = entries.get(objectId)\n if (!e || !world.has(objectId)) return null\n const box = new THREE.Box3().setFromObject(e.so.root)\n return box.isEmpty() ? null : { min: [box.min.x, box.min.y, box.min.z], max: [box.max.x, box.max.y, box.max.z] }\n },\n equip: (weapon) => {\n if (!arsenal.weapons.has(weapon)) return false\n if (heldEntry) releaseHeld()\n equip(weapon)\n room.waitUntilReady()\n return true\n },\n look: (eye, target) => lookAt(eye, target),\n use: (hold) => room.use(hold),\n blastAt: (weapon, point) => {\n const def = arsenal.weapons.get(weapon)\n const explosive = def?.action.kind === 'throwable' ? def.action.explosive : def?.action.kind === 'launcher' ? def.action.projectile : undefined\n return explosive !== undefined && explosives.blastAt(weapon, explosive, point)\n },\n log: (type, text, data) => action(type, text, { data }),\n translate: t,\n },\n tableOptions,\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 setStrikeCombo(on: boolean): void\n readonly strikeCombo: boolean | null\n kick(): boolean\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 testTable,\n spawn,\n clear,\n resetAll,\n setTool,\n useItem,\n use(hold = 0) {\n if (tool.def.category === 'hand') {\n const status = handUse()\n flush()\n return status\n }\n const status = useTool(FIXED_DT, false)\n flush()\n let t0 = 0\n while (t0 < hold) {\n useTool(FIXED_DT, true)\n directStep = true\n try {\n runHeadless(() => scheduler.advance(FIXED_DT))\n } finally {\n directStep = false\n }\n t0 += FIXED_DT\n }\n releaseTrigger()\n return status\n },\n grab,\n throwHeld,\n look(position, target) {\n lookAt(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: (dt: number): void => runHeadless(() => scheduler.frame(dt, { render: false, exact: true })),\n waitUntilReady(maxSeconds = 5) {\n let waited = 0\n while (tool.phase && waited < maxSeconds) {\n room.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 room.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 scheduler.pause()\n },\n resume() {\n scheduler.resume()\n },\n get paused() {\n return scheduler.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 scheduler.timeScale = on ? 0.25 : 1\n },\n setFastForward(on) {\n fastForward = on\n },\n setStrikeCombo,\n kick,\n get strikeCombo() {\n return combo ? comboOn : null\n },\n equip,\n terrain,\n openArea,\n modules: () => [...modules.values()].map((m) => ({ id: m.id, name: m.name, group: m.group, hasArea: typeof m.area === 'function' })),\n openAreaAsync: (area) => loading.busy(t('loading.open_area', { area: areaLabel(area) }), () => openArea(area)),\n loading,\n graphics: graphics?.controller ?? null,\n graphicsScreen: graphics?.screen ?? null,\n busy: (label, work, busyOptions) => loading.busy(label, work, busyOptions),\n loadModule,\n warmUp: () => {\n audio?.warmUp()\n warmUp()\n },\n animations: animationsOf,\n playAnimation,\n useLeaf: (objectId, part) => doors.useLeaf(objectId, part),\n leafOpening: (objectId, part) => doors.opening(objectId, part ?? leavesOf(objectId)[0]?.part ?? ''),\n leaves: (objectId) => leavesOf(objectId).map((l) => l.part),\n lockLeaf(objectId, locked = true, part) {\n const k = `${objectId}\\0${part ?? '*'}`\n if (locked) lockedLeaves.add(k)\n else lockedLeaves.delete(k)\n },\n get door() {\n return doors.state\n },\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) {\n downForced = state.down\n avatarState.down = state.down || Boolean(player.knocked?.down)\n }\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 get playerPosition() {\n return player.position\n },\n get playerKnock() {\n return player.knocked\n },\n sit: (objectId, seatId) => seating.sit(objectId, seatId),\n stand: () => seating.stand(),\n get seat() {\n return seating.seat\n },\n push: { begin: () => push.begin(), end: () => push.end(), setWalk: (walk) => push.setWalk(walk), get state() { return push.state } },\n setCameraMode,\n get cameraMode() {\n return cameraMode\n },\n metrics() {\n return { room: roomMetrics.sample(), module: moduleMetrics() }\n },\n frameStats: () => scheduler.stats(),\n lights,\n webgl: gl,\n dispose() {\n destructionSound?.dispose()\n if (ownAudio) audio?.dispose()\n for (const detach of detachers.values()) detach()\n detachers.clear()\n moduleViews.dispose()\n for (const store of benches.values()) store.dispose()\n benches.clear()\n stopLoop?.()\n disposePacer?.()\n scheduler.dispose()\n window.removeEventListener('resize', onResize)\n player.dispose()\n ui?.dispose()\n graphics?.dispose()\n loading.dispose()\n renderer.dispose()\n vfx.dispose()\n lights.dispose()\n pools.materials.dispose()\n pools.geometries.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 ...(graphics?.screen ? { onGraphics: () => graphics.screen?.open() } : {}),\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 ...(combo ? { combo: { label: combo.name?.[locale] ?? combo.id, onToggle: () => setStrikeCombo(!comboOn) } } : {}),\n ...(arsenal.weapons.has('kick') ? { kick: { label: `${t('ui.kick')} (${kickKeys.map((key) => key.replace(/^Key/, '')).join('/')})`, onKick: () => void kick() } } : {}),\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 ...(options.testTable !== false && arena.tops.some((x) => x.id === tableScenery) ? { testTable } : {}),\n })\n ui.hud(hudState())\n showBench()\n }\n\n let directStep = false\n scheduler.add(\n (ctx) => {\n if (directStep) return\n if (!ctx.scripted) return updateInput(ctx.dt, ctx.paused)\n seating.update()\n player.update(0)\n push.step(ctx.dt)\n doors.step(ctx.dt)\n followHeld(ctx.dt)\n },\n { phase: 'input', id: 'room.input' },\n )\n scheduler.add((ctx) => simulateBeforeModules(ctx.dt), { phase: 'lateSimulate', order: -1000, id: 'room.simulate' })\n scheduler.add((ctx) => simulateAfterModules(ctx.dt), { phase: 'lateSimulate', order: 1000, id: 'room.simulate-end' })\n scheduler.add(\n (ctx) => {\n if (ctx.simulated && !ctx.scripted) updatePresent(ctx.realDt)\n },\n { phase: 'present', id: 'room.present' },\n )\n scheduler.add((ctx) => lights.present([camera.position.x, camera.position.y, camera.position.z], ctx.realDt), { phase: 'present', order: 10, id: 'room.lights' })\n let stopLoop: (() => void) | undefined\n let disposePacer: (() => void) | undefined\n if (ownRenderer) {\n let nextLightsCheck = 0\n let warnedState = ''\n // modules that add a light of their own after the load (or change the fog, the tone mapping...) change the program key of every lit material: warm again when the sealed state breaks\n scheduler.add(\n (ctx) => {\n if (ctx.scripted) return\n const now = performance.now()\n if (now < nextLightsCheck) return\n nextLightsCheck = now + LIGHTS_CHECK_MS\n const state = lights.check(gl, scene)\n if (warmedUp && (state.ok || state.actual === warnedState)) return\n warnedState = state.actual\n warmUp()\n },\n { phase: 'render', order: -1000, id: 'room.lights-check' },\n )\n // a GPU slower than the CPU fills the driver queue and stalls the compositor for the whole queue: keep it a few frames behind at most\n const pacer = createFramePacer(typeof gl.getContext === 'function' ? (gl.getContext() as unknown as WebGL2RenderingContext) : null, options.framesInFlight === undefined ? {} : { framesInFlight: options.framesInFlight })\n disposePacer = () => pacer.dispose()\n scheduler.add(\n (ctx) => {\n if (!ctx.scripted && !pacer.ready()) return\n for (const batcher of batchers.values()) batcher.update()\n const restoreCamera = room.applyCamera()\n graphics?.beforeRender(camera)\n gl.render(scene, debugView ?? moduleViews.main(camera))\n moduleViews.render(scene)\n graphics?.afterRender()\n restoreCamera()\n pacer.submitted()\n roomMetrics.rendered()\n if (!ctx.scripted) graphics?.frameEnd()\n },\n { phase: 'render', id: 'room.render' },\n )\n try {\n stopLoop = startLoop(scheduler, {\n onFrame: (realSeconds) => {\n graphics?.frameStart()\n roomMetrics.frame(realSeconds)\n },\n skipSimulation: () => scenarioRunning,\n // the player's frame cap (Gráficos → Limite de FPS)\n ...(graphics ? { minFrameMs: () => graphics.controller.minFrameMs() } : {}),\n })\n ownsLoop = true\n } catch {\n // no display frames here (a worker): the host calls room.update\n }\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 { BODY_FOLEY_BANK } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { SWING_LEAD_SECONDS, hitSoundId, landSoundId, swingSoundId } from '@adatechnology/game-contracts'\nimport type { BlowId, BlowTarget, GaitId, SurfaceId, Vec3 } from '@adatechnology/game-contracts'\n\n/** How each melee tool of the arsenal strikes, by tool id; a tool not here goes by its category (`melee_blade` cuts, `melee_blunt` and `hand` knock). */\nexport const DEFAULT_TOOL_BLOWS: Readonly<Record<string, BlowId>> = {\n hand: 'punch',\n fists: 'punch',\n kick: 'kick',\n shove: 'shove',\n knife: 'blade',\n machete: 'blade',\n utility_knife: 'blade',\n axe: 'chop',\n hammer: 'blunt',\n claw_hammer: 'blunt',\n sledgehammer: 'blunt',\n baseball_bat: 'blunt',\n crowbar: 'blunt',\n wrench: 'blunt',\n}\n\n/** The blow a tool strikes with, or null when it is not a melee tool. */\nexport function blowOfTool(id: string, category: string, table: Readonly<Record<string, BlowId>> = DEFAULT_TOOL_BLOWS): BlowId | null {\n const listed = table[id]\n if (listed) return listed\n if (category === 'melee_blade') return 'blade'\n if (category === 'melee_blunt' || category === 'hand') return id === 'kick' ? 'kick' : 'blunt'\n return null\n}\n\n/** Joules of a blow to its level: a jab (about 40 J) is 0.6, a full swing of a sledgehammer (400 J and up) is 1. */\nconst levelOf = (energyJ: number): number => Math.max(0.5, Math.min(1, 0.5 + energyJ / 800))\n\n/** Metres of ground per footfall when no body says where its feet are: a walking stride, a running one. */\nexport const STRIDE_METRES: Readonly<Record<GaitId, number>> = { walk: 0.72, run: 1.05 }\n\nexport type BodySounds = {\n /** The swing of a blow through the air, `delay` seconds from now (its loudest part `SWING_LEAD_SECONDS` later); nothing for a blow without one. */\n swing(blow: BlowId, position: Vec3, delay?: number): void\n /** The body's side of a blow that landed (knuckles, sole, blade, club) on a body, a head or an object; the material's own impact plays beside it. */\n hit(blow: BlowId, target: Exclude<BlowTarget, 'air'>, position: Vec3, energyJ: number): void\n jump(position: Vec3): void\n /** The feet meet the floor after a fall of `speed` m/s on `surface`. */\n land(surface: SurfaceId, speed: number, position: Vec3): void\n /** A thrown body hits a wall or the floor at `speed` m/s: the fall of the body, and the hurt cry when it was hard (`SLAM_HURT_SPEED`). */\n slam(speed: number, position: Vec3): void\n /** Ids played, oldest first, for the room's checks (the last 64). */\n readonly played: readonly string[]\n}\n\n/** From this speed (m/s) a body thrown into a wall or onto the floor is hurt: it cries out. */\nexport const SLAM_HURT_SPEED = 3.5\n\n/** The test room's body sounds on its engine (the bank is registered in it); with no engine every call does nothing. */\nexport function createBodySounds(audio: AudioEngine | null): BodySounds {\n audio?.register(BODY_FOLEY_BANK)\n const played: string[] = []\n const play = (id: string, position: Vec3, volume: number, delay = 0): void => {\n played.push(id)\n if (played.length > 64) played.shift()\n audio?.play(id, { position, volume, urgent: true, ...(delay > 0 ? { delay } : {}) })\n }\n return {\n swing(blow, position, delay = 0) {\n const id = swingSoundId(blow)\n if (id) play(id, position, 0.8, delay)\n },\n hit(blow, target, position, energyJ) {\n play(hitSoundId(blow, target), position, levelOf(energyJ))\n },\n jump: (position) => play('jump', position, 0.6),\n land: (surface, speed, position) => play(landSoundId(surface, speed), position, Math.min(1, 0.45 + speed / 8)),\n slam(speed, position) {\n play('body_fall', position, Math.min(1, 0.4 + speed / 8))\n if (speed >= SLAM_HURT_SPEED) play('player_hurt', position, Math.min(1, 0.5 + speed / 12))\n },\n played,\n }\n}\n\n/** Seconds before the contact the swing of `blow` starts, so its loudest part meets the hit. */\nexport const swingLead = (blow: BlowId): number => SWING_LEAD_SECONDS[blow]\n\n/** Counts strides along the ground the player walked, for a room with no body to put the feet down: one footfall per stride, the feet alternating. */\nexport function createStrideCounter(stride: Readonly<Record<GaitId, number>> = STRIDE_METRES): { advance(metres: number, gait: GaitId): 'left' | 'right' | null; reset(): void } {\n // the first footfall comes after half a stride: starting to walk is a step\n let left = stride.walk / 2\n let next: 'left' | 'right' = 'right'\n return {\n advance(metres, gait) {\n left -= metres\n if (left > 0) return null\n left += stride[gait]\n const foot = next\n next = next === 'right' ? 'left' : 'right'\n return foot\n },\n reset() {\n left = stride.walk / 2\n next = 'right'\n },\n }\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 { markKitOrigin } from '@adatechnology/game-contracts'\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 follow?: SceneryObject['follow']\n label?: string\n top?: SceneryObject['top']\n spout?: SceneryObject['spout']\n free?: boolean\n pushable?: boolean\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 /** A top made of boards (`SceneryObject.top.parts`): each holds what is over it while it stands; `topPart` is one of them. */\n boards?: ReadonlyArray<{ part: string; minX: number; maxX: number; minZ: number; maxZ: number }>\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 /** The object of each collider (`colliders[i]`), `null` for what is not an object of the world (the tap's post). */\n colliderIds: Array<string | null>\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, follow: o.follow, label: o.label, top: o.top, spout: o.spout, free: o.free, pushable: o.pushable }))\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 // the room's own floor, grid and ruler (not a piece: the pieces in the room come from their packages)\n const group = markKitOrigin(new THREE.Group(), { owner: 'game-test-room', kind: 'room' })\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 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 boards = (o.top.parts ?? []).flatMap((part) => {\n const f = specBounds(THREE, o.spec, o.position, o.rotationY, { onlyPart: part })\n return f ? [{ part, minX: f.minX, maxX: f.maxX, minZ: f.minZ, maxZ: f.maxZ }] : []\n })\n const whole = specBounds(THREE, o.spec, o.position, o.rotationY, { onlyPart: o.top.part })\n if (!whole) continue\n const b = boards.length === 0 ? whole : { minX: Math.min(...boards.map((f) => f.minX)), maxX: Math.max(...boards.map((f) => f.maxX)), minZ: Math.min(...boards.map((f) => f.minZ)), maxZ: Math.max(...boards.map((f) => f.maxZ)) }\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, ...(boards.length > 0 ? { boards } : {}) })\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 const colliderIds: Array<string | null> = []\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 colliderIds.push(o.id)\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 colliderIds.push(null)\n }\n }\n\n return {\n group,\n objects: sceneryObjects,\n surfaces,\n colliders,\n colliderIds,\n playerStart,\n wallZ,\n tops,\n tapSpout,\n sun,\n }\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","/**\n * Which sound the hand makes with what it works: the item's own choice (`TestableItem.sounds`) first, else what its material says. The ids are those of the\n * foley bank of game-audio (`FOLEY_BANK`), named after the sound list, so a recorded take under the same id replaces the synthesised one.\n */\nimport { LEAF_FOLEY_SETS } from '@adatechnology/game-audio'\nimport type { LeafFoley, PickupClass } from '@adatechnology/game-audio'\nimport type { ItemSounds } from '@adatechnology/game-contracts'\nimport type { MaterialDef } from '@adatechnology/game-destruction'\n\n/** The pickup class of a material: by its tags (metal, glass and ceramic, plastic and rubber, wood, cloth, plants), paper by its id; plastic when nothing says. */\nexport function pickupClassOf(def: MaterialDef | undefined): PickupClass {\n if (!def) return 'plastic'\n const tags = def.tags ?? []\n if (def.id === 'paper') return 'paper'\n if (tags.includes('metal')) return 'metal'\n if (tags.includes('glass') || tags.includes('ceramic')) return 'glass'\n if (tags.includes('plastic') || tags.includes('rubber')) return 'plastic'\n if (tags.includes('wood')) return 'wood'\n if (tags.includes('fabric')) return 'fabric'\n if (tags.includes('plant')) return 'food'\n return 'plastic'\n}\n\n/** The sound of picking the item up. */\nexport const pickupSoundOf = (sounds: ItemSounds | undefined, def: MaterialDef | undefined): string => `item_pickup_${sounds?.handling ?? pickupClassOf(def)}`\n\n/**\n * The sound set of a leaf: the one the item names for this part (or for `*`), else a drawer for a leaf that slides, else a metal or a wooden door by the\n * sound class of its material (`impact_metal`, `impact_glass` ring like metal). An unknown set name falls back the same way.\n */\nexport function leafFoleyOf(sounds: ItemSounds | undefined, part: string, impactKey: string, slides: boolean): LeafFoley {\n const named = sounds?.leaves?.[part] ?? sounds?.leaves?.['*']\n const set = named ? LEAF_FOLEY_SETS[named] : undefined\n if (set) return set\n if (slides) return LEAF_FOLEY_SETS.drawer\n return /metal|glass/.test(impactKey) ? LEAF_FOLEY_SETS.metal_door : LEAF_FOLEY_SETS.wood_door\n}\n\n/** The sound of opening the item's seal: the item's own, else a metal seal is a can's tab and anything else a screw cap. */\nexport const openSoundOf = (sounds: ItemSounds | undefined, def: MaterialDef | undefined): string => sounds?.open ?? (pickupClassOf(def) === 'metal' ? 'can_open' : 'bottle_open')\n\n/** The sound each use repeats while it lasts, when the item does not name its own. */\nexport const USE_SOUNDS: Readonly<Record<string, string>> = {\n drink: 'drink_gulp',\n sip: 'drink_gulp',\n chug: 'drink_gulp',\n eat: 'eat_chew',\n}\n/** Seconds between two sounds of a use that lasts (a gulp, a bite chewed). */\nexport const USE_SOUND_EVERY = 0.55\n\n/** The sound a use repeats, if any. */\nexport const useSoundOf = (sounds: ItemSounds | undefined, useId: string): string | undefined => sounds?.uses?.[useId] ?? USE_SOUNDS[useId]\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 { releaseObject3D } from '@adatechnology/game-shapes-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 { ExplosiveBody, backblastEffect, blastEffect, createExplosiveBody, tripwireSegment } from '@adatechnology/game-weapons'\nimport type { Arsenal, Detonation, 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 /** Sets the explosive `explosive` off at `point` at once, as if `weapon` had put it there (the test table's blast); false for an unknown explosive. */\n blastAt: (weapon: string, explosive: string, point: Vec3) => boolean\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 // a projectile's mesh is its own (geometry, material, the model the host built for it): freed when it leaves the scene, keeping what the scene still draws\n const drop = (objects: THREE_NS.Object3D[]): void => {\n for (const object of objects) object.removeFromParent()\n releaseObject3D(objects, { keep: scene })\n }\n\n const clear = (): void => {\n projectiles.length = 0\n drop(meshes)\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 const extraAt = meshes.indexOf(extra)\n if (extraAt >= 0) meshes.splice(extraAt, 1)\n }\n const meshAt = meshes.indexOf(projectile.mesh)\n if (meshAt >= 0) meshes.splice(meshAt, 1)\n drop([...(projectile.attached ?? []), projectile.mesh])\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, effect: detonation.explosive })\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 blastAt = (weapon: string, explosive: string, point: Vec3): boolean => {\n const def = arsenal.explosives.get(explosive)\n if (!def) return false\n const event = new ExplosiveBody({ explosive: def, origin: point, triggers: ['remote'], rules: arsenal.rules.explosives }).trigger('remote')\n if (event?.type !== 'detonate') return false\n detonate({ weapon } as Projectile, event.detonation)\n return true\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, blastAt, 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 { Vec3 } from '@adatechnology/game-contracts'\n\n/**\n * What a trial does to one object: a shot, a punch, a knife blow, a flame on it or a blast beside it. The test table runs one on the object it has picked, so every item of the\n * catalogue can be tried one by one with the same hit.\n */\nexport type TrialKind = 'shot' | 'punch' | 'stab' | 'fire' | 'blast'\n\nexport const TRIAL_KINDS: readonly TrialKind[] = ['shot', 'punch', 'stab', 'fire', 'blast']\n\n/**\n * How the room runs a trial: the tool (an id of the arsenal), where the player stands and how long the trigger is held.\n * `distance` is metres from the front face of the object (the side the player comes from) to the eye, `lift` metres the eye is above the object's centre, `hold` seconds the\n * trigger stays down (a flame). For `blast` the explosive of `weapon` goes off `distance` metres behind the object, and the player watches from `watch` metres in front.\n */\nexport interface TrialTool {\n readonly weapon: string\n readonly distance: number\n readonly lift: number\n readonly hold?: number\n readonly watch?: number\n}\n\n/** The tools of the trials: a 9 mm pistol, the fists, a knife, a flamethrower and a fragmentation grenade, all of the default arsenal. */\nexport const DEFAULT_TRIALS: Readonly<Record<TrialKind, TrialTool>> = {\n shot: { weapon: 'pistol_9mm', distance: 2.5, lift: 0.5 },\n punch: { weapon: 'fists', distance: 0.3, lift: 0.15 },\n stab: { weapon: 'knife', distance: 0.22, lift: 0.1 },\n fire: { weapon: 'flamethrower', distance: 1.6, lift: 0.4, hold: 0.8 },\n blast: { weapon: 'frag_grenade', distance: 0.3, lift: 1, watch: 6 },\n}\n\n/** The test table: which piece of the arena it is, the gap between the things laid on it and the trial tools (each one replaces the default's fields it gives). */\nexport interface TestTableOptions {\n /** Id of the `scenery` piece with a `top` the items are laid on (default `test_table`). */\n readonly scenery?: string\n /** Metres between two items on the table (default 0.12). */\n readonly gap?: number\n /** Metres kept free at each end of the table (default 0.1). */\n readonly margin?: number\n readonly trials?: Partial<Record<TrialKind, Partial<TrialTool>>>\n}\n\n/** One item laid on the table. */\nexport interface TestTableObject {\n readonly objectId: string\n readonly itemId: string\n readonly name: string\n}\n\n/** The page of a group that lies on the table now. */\nexport interface TestTablePage {\n /** The catalogue group (its translated name, as the catalogue tabs show it). */\n readonly group: string\n /** Index of the page, from 0. */\n readonly page: number\n /** Index in the group of the first item on the table, and how many the group has. */\n readonly first: number\n readonly total: number\n readonly objects: readonly TestTableObject[]\n /** The object the trials hit (the first one until another is picked). */\n readonly selected: string | null\n readonly hasPrev: boolean\n readonly hasNext: boolean\n}\n\n/** The test table of the room: lays a group of the catalogue on the table a page at a time, picks one object and runs the trials on it. */\nexport interface TestTable {\n /** The groups of the catalogue that can be laid (every group with items). */\n groups(): string[]\n /** Every item that can be laid, with its group (what a search looks in). */\n items(): Array<{ id: string; name: string; group: string }>\n /** Clears the room and lays page `page` (default 0) of `group`; null when the room has no table or the group no items. */\n open(group: string, page?: number): TestTablePage | null\n next(): TestTablePage | null\n prev(): TestTablePage | null\n /** Lays the page of the group that holds `itemId` and picks it; null when no group has it (or the room has no table). */\n find(itemId: string): TestTablePage | null\n /** Puts the table and the page back as they were before the trials: everything is restored and laid again. */\n relay(): TestTablePage | null\n state(): TestTablePage | null\n /** Picks the object the trials hit; false when it is not on the table. */\n select(objectId: string): boolean\n /** Runs a trial on the picked object (or on `objectId`): the room equips the tool, puts the player in front of it, aims and uses it. False when there is nothing to hit. */\n trial(kind: TrialKind, objectId?: string): boolean\n /** Follow the table: a page laid, an object picked, a trial run. Returns the unsubscribe function. */\n on(listener: (page: TestTablePage | null) => void): () => void\n}\n\nexport const resolveTrials = (overrides: TestTableOptions['trials'] = {}): Record<TrialKind, TrialTool> =>\n Object.fromEntries(TRIAL_KINDS.map((kind) => [kind, { ...DEFAULT_TRIALS[kind], ...overrides[kind] }])) as Record<TrialKind, TrialTool>\n\n/**\n * How many items, from `start`, fit side by side along a table of `length` metres with `gap` between them (`width(i)` is the width of item i). At least one, so an item longer\n * than the table still gets a page of its own. Pure.\n */\nexport function fitRow(width: (index: number) => number, start: number, total: number, length: number, gap: number): number {\n let used = 0\n let count = 0\n for (let i = start; i < total; i++) {\n const w = width(i)\n const next = count === 0 ? w : used + gap + w\n if (count > 0 && next > length) break\n used = next\n count++\n }\n return count\n}\n\n/** The x of the centre of each item of a row laid side by side, centred on `centreX`, with `gap` between them. Pure. */\nexport function rowCentres(widths: readonly number[], centreX: number, gap: number): number[] {\n const length = widths.reduce((sum, w) => sum + w, 0) + gap * Math.max(0, widths.length - 1)\n let x = centreX - length / 2\n return widths.map((w) => {\n const centre = x + w / 2\n x += w + gap\n return centre\n })\n}\n\n/**\n * Where the player's eye goes for a trial on an object whose box is `min`..`max` (world), and where it looks. The player comes from +z (the side of the room the table faces),\n * so a melee blow lands on the front face. A blast is watched from `watch` metres. Pure.\n */\nexport function trialView(tool: TrialTool, kind: TrialKind, min: Vec3, max: Vec3): { eye: Vec3; target: Vec3 } {\n const target: Vec3 = [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2]\n const away = kind === 'blast' ? (tool.watch ?? 6) : tool.distance\n return { eye: [target[0], target[1] + tool.lift, max[2] + away], target }\n}\n\n/** What the test table needs of the room. */\nexport interface TestTableContext {\n /** The catalogue by group: the ids and names of the items of each one. */\n readonly groups: () => ReadonlyMap<string, ReadonlyArray<{ readonly id: string; readonly name: string }>>\n /** The top of the table in the world (null: the room has no such piece, or its top is broken). */\n readonly top: () => { readonly minX: number; readonly maxX: number; readonly minZ: number; readonly maxZ: number; readonly top: number } | null\n /** Width (x) and depth (z) of an item's model at rotation 0, metres. */\n readonly measure: (itemId: string) => { readonly w: number; readonly d: number }\n readonly spawn: (itemId: string, position: Vec3) => { readonly objectId: string }\n readonly clear: () => void\n readonly resetAll: () => void\n /** The world box of an object still in the room, else null. */\n readonly box: (objectId: string) => { readonly min: Vec3; readonly max: Vec3 } | null\n /** Puts the tool in hand (added to the hotbar) and waits for its draw. False for an id the arsenal does not have. */\n readonly equip: (weapon: string) => boolean\n readonly look: (eye: Vec3, target: Vec3) => void\n readonly use: (hold: number) => void\n /** Sets off the explosive of `weapon` at `point`. False when the weapon throws or places no explosive. */\n readonly blastAt: (weapon: string, point: Vec3) => boolean\n readonly log: (type: string, text: string, data: Record<string, unknown>) => void\n readonly translate: (key: string, vars?: Record<string, string | number>) => string\n}\n\n/** The test table over a room (see `TestTable`). */\nexport function createTestTable(context: TestTableContext, options: TestTableOptions = {}): TestTable {\n const gap = options.gap ?? 0.12\n const margin = options.margin ?? 0.1\n const trials = resolveTrials(options.trials)\n const listeners = new Set<(page: TestTablePage | null) => void>()\n let current: { group: string; page: number; first: number; objects: TestTableObject[]; selected: string | null } | null = null\n\n const itemsOf = (group: string) => context.groups().get(group) ?? []\n const emit = (): TestTablePage | null => {\n const page = state()\n for (const listener of [...listeners]) listener(page)\n return page\n }\n const state = (): TestTablePage | null => {\n if (!current) return null\n const total = itemsOf(current.group).length\n const live = current.objects.filter((o) => context.box(o.objectId))\n return {\n group: current.group,\n page: current.page,\n first: current.first,\n total,\n objects: live,\n selected: current.selected,\n hasPrev: current.page > 0,\n hasNext: current.first + current.objects.length < total,\n }\n }\n\n // the bounds of each page of each group: page n is [bounds[n], bounds[n + 1]), found one after the other (a page holds what fits on the table), up to the group's length\n const bounds = new Map<string, number[]>()\n const widthOf = (itemId: string): number => context.measure(itemId).w\n /** The bounds of `group` known at least up to the page that holds item `index` (or page `page`). */\n const boundsUntil = (group: string, length: number, until: (bound: number[]) => boolean): number[] => {\n const items = itemsOf(group)\n const known = bounds.get(group) ?? [0]\n bounds.set(group, known)\n while (known[known.length - 1] < items.length && !until(known)) {\n const first = known[known.length - 1]\n known.push(first + fitRow((i) => widthOf(items[i].id), first, items.length, length, gap))\n }\n return known\n }\n const lengthOf = (top: NonNullable<ReturnType<TestTableContext['top']>>): number => top.maxX - top.minX - 2 * margin\n\n const lay = (group: string, page: number, top: NonNullable<ReturnType<TestTableContext['top']>>): TestTablePage | null => {\n const items = itemsOf(group)\n const known = boundsUntil(group, lengthOf(top), (b) => b.length > page + 1)\n const index = Math.max(0, Math.min(page, known.length - 2))\n const first = known[index]\n const laid = items.slice(first, known[index + 1])\n context.clear()\n const sizes = laid.map((item) => context.measure(item.id))\n const centres = rowCentres(sizes.map((size) => size.w), (top.minX + top.maxX) / 2, gap)\n // along the front edge of the table (the player's side), so a blow from in front reaches each one\n const objects = laid.map((item, i) => {\n const d = Math.min(sizes[i].d, top.maxZ - top.minZ)\n const { objectId } = context.spawn(item.id, [centres[i], top.top, top.maxZ - margin / 2 - d / 2])\n return { objectId, itemId: item.id, name: item.name }\n })\n current = { group, page: index, first, objects, selected: objects[0]?.objectId ?? null }\n context.log('test_table', context.translate('act.test_table', { group, from: first + 1, to: first + laid.length, total: items.length }), { group, page: index, items: laid.map((i) => i.id) })\n return emit()\n }\n\n const open = (group: string, page = 0): TestTablePage | null => {\n const top = context.top()\n if (!itemsOf(group).length || !top) return null\n return lay(group, page, top)\n }\n\n const find = (itemId: string): TestTablePage | null => {\n const top = context.top()\n const group = [...context.groups()].find(([, items]) => items.some((i) => i.id === itemId))?.[0]\n if (group === undefined || !top) return null\n const index = itemsOf(group).findIndex((i) => i.id === itemId)\n // only the widths are measured on the way: nothing is laid until the page that holds the item\n const known = boundsUntil(group, lengthOf(top), (b) => b[b.length - 1] > index)\n lay(group, known.findIndex((bound, i) => bound <= index && index < known[i + 1]), top)\n const target = current?.objects.find((o) => o.itemId === itemId)\n if (current && target) current.selected = target.objectId\n return emit()\n }\n\n const selected = (objectId?: string): string | null => {\n const id = objectId ?? current?.selected ?? null\n return id && context.box(id) ? id : null\n }\n\n const trial = (kind: TrialKind, objectId?: string): boolean => {\n const id = selected(objectId)\n const box = id ? context.box(id) : null\n if (!id || !box) return false\n const tool = trials[kind]\n if (!context.equip(tool.weapon)) return false\n const view = trialView(tool, kind, box.min, box.max)\n context.look(view.eye, view.target)\n const name = current?.objects.find((o) => o.objectId === id)?.name ?? id\n context.log('trial', context.translate(`act.trial.${kind}`, { name }), { kind, objectId: id, weapon: tool.weapon })\n if (kind === 'blast') {\n const point: Vec3 = [view.target[0], box.min[1] + 0.05, box.min[2] - tool.distance]\n return context.blastAt(tool.weapon, point)\n }\n context.use(tool.hold ?? 0)\n emit()\n return true\n }\n\n return {\n groups: () => [...context.groups()].filter(([, items]) => items.length > 0).map(([group]) => group),\n items: () => [...context.groups()].flatMap(([group, items]) => items.map((item) => ({ id: item.id, name: item.name, group }))),\n open,\n find,\n next: () => {\n const page = state()\n return page?.hasNext ? open(page.group, page.page + 1) : page\n },\n prev: () => {\n const page = state()\n return page?.hasPrev ? open(page.group, page.page - 1) : page\n },\n relay: () => {\n if (!current) return null\n context.resetAll()\n return open(current.group, current.page)\n },\n state,\n select: (objectId) => {\n if (!current || !current.objects.some((o) => o.objectId === objectId) || !context.box(objectId)) return false\n current.selected = objectId\n emit()\n return true\n },\n trial,\n on: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\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 * as THREE_NS from 'three'\nimport type { BusySink, BusyTask, HostGraphics } from '@adatechnology/game-contracts'\nimport { createGraphicsController, frameLoad, targetFrameMs } from '@adatechnology/game-graphics'\nimport type { GraphicsController, StorageLike } from '@adatechnology/game-graphics'\nimport { createFpsOverlay, createGraphicsScreen } from '@adatechnology/game-graphics/screen'\nimport type { FpsOverlay, GraphicsScreen } from '@adatechnology/game-graphics/screen'\nimport { createGpuFrameTimer, createGraphicsView, gpuName } from '@adatechnology/game-graphics-three'\nimport type { GpuFrameTimer, GraphicsView } from '@adatechnology/game-graphics-three'\n\nconst QUIET_FRAMES = 10\n\n/** The room's graphics settings (`TestRoomOptions.graphics`). */\nexport interface RoomGraphicsOptions {\n /** Where the player's choice is kept (default `localStorage`; null keeps it in memory). */\n readonly storage?: StorageLike | null\n /** The key it is kept under (default `adatechnology.graphics`). */\n readonly key?: string\n /** The short test of the first load, seconds (default 3; 0 skips it and starts the automatic mode at Alta). */\n readonly calibrationSeconds?: number\n /**\n * When the calibration of a first run starts: `idle` (default) after a few drawn frames with nothing on the loading indicator, or `manual`, where the page calls\n * `room.graphics.calibrateIfNeeded()` once its content is in (a page that loads its content before it shows the room).\n */\n readonly calibrate?: 'idle' | 'manual'\n}\n\nexport interface RoomGraphics {\n readonly controller: GraphicsController\n readonly view: GraphicsView\n readonly screen: GraphicsScreen | null\n /** What modules get as `host.graphics`. */\n readonly host: HostGraphics\n /** Marks the start of a display frame (before the scheduler runs it). */\n frameStart(): void\n /** Around the draw call of the frame: the GPU timer and the near shadow box that follows the camera. */\n beforeRender(camera: THREE_NS.Camera): void\n afterRender(): void\n /** The end of a frame that was drawn: what it cost goes to the automatic mode, with the wall time since the last drawn frame (a frame the pacer skipped is in it). */\n frameEnd(): void\n dispose(): void\n}\n\n/**\n * The graphics settings on the test room: the controller of `game-graphics` (choice in the browser, calibration, automatic mode), the three.js view of\n * `game-graphics-three` on the room's renderer, camera and sun, the settings screen and the frame counter, and the calibration shown on the loading indicator.\n */\nexport function createRoomGraphics(o: {\n readonly gl: THREE_NS.WebGLRenderer\n readonly camera: THREE_NS.PerspectiveCamera\n readonly sun: THREE_NS.DirectionalLight\n readonly container: HTMLElement\n readonly locale: string\n readonly loading: BusySink & { readonly active: boolean }\n readonly label: string\n readonly ui: boolean\n readonly options: RoomGraphicsOptions\n}): RoomGraphics {\n const view = createGraphicsView({ renderer: o.gl, camera: o.camera, sun: o.sun })\n const seconds = o.options.calibrationSeconds ?? 3\n const controller = createGraphicsController({\n store: { ...(o.options.storage !== undefined ? { storage: o.options.storage } : {}), ...(o.options.key ? { key: o.options.key } : {}) },\n gpu: gpuName(o.gl),\n benchmark: seconds > 0 ? { durationS: seconds } : false,\n // the room measures its own frames once it is up, not the loading of its content\n calibrate: 'manual',\n apply: (e) => view.apply(e),\n })\n const timer: GpuFrameTimer = createGpuFrameTimer(o.gl)\n const screen = o.ui ? createGraphicsScreen({ container: o.container, controller, locale: o.locale }) : null\n const overlay: FpsOverlay | null = o.ui ? createFpsOverlay({ container: o.container, controller, locale: o.locale }) : null\n const listeners = new Set<() => void>()\n let lastHorde = controller.settings.hordeDetail\n const unsubscribe = controller.subscribe(() => {\n if (controller.settings.hordeDetail === lastHorde) return\n lastHorde = controller.settings.hordeDetail\n for (const l of listeners) l()\n })\n\n // the calibration is a task of the loading indicator, with its bar\n let task: BusyTask | null = null\n const syncTask = (): void => {\n if (controller.phase === 'calibrating') {\n task ??= o.loading.begin(o.label, { total: 100 })\n task.step(`${Math.round(controller.calibrationProgress * 100)}%`, Math.round(controller.calibrationProgress * 100))\n } else if (task) {\n task.end()\n task = null\n }\n }\n syncTask()\n\n let started = 0\n // drawn frames in a row with nothing loading: the calibration waits for a few (the first frames after a load compile and upload)\n let quiet = 0\n let lastEnd = 0\n return {\n controller,\n view,\n screen,\n host: {\n hordeDetail: () => controller.settings.hordeDetail,\n onChange(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n report: (key, value) => controller.report(key, value),\n },\n frameStart() {\n started = performance.now()\n },\n beforeRender(camera) {\n view.hold()\n view.follow(camera.position.x, camera.position.z)\n timer.begin()\n },\n afterRender() {\n timer.end()\n },\n frameEnd() {\n const now = performance.now()\n const realSeconds = lastEnd > 0 ? (now - lastEnd) / 1000 : 0\n lastEnd = now\n if (!(realSeconds > 0)) return\n const cpuMs = started > 0 ? now - started : realSeconds * 1000\n controller.frame(realSeconds, frameLoad({ cpuMs, gpuMs: timer.ms, intervalMs: realSeconds * 1000, targetMs: targetFrameMs(controller.settings.fpsCap) }))\n quiet = o.loading.active && !task ? 0 : quiet + 1\n if (o.options.calibrate !== 'manual' && quiet >= QUIET_FRAMES) controller.calibrateIfNeeded()\n syncTask()\n },\n dispose() {\n task?.end()\n unsubscribe()\n listeners.clear()\n timer.dispose()\n screen?.dispose()\n overlay?.dispose()\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', 'geometries', 'textures', 'heap_mb']\n\nconst WINDOW_S = 0.5\n\ninterface RenderInfo {\n info?: { render?: { calls: number; triangles: number }; memory?: { geometries: number; textures: 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\n/** The JS heap in MB where the browser tells it (Chrome's `performance.memory`), undefined elsewhere. */\nexport function heapMB(): number | undefined {\n const memory = (globalThis.performance as { memory?: { usedJSHeapSize?: number } } | undefined)?.memory\n return typeof memory?.usedJSHeapSize === 'number' ? memory.usedJSHeapSize / 1048576 : undefined\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 put('geometries', gl.info?.memory?.geometries)\n put('textures', gl.info?.memory?.textures)\n put('heap_mb', heapMB())\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","/**\n * Watches what the room keeps after each clear (CLAUDE.md, \"Memória\"). Right after a clear the scene holds only the scenery, so the GPU counts of three\n * (geometries and textures alive, `renderer.info.memory`) should come back to the same level every time. A cache fills once (the first use of a\n * model, a palette); a leak grows on every clear. The watch warns when the counts grew on each of the last clears and, over them, by more than the\n * budget: something taken out of the scene was not released (`discardObject3D` / `releaseObject3D` of game-shapes-three) or a list still holds it.\n */\nexport interface MemorySample {\n readonly geometries: number\n readonly textures: number\n /** JS heap in MB, where the browser tells it (Chrome). Shown, never used to warn: without a forced GC it moves with the garbage. */\n readonly heapMB?: number\n}\n\nexport interface MemoryWatchOptions {\n /** Reads the counts now. */\n readonly read: () => MemorySample | undefined\n /** How many clears in a row must each grow before the watch warns (default 4). */\n readonly clears?: number\n /** Growth over those clears that is a leak and not a cache (defaults: 40 geometries, 4 textures). */\n readonly budget?: { readonly geometries?: number; readonly textures?: number }\n}\n\nexport interface MemoryVerdict {\n /** The counts right after the last clear. */\n readonly after: MemorySample\n /** Growth over the watched clears (last minus first). */\n readonly grew: { readonly geometries: number; readonly textures: number }\n /** True when the counts keep growing clear after clear past the budget. */\n readonly leaking: boolean\n}\n\nexport interface MemoryWatch {\n /**\n * Call right after the room clears; returns the verdict, or undefined when the counts are not readable. `context` names what was on the table\n * (the area or bench): clears are compared only with clears of the same context, so visiting a new area (its caches filling) is not a leak.\n */\n cleared(context?: string): MemoryVerdict | undefined\n /** The last verdict (none before the first clear). */\n readonly last: MemoryVerdict | undefined\n /** Forgets every history. */\n reset(): void\n}\n\nexport function createMemoryWatch(options: MemoryWatchOptions): MemoryWatch {\n const clears = Math.max(2, options.clears ?? 4)\n const budget = { geometries: options.budget?.geometries ?? 40, textures: options.budget?.textures ?? 4 }\n const histories = new Map<string, MemorySample[]>()\n let last: MemoryVerdict | undefined\n return {\n cleared(where) {\n const now = options.read()\n if (!now) return undefined\n const key = where ?? ''\n const history = histories.get(key) ?? []\n histories.set(key, history)\n history.push(now)\n if (history.length > clears + 1) history.shift()\n const first = history[0]\n const grew = { geometries: now.geometries - first.geometries, textures: now.textures - first.textures }\n let growing = history.length === clears + 1\n for (let i = 1; growing && i < history.length; i++) {\n const before = history[i - 1]\n const after = history[i]\n growing = after.geometries > before.geometries || after.textures > before.textures\n }\n const leaking = growing && (grew.geometries > budget.geometries || grew.textures > budget.textures)\n last = { after: now, grew, leaking }\n return last\n },\n get last() {\n return last\n },\n reset() {\n histories.clear()\n last = undefined\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 // food eaten with its liquid: the host says what was eaten, not what was drunk\n if (ev.eaten) break\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 { stepKnock } from '@adatechnology/game-contracts'\nimport type { Knock } from '@adatechnology/game-contracts'\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 /**\n * What stands where the body would be, asked on every step with the feet height: `floor` is the highest top it can step onto there (a low\n * heap of debris; 0 is the floor), `blocked` that something taller is in the way. Without it the floor is flat and only the colliders stop.\n */\n footing?: (x: number, z: number, radius: number, feet: number) => { floor: number; blocked: boolean }\n /** Half size of the arena. */\n limit: number\n start: Vec3\n hooks: PlayerHooks\n /** `KeyboardEvent.code`s that crouch (default `['KeyC']`): a tap stays crouched until the next tap, a longer press crouches while held. Ctrl is not one by default: Ctrl+W closes the tab and no page can stop it. */\n crouchKeys?: readonly string[]\n /** Height of the ground the player walks on (a crater, a heap). Default flat at 0. */\n floorAt?: (x: number, z: number) => number\n /** The feet leave the floor on a jump, or meet it again after a fall (`speed`: m/s downward at the touch). For the body's sounds. */\n /**\n * A body thrown by a knock hit something on its way (`obstacle`: a wall, a car, a cupboard, which stopped it) or the floor (`ground`, falling): `speed` m/s into it,\n * `direction` the unit way it was going. For the impact on what it hit, the sound and the hurt.\n */\n onSlam?(event: PlayerSlam): void\n onFeet?: (event: PlayerFeetEvent) => void\n}\n\n/** What the feet did this frame: a jump, or a landing with the speed of the fall (a jump on the spot comes down at about 4.6 m/s). */\nexport type PlayerFeetEvent = { readonly type: 'jump' } | { readonly type: 'land'; readonly speed: number }\n\n/** A thrown body meeting a wall or the floor (`PlayerOptions.onSlam`). */\nexport interface PlayerSlam {\n readonly against: 'obstacle' | 'ground'\n readonly speed: number\n readonly direction: Vec3\n}\n\n/** Slower than this (m/s) a thrown body meeting something only stops: no slam. */\nexport const SLAM_MIN_SPEED = 1.5\n\n/** Below this fall speed (m/s) a touch of the floor is a step down, not a landing. */\nexport const LANDING_MIN_SPEED = 1\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 /** The feet are on the floor (not in a jump or a fall). */\n readonly grounded: boolean\n /** Whether the player is crouched (a crouch key tapped or 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 /** Where the keys ask to go on the floor: a unit `[x, z]`, or `[0, 0]`. */\n readonly walkIntent: readonly [number, number]\n /** Whether a body can stand at this point (arena, colliders, blockers). */\n canStand(x: number, z: number): boolean\n /** While held the keys do not walk or jump: whoever holds it moves the player with `moveBy` (pushing a piece of furniture). */\n setWalkHeld(held: boolean): void\n /** Seated, the body stays at the height its pose set: what it sits on is not a step to climb and it does not fall. */\n setSeated(seated: boolean): void\n /** Lowers the eye by this many metres, eased (bending over something low); 0 stands up. */\n setBend(metres: number): void\n /** Keeps the view within `range` radians of `yaw`; null frees it. */\n setLookLimit(limit: { readonly yaw: number; readonly range: number } | null): void\n /** The floor offset the player tried to walk (keys, `moveBy`, `walk`) since the last call, blocked or not; the call resets it. */\n takeWish(): [number, number]\n /** Walk by hand (tests): moves the player `forward` and `right` metres along its facing. */\n walk(forward: number, right: number): void\n /**\n * A blast's shove (`knockOf` of game-contracts): the body is thrown with its velocity, slides and stops against what is in the way, and, when the knock takes it off\n * its feet, falls, lies a while and gets up. The keys do nothing until it stands again. A second knock while one is on adds its velocity.\n */\n knock(knock: Knock): void\n /** The knock on now, or null: `lying` 0..1 says how far down the body is. */\n readonly knocked: Readonly<Knock> | null\n /** Whether the knock that put the body down pushed it toward its facing (falls face down) rather than from the front (falls on its back). */\n readonly knockedForward: boolean\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\n/** Share of the radius the feet stand on: at the edge of a heap the player steps down instead of hovering on its corner. */\nconst FOOT = 0.5\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 BEND_RATE = 7\n/** The widths of the body, against its full width, that say how deep something has come into it. */\nconst CLEAR_SHARES = [1, 0.75, 0.5, 0.25]\n/** A crouch key released within this many seconds was a tap, which stays crouched; a longer press was a hold. */\nconst CROUCH_TAP = 0.25\nconst RUN = 6.2\nconst JUMP = 4.6\nconst GRAVITY = 13\nconst FLOOR_CLIMB_SPEED = 3\nconst FLOOR_FALL_SPEED = 6\nconst LOOK = 0.0022\n/** Height of the eye (m above the floor) of a body lying on its back, where the view turns up to (radians above the level), and how far it rolls to one side. */\nconst LYING_EYE = 0.3\nconst LYING_PITCH = 1.05\nconst LYING_ROLL = 0.35\n/** Where the view of a body fallen face down turns to: below the level, at the ground under the face (radians). */\nconst LYING_PITCH_FACE_DOWN = -1.05\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 bend = 0\n let bendTarget = 0\n let vy = 0\n /** The floor under the feet at the last update (0 before the first). */\n let floorUnder = 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 let crouchLatched = false\n let crouchPress: { held: number; latched: boolean } | null = null\n const isCrouched = (): boolean => crouchLatched || isCrouchHeld()\n const pressCrouch = (code: string): void => {\n if (crouchKeys.includes(code) && !isCrouchHeld()) crouchPress = { held: 0, latched: crouchLatched }\n }\n const releaseCrouch = (code: string): void => {\n if (!crouchKeys.includes(code) || !crouchPress || isCrouchHeld()) return\n crouchLatched = crouchPress.held < CROUCH_TAP ? !crouchPress.latched : false\n crouchPress = null\n }\n const euler = new THREE.Euler(0, 0, 0, 'YXZ')\n const floorHere = (): number => o.floorAt?.(px.x, px.z) ?? 0\n let floorLevel = 0\n // the eye eases over a rim and falls into a hole instead of jumping with every cell of the ground\n const followFloor = (dt: number): void => {\n const gap = floorHere() - floorLevel\n const reach = (gap > 0 ? FLOOR_CLIMB_SPEED : FLOOR_FALL_SPEED) * dt\n floorLevel += Math.max(-reach, Math.min(reach, gap))\n }\n\n /** The knock of a blast on the body, while it lasts. */\n let knocked: Knock | null = null\n let knockedForward = false\n /** Which way the view rolls when the body falls: toward the side the shove came from. */\n let rollSide = 1\n const apply = (): void => {\n const lying = knocked?.lying ?? 0\n // a fall eases in: the eye goes down to the floor and the view turns up to the sky, a little onto one side (on its back, thrown away from the blast)\n const fallen = lying * lying * (3 - 2 * lying)\n euler.set(pitch + ((knockedForward ? LYING_PITCH_FACE_DOWN : LYING_PITCH) - pitch) * fallen, yaw, LYING_ROLL * rollSide * fallen, 'YXZ')\n cam.quaternion.setFromEuler(euler)\n const standing = eye - CROUCH_DROP * crouch - bend\n cam.position.set(px.x, floorLevel + y + standing + (LYING_EYE - standing) * fallen, px.z)\n cam.updateMatrixWorld(true)\n }\n apply()\n\n const outside = (x: number, z: number): boolean => Math.abs(x) > o.limit - PLAYER_RADIUS || Math.abs(z) > o.limit - PLAYER_RADIUS\n const blocked = (x: number, z: number, radius = PLAYER_RADIUS): boolean => {\n if (outside(x, z)) return true\n for (const c of o.colliders) if (x > c[0] - radius && x < c[2] + radius && z > c[1] - radius && z < c[3] + radius) return true\n if (o.blockers) for (const isBlocked of o.blockers) if (isBlocked(x, z, radius)) return true\n return o.footing ? o.footing(x, z, radius, y).blocked : false\n }\n /** The widest body that fits where the player is, or null when not even the narrowest does: how deep something has come into the player. */\n const clearRadius = (): number | null => {\n for (const share of CLEAR_SHARES) if (!blocked(px.x, px.z, PLAYER_RADIUS * share)) return PLAYER_RADIUS * share\n return null\n }\n // what the player tried to walk since the last `takeWish` (blocked or not): the room pushes what stands in the way by it\n const wish = { x: 0, z: 0 }\n const move = (dx: number, dz: number): void => {\n wish.x += dx\n wish.z += dz\n // caught in something (a piece fell on the spot, a piece settling touches the body) the player walks out of it, and never deeper; right inside, every way is out\n const radius = clearRadius()\n const free = (x: number, z: number): boolean => (radius === null ? !outside(x, z) : !blocked(x, z, radius))\n // in steps no longer than a third of the body's width, so a long move (a slow frame, the end of a scripted walk) cannot jump over a thin obstacle\n const steps = Math.max(1, Math.ceil(Math.hypot(dx, dz) / (PLAYER_RADIUS / 3)))\n const sx = dx / steps\n const sz = dz / steps\n for (let i = 0; i < steps; i++) {\n if (free(px.x + sx, px.z)) px.x += sx\n if (free(px.x, px.z + sz)) px.z += sz\n }\n }\n\n const walkKeys = (): readonly [number, number] => {\n const f = (keys.has('KeyW') || keys.has('ArrowUp') ? 1 : 0) - (keys.has('KeyS') || keys.has('ArrowDown') ? 1 : 0)\n const r = (keys.has('KeyD') || keys.has('ArrowRight') ? 1 : 0) - (keys.has('KeyA') || keys.has('ArrowLeft') ? 1 : 0)\n if (!f && !r) return [0, 0]\n const len = Math.hypot(f, r)\n return [(-Math.sin(yaw) * f + Math.cos(yaw) * r) / len, (-Math.cos(yaw) * f - Math.sin(yaw) * r) / len]\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 let walkHeld = false\n let seated = false\n let lookLimit: { readonly yaw: number; readonly range: number } | null = null\n const look = (dx: number, dy: number): void => {\n yaw -= dx * LOOK\n if (lookLimit) {\n const off = Math.atan2(Math.sin(yaw - lookLimit.yaw), Math.cos(yaw - lookLimit.yaw))\n yaw = lookLimit.yaw + Math.max(-lookLimit.range, Math.min(lookLimit.range, off))\n }\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) {\n pressCrouch(e.code)\n keys.add(e.code)\n }\n o.hooks.key(e.code, true, e)\n }\n const onKeyUp = (e: KeyboardEvent): void => {\n keys.delete(e.code)\n releaseCrouch(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 => {\n keys.clear()\n crouchPress = null\n }\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 /** One step of a knock: the body flies and slides, stopped by the colliders like a walk, falls, lies and gets up; the keys wait. */\n const stepKnocked = (dt: number): void => {\n const k = knocked\n if (!k) return\n const floor = Math.max(floorHere(), o.footing?.(px.x, px.z, PLAYER_RADIUS * FOOT, y).floor ?? -Infinity)\n floorUnder = floor\n const at = { x: px.x, y, z: px.z }\n const fromY = y\n const fallSpeed = Math.max(0, -k.velocity[1])\n const done = stepKnock(k, at, dt, () => floor, true)\n const wantX = at.x - px.x\n const wantZ = at.z - px.z\n const fromX = px.x\n const fromZ = px.z\n const vx = k.velocity[0]\n const vz = k.velocity[2]\n move(wantX, wantZ)\n // what stopped the body takes the speed that went into it, and the body slams into it\n const stoppedX = Math.abs(wantX) > 1e-6 && Math.abs(px.x - fromX) < Math.abs(wantX) * 0.5\n const stoppedZ = Math.abs(wantZ) > 1e-6 && Math.abs(px.z - fromZ) < Math.abs(wantZ) * 0.5\n if (stoppedX) k.velocity[0] = 0\n if (stoppedZ) k.velocity[2] = 0\n const into = Math.hypot(stoppedX ? vx : 0, stoppedZ ? vz : 0)\n if (into >= SLAM_MIN_SPEED) o.onSlam?.({ against: 'obstacle', speed: into, direction: [stoppedX ? vx / into : 0, 0, stoppedZ ? vz / into : 0] })\n y = at.y\n if (fromY > floor && y <= floor) {\n const speed = Math.max(fallSpeed, (fromY - y) / Math.max(dt, 1e-6))\n if (k.down && speed >= SLAM_MIN_SPEED * 0.5) o.onSlam?.({ against: 'ground', speed: Math.hypot(speed, Math.hypot(vx, vz) * 0.5), direction: [0, -1, 0] })\n else if (speed >= LANDING_MIN_SPEED) o.onFeet?.({ type: 'land', speed })\n }\n vy = 0\n walked = dt > 0 ? Math.hypot(px.x - fromX, px.z - fromZ) / dt : 0\n running = false\n if (done) knocked = null\n followFloor(dt)\n apply()\n }\n\n return {\n get walkIntent() {\n return walkKeys()\n },\n canStand(x, z) {\n return !blocked(x, z)\n },\n setWalkHeld(held) {\n walkHeld = held\n },\n setSeated(value) {\n seated = value\n y = 0\n vy = 0\n },\n setBend(metres) {\n bendTarget = metres\n },\n setLookLimit(limit) {\n lookLimit = limit\n },\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 floorLevel + y\n },\n get position() {\n return [px.x, floorLevel + y, px.z] as Vec3\n },\n get speed() {\n return walked\n },\n get running() {\n return running\n },\n get grounded() {\n return y <= floorUnder + 1e-3 && vy <= 0\n },\n get crouching() {\n return isCrouched()\n },\n keys,\n knock(next) {\n if (seated) return\n if (knocked) {\n knocked.velocity = [knocked.velocity[0] + next.velocity[0], knocked.velocity[1] + next.velocity[1], knocked.velocity[2] + next.velocity[2]]\n knocked.airborne ||= next.airborne\n knocked.down ||= next.down\n } else knocked = { ...next, velocity: [...next.velocity] }\n if (next.down) {\n // the view rolls to the side the shove pushes toward, seen from the facing\n const right = Math.cos(yaw) * next.velocity[0] - Math.sin(yaw) * next.velocity[2]\n rollSide = right >= 0 ? -1 : 1\n // pushed from behind the body pitches onto its face; from the front (the blast seen) onto its back\n knockedForward = -Math.sin(yaw) * next.velocity[0] - Math.cos(yaw) * next.velocity[2] > 0\n crouchLatched = false\n }\n if (knocked.airborne) vy = Math.max(vy, knocked.velocity[1])\n },\n get knocked() {\n return knocked\n },\n get knockedForward() {\n return knockedForward\n },\n update(dt) {\n if (knocked) {\n stepKnocked(dt)\n return\n }\n if (crouchPress) crouchPress.held += dt\n const crouched = isCrouched()\n crouch += ((crouched ? 1 : 0) - crouch) * Math.min(1, dt * CROUCH_RATE)\n if (!crouched && crouch < 1e-3) crouch = 0\n bend += (bendTarget - bend) * Math.min(1, dt * BEND_RATE)\n const run = !crouched && !walkHeld && (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 const [walkX, walkZ] = walkKeys()\n if ((walkX || walkZ || keys.has('Space')) && eye !== EYE) eye = EYE\n if ((walkX || walkZ) && !walkHeld) move(walkX * speed * dt, walkZ * speed * dt)\n walked = dt > 0 ? Math.hypot(px.x - fromX, px.z - fromZ) / dt : 0\n running = run && walked > 0\n if (seated) {\n followFloor(dt)\n apply()\n return\n }\n // the floor under the feet: a step up is taken at once, a drop is a fall\n const floor = Math.max(floorHere(), o.footing?.(px.x, px.z, PLAYER_RADIUS * FOOT, y).floor ?? -Infinity)\n floorUnder = floor\n if (y < floor && vy <= 0) y = floor\n if (y <= floor && keys.has('Space') && !walkHeld) {\n vy = JUMP\n o.onFeet?.({ type: 'jump' })\n }\n if (y > floor || vy > 0) {\n vy -= GRAVITY * dt\n y += vy * dt\n if (y <= floor) {\n y = floor\n if (-vy >= LANDING_MIN_SPEED) o.onFeet?.({ type: 'land', speed: -vy })\n vy = 0\n }\n }\n followFloor(dt)\n apply()\n },\n setPose(position, yw, pt) {\n knocked = null\n px.x = position[0]\n px.z = position[2]\n floorLevel = floorHere()\n eye = position[1] - floorLevel\n y = 0\n vy = 0\n yaw = yw\n pitch = pt\n apply()\n },\n look(position, target) {\n knocked = null\n px.x = position[0]\n px.z = position[2]\n floorLevel = floorHere()\n eye = position[1] - floorLevel\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 takeWish() {\n const out: [number, number] = [wish.x, wish.z]\n wish.x = 0\n wish.z = 0\n return out\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 room's side of pushing furniture: finds what the player leans on, asks `createFurniturePush` (game-player) how it goes, tests the volume of the piece before each\n * step (the world, the walls of the arena, the blockers of the modules) and moves it with the player. The animations read `avatarState` and `handTargets`.\n */\nimport type * as THREE_NS from 'three'\nimport type { DestructionWorld, Vec3 } from '@adatechnology/game-destruction'\nimport type { Piece } from '@adatechnology/game-destruction-three'\nimport type { HandTargets } from '@adatechnology/game-contracts'\nimport { createFurniturePush } from '@adatechnology/game-player'\nimport type { FurniturePushBlock, FurniturePushPhase, FurniturePushRules } from '@adatechnology/game-player'\nimport type { Player } from './player'\n\n/** How close to the piece the player must be to lean on it, metres from the feet to its box. */\nexport const PUSH_REACH = 1.1\n/** Where the player ends up from the face, for the arms to be straight but not stretched. */\nconst STANDOFF = 0.58\n/** Lower than this the hands go on top of the piece and the player bends over it, closer. */\nconst LOW_TOP = 0.95\nconst LOW_STANDOFF = 0.42\nconst LOW_HAND_ON_TOP = 0.07\n/** How far above the top of a low piece the eye stays, and the most the player bends. */\nconst LOW_EYE_OVER_TOP = 0.62\nconst MAX_BEND = 0.8\nconst STANDING_EYE = 1.7\nconst APPROACH_SPEED = 1.2\n/** A piece whose base is higher than this is on something, not on the floor. */\nconst MAX_BASE_HEIGHT = 0.12\nconst FLOOR_CLEARANCE = 0.06\nconst SWEEP_SKIN = 0.015\n/** Hands: half the gap between them, the highest they go, how far under the top of the piece. */\nconst HAND_SPREAD = 0.2\nconst HAND_TOP = 1.35\nconst HAND_UNDER_TOP = 0.05\nconst LOOK_RANGE = 0.9\nconst DRAG_GRAIN_METRES = 0.3\nconst RING_DELAY_S = 0.1\n\nexport type RoomPushTarget = {\n readonly objectId: string\n readonly root: THREE_NS.Object3D\n readonly name: string\n /** The body it already has, or null when it stands free and only becomes one when it moves. */\n readonly piece: Piece | null\n}\n\nexport type RoomPushOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n readonly world: DestructionWorld\n readonly arena: { readonly limit: number; readonly colliders: ReadonlyArray<readonly [number, number, number, number]> }\n readonly blockers: ReadonlySet<(x: number, z: number, radius: number) => boolean>\n readonly rules?: Partial<FurniturePushRules>\n /** What the eye rests on and could be pushed, or null. */\n pick(): RoomPushTarget | null\n massOf(objectId: string): number\n materialOf(objectId: string): string | undefined\n /** Turns a free-standing object into a body (the first step it takes). */\n makePiece(objectId: string): Piece\n dragSound(objectId: string, point: Vec3, volume: number): void\n hitSound(objectId: string, point: Vec3): void\n onEvent(event: RoomPushEvent): void\n ring(value: number | null): void\n /** The room draws a body whose pose bends over a low piece: the player's own eye is not lowered (without a body the eye is the camera and bends). */\n hasBody?(): boolean\n}\n\nexport type RoomPushEvent =\n | { readonly type: 'grip' | 'release'; readonly objectId: string; readonly name: string; readonly massKg: number }\n | { readonly type: 'engaged' | 'too_heavy' | 'obstacle'; readonly objectId: string; readonly name: string; readonly massKg: number }\n\nexport type RoomPushState = {\n readonly objectId: string\n readonly phase: FurniturePushPhase\n readonly progress: number\n readonly block: FurniturePushBlock\n readonly massKg: number\n}\n\nexport interface RoomPush {\n readonly active: boolean\n readonly state: RoomPushState | null\n /** What the body does this frame, for the avatar. */\n /** The piece is low: the body bends over it. */\n readonly isBent: boolean\n readonly avatarState: { readonly phase: Exclude<FurniturePushPhase, 'idle'>; readonly progress: number } | null\n /** Starts leaning on what the eye rests on; false when there is nothing to lean on. */\n begin(): boolean\n /** Lets go. Answers true when the press was short enough to be a tap (the room then grabs). */\n end(): boolean\n /** Scripted walk (scenarios), world `[x, z]`; null gives the walk back to the keys. */\n setWalk(walk: readonly [number, number] | null): void\n step(dt: number): void\n handTargets(): HandTargets | null\n}\n\ntype Leaning = {\n readonly target: RoomPushTarget\n readonly massKg: number\n piece: Piece | null\n readonly min: [number, number, number]\n readonly max: [number, number, number]\n /** The point of the near face the hands go to, and the way into the face (unit, on the floor). */\n readonly contact: [number, number]\n readonly into: [number, number]\n readonly isLow: boolean\n readonly palm: [number, number, number, number]\n}\n\n/** The closest point of a box (on the floor plane) to a point; the way in when the point is inside the box is the way the player faces. */\nfunction contactOf(box: { min: readonly number[]; max: readonly number[] }, player: Player): { contact: [number, number]; into: [number, number]; distance: number } {\n const x = Math.max(box.min[0] ?? 0, Math.min(box.max[0] ?? 0, player.x))\n const z = Math.max(box.min[2] ?? 0, Math.min(box.max[2] ?? 0, player.z))\n const dx = x - player.x\n const dz = z - player.z\n const distance = Math.hypot(dx, dz)\n if (distance < 1e-3) return { contact: [x, z], into: [-Math.sin(player.yaw), -Math.cos(player.yaw)], distance: 0 }\n return { contact: [x, z], into: [dx / distance, dz / distance], distance }\n}\n\nexport function createRoomPush(options: RoomPushOptions): RoomPush {\n const { THREE, player, world, arena, blockers } = options\n const control = createFurniturePush(options.rules)\n const box3 = new THREE.Box3()\n let leaning: Leaning | null = null\n let scriptedWalk: readonly [number, number] | null = null\n let dragged = 0\n\n const event = (type: RoomPushEvent['type'], lean: Leaning): void => options.onEvent({ type, objectId: lean.target.objectId, name: lean.target.name, massKg: lean.massKg })\n\n const standsClear = (lean: Leaning, dx: number, dz: number): boolean => {\n const minX = lean.min[0] + dx\n const maxX = lean.max[0] + dx\n const minZ = lean.min[2] + dz\n const maxZ = lean.max[2] + dz\n if (Math.max(Math.abs(minX), Math.abs(maxX)) > arena.limit || Math.max(Math.abs(minZ), Math.abs(maxZ)) > arena.limit) return false\n for (const c of arena.colliders) {\n // what the piece already stands in does not hold it: it can always back out\n if (lean.max[0] > c[0] && lean.min[0] < c[2] && lean.max[2] > c[1] && lean.min[2] < c[3]) continue\n if (maxX > c[0] && minX < c[2] && maxZ > c[1] && minZ < c[3]) return false\n }\n if (blockers.size === 0) return true\n const midX = (minX + maxX) / 2\n const midZ = (minZ + maxZ) / 2\n for (const [x, z] of [[minX, minZ], [maxX, minZ], [minX, maxZ], [maxX, maxZ], [midX, minZ], [midX, maxZ], [minX, midZ], [maxX, midZ]] as const) {\n for (const isBlocked of blockers) if (isBlocked(x, z, 0)) return false\n }\n return true\n }\n\n const isFree = (lean: Leaning, dx: number, dz: number): boolean => {\n if (!standsClear(lean, dx, dz) || !player.canStand(player.x + dx, player.z + dz)) return false\n const distance = Math.hypot(dx, dz)\n const box = { min: [lean.min[0], lean.min[1] + FLOOR_CLEARANCE, lean.min[2]] as Vec3, max: [lean.max[0], lean.max[1], lean.max[2]] as Vec3 }\n return world.sweepBox(box, [dx / distance, 0, dz / distance], distance + SWEEP_SKIN, { ignore: lean.target.objectId }) === null\n }\n\n const release = (): void => {\n const lean = leaning\n if (!lean) return\n leaning = null\n if (lean.piece) {\n lean.piece.held = false\n lean.piece.sleeping = false\n lean.piece.velocity = [0, 0, 0]\n }\n control.release()\n player.setWalkHeld(false)\n if (!options.hasBody?.()) player.setBend(0)\n player.setLookLimit(null)\n options.ring(null)\n event('release', lean)\n }\n\n const approach = (lean: Leaning, dt: number): void => {\n const off = Math.hypot(lean.contact[0] - player.x, lean.contact[1] - player.z) - (lean.isLow ? LOW_STANDOFF : STANDOFF)\n const move = Math.sign(off) * Math.min(Math.abs(off), APPROACH_SPEED * dt)\n if (move !== 0) player.moveBy(lean.into[0] * move, lean.into[1] * move)\n }\n\n const moveWith = (lean: Leaning, dx: number, dz: number): void => {\n lean.target.root.position.x += dx\n lean.target.root.position.z += dz\n lean.target.root.updateMatrixWorld(true)\n player.moveBy(dx, dz)\n lean.min[0] += dx\n lean.max[0] += dx\n lean.min[2] += dz\n lean.max[2] += dz\n lean.contact[0] += dx\n lean.contact[1] += dz\n dragged += Math.hypot(dx, dz)\n if (dragged < DRAG_GRAIN_METRES) return\n dragged = 0\n options.dragSound(lean.target.objectId, [lean.contact[0], lean.min[1], lean.contact[1]], 0.3 + 0.5 * Math.min(1, lean.massKg / 100))\n }\n\n return {\n get active() {\n return leaning !== null\n },\n get state() {\n return leaning ? { objectId: leaning.target.objectId, phase: control.phase, progress: control.progress, block: control.block, massKg: leaning.massKg } : null\n },\n get isBent() {\n return leaning?.isLow ?? false\n },\n get avatarState() {\n return leaning && control.phase !== 'idle' ? { phase: control.phase, progress: control.progress } : null\n },\n begin() {\n if (leaning) return true\n const target = options.pick()\n if (!target || !world.has(target.objectId)) return false\n box3.setFromObject(target.root)\n if (box3.min.y > player.feet + MAX_BASE_HEIGHT) return false\n const min: [number, number, number] = [box3.min.x, box3.min.y, box3.min.z]\n const max: [number, number, number] = [box3.max.x, box3.max.y, box3.max.z]\n const { contact, into, distance } = contactOf({ min, max }, player)\n if (distance > PUSH_REACH) return false\n const massKg = options.massOf(target.objectId)\n const material = options.materialOf(target.objectId)\n const isLow = max[1] - player.feet < LOW_TOP\n // the palms lie flat on the face that takes the push (HandPose of game-contracts): on a tall piece fingers up and backs to the player, on a low one fingers ahead and backs up\n const side = new THREE.Vector3(-into[1], 0, into[0])\n const way = new THREE.Vector3(into[0], 0, into[1])\n const up = new THREE.Vector3(0, 1, 0)\n const basis = isLow ? new THREE.Matrix4().makeBasis(way, up, side) : new THREE.Matrix4().makeBasis(up, way.clone().negate(), side)\n const palm = new THREE.Quaternion().setFromRotationMatrix(basis)\n leaning = { target, massKg, piece: target.piece, min, max, contact, into, isLow, palm: [palm.x, palm.y, palm.z, palm.w] }\n if (target.piece) target.piece.held = true\n control.begin(material === undefined ? { massKg } : { massKg, material })\n dragged = 0\n player.setWalkHeld(true)\n if (isLow && !options.hasBody?.()) player.setBend(Math.min(MAX_BEND, Math.max(0, STANDING_EYE - (max[1] - player.feet + LOW_EYE_OVER_TOP))))\n player.setLookLimit({ yaw: Math.atan2(-into[0], -into[1]), range: LOOK_RANGE })\n event('grip', leaning)\n return true\n },\n end() {\n if (!leaning) return false\n const tap = control.isTap\n release()\n return tap\n },\n setWalk(walk) {\n scriptedWalk = walk\n },\n step(dt) {\n const lean = leaning\n if (!lean) return\n if (!world.has(lean.target.objectId)) {\n release()\n return\n }\n const gripping = control.phase === 'grip'\n if (gripping) approach(lean, dt)\n const result = control.update(dt, { walk: scriptedWalk ?? player.walkIntent, isFree: (dx, dz) => isFree(lean, dx, dz) })\n if (result.engaged) {\n // a body from here on: held, the room's collision of the player and of this sweep no longer sees it as something in the way\n if (control.block !== 'too_heavy') {\n lean.piece ??= options.makePiece(lean.target.objectId)\n lean.piece.held = true\n }\n event(control.block === 'too_heavy' ? 'too_heavy' : 'engaged', lean)\n }\n if (result.hitObstacle) {\n options.hitSound(lean.target.objectId, [lean.contact[0], lean.min[1] + 0.3, lean.contact[1]])\n event('obstacle', lean)\n }\n if (result.dx !== 0 || result.dz !== 0) moveWith(lean, result.dx, result.dz)\n options.ring(control.phase === 'grip' && control.heldSeconds >= RING_DELAY_S ? control.progress : null)\n },\n handTargets() {\n const lean = leaning\n if (!lean) return null\n const strain = control.phase === 'strain'\n const y = lean.isLow ? lean.max[1] + 0.01 : Math.min(HAND_TOP, lean.max[1] - HAND_UNDER_TOP)\n // the arms give a little under the effort, and shake\n const shake = strain ? Math.sin(performance.now() * 0.045) * 0.006 : 0\n const inset = lean.isLow ? -LOW_HAND_ON_TOP + shake : (strain ? 0.05 : 0.02) + shake\n const px = lean.contact[0] - lean.into[0] * inset\n const pz = lean.contact[1] - lean.into[1] * inset\n const sideX = -lean.into[1] * HAND_SPREAD\n const sideZ = lean.into[0] * HAND_SPREAD\n const grip = 0.05 + 0.2 * control.progress\n return {\n R: { position: [px + sideX, y, pz + sideZ], quaternion: lean.palm },\n L: { position: [px - sideX, y, pz - sideZ], quaternion: lean.palm },\n grip,\n gripL: grip,\n }\n },\n }\n}\n","/**\n * The room's seats: puts the player on a seat an item brings (`TestRoomItem.seats`, the shape of a `game-interactables` seat) and back on its feet at the seat's exit.\n * Seated, the keys do not walk and the view stays within reach of the seat's facing; a walk key or a jump gets up, and so does losing the seat (the item is gone).\n */\nimport type * as THREE_NS from 'three'\nimport type { ItemSeat, Vec3 } from '@adatechnology/game-contracts'\nimport type { Player } from './player'\n\nconst SIT_EYE = 0.62\nconst LIE_EYE = 0.18\nconst STANDING_EYE = 1.7\n/** How far (radians) the view turns away from the seat's facing, either side. */\nconst LOOK_RANGE = 1.6\n\n/** Something the player can sit on: where its object is drawn now and the seats it brings. */\nexport type SeatHolder = {\n readonly objectId: string\n readonly root: THREE_NS.Object3D\n readonly seats: readonly ItemSeat[]\n}\n\n/** The seat the player is on. */\nexport type RoomSeat = {\n readonly objectId: string\n readonly seatId: string\n readonly pose: ItemSeat['pose']\n /** Where the hips (sit) or the pelvis (lie) are, in the world. */\n readonly hips: Vec3\n}\n\nexport type SeatingOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n /** The aimed thing that has seats, or null. */\n pick(): SeatHolder | null\n /** The thing with that object id, or null when it is gone. */\n find(objectId: string): SeatHolder | null\n /** Height of the ground at a point, where the player stands when getting up. */\n groundAt(x: number, z: number): number\n onSit?(seat: RoomSeat): void\n onStand?(seat: RoomSeat): void\n /** The room draws a body that sits by its pose: the player's own eye does not drop to the seat (without a body the eye is the camera). */\n hasBody?(): boolean\n}\n\nexport type Seating = {\n /** Sits on `objectId` (default: the aimed thing), on `seatId` (default: the seat nearest the player). Null when there is no seat there. */\n sit(objectId?: string, seatId?: string): RoomSeat | null\n /** Gets up at the seat's exit; false when not seated or the exit is blocked. */\n stand(): boolean\n /** Once a frame, before the player moves: a walk key or a jump gets up. */\n update(): void\n /** Lets go of the seat without moving the player (the room is reset). */\n release(): void\n readonly seat: RoomSeat | null\n}\n\nexport function createSeating(o: SeatingOptions): Seating {\n const { THREE, player } = o\n const v = new THREE.Vector3()\n const q = new THREE.Quaternion()\n const e = new THREE.Euler()\n let current: RoomSeat | null = null\n let facing = 0\n\n const toWorld = (root: THREE_NS.Object3D, local: Vec3): Vec3 => {\n root.updateWorldMatrix(true, false)\n v.set(local[0], local[1], local[2]).applyMatrix4(root.matrixWorld)\n return [v.x, v.y, v.z]\n }\n const yawOf = (root: THREE_NS.Object3D): number => {\n root.getWorldQuaternion(q)\n return e.setFromQuaternion(q, 'YXZ').y\n }\n const nearest = (holder: SeatHolder): ItemSeat | undefined => {\n let best: ItemSeat | undefined\n let bestDistance = Infinity\n for (const seat of holder.seats) {\n const [x, , z] = toWorld(holder.root, seat.pos)\n const distance = Math.hypot(x - player.x, z - player.z)\n if (distance < bestDistance) {\n best = seat\n bestDistance = distance\n }\n }\n return best\n }\n const hold = (): void => {\n player.setSeated(true)\n player.setWalkHeld(true)\n player.setLookLimit({ yaw: facing, range: LOOK_RANGE })\n }\n const release = (): void => {\n player.setSeated(false)\n player.setWalkHeld(false)\n player.setLookLimit(null)\n current = null\n }\n\n const seating: Seating = {\n sit(objectId, seatId) {\n const holder = objectId ? o.find(objectId) : o.pick()\n if (!holder) return null\n const seat = seatId ? holder.seats.find((s) => s.id === seatId) : nearest(holder)\n if (!seat) return null\n const [x, y, z] = toWorld(holder.root, seat.pos)\n const eye = o.hasBody?.() ? STANDING_EYE : (seat.eye ?? (seat.pose === 'lie' ? LIE_EYE : SIT_EYE))\n // a seat faces the front of its item (+z); the player looks down -z at yaw 0\n facing = yawOf(holder.root) + seat.ry + Math.PI\n player.setPose([x, y + eye, z], facing, 0)\n current = { objectId: holder.objectId, seatId: seat.id, pose: seat.pose, hips: [x, y, z] }\n hold()\n o.onSit?.(current)\n return current\n },\n stand() {\n if (!current) return false\n const holder = o.find(current.objectId)\n const seat = holder?.seats.find((s) => s.id === current?.seatId)\n if (holder && seat) {\n const [x, , z] = toWorld(holder.root, seat.exit)\n if (!player.canStand(x, z)) return false\n player.setPose([x, o.groundAt(x, z) + STANDING_EYE, z], player.yaw, 0)\n } else player.setPose([player.x, o.groundAt(player.x, player.z) + STANDING_EYE, player.z], player.yaw, 0)\n const left = current\n release()\n o.onStand?.(left)\n return true\n },\n update() {\n if (!current) return\n if (!o.find(current.objectId)) {\n seating.stand()\n return\n }\n const [walkX, walkZ] = player.walkIntent\n if (walkX || walkZ || player.keys.has('Space')) {\n seating.stand()\n return\n }\n // pushing or carrying lets the walk go when it ends: the seat holds it again\n hold()\n },\n release,\n get seat() {\n return current\n },\n }\n return seating\n}\n","/**\n * The room's side of opening and closing by hand: finds the leaf the eye rests on (a door, a lid, a drawer of furniture or of a vehicle: a part an `open_*` clip of the item moves),\n * asks `createDoorUse` (game-player) how far it goes, tests the sweep of the leaf against what is around before each step and puts the hand on the handle.\n * The leaf is posed along its item's own open clip, so the same opening the item's animation shows is the one the hand drives.\n */\nimport type * as THREE_NS from 'three'\nimport type { DestructionWorld, Vec3 } from '@adatechnology/game-destruction'\nimport type { AnimationClipSpec, HandTargets, HostReach } from '@adatechnology/game-contracts'\nimport { createDoorUse, DOOR_USE_DEFAULTS } from '@adatechnology/game-player'\nimport type { DoorUsePhase, DoorUseRules } from '@adatechnology/game-player'\nimport type { LeafFoley } from '@adatechnology/game-audio'\nimport { PLAYER_RADIUS } from './player'\nimport type { Player } from './player'\n\n/** How far the hand reaches a handle, metres from the eye. */\nexport const DOOR_REACH = 2.2\n/** A hit this close to a leaf (the handle, the glass of the door) counts as on the leaf. */\nconst NEAR_LEAF = 0.25\n/** Looking into an open fridge or wardrobe, the open leaf this close to the point is the one E closes. */\nconst NEAR_OPEN_LEAF = 0.9\nconst BODY_HEIGHT = 1.8\n/** The hand at rest in front of the chest, in the eye's space (x right, y up, -z ahead). */\nconst HAND_REST: Vec3 = [0.22, -0.42, -0.32]\nconst SKIN = 0.01\n/** How far in from the free edge of a leaf its handle is, metres. */\nconst HANDLE_INSET = 0.06\n/** Where the feet stop in front of a handle (a drawer, a leaf with no hinge known) for the hand to hold it with a bent arm, metres on the floor, and how fast the player steps up. */\nconst STANDOFF = 0.55\n/** A drawer comes out about this far toward the player. */\nconst DRAWER_TRAVEL = 0.3\n/** Standing by a turning leaf: this far past the arc of its free edge, and this far out in front of its face. */\nconst CLEAR_OF_ARC = 0.3\nconst OUT_IN_FRONT = 0.42\n/** Close enough to the place, metres; the longest walk to it before the hand goes anyway, seconds. */\nconst ARRIVED = 0.05\n/** How fast the head turns to the handle (share per second). */\nconst TURN_RATE = 8\nconst MAX_WALK_SECONDS = 1.5\nconst APPROACH_SPEED = 3\n/** How far over the floor a leaf swings (the gap under a door). */\nconst FLOOR_GAP = 0.03\n\n/** A leaf an item can open: the part, and the clip that opens it (the pose at the end of the clip is the leaf open). */\nexport type RoomLeaf = { readonly part: string; readonly clip: AnimationClipSpec }\n\nexport type RoomDoorOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n readonly world: DestructionWorld\n readonly camera: THREE_NS.Object3D\n readonly arena: { readonly limit: number; readonly colliders: ReadonlyArray<readonly [number, number, number, number]>; readonly ids: ReadonlyArray<string | null> }\n readonly rules?: Partial<DoorUseRules>\n /** What the eye rests on within reach, best first (the crosshair, then what the eye faces over the shoulder). */\n pick(): ReadonlyArray<{ readonly objectId: string; readonly part: string; readonly point: Vec3 }>\n /** The leaves of an object (none when it has nothing to open). */\n leaves(objectId: string): readonly RoomLeaf[]\n /** The drawn part of a leaf. */\n objectOf(objectId: string, part: string): THREE_NS.Object3D | null\n /** Poses the leaf at `fraction` of its clip (0 closed, 1 open), drawing and collision both. */\n pose(objectId: string, part: string, clip: AnimationClipSpec, fraction: number): void\n isLocked(objectId: string, part: string): boolean\n nameOf(objectId: string): string\n /** The sound class of what the leaf is made of (`impact_wood`, `impact_metal`...). */\n impactKey(objectId: string, part: string): string\n /**\n * The leaf's own sound key for a moment, when it has one (a car door is a padded thump with a latch, not the hollow metal of a fridge): `open` as\n * the leaf leaves the frame, `shut` as it meets it. Left out or `undefined`, the latch, the hinge and the shut of the leaf's material play.\n */\n leafSound?(objectId: string, part: string, moment: 'open' | 'shut'): string | undefined\n sound(key: string, point: Vec3, volume: number): void\n /**\n * The sound set of a leaf (a car door, a fridge, a wooden door: `LEAF_FOLEY_SETS` of game-audio), from its item or its material; `null` keeps the\n * material keys of the destruction renderer (`leaf_latch`, `leaf_creak_*`, `leaf_shut_*`).\n */\n leafFoley?(objectId: string, part: string, slides: boolean): LeafFoley | null\n onEvent(event: RoomDoorEvent): void\n}\n\n/** At or above this volume (a heavy leaf, see `shutVolume`) a leaf with a `slam` sound slams instead of closing gently. */\nexport const LEAF_SLAM_VOLUME = 0.85\n/** The volume a leaf meets its frame with: heavier leaves are louder. */\nexport const shutVolume = (massKg: number): number => Math.min(1, 0.3 + massKg * 0.03)\n\nexport type RoomDoorEventType = 'reach' | 'opened' | 'closed' | 'blocked' | 'locked' | 'stepped_back'\n\nexport type RoomDoorEvent = {\n readonly type: RoomDoorEventType\n readonly objectId: string\n readonly part: string\n readonly name: string\n /** How open the leaf is, 0 to 1. */\n readonly opening: number\n /** What stopped it (`blocked`): another object, the wall of the room, the player. */\n readonly by?: string\n}\n\nexport type RoomDoorState = { readonly objectId: string; readonly part: string; readonly phase: DoorUsePhase; readonly opening: number; readonly goal: 0 | 1 }\n\nexport interface RoomDoors {\n readonly active: boolean\n readonly state: RoomDoorState | null\n /** What the body does this frame, for the avatar: the hand height (metres over the feet) and the phase. */\n readonly avatarState: { readonly phase: Exclude<DoorUsePhase, 'idle'>; readonly progress: number; readonly height: number; readonly pull: boolean } | null\n /** Whether the eye rests on a leaf in reach (the prompt). */\n aimed(): { readonly objectId: string; readonly part: string; readonly open: boolean; readonly locked: boolean } | null\n /** Uses the leaf the eye rests on; false when there is none. */\n use(): boolean\n /** Opens or closes a leaf by its ids, as if the hand did it (scenarios). Answers false when the object has no such leaf. */\n useLeaf(objectId: string, part?: string): boolean\n /** How open a leaf is, 0 to 1. */\n opening(objectId: string, part: string): number\n step(dt: number): void\n handTargets(): HandTargets | null\n /** Puts the hand on a leaf a module moves itself (`ModuleHost.reachFor`): reach, grip (`onGrip`), hold it while it moves, let go. */\n reachFor(reach: HostReach): void\n /** Forgets an object (it was removed). */\n forget(objectId: string): void\n}\n\ntype Using = {\n readonly objectId: string\n readonly leaf: RoomLeaf\n readonly obj: THREE_NS.Object3D\n /** Where the hand holds the leaf, in the leaf's own space. */\n readonly grip: THREE_NS.Vector3\n readonly pull: boolean\n phase: DoorUsePhase\n progress: number\n /** Seconds walked to the handle, and whether the player got there. */\n walked: number\n there: boolean\n}\n\nconst key = (objectId: string, part: string): string => `${objectId}\\0${part}`\n\n/** Whether a clip slides its part (a drawer) rather than turning it. */\nconst slides = (clip: AnimationClipSpec, part: string): boolean => {\n const last = clip.keys[clip.keys.length - 1]?.parts?.[part]\n const r = last?.rotation ?? [0, 0, 0]\n return Math.abs(r[0]) + Math.abs(r[1]) + Math.abs(r[2]) < 1e-3\n}\n\nexport function createRoomDoors(options: RoomDoorOptions): RoomDoors {\n const { THREE, player, world, camera, arena } = options\n const control = createDoorUse(options.rules)\n const openings = new Map<string, number>()\n const box = new THREE.Box3()\n const before = new THREE.Box3()\n const tmp = new THREE.Vector3()\n const centre = new THREE.Vector3()\n let using: Using | null = null\n /** A module's own leaf under the hand (a house door). */\n let reaching: { readonly reach: HostReach; phase: Exclude<DoorUsePhase, 'idle'>; time: number; progress: number; walked: number; there: boolean } | null = null\n const rules = { ...DOOR_USE_DEFAULTS, ...options.rules }\n\n /** Where the hand is going or holding now, and how: the leaf in use or the module's leaf. */\n const holding = (): { phase: Exclude<DoorUsePhase, 'idle'>; progress: number; at: THREE_NS.Vector3; pull: boolean } | null => {\n if (reaching) {\n const h = reaching.reach.handle()\n return { phase: reaching.phase, progress: reaching.progress, at: new THREE.Vector3(h[0], h[1], h[2]), pull: reaching.reach.pull ?? true }\n }\n if (!using || control.phase === 'idle') return null\n using.obj.updateMatrixWorld(true)\n return { phase: control.phase, progress: using.progress, at: using.obj.localToWorld(new THREE.Vector3().copy(using.grip)), pull: using.pull }\n }\n /**\n * Where the player takes the handle from. A turning leaf: beside its free edge, past the arc it sweeps and a little out in front, on the side the player is on, so the leaf\n * swings by and not into the body (a person opens a fridge standing by the handle side). A drawer or a leaf with no hinge known: straight in front of the handle.\n */\n const standFor = (handle: THREE_NS.Vector3, hinge: THREE_NS.Vector3 | null, slide: boolean): [number, number] => {\n if (!hinge || slide) {\n const dx = handle.x - player.x\n const dz = handle.z - player.z\n const d = Math.hypot(dx, dz) || 1\n const off = slide ? STANDOFF + DRAWER_TRAVEL : STANDOFF\n return [handle.x - (dx / d) * off, handle.z - (dz / d) * off]\n }\n let ax = handle.x - hinge.x\n let az = handle.z - hinge.z\n const width = Math.hypot(ax, az)\n if (width < 0.05) return standFor(handle, null, false)\n ax /= width\n az /= width\n // out of the face, toward the player\n let nx = -az\n let nz = ax\n if ((player.x - handle.x) * nx + (player.z - handle.z) * nz < 0) {\n nx = -nx\n nz = -nz\n }\n const x = hinge.x + ax * (width + CLEAR_OF_ARC) + nx * OUT_IN_FRONT\n const z = hinge.z + az * (width + CLEAR_OF_ARC) + nz * OUT_IN_FRONT\n // something stands there (the next cabinet, a nightstand): in front of the handle, and the leaf will make the player step back\n return player.canStand(x, z) ? [x, z] : standFor(handle, null, false)\n }\n /** The head turns to the handle as the player goes for it. */\n const face = (handle: THREE_NS.Vector3, dt: number): void => {\n camera.updateMatrixWorld(true)\n const eye = camera.getWorldPosition(new THREE.Vector3())\n const dx = handle.x - player.x\n const dz = handle.z - player.z\n const flat = Math.hypot(dx, dz)\n if (flat < 0.05) return\n const yaw = Math.atan2(-dx, -dz)\n const pitch = Math.atan2(handle.y - eye.y, flat)\n let dYaw = yaw - player.yaw\n dYaw = Math.atan2(Math.sin(dYaw), Math.cos(dYaw))\n const k = Math.min(1, dt * TURN_RATE)\n player.setPose([player.x, eye.y, player.z], player.yaw + dYaw * k, player.pitch + (pitch - player.pitch) * k)\n }\n /** The player steps toward where the handle is taken from. Answers true once there, or when nothing more can be gained (in the way, or walking too long). */\n const approach = (handle: THREE_NS.Vector3, hinge: THREE_NS.Vector3 | null, slide: boolean, dt: number, walked: number): boolean => {\n const [x, z] = standFor(handle, hinge, slide)\n const dx = x - player.x\n const dz = z - player.z\n const d = Math.hypot(dx, dz)\n if (d < ARRIVED || walked > MAX_WALK_SECONDS) return true\n const go = Math.min(d, APPROACH_SPEED * dt)\n if (go < 1e-4) return false\n const x0 = player.x\n const z0 = player.z\n player.moveBy((dx / d) * go, (dz / d) * go)\n return Math.hypot(player.x - x0, player.z - z0) < go * 0.2\n }\n\n const openingOf = (objectId: string, part: string): number => openings.get(key(objectId, part)) ?? 0\n\n /** Where the last use sent each leaf (`objectId|part`), for the next use to turn it round. */\n const lastGoals = new Map<string, 0 | 1>()\n\n const leafAt = (objectId: string, part: string, point: Vec3): RoomLeaf | null => {\n const leaves = options.leaves(objectId)\n if (leaves.length === 0) return null\n const exact = leaves.find((l) => l.part === part)\n if (exact) return exact\n // the ray found the handle, a pane or the frame next to the leaf: the closest leaf to the point, if it is close enough;\n // looking into what an open leaf opened (the shelves of an open fridge), the closest open leaf\n let best: RoomLeaf | null = null\n let bestD = NEAR_LEAF\n let open: RoomLeaf | null = null\n let openD = NEAR_OPEN_LEAF\n for (const l of leaves) {\n const obj = options.objectOf(objectId, l.part)\n if (!obj) continue\n box.setFromObject(obj)\n const d = box.distanceToPoint(tmp.set(point[0], point[1], point[2]))\n if (d < bestD) {\n bestD = d\n best = l\n }\n if (openingOf(objectId, l.part) > 0.5 && d < openD) {\n openD = d\n open = l\n }\n }\n return best ?? open\n }\n\n /** The first thing the eye rests on that has a leaf there. */\n const picked = (): { hit: { objectId: string; part: string; point: Vec3 }; leaf: RoomLeaf } | null => {\n for (const hit of options.pick()) {\n const leaf = leafAt(hit.objectId, hit.part, hit.point)\n if (leaf) return { hit, leaf }\n }\n return null\n }\n\n const massOf = (objectId: string, part: string): number => world.part(objectId, part)?.mass ?? 10\n\n const event = (type: RoomDoorEventType, u: Using, by?: string): void =>\n options.onEvent({ type, objectId: u.objectId, part: u.leaf.part, name: options.nameOf(u.objectId), opening: openingOf(u.objectId, u.leaf.part), ...(by ? { by } : {}) })\n\n const overlaps2d = (b: THREE_NS.Box3, c: readonly [number, number, number, number]): boolean => b.max.x > c[0] && b.min.x < c[2] && b.max.z > c[1] && b.min.z < c[3]\n\n /** The player's body against the leaf at `b`: the overlap on the floor, or null. */\n const bodyOverlap = (b: THREE_NS.Box3): [number, number] | null => {\n if (b.min.y > player.feet + BODY_HEIGHT || b.max.y < player.feet + 0.05) return null\n const cx = Math.max(b.min.x, Math.min(b.max.x, player.x))\n const cz = Math.max(b.min.z, Math.min(b.max.z, player.z))\n const dx = player.x - cx\n const dz = player.z - cz\n const d = Math.hypot(dx, dz)\n if (d >= PLAYER_RADIUS) return null\n if (d < 1e-4) {\n // the centre is inside the leaf's box: out the shortest way\n const outs: Array<[number, number, number]> = [\n [b.max.x - player.x, 1, 0],\n [player.x - b.min.x, -1, 0],\n [b.max.z - player.z, 0, 1],\n [player.z - b.min.z, 0, -1],\n ]\n outs.sort((a, c) => a[0] - c[0])\n const o = outs[0]!\n return [o[1] * (o[0] + PLAYER_RADIUS), o[2] * (o[0] + PLAYER_RADIUS)]\n }\n const push = PLAYER_RADIUS - d + SKIN\n return [(dx / d) * push, (dz / d) * push]\n }\n\n /** Can the leaf go from one opening to the other: poses it there and looks at what it would go through. Leaves it where it can be. */\n const isFree = (u: Using, from: number, to: number): boolean => {\n const { objectId, leaf, obj } = u\n obj.updateMatrixWorld(true)\n before.setFromObject(obj)\n options.pose(objectId, leaf.part, leaf.clip, to)\n obj.updateMatrixWorld(true)\n box.setFromObject(obj)\n box.expandByScalar(-SKIN)\n let by: string | null = null\n // the walls and the furniture of the room that stand on the floor (not the object's own footprint)\n if (Math.max(Math.abs(box.min.x), Math.abs(box.max.x), Math.abs(box.min.z), Math.abs(box.max.z)) > arena.limit) by = 'wall'\n else\n for (let i = 0; i < arena.colliders.length; i++) {\n const c = arena.colliders[i]!\n if (arena.ids[i] === objectId) continue\n if (overlaps2d(box, c) && !overlaps2d(before, c)) {\n by = arena.ids[i] ?? 'wall'\n break\n }\n }\n // anything of the destruction world between the two poses\n if (!by) {\n before.getCenter(centre)\n box.getCenter(tmp)\n const dir: Vec3 = [tmp.x - centre.x, tmp.y - centre.y, tmp.z - centre.z]\n const len = Math.hypot(dir[0], dir[1], dir[2])\n // the far edge of a turning leaf moves about twice as far as its middle\n if (len > 1e-5) {\n // a leaf clears the floor it stands over (and what it rests on): only what stands up in its way stops it\n const hit = world.sweepBox({ min: [before.min.x + SKIN, before.min.y + FLOOR_GAP, before.min.z + SKIN], max: [before.max.x - SKIN, before.max.y - SKIN, before.max.z - SKIN] }, dir, len * 2, { ignore: objectId, spacing: 0.12 })\n if (hit && hit.normal[1] < 0.7) by = hit.object\n }\n }\n // the player: steps back out of the way of the leaf, or holds it when there is no room behind\n if (!by) {\n const out = bodyOverlap(box)\n if (out) {\n const x0 = player.x\n const z0 = player.z\n player.moveBy(out[0], out[1])\n if (Math.hypot(player.x - x0, player.z - z0) < Math.hypot(out[0], out[1]) * 0.5) by = 'player'\n else if (u.phase !== 'swing' || from === 0) event('stepped_back', u)\n }\n }\n if (by) {\n options.pose(objectId, leaf.part, leaf.clip, from)\n const at: Vec3 = [box.getCenter(tmp).x, tmp.y, tmp.z]\n options.sound(options.impactKey(objectId, leaf.part), at, Math.min(0.6, 0.15 + massOf(objectId, leaf.part) * 0.02))\n event('blocked', u, by)\n return false\n }\n return true\n }\n\n /**\n * Where the hand takes the leaf, in the leaf's own space: a turning leaf by its free edge (the handle side, away from the hinge, at the height the eye was or at a handle's height),\n * a drawer by the middle of its front where the eye was.\n */\n const handleOf = (obj: THREE_NS.Object3D, leaf: RoomLeaf, point: Vec3 | null): THREE_NS.Vector3 => {\n obj.updateMatrixWorld(true)\n box.setFromObject(obj)\n const lo = new THREE.Vector3(Infinity, Infinity, Infinity)\n const hi = new THREE.Vector3(-Infinity, -Infinity, -Infinity)\n for (let i = 0; i < 8; i++) {\n tmp.set(i & 1 ? box.max.x : box.min.x, i & 2 ? box.max.y : box.min.y, i & 4 ? box.max.z : box.min.z)\n obj.worldToLocal(tmp)\n lo.min(tmp)\n hi.max(tmp)\n }\n const aimed = point ? obj.worldToLocal(new THREE.Vector3(point[0], point[1], point[2])) : lo.clone().add(hi).multiplyScalar(0.5)\n if (!point) {\n // no eye on it (a script): the hand at the height of a handle, about a metre over the feet\n const local = obj.worldToLocal(obj.getWorldPosition(new THREE.Vector3()).setY(player.feet + 1.0))\n aimed.y = local.y\n }\n aimed.clamp(lo, hi)\n if (slides(leaf.clip, leaf.part)) return aimed\n // the hinge is the leaf's own origin; the free edge is the far end of the leaf across the axis it turns about\n const last = leaf.clip.keys[leaf.clip.keys.length - 1]?.parts?.[leaf.part]?.rotation ?? [0, 1, 0]\n const axis = Math.abs(last[0]) >= Math.abs(last[1]) && Math.abs(last[0]) >= Math.abs(last[2]) ? 0 : Math.abs(last[1]) >= Math.abs(last[2]) ? 1 : 2\n const size = [hi.x - lo.x, hi.y - lo.y, hi.z - lo.z]\n const reachOf = (k: number): number => Math.max(Math.abs(lo.getComponent(k)), Math.abs(hi.getComponent(k)))\n let across = -1\n for (let k = 0; k < 3; k++) {\n if (k === axis || size[k]! < Math.min(size[0]!, size[1]!, size[2]!) + 1e-6) continue\n if (across < 0 || reachOf(k) > reachOf(across)) across = k\n }\n if (across < 0) return aimed\n const far = Math.abs(hi.getComponent(across)) >= Math.abs(lo.getComponent(across)) ? hi.getComponent(across) : lo.getComponent(across)\n aimed.setComponent(across, far - Math.sign(far) * Math.min(HANDLE_INSET, size[across]! * 0.25))\n return aimed\n }\n\n const start = (objectId: string, leaf: RoomLeaf, point: Vec3 | null): boolean => {\n reaching = null\n const obj = options.objectOf(objectId, leaf.part)\n if (!obj) return false\n if (using && (using.objectId !== objectId || using.leaf.part !== leaf.part)) control.cancel()\n obj.updateMatrixWorld(true)\n // the hand goes where the eye was, else to the middle of the free edge of the leaf at the height of a handle\n const grip = handleOf(obj, leaf, point)\n const opening = openingOf(objectId, leaf.part)\n const key = `${objectId}|${leaf.part}`\n const lastGoal = lastGoals.get(key)\n const goal = control.begin({ opening, massKg: massOf(objectId, leaf.part), locked: options.isLocked(objectId, leaf.part), ...(lastGoal !== undefined ? { lastGoal } : {}) })\n if (goal !== null) lastGoals.set(key, goal)\n // a leaf that comes toward the body is pulled, one that goes away is pushed: compare the leaf open and closed with where the player stands\n let pull = true\n if (goal !== null) {\n obj.updateMatrixWorld(true)\n options.pose(objectId, leaf.part, leaf.clip, 1)\n obj.updateMatrixWorld(true)\n const openAt = obj.localToWorld(grip.clone())\n options.pose(objectId, leaf.part, leaf.clip, 0)\n obj.updateMatrixWorld(true)\n const shutAt = obj.localToWorld(grip.clone())\n options.pose(objectId, leaf.part, leaf.clip, opening)\n const dOpen = Math.hypot(openAt.x - player.x, openAt.z - player.z)\n const dShut = Math.hypot(shutAt.x - player.x, shutAt.z - player.z)\n pull = goal === 1 ? dOpen <= dShut : dShut <= dOpen\n }\n using = { objectId, leaf, obj, grip, pull, phase: control.phase, progress: 0, walked: 0, there: goal === null }\n const at = obj.localToWorld(grip.clone())\n if (goal === null) {\n options.sound(options.leafFoley?.(objectId, leaf.part, slides(leaf.clip, leaf.part))?.locked ?? 'leaf_rattle', [at.x, at.y, at.z], 0.6)\n event('locked', using)\n } else event('reach', using)\n return true\n }\n\n return {\n get active() {\n return reaching !== null || (using !== null && control.phase !== 'idle')\n },\n get state() {\n return using ? { objectId: using.objectId, part: using.leaf.part, phase: control.phase, opening: openingOf(using.objectId, using.leaf.part), goal: control.goal } : null\n },\n get avatarState() {\n const h = holding()\n return h ? { phase: h.phase, progress: h.progress, height: h.at.y - player.feet, pull: h.pull } : null\n },\n aimed() {\n const found = picked()\n if (!found) return null\n const { hit, leaf } = found\n return { objectId: hit.objectId, part: leaf.part, open: openingOf(hit.objectId, leaf.part) > 0.5, locked: options.isLocked(hit.objectId, leaf.part) }\n },\n use() {\n const found = picked()\n return found ? start(found.hit.objectId, found.leaf, found.hit.point) : false\n },\n useLeaf(objectId, part) {\n const leaves = options.leaves(objectId)\n const leaf = part === undefined ? leaves[0] : leaves.find((l) => l.part === part)\n return leaf ? start(objectId, leaf, null) : false\n },\n opening: openingOf,\n step(dt) {\n const r = reaching\n if (r) {\n r.time += dt\n if (r.phase === 'reach' && !r.there) {\n const h = r.reach.handle()\n const hinge = r.reach.hinge?.()\n r.walked += dt\n const g = new THREE.Vector3(h[0], h[1], h[2])\n r.there = approach(g, hinge ? new THREE.Vector3(hinge[0], hinge[1], hinge[2]) : null, false, dt, r.walked)\n face(g, dt)\n if (r.there) r.time = 0\n } else if (r.phase === 'reach') {\n r.progress = Math.min(1, r.time / rules.reachSeconds)\n if (r.progress >= 1) {\n r.reach.onGrip?.()\n r.phase = r.reach.locked ? 'rattle' : 'swing'\n r.time = 0\n r.progress = 0\n }\n } else if (r.phase === 'swing' || r.phase === 'rattle') {\n r.progress = Math.min(1, r.time / (r.phase === 'rattle' ? rules.rattleSeconds : Math.max(0.05, r.reach.seconds)))\n if (r.progress >= 1) {\n r.phase = 'release'\n r.time = 0\n r.progress = 0\n }\n } else {\n r.progress = Math.min(1, r.time / rules.releaseSeconds)\n if (r.progress >= 1) reaching = null\n }\n return\n }\n const u = using\n if (!u || control.phase === 'idle') return\n const was = openingOf(u.objectId, u.leaf.part)\n const wasPhase = control.phase\n // the player walks to the handle first; the hand goes out once there\n if (wasPhase === 'reach' && !u.there) {\n u.obj.updateMatrixWorld(true)\n u.walked += dt\n const g = u.obj.localToWorld(new THREE.Vector3().copy(u.grip))\n u.there = approach(g, u.obj.getWorldPosition(new THREE.Vector3()), slides(u.leaf.clip, u.leaf.part), dt, u.walked)\n face(g, dt)\n if (!u.there) return\n }\n const s = control.step(dt, (from, to) => isFree(u, from, to))\n u.phase = s.phase\n u.progress = s.progress\n openings.set(key(u.objectId, u.leaf.part), s.opening)\n u.obj.updateMatrixWorld(true)\n const at = u.obj.localToWorld(tmp.copy(u.grip))\n const point: Vec3 = [at.x, at.y, at.z]\n const slide = slides(u.leaf.clip, u.leaf.part)\n const foley = options.leafFoley?.(u.objectId, u.leaf.part, slide) ?? null\n const own = (moment: 'open' | 'shut'): string | undefined => options.leafSound?.(u.objectId, u.leaf.part, moment)\n const shut = own('shut') ?? options.impactKey(u.objectId, u.leaf.part).replace('impact_', 'leaf_shut_')\n // the latch gives as the leaf leaves the frame, the hinge sounds while it turns, the leaf meets the frame closing\n if (wasPhase === 'reach' && s.phase !== 'reach') {\n const opening = foley ? undefined : own('open')\n if (foley) {\n // a closed leaf lets go of its latch or seal; one already ajar only turns\n if (was < 0.02) options.sound(foley.open, point, 0.5)\n if (foley.turn) options.sound(foley.turn, point, 0.35)\n } else if (slide) options.sound('leaf_slide', point, 0.5)\n else if (opening) {\n if (was < 0.02) options.sound(opening, point, 0.5)\n } else {\n if (was < 0.02) options.sound('leaf_latch', point, 0.5)\n options.sound(/metal|glass/.test(shut) ? 'leaf_creak_metal' : 'leaf_creak_wood', point, 0.35)\n }\n }\n if (s.arrived) {\n if (s.opening <= 0) {\n const volume = shutVolume(massOf(u.objectId, u.leaf.part))\n if (foley) options.sound(foley.slam && volume >= LEAF_SLAM_VOLUME ? foley.slam : foley.close, point, volume)\n else options.sound(slide ? 'leaf_slide' : shut, point, volume)\n event('closed', u)\n } else event('opened', u)\n }\n if (s.phase === 'idle') using = null\n },\n handTargets() {\n const h = holding()\n if (!h || (h.phase === 'rattle' && h.progress > 0.92)) return null\n const { at, phase, progress } = h\n // the rattle shakes the handle under the hand\n if (phase === 'rattle') at.y += Math.sin(progress * 60) * 0.012\n camera.updateMatrixWorld(true)\n const rest = camera.localToWorld(new THREE.Vector3(HAND_REST[0], HAND_REST[1], HAND_REST[2]))\n // reach: the hand travels to the handle; release: back to the chest\n const k = phase === 'reach' ? progress : phase === 'release' ? 1 - progress : 1\n const ease = k * k * (3 - 2 * k)\n const pos = rest.lerp(at, ease)\n // a hand round a vertical handle: fingers away from the player, thumb up (HandPose of game-contracts: +x to the knuckles, +z to the little finger)\n const way = new THREE.Vector3(at.x - player.x, 0, at.z - player.z)\n if (way.lengthSq() < 1e-6) way.set(-Math.sin(player.yaw), 0, -Math.cos(player.yaw))\n way.normalize()\n const down = new THREE.Vector3(0, -1, 0)\n const back = new THREE.Vector3().crossVectors(down, way)\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(way, back, down))\n const grip = phase === 'reach' ? 0.15 + 0.75 * progress : phase === 'release' ? 0.9 * (1 - progress) : 0.9\n return { R: { position: [pos.x, pos.y, pos.z], quaternion: [q.x, q.y, q.z, q.w] }, L: null, grip }\n },\n reachFor(reach) {\n if (using) {\n control.cancel()\n using = null\n }\n reaching = { reach, phase: 'reach', time: 0, progress: 0, walked: 0, there: false }\n },\n forget(objectId) {\n for (const k of [...openings.keys()]) if (k.startsWith(`${objectId}\\0`)) openings.delete(k)\n if (using?.objectId === objectId) {\n control.cancel()\n using = null\n }\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 /** How closed the other hand is when it works on the item (turning a cap off); the room brings it there with `reach`. */\n readonly gripL?: 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 /** Which way the body falls while `down`: true face down, false on its back; left out, the avatar picks. A blast falls it the way it pushed. */\n fallForward?: 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 /** Hands on a piece of furniture: `grip` while the hold timer fills (`progress`), `push` walking with it, `strain` straining against what does not give. */\n push?: { readonly phase: 'grip' | 'push' | 'strain'; readonly progress: number } | null\n /** On a seat: the pose and how high the hips (or the pelvis) are above the feet. */\n seat?: { readonly pose: 'sit' | 'lie'; readonly hip: number } | null\n /** A hand on a door, lid or drawer: `reach` to the handle, `swing` with it (`pull` toward the body or pushed away), `release`, `rattle` on a locked one; `height` of the hand over the feet, metres. */\n door?: { readonly phase: 'reach' | 'swing' | 'release' | 'rattle'; readonly progress: number; readonly height: number; readonly pull: boolean } | 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 /** The joint of a shoulder: in third person the room rests a long gun's stock in the pocket just inside the right one (`ModuleHost.holdFrame`). */\n shoulder?(side: 'R' | 'L'): THREE_NS.Object3D\n /**\n * Where the body's eyes are after its pose (world space), sampled before `reach`: with it the room draws the body in both views, puts the first-person camera there (pulled back out of\n * walls) and shoots, aims and reaches from there in both views. Without it the room keeps the player's own eye.\n */\n eye?(out?: THREE_NS.Vector3): THREE_NS.Vector3\n /** Hides the head and neck from `camera` while the view is `first` (shadows, mirrors and other cameras keep seeing them). */\n setView?(mode: CameraMode, camera: THREE_NS.Object3D | null): void\n /**\n * Plays the strike `clipId` (on the body, in both views) 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'; hand?: 'left' | 'right' }): number | null\n /**\n * The foot the body put down since the last call (its walk cycle reached a heel strike), or null. The room asks after each `update` and sends the footfall to the\n * modules (`HostEvent` `footfall`), so the step is heard on the frame the foot is seen on the ground. Without it the room counts strides by distance.\n */\n footfall?(): 'left' | 'right' | null\n /**\n * Brings the body's hands to the tool in them (`HandTargets`, world space: the module's). The room calls it in both views every frame, after the modules have placed the tool and\n * before the render, with `view` (the eye's camera, and `contact` to keep the hands out of walls) in both views. An avatar without it keeps the hands where its own pose puts them.\n */\n reach?(targets: HandTargets | null, view?: RoomReachView): void\n}\n\n/** The first-person view the body's hands keep to: the camera, and the room's ray (`contact`) so a hand stops before a wall. */\nexport interface RoomReachView {\n camera: THREE_NS.Object3D\n keepOutside?: { contact(origin: [number, number, number], direction: [number, number, number], maxDistance: number): number | null }\n}\n\n/** Which leg a kick uses: `alternate` swaps at each kick (right first). */\nexport type KickLeg = 'alternate' | 'left' | 'right'\n/** Which hand a punch uses: `alternate` swaps at each punch (right first). */\nexport type PunchHand = '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 'metric.geometries': 'Geometries',\n 'metric.textures': 'Textures',\n 'metric.heap_mb': 'Heap MB',\n 'memory.leak_short': 'memory leak: +{geometries} geometries, +{textures} textures per {clears} clears',\n 'memory.leak': 'Memory keeps growing after each clear: +{geometries} geometries and +{textures} textures over the last {clears} clears. Something removed from the scene was not released (discardObject3D).',\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.strike.hand': '{weapon}: {clip} with the {hand} hand begins, impact in {seconds} s',\n 'hand.left': 'left',\n 'hand.right': 'right',\n 'act.combo.on': '{name}: on (each blow follows the sequence)',\n 'act.combo.off': '{name}: off',\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.bump': 'Pushed {name} ({kg} kg) walking into it',\n 'act.drop': 'Dropped {name}',\n 'act.throw': 'Threw {name} at {speed} m/s',\n 'ground.name': 'Ground',\n 'act.landing': '{name} landed at {speed} m/s: {energy} J',\n 'act.player_land': 'You landed at {speed} m/s',\n 'act.bench_failed': '{name} failed: {error}',\n 'loading.working': 'Working…',\n 'loading.graphics': 'Calibrating graphics…',\n 'ui.graphics': 'Graphics',\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.knocked_down': 'The blast threw the player off their feet at {speed} m/s ({reach}% got through the cover)',\n 'act.player_slammed': 'The player was thrown into {what} at {speed} m/s',\n 'act.player_fell': 'The player hit the floor at {speed} m/s',\n 'act.player_shoved': 'The blast pushed the player at {speed} m/s ({reach}% got through the cover)',\n 'act.came_apart': '{name} came apart: what stayed is loose and falls',\n 'act.shoved': '{name} stands free: the shots 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.open_with': 'Opened {name} with {tool}',\n 'act.open_by_hand': 'Opened {name} by hand',\n 'act.ate': 'Ate {grams} g of {name}',\n 'act.ate_all': 'Ate all of {name} ({grams} g): the packaging is empty',\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.eat': 'eat',\n 'use.pour': 'pour',\n 'use.pour_out': 'pour out',\n 'use.open': 'open',\n 'use.unscrew': 'unscrew',\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.door_locked': '{name} is locked',\n 'hud.door_blocked': '{name} hits something and stops ({percent}% open)',\n 'hud.door_hint_open': 'E: open',\n 'hud.door_hint_close': 'E: close',\n 'hud.door_hint_locked': 'Locked',\n 'act.door_reach': 'reaches for the handle of {name}',\n 'act.door_opened': 'opens {name}',\n 'act.door_closed': 'closes {name}',\n 'act.door_blocked': '{name} hits something and stops at {percent}%',\n 'act.door_locked': 'tries {name}: locked, it only rattles',\n 'act.door_stepped_back': 'steps back out of the way of {name}',\n 'hud.push_on': 'Pushing {name}: W pushes, S pulls, let go of E to stop',\n 'hud.push_too_heavy': '{name} does not budge ({kg} kg)',\n 'hud.push_blocked': '{name} is stuck: there is something in the way',\n 'act.push_grip': 'leans on {name} ({kg} kg)',\n 'act.push_engaged': 'starts pushing {name} ({kg} kg)',\n 'act.sit': 'sits on {name}',\n 'act.lie': 'lies down on {name}',\n 'act.stand': 'gets up from {name}',\n 'act.push_too_heavy': 'strains against {name}: {kg} kg is too much',\n 'act.push_obstacle': '{name} hits something and locks',\n 'act.push_release': 'lets go of {name}',\n 'hud.empty_container': '{name} is empty',\n 'hud.needs_opener': 'Opening {name} needs {tools} (put one within reach or in the loadout)',\n 'hud.spoiled_hole': '{name}: the packaging is holed through, what is inside is contaminated; do not eat or drink it',\n 'hud.spoiled_leak': '{name} leaked: what is left is contaminated; do not eat or drink it',\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 (tap stays, hold while pressed) · Space: jump · 1-0 / wheel: tool · LMB: use (bare hands: punch) · E: grab/drop (hold against furniture: push) · G or RMB: throw · R: reload · Q: fire mode · X: clear a jam · B: safety · Y: detonate charges set down · K: kick · N: strike combo on/off · 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.test_table': 'Test table',\n 'ui.test_table.group': 'Group to lay on the table',\n 'ui.test_table.lay': 'Lay',\n 'ui.test_table.prev': 'Previous items',\n 'ui.test_table.next': 'Next items',\n 'ui.test_table.relay': 'Put back',\n 'ui.test_table.search': 'Find an item to put on the table',\n 'ui.test_table.hint': 'Pick a group and lay it on the table, then pick an item and try it.',\n 'ui.test_table.page': 'Items {from}–{to} of {total}. Pick one, then a trial:',\n 'ui.trial.shot': 'Shot',\n 'ui.trial.punch': 'Punch',\n 'ui.trial.stab': 'Knife',\n 'ui.trial.fire': 'Fire',\n 'ui.trial.blast': 'Blast',\n 'ui.trial.shot.hint': 'A 9 mm round from 2.5 m',\n 'ui.trial.punch.hint': 'A punch, up close',\n 'ui.trial.stab.hint': 'A knife blow, up close',\n 'ui.trial.fire.hint': 'A flamethrower burst from 1.6 m',\n 'ui.trial.blast.hint': 'A fragmentation grenade goes off just behind it (it reaches the neighbours too)',\n 'act.test_table': 'Test table: {group}, items {from}–{to} of {total}',\n 'act.trial.shot': 'Trial: shooting {name}',\n 'act.trial.punch': 'Trial: punching {name}',\n 'act.trial.stab': 'Trial: stabbing {name}',\n 'act.trial.fire': 'Trial: setting fire to {name}',\n 'act.trial.blast': 'Trial: a blast beside {name}',\n 'arena.test_table': 'Test table',\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.kick': 'Kick',\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.dug': 'Dug',\n 'ins.dig_limit': 'Ground left to dig',\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 'metric.geometries': 'Geometrias',\n 'metric.textures': 'Texturas',\n 'metric.heap_mb': 'Heap MB',\n 'memory.leak_short': 'vazamento de memória: +{geometries} geometrias, +{textures} texturas em {clears} limpezas',\n 'memory.leak': 'A memória continua subindo a cada limpeza: +{geometries} geometrias e +{textures} texturas nas últimas {clears} limpezas. Algo tirado da cena não foi liberado (discardObject3D).',\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.strike.hand': '{weapon}: {clip} com a mão {hand} começa, impacto em {seconds} s',\n 'hand.left': 'esquerda',\n 'hand.right': 'direita',\n 'act.combo.on': '{name}: ligada (cada golpe segue a sequência)',\n 'act.combo.off': '{name}: desligada',\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.bump': 'Empurrou {name} ({kg} kg) ao esbarrar',\n 'act.drop': 'Soltou {name}',\n 'act.throw': 'Arremessou {name} a {speed} m/s',\n 'ground.name': 'Chão',\n 'act.landing': '{name} caiu a {speed} m/s: {energy} J',\n 'act.player_land': 'Você aterrissou a {speed} m/s',\n 'act.bench_failed': '{name} falhou: {error}',\n 'loading.working': 'Trabalhando…',\n 'loading.graphics': 'Calibrando os gráficos…',\n 'ui.graphics': 'Gráficos',\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.knocked_down': 'A explosão derrubou o jogador a {speed} m/s ({reach}% passou pela cobertura)',\n 'act.player_slammed': 'O jogador foi arremessado contra {what} a {speed} m/s',\n 'act.player_fell': 'O jogador bateu no chão a {speed} m/s',\n 'act.player_shoved': 'A explosão empurrou o jogador a {speed} m/s ({reach}% passou pela cobertura)',\n 'act.came_apart': '{name} se desmontou: o que ficou está solto e cai',\n 'act.shoved': '{name} estava solto no chão: os tiros o moveram',\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.open_with': 'Abriu {name} com {tool}',\n 'act.open_by_hand': 'Abriu {name} com a mão',\n 'act.ate': 'Comeu {grams} g de {name}',\n 'act.ate_all': 'Comeu todo o conteúdo de {name} ({grams} g): a embalagem ficou vazia',\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.eat': 'comer',\n 'use.pour': 'despejar',\n 'use.pour_out': 'esvaziar',\n 'use.open': 'abrir',\n 'use.unscrew': 'desenroscar',\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.door_locked': '{name} está trancado(a)',\n 'hud.door_blocked': '{name} bateu em algo e parou ({percent}% aberto)',\n 'hud.door_hint_open': 'E: abrir',\n 'hud.door_hint_close': 'E: fechar',\n 'hud.door_hint_locked': 'Trancado',\n 'act.door_reach': 'leva a mão à maçaneta de {name}',\n 'act.door_opened': 'abre {name}',\n 'act.door_closed': 'fecha {name}',\n 'act.door_blocked': '{name} bate em algo e para em {percent}%',\n 'act.door_locked': 'tenta abrir {name}: trancado, só chacoalha',\n 'act.door_stepped_back': 'dá um passo para trás para {name} passar',\n 'hud.push_on': 'Empurrando {name}: W empurra, S puxa, solte o E para parar',\n 'hud.push_too_heavy': '{name} não se mexe ({kg} kg)',\n 'hud.push_blocked': '{name} travou: tem algo no caminho',\n 'act.push_grip': 'encosta em {name} ({kg} kg)',\n 'act.push_engaged': 'começa a empurrar {name} ({kg} kg)',\n 'act.sit': 'senta em {name}',\n 'act.lie': 'deita em {name}',\n 'act.stand': 'levanta de {name}',\n 'act.push_too_heavy': 'faz força contra {name}: {kg} kg é demais',\n 'act.push_obstacle': '{name} bate em algo e trava',\n 'act.push_release': 'solta {name}',\n 'hud.empty_container': '{name} está vazio',\n 'hud.needs_opener': 'Para abrir {name} precisa de {tools} (deixe um ao alcance ou no inventário)',\n 'hud.spoiled_hole': '{name}: a embalagem furou, o conteúdo está contaminado; não dá para comer nem beber',\n 'hud.spoiled_leak': '{name} vazou: o que sobrou está contaminado; não dá para comer nem beber',\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 (toque fixa, segurar só enquanto aperta) · Espaço: pular · 1-0 / roda: ferramenta · botão esquerdo: usar (mão livre: soco) · E: pegar/soltar (segurar encostado no móvel: empurrar) · G ou botão direito: arremessar · R: recarregar · Q: modo de tiro · X: destravar · B: trava · Y: detonar cargas postas · K: chute · N: liga/desliga a sequência de golpes · 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.test_table': 'Mesa de testes',\n 'ui.test_table.group': 'Grupo para pôr na mesa',\n 'ui.test_table.lay': 'Pôr na mesa',\n 'ui.test_table.prev': 'Itens anteriores',\n 'ui.test_table.next': 'Próximos itens',\n 'ui.test_table.relay': 'Repor',\n 'ui.test_table.search': 'Buscar item para pôr na mesa',\n 'ui.test_table.hint': 'Escolha um grupo e ponha na mesa; depois escolha um item e teste.',\n 'ui.test_table.page': 'Itens {from}–{to} de {total}. Escolha um e um teste:',\n 'ui.trial.shot': 'Tiro',\n 'ui.trial.punch': 'Soco',\n 'ui.trial.stab': 'Faca',\n 'ui.trial.fire': 'Fogo',\n 'ui.trial.blast': 'Explosão',\n 'ui.trial.shot.hint': 'Um tiro de 9 mm a 2,5 m',\n 'ui.trial.punch.hint': 'Um soco, de perto',\n 'ui.trial.stab.hint': 'Um golpe de faca, de perto',\n 'ui.trial.fire.hint': 'Uma rajada de lança-chamas a 1,6 m',\n 'ui.trial.blast.hint': 'Uma granada de fragmentação explode logo atrás dele (pega os vizinhos também)',\n 'act.test_table': 'Mesa de testes: {group}, itens {from}–{to} de {total}',\n 'act.trial.shot': 'Teste: tiro em {name}',\n 'act.trial.punch': 'Teste: soco em {name}',\n 'act.trial.stab': 'Teste: faca em {name}',\n 'act.trial.fire': 'Teste: fogo em {name}',\n 'act.trial.blast': 'Teste: explosão ao lado de {name}',\n 'arena.test_table': 'Mesa de testes',\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.kick': 'Chute',\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.dug': 'Escavado',\n 'ins.dig_limit': 'Chão até o limite',\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 { TRIAL_KINDS } from './test-table'\nimport type { TestTable, TestTablePage } from './test-table'\n\n/** The CSS of the test table panel (the room's panel look: `.tr-panel`, `.tr-btn`, `.tr-row`). */\nexport const TEST_TABLE_CSS = `\n.tr-table{flex:0 0 auto;max-height:42%}\n.tr-table .sub{color:#9aa3b2;margin:4px 0}\n.tr-table .list{display:flex;flex-wrap:wrap;gap:3px}\n.tr-table .list .tr-btn{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-table select{flex:1;min-width:0;max-width:55%}\n.tr-table .tr-search{margin:6px 0 0}\n.tr-root .tr-table button.tr-btn.on{background:#3b3a14;border-color:#ffd23f;color:#fff}\n`\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/**\n * The panel of the test table: a group, its pages (◀ ▶), the items on the table (a click picks the one the trials hit) and one button per trial, plus one that puts the table back.\n */\nexport function createTestTablePanel(table: TestTable, t: (key: string, vars?: Record<string, string | number>) => string): { element: HTMLElement; refresh(): void; dispose(): void } {\n const element = mk('div', 'tr-panel tr-table')\n element.appendChild(mk('h3', undefined, t('ui.test_table')))\n const head = mk('div', 'tr-row')\n const select = mk('select')\n select.setAttribute('aria-label', t('ui.test_table.group'))\n const lay = mk('button', 'tr-btn', t('ui.test_table.lay'))\n const prev = mk('button', 'tr-btn', '◀')\n const next = mk('button', 'tr-btn', '▶')\n prev.title = t('ui.test_table.prev')\n next.title = t('ui.test_table.next')\n for (const b of [lay, prev, next]) b.type = 'button'\n head.append(select, lay, prev, next)\n // a group has hundreds of items: the search lays the page that holds the one asked for\n const search = mk('input', 'tr-search')\n search.type = 'search'\n search.placeholder = t('ui.test_table.search')\n const found = mk('div', 'list')\n const sub = mk('div', 'sub', t('ui.test_table.hint'))\n const list = mk('div', 'list')\n const trials = mk('div', 'tr-row')\n const trialButtons = TRIAL_KINDS.map((kind) => {\n const b = mk('button', 'tr-btn', t(`ui.trial.${kind}`))\n b.type = 'button'\n b.dataset.trial = kind\n b.title = t(`ui.trial.${kind}.hint`)\n b.onclick = () => table.trial(kind)\n trials.appendChild(b)\n return b\n })\n const relay = mk('button', 'tr-btn', t('ui.test_table.relay'))\n relay.type = 'button'\n relay.onclick = () => table.relay()\n trials.appendChild(relay)\n // the trial buttons stay over the list: a page of small things is a long list, and the buttons must not scroll away under it\n element.append(head, search, found, sub, trials, list)\n\n const groups = (): void => {\n const keep = select.value\n select.textContent = ''\n for (const group of table.groups()) {\n const op = mk('option', undefined, group)\n op.value = group\n select.appendChild(op)\n }\n if ([...select.options].some((o) => o.value === keep)) select.value = keep\n }\n const render = (page: TestTablePage | null): void => {\n list.textContent = ''\n prev.disabled = !page?.hasPrev\n next.disabled = !page?.hasNext\n for (const b of [...trialButtons, relay]) b.disabled = !page?.selected\n if (!page) {\n sub.textContent = t('ui.test_table.hint')\n return\n }\n if (select.value !== page.group) select.value = page.group\n sub.textContent = t('ui.test_table.page', { from: page.first + 1, to: page.first + page.objects.length, total: page.total })\n for (const o of page.objects) {\n const b = mk('button', o.objectId === page.selected ? 'tr-btn on' : 'tr-btn', o.name)\n b.type = 'button'\n b.title = o.itemId\n b.onclick = () => table.select(o.objectId)\n list.appendChild(b)\n }\n }\n const fold = (text: string): string => text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase()\n search.oninput = () => {\n found.textContent = ''\n const term = fold(search.value.trim())\n if (!term) return\n const hits = table.items().filter((item) => fold(`${item.name} ${item.id}`).includes(term)).slice(0, 8)\n for (const item of hits) {\n const b = mk('button', 'tr-btn', item.name)\n b.type = 'button'\n b.title = `${item.group} · ${item.id}`\n b.onclick = () => {\n search.value = ''\n found.textContent = ''\n table.find(item.id)\n }\n found.appendChild(b)\n }\n if (!hits.length) found.appendChild(mk('div', 'sub', t('ui.no_results')))\n }\n lay.onclick = () => table.open(select.value)\n prev.onclick = () => table.prev()\n next.onclick = () => table.next()\n select.onchange = () => table.open(select.value)\n // typing in the select must not move the player or switch tools\n for (const box of [select, search]) box.addEventListener('keydown', (e) => e.stopPropagation())\n const off = table.on(render)\n groups()\n render(table.state())\n return {\n element,\n refresh: () => {\n groups()\n render(table.state())\n },\n dispose: off,\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 { createTestTablePanel, TEST_TABLE_CSS } from './test-table-panel'\nimport type { TestTable } from './test-table'\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 /** Set when the aim rests on the floor: what the ground is there (the room's terrain) instead of an object's part. */\n ground?: GroundInspect\n}\n\n/** The floor under the aim: its profile, the layer a blow reaches now and what has been done to it. */\nexport interface GroundInspect {\n /** Name of the ground profile (Dirt, Concrete slab). */\n surface: string\n /** Name of the material exposed at that point (the turf, or the soil under it once dug). */\n material: string\n /** Metres dug out under the untouched surface. */\n dug: number\n /** Metres left before the digging limit (bedrock, or the bottom of a slab). */\n remaining: number\n /** 0..1, how burnt the surface is. */\n scorch: 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 strike combo (`strikeCombo`) is on; null when the room has none. */\n combo?: boolean | null\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 /** Opens the graphics screen: the button takes the place of the quality select. Absent: the select. */\n onGraphics?: () => void\n scenarios: () => TestRoomScenario[]\n onRun: (s: TestRoomScenario) => Promise<ScenarioReport | void>\n onRunAll: () => Promise<ScenarioReport | void>\n onTool: (index: number) => void\n onTap: () => void\n /** The combo button: its label (the combo's name) and what it toggles; absent when the room has no combo. */\n combo?: { label: string; onToggle: () => void }\n kick?: { label: string; onKick: () => 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 /** The room's test table: its panel goes between the inspector and the log. Absent: no panel. */\n testTable?: TestTable\n}\n\nexport interface RoomUi {\n /** Writes the log lines queued since the last frame (the room calls it every frame; a burst costs one DOM write). */\n flushLog(): void\n hud(state: HudState): void\n /** The hold timer around the crosshair, 0 to 1; null hides it. Called every frame while it runs. */\n holdRing(value: number | null): void\n toast(text: string): void\n /** A warning that stays on screen under the tool (the memory watch: memory keeps growing after each clear); null takes it away. */\n alert(text: string | null): 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-ring{position:absolute;left:50%;top:50%;width:64px;height:64px;margin:-32px 0 0 -32px;transform:rotate(-90deg);display:none;pointer-events:none;filter:drop-shadow(0 0 2px #000)}\n.tr-ring circle{fill:none;stroke-width:5}.tr-ring .tr-ring-bg{stroke:rgba(255,255,255,.25)}.tr-ring .tr-ring-fill{stroke:#ffd166;stroke-linecap:round}\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-alert{display:none;position:relative;z-index:20;margin-top:6px;background:rgba(183,28,28,.92);color:#fff;padding:6px 12px;border-radius:6px;font-size:13px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,.4)}\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 + (o.testTable ? TEST_TABLE_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 ring = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n ring.setAttribute('class', 'tr-ring')\n ring.setAttribute('viewBox', '0 0 64 64')\n const ringCircle = (className: string): SVGCircleElement => {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n circle.setAttribute('class', className)\n circle.setAttribute('cx', '32')\n circle.setAttribute('cy', '32')\n circle.setAttribute('r', '27')\n ring.appendChild(circle)\n return circle\n }\n ringCircle('tr-ring-bg')\n const ringFill = ringCircle('tr-ring-fill')\n const RING_LENGTH = 2 * Math.PI * 27\n ringFill.style.strokeDasharray = String(RING_LENGTH)\n const top = mk('div', 'tr-top')\n const toolBox = mk('div', 'tr-tool')\n const status = mk('div', 'tr-status')\n const alertBox = mk('div', 'tr-alert')\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, alertBox, 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 // the test table sits between the inspector and the log (the log gives way), so the catalogue keeps its room on the right\n const tablePanel = o.testTable ? createTestTablePanel(o.testTable, t) : null\n left.append(insp, ...(tablePanel ? [tablePanel.element] : []), 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 rebuildLog()\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 // a blast storm logs hundreds of lines in one frame: they queue and the DOM is touched once per frame, for the last MAX_LINES only\n let pendingAdds: LogEntry[] = []\n const pendingUpdates = new Map<number, LogEntry>()\n let isLogStale = false\n const isLogVisible = (): boolean => !window.matchMedia?.('(max-width:980px)').matches || root.classList.contains('open')\n const buildNode = (e: LogEntry): HTMLElement => {\n const n = mk('div')\n fill(n, e)\n nodes.set(e.seq, n)\n return n\n }\n function rebuildLog(): void {\n pendingAdds = []\n pendingUpdates.clear()\n isLogStale = false\n logBody.textContent = ''\n nodes.clear()\n const fragment = document.createDocumentFragment()\n for (const e of o.log.entries().slice(-MAX_LINES * 3)) if (filters[e.channel]) fragment.appendChild(buildNode(e))\n logBody.appendChild(fragment)\n trimLog()\n }\n function trimLog(): void {\n while (logBody.childElementCount > MAX_LINES) {\n const oldest = nodes.keys().next()\n if (oldest.done) break\n nodes.delete(oldest.value)\n logBody.firstElementChild?.remove()\n }\n // scrolled at the next flush, before it touches the DOM: read now, scrollHeight would lay the page out in the middle of the frame\n // (perf.mjs, 2026-11-03: part of the 118 ms long task of the horde chain's first blast)\n if (autoscroll) isScrollDue = true\n }\n let isScrollDue = false\n const scrollToEnd = (): void => {\n if (!isScrollDue) return\n isScrollDue = false\n logBody.scrollTop = logBody.scrollHeight\n }\n const flushLog = (): void => {\n scrollToEnd()\n if (pendingAdds.length === 0 && pendingUpdates.size === 0) return\n if (!isLogVisible()) {\n isLogStale = true\n pendingAdds = []\n pendingUpdates.clear()\n return\n }\n if (isLogStale) return rebuildLog()\n const fragment = document.createDocumentFragment()\n for (const e of pendingAdds.slice(-MAX_LINES)) if (filters[e.channel]) fragment.appendChild(buildNode(e))\n pendingAdds = []\n logBody.appendChild(fragment)\n for (const [seq, e] of pendingUpdates) {\n const n = nodes.get(seq)\n if (n) fill(n, e)\n }\n pendingUpdates.clear()\n trimLog()\n }\n const offLog = o.log.on((e, updated) => {\n if (updated) pendingUpdates.set(e.seq, e)\n else pendingAdds.push(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 comboBtn = o.combo ? ctl(`${o.combo.label} (N)`, () => o.combo!.onToggle()) : null\n if (o.kick) ctl(o.kick.label, () => o.kick!.onKick())\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 if (o.onGraphics) {\n const g = ctl(t('ui.graphics'), () => o.onGraphics!())\n g.dataset.testid = 'graphics-button'\n } else {\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 }\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 if (isLogStale && isLogVisible()) rebuildLog()\n o.onResize()\n }\n toggle.onclick = togglePanels\n\n root.append(cross, ring, 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.ground) {\n const g = i.ground\n insp.appendChild(mk('div', 't', `${i.object} › ${g.surface}`))\n insp.appendChild(row(t('ins.material'), g.material))\n insp.appendChild(row(t('ins.dug'), `${num(g.dug * 100, 0)} cm`))\n insp.appendChild(row(t('ins.dig_limit'), `${num(g.remaining, 2)} m`))\n if (g.scorch > 0.01) insp.appendChild(row(t('ins.char'), `${num(g.scorch * 100, 0)} %`))\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 holdRing(value) {\n ring.style.display = value === null ? 'none' : 'block'\n if (value !== null) ringFill.style.strokeDashoffset = String(RING_LENGTH * (1 - value))\n },\n flushLog,\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 comboBtn?.classList.toggle('on', !!s.combo)\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 alert(text) {\n alertBox.textContent = text ?? ''\n alertBox.style.display = text ? 'block' : 'none'\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 tablePanel?.refresh()\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 tablePanel?.dispose()\n if (toastTimer) clearTimeout(toastTimer)\n root.remove()\n },\n }\n rebuildLog()\n return api\n}\n","/**\n * The extra views modules ask for (`ModuleHost.addView`: rear-view and side mirrors, a reversing camera) and the main-view takeover (`ModuleHost.setViewCamera`: a vehicle's chase or\n * cockpit camera). Each extra view is rendered into its own render target and laid on the screen as a quad, flipped for a mirror and with rounded corners when asked; everything it\n * creates is disposed when the view is taken away or the room is torn down.\n */\nimport type * as THREE_NS from 'three'\nimport type { ModuleView } from '@adatechnology/game-contracts'\n\ntype Entry = {\n readonly view: ModuleView\n readonly target: THREE_NS.WebGLRenderTarget\n readonly quad: THREE_NS.Mesh\n readonly frame: THREE_NS.Mesh\n readonly alpha: THREE_NS.Texture | null\n}\n\nexport type ModuleViews = {\n add(view: ModuleView): () => void\n setMain(camera: THREE_NS.Camera | null): void\n /** The camera the main view renders from: the module's when one took it over. */\n main(fallback: THREE_NS.Camera): THREE_NS.Camera\n /** Draws every extra view over what is already on the screen. */\n render(scene: THREE_NS.Scene): void\n readonly count: number\n dispose(): void\n}\n\nconst FRAME_PX = 3\n\nexport function createModuleViews(THREE: typeof THREE_NS, gl: THREE_NS.WebGLRenderer): ModuleViews {\n const entries: Entry[] = []\n let mainCamera: THREE_NS.Camera | null = null\n const overlay = new THREE.Scene()\n const ortho = new THREE.OrthographicCamera(-0.5, 0.5, 0.5, -0.5, 0, 2)\n ortho.position.z = 1\n const plane = new THREE.PlaneGeometry(1, 1)\n\n // a rounded rectangle as an alpha mask (white inside), drawn once per view on a small canvas\n const roundedMask = (rounded: number, aspect: number): THREE_NS.Texture | null => {\n if (!rounded || typeof document === 'undefined') return null\n const canvas = document.createElement('canvas')\n canvas.width = 256\n canvas.height = Math.max(16, Math.round(256 / aspect))\n const g = canvas.getContext('2d')\n if (!g) return null\n const r = Math.min(canvas.width, canvas.height) * Math.min(0.5, rounded)\n g.fillStyle = '#000'\n g.fillRect(0, 0, canvas.width, canvas.height)\n g.fillStyle = '#fff'\n g.beginPath()\n g.roundRect(0, 0, canvas.width, canvas.height, r)\n g.fill()\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.NoColorSpace\n return texture\n }\n\n const size = (): { w: number; h: number } => {\n // a stand-in renderer (tests, a headless host) may not measure itself\n if (typeof gl.getSize !== 'function') return { w: 960, h: 600 }\n const v = new THREE.Vector2()\n gl.getSize(v)\n return { w: v.x, h: v.y }\n }\n\n const take = (entry: Entry): void => {\n const i = entries.indexOf(entry)\n if (i < 0) return\n entries.splice(i, 1)\n overlay.remove(entry.quad, entry.frame)\n entry.target.dispose()\n ;(entry.quad.material as THREE_NS.Material).dispose()\n ;(entry.frame.material as THREE_NS.Material).dispose()\n entry.alpha?.dispose()\n }\n\n return {\n add(view) {\n const { w, h } = size()\n const scale = view.resolution ?? 0.5\n const pr = typeof gl.getPixelRatio === 'function' ? gl.getPixelRatio() : 1\n const target = new THREE.WebGLRenderTarget(Math.max(16, Math.round(w * view.rect.width * pr * scale)), Math.max(16, Math.round(h * view.rect.height * pr * scale)), { samples: 2 })\n target.texture.colorSpace = THREE.LinearSRGBColorSpace\n const alpha = roundedMask(view.rounded ?? 0, (w * view.rect.width) / Math.max(1, h * view.rect.height))\n const quad = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ map: target.texture, side: THREE.DoubleSide, depthTest: false, depthWrite: false, ...(alpha ? { alphaMap: alpha, transparent: true } : {}) }))\n const frame = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ color: 0x0b0c0e, side: THREE.DoubleSide, depthTest: false, depthWrite: false, ...(alpha ? { alphaMap: alpha, transparent: true } : {}) }))\n quad.renderOrder = 1\n frame.visible = quad.visible = false\n overlay.add(frame, quad)\n const entry: Entry = { view, target, quad, frame, alpha }\n entries.push(entry)\n return () => take(entry)\n },\n setMain(camera) {\n mainCamera = camera\n },\n main(fallback) {\n if (!mainCamera) return fallback\n const persp = mainCamera as THREE_NS.PerspectiveCamera\n const back = fallback as THREE_NS.PerspectiveCamera\n if (persp.isPerspectiveCamera && back.isPerspectiveCamera && persp.aspect !== back.aspect) {\n persp.aspect = back.aspect\n persp.updateProjectionMatrix()\n }\n return mainCamera\n },\n render(scene) {\n if (!entries.length) return\n const { w, h } = size()\n const autoClear = gl.autoClear\n const shadows = gl.shadowMap.autoUpdate\n // the shadow maps were drawn for the main view this frame: the extra views reuse them\n gl.shadowMap.autoUpdate = false\n for (const entry of entries) {\n const cam = entry.view.camera as THREE_NS.PerspectiveCamera\n const aspect = (w * entry.view.rect.width) / Math.max(1, h * entry.view.rect.height)\n if (cam.isPerspectiveCamera && Math.abs(cam.aspect - aspect) > 1e-3) {\n cam.aspect = aspect\n cam.updateProjectionMatrix()\n }\n gl.setRenderTarget(entry.target)\n gl.clear()\n gl.render(scene, cam)\n }\n gl.setRenderTarget(null)\n gl.autoClear = false\n gl.setScissorTest(true)\n for (const entry of entries) {\n const r = entry.view.rect\n const x = r.x * w\n const y = (1 - r.y - r.height) * h\n const vw = r.width * w\n const vh = r.height * h\n for (const mesh of [entry.frame, entry.quad]) mesh.visible = false\n // the dark frame a few pixels larger, then the picture\n entry.frame.visible = true\n gl.setViewport(x - FRAME_PX, y - FRAME_PX, vw + 2 * FRAME_PX, vh + 2 * FRAME_PX)\n gl.setScissor(x - FRAME_PX, y - FRAME_PX, vw + 2 * FRAME_PX, vh + 2 * FRAME_PX)\n gl.render(overlay, ortho)\n entry.frame.visible = false\n entry.quad.visible = true\n entry.quad.scale.x = entry.view.mirror ? -1 : 1\n gl.setViewport(x, y, vw, vh)\n gl.setScissor(x, y, vw, vh)\n gl.render(overlay, ortho)\n entry.quad.visible = false\n }\n gl.setScissorTest(false)\n gl.setViewport(0, 0, w, h)\n gl.autoClear = autoClear\n gl.shadowMap.autoUpdate = shadows\n },\n get count() {\n return entries.length\n },\n dispose() {\n for (const entry of [...entries]) take(entry)\n plane.dispose()\n mainCamera = null\n },\n }\n}\n"],"mappings":"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","names":["impactKey","slides","control","key","key","box","box","document","key","key","key","key","a","b","g","box","STANDING_EYE","LOOK_RANGE","STANDOFF","APPROACH_SPEED","box","key","releaseObject3D","box","key","mk","fold","box","mk","list","box","key","BODY_HEIGHT","key","t","host","slides","box","releaseObject3D","push","height","step","fire","px","py","pz","tool","grab","room","id","status"]}
|
|
1
|
+
{"version":3,"sources":["../src/room.ts","../src/body-sounds.ts","../src/arena.ts","../src/items.ts","../src/hand-sounds.ts","../src/bench.ts","../src/build-from-spec.ts","../src/explosives.ts","../src/segment-box.ts","../src/test-table.ts","../src/host-events.ts","../src/loading-view.ts","../src/loading.ts","../src/graphics.ts","../src/log.ts","../src/metrics.ts","../src/memory-watch.ts","../src/narrate.ts","../src/player.ts","../src/furniture-push.ts","../src/seating.ts","../src/door-open.ts","../src/avatar.ts","../src/locale.ts","../src/bench-panel.ts","../src/test-table-panel.ts","../src/ui.ts","../src/module-views.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, loadKitSamples, loadUserSamples } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { createDestructionRenderer, createDestructionSound, dragSoundKey, impactKey, impactSoundKeys, specFromObject3D } from '@adatechnology/game-destruction-three'\nimport type { SoundDetail } from '@adatechnology/game-destruction-three'\nimport { bodyMass, KNOCK_CHEST, KNOCK_DOWN_SPEED, knockOf, surfaceOfMaterial } from '@adatechnology/game-contracts'\nimport type { GaitId, SurfaceId } from '@adatechnology/game-contracts'\nimport { blowOfTool, createBodySounds, createStrideCounter, swingLead } from './body-sounds'\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 { SPRITE_KINDS, createVfx, patchSpriteKinds } from '@adatechnology/game-vfx'\nimport { createVfxRenderer } from '@adatechnology/game-vfx-three'\nimport { createFramePacer, createGeometryPool, createLightBudget, createMaterialPool, createProgramWarmup, createStaticBatcher, spriteProbes } from '@adatechnology/game-render-three'\nimport type { EffectWarmup, RenderPools, StaticBatcher, WarmupProbe } from '@adatechnology/game-render-three'\nimport type { FluidRenderer } from '@adatechnology/game-fluids-three'\nimport { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, checkAnimation, checkBench, checkDestructible, checkSpec, createEnvironmentBus, sealBlock, sealOpener, shotExtras, twistStroke, TWIST_LIFT, useToHit } from '@adatechnology/game-contracts'\nimport type { AnimationClipSpec, HandPose, HandTargetSource, HandTargets, HostEvent, ItemUseDef, TwistStroke, ModuleArea, ModuleBench, ModuleHost, TestableModule, ToolCommand, ToolCommandResult } from '@adatechnology/game-contracts'\nimport { createScheduler, startLoop } from '@adatechnology/game-runtime'\nimport { createArena } from './arena'\nimport { leafFoleyOf, openSoundOf, pickupSoundOf, USE_SOUND_EVERY, useSoundOf } from './hand-sounds'\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 { createTestTable } from './test-table'\nimport type { BlastSummary } from './explosives'\nimport { toHostEvent } from './host-events'\nimport { createLoading } from './loading'\nimport { createRoomGraphics } from './graphics'\nimport type { RoomGraphics } from './graphics'\nimport { createLog } from './log'\nimport { createRoomMetrics, heapMB, ROOM_METRICS } from './metrics'\nimport { createMemoryWatch } from './memory-watch'\nimport { createNarrator } from './narrate'\nimport { createPlayer, PLAYER_RADIUS } from './player'\nimport type { PlayerSlam } from './player'\nimport { createRoomPush, PUSH_REACH } from './furniture-push'\nimport type { RoomPushTarget } from './furniture-push'\nimport { createSeating } from './seating'\nimport type { SeatHolder } from './seating'\nimport { createRoomDoors, DOOR_REACH } from './door-open'\nimport type { RoomLeaf } from './door-open'\nimport { releaseObject3D } from '@adatechnology/game-shapes-three'\nimport { createTerrain, createTerrainImpl, DEFAULT_PROFILE, type TerrainBlowResult } from '@adatechnology/game-terrain'\nimport { createTerrainRenderer, terrainProfileName } from '@adatechnology/game-terrain-three'\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 { createModuleViews } from './module-views'\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 UseStatus,\n} from './types'\n\ntype Vars = Record<string, string | number>\n\ninterface Entry {\n so: SpawnedObject\n /** What draws the object's own damage on it (`SceneryObject.follow`). */\n follower?: { restore?(): void; dispose?(): void; update?(): void } | null\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 /** A sealed item (`TestRoomItem.seal`) was opened. */\n opened?: boolean\n /** Litres the container started with, and litres the player ate or drank out of it: the rest of a loss is a leak. */\n fluidStart?: number\n fluidUsed?: number\n /** Litres a sealed item had lost when it was opened (`sealLoss`). */\n sealLoss?: number\n /** Leaning on it pushes it. */\n pushable?: 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\n/** The effect ids of the explosives of the arsenal (the profiles of `game-vfx`) the room draws at load. */\nconst EXPLOSIVE_EFFECT_IDS = ['m67', 'molotov', 'pipe_bomb', 'm79_40mm', 'm72_66mm', 'at4_84mm', 'dynamite', 'c4', 'claymore'] as const\n/** The fog the scene may be in while the room runs: none, the weather's linear fog and its exponential one (the weather module comes in after the load). */\n/** The most loose bodies (casings, magazines) the room lets its modules keep alive at once: the cap the weapons viewmodel had on its own. */\nconst DEFAULT_PARTICLE_LIMIT = 900\nconst WARMED_FOG_STATES = ['none', 'linear', 'exp2'] as const\n/** Slots of the room's LightBudget: the default 16 point and 4 spot (perf.mjs on a real GPU: p50 and p99 of every phase the same as with 13 and 3, and the fixed cost of the light loop is lost in the noise). */\nconst ROOM_LIGHT_SIZES = { point: 16, spot: 4, pointShadows: 0, hemisphere: 1 } as const\n/** Widest scenery footprint (m) the renderer's drawn boxes stand for (as its own limit for fixed meshes); a wider one keeps its collider. */\nconst SOLID_SPAN = 3\n/** Meshes an object needs before the room draws its still ones in batches (a bookcase, a shelf of books): fewer cost less than the batch check. */\nconst BATCH_MIN_MESHES = 8\n/** Milliseconds a frame the batches of a new object may take to be made. */\nconst BATCH_BUDGET_MS = 1\n/** Owners that draw their own batches or move every frame (a vehicle batches itself; people and animals are posed each frame). */\nconst UNBATCHED_OWNERS = /vehicles|characters|animals|crowd/\n/** Highest top (m above the feet) the player steps onto: low debris; higher stops the walk. */\nconst STEP_UP = 0.45\n/** Height of the walking body (m): what starts above it is walked under. */\nconst BODY_HEIGHT = 1.75\n/** Pieces lighter than this (kg) are kicked out of the way instead of stepped on or stopping the player; how high above the feet they still are. */\nconst KICK_MASS = 6\nconst KICK_HEIGHT = 0.6\n/** Object id of the floor in the destruction world. */\nconst GROUND_ID = 'room_ground'\nconst TERRAIN_CELL = 0.1\n/** A huge arena gets coarser cells, not more memory. */\nconst TERRAIN_MAX_CELLS = 1000\nconst GROUND_BURST_MAX = 28\nconst GROUND_BURST_PER_METRE = 30\nconst GROUND_DUST_RADIUS = 0.2\nconst GROUND_FIRE_EVERY = 0.3\n\n/** Speed (m/s) the rounds of one trigger pull must give a free-standing object to move it: a shotgun moves a bookcase, a pistol does not. */\nconst SHOVE_SPEED = 0.04\nconst METRICS_INTERVAL_S = 0.25\n/** How far the palm sits off the part of a carried item it holds (m). */\nconst CARRY_PALM = 0.012\n/** Metres a screw cap rises off its thread at the end of an opening use, which the hand on it follows. */\nconst CAP_RISE = 0.03\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 */\n/**\n * The sound key of a vehicle's door, hood or trunk lid (`vehicle_door_shut`...): a car leaf has its own sounds, not those of its sheet metal. The part's\n * role tag (`door`, `hood`, `lid`, from game-vehicles) says which; an untagged leaf counts as a door.\n */\nconst vehicleLeafKey = (spec: DestructibleSpec, part: string, moment: 'open' | 'shut'): string => {\n const tags = spec.parts.find((p) => p.id === part)?.tags ?? []\n const leaf = tags.includes('hood') ? 'hood' : tags.includes('lid') || tags.includes('trunk') ? 'trunk' : 'door'\n return `vehicle_${leaf}_${moment}`\n}\n\n/** The destruction events that already play the impact of a blow (a mark, a break): a blow without any of them plays its contact sound itself. */\nconst MARK_EVENTS: ReadonlySet<string> = new Set(['dent', 'hole', 'crack', 'chip', 'stage', 'fracture'])\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 // the extra views (mirrors, reversing cameras) and the main-view takeover that modules ask for\n const moduleViews = createModuleViews(THREE, gl)\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 // the player's graphics settings (game-graphics): only on a renderer the room owns, and only when the page asks (the example page does; tests keep the fixed look)\n const graphics: RoomGraphics | null =\n ownRenderer && options.graphics\n ? createRoomGraphics({\n gl,\n camera,\n sun: arena.sun,\n container,\n locale,\n loading,\n label: t('loading.graphics'),\n ui: options.ui !== false,\n options: options.graphics === true ? {} : options.graphics,\n })\n : null\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 partStands = (object: string, part: string): boolean => {\n const p = world.part(object, part)\n return !!p && p.status !== 'broken' && p.status !== 'melted' && p.status !== 'ashes' && !renderer.piece(object)\n }\n const topOk = (t: ArenaTop): boolean => (t.boards ? t.boards.some((b) => partStands(t.id, b.part)) : partStands(t.id, t.topPart))\n /** Whether the top holds what is at (x, z): the board there, on a top of boards. */\n const topHolds = (t: ArenaTop, x: number, z: number): boolean => (t.boards ? t.boards.some((b) => x > b.minX && x < b.maxX && z > b.minZ && z < b.maxZ && partStands(t.id, b.part)) : topOk(t))\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 && topHolds(t, x, z)) top = t.top\n return top\n }\n // the floor is the terrain: 0 was the height of a flat floor, now a hole goes under it and a heap over it; a top (a table, a counter) answers only where there is one\n const defaultGround = options.ground ?? { surface: DEFAULT_PROFILE }\n const terrain = createTerrain({ bounds: [-arenaSize, -arenaSize, arenaSize, arenaSize], cellSize: Math.max(TERRAIN_CELL, (2 * arenaSize) / TERRAIN_MAX_CELLS), layout: defaultGround, ...(options.terrainBudget ? { budget: options.terrainBudget } : {}) })\n const terrainView = createTerrainRenderer(THREE, { terrain })\n arena.group.add(terrainView.group)\n const groundAt = (x: number, z: number): number => {\n const top = Math.max(sceneryTopAt(x, z), restingTopAt(x, z))\n const floor = terrain.heightAt(x, z)\n return top > 0 ? Math.max(top, floor) : floor\n }\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({ deferredStart: {} }))\n const destructionSound = audio ? createDestructionSound(audio) : null\n // the kit's recorded files (game-audio assets/sfx), served next to the page: each recipe of the same id plays until its takes load, and stays where they cannot be fetched\n if (audio && options.samplesBaseUrl !== null) {\n void loadKitSamples(audio, { baseUrl: options.samplesBaseUrl ?? './sfx/' }).then(async (bank) => {\n // the owner's own sounds after the kit's, so each one the kit has keeps the kit's recording in front\n if (options.userSamplesBaseUrl !== null) {\n const own = await loadUserSamples(audio, { baseUrl: options.userSamplesBaseUrl ?? './sfx-local/' })\n if (own) log.add({ channel: 'event', type: 'user_sounds', text: `sons do dono: ${own.playing.length} tocando, ${own.behindKit.length} atrás do SDK`, data: { playing: own.playing, behindKit: own.behindKit } })\n }\n if (!bank || typeof window === 'undefined') return\n // the hand's sounds (a door, an item taken) load on the first key or click, when the page may make its AudioContext, so even the first one is the recording\n const preload = (): void => {\n window.removeEventListener('keydown', preload, true)\n window.removeEventListener('pointerdown', preload, true)\n void audio.loadSamples(['latch', 'creak_wood', 'shut_wood', 'rattle', 'grab_hard', 'grab_soft']).catch(() => undefined)\n }\n window.addEventListener('keydown', preload, true)\n window.addEventListener('pointerdown', preload, true)\n })\n }\n // the body's own sounds (jump, landing, the swing and the knuckles, sole or blade of a blow); the footsteps are the player module's, on the footfalls the room sends\n const bodySounds = createBodySounds(audio)\n const playSound = (key: string, point: Vec3, volume: number, detail?: SoundDetail): void => {\n destructionSound?.onSound(key, point, volume, detail)\n if (detail) options.onSound?.(key, point, volume, detail)\n else options.onSound?.(key, point, volume)\n }\n\n // the one owner of the point and spot lights: its size is what the clients of the room ask of it (T4.4 raises it client by client)\n const lights = createLightBudget(THREE, scene, { ...ROOM_LIGHT_SIZES, ...options.lightSizes })\n // what the effects of the room and of its modules ask for instead of making their own; the warmup's anchors keep the programs of the materials that are given back\n const warmup = createProgramWarmup(THREE)\n const pools: RenderPools = { geometries: createGeometryPool(), materials: createMaterialPool({ anchors: warmup.anchors, renderer: gl }) }\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 vfx = createVfxRenderer(THREE, {\n scene,\n lights,\n camera,\n overlay: container,\n quality,\n pointScale,\n vfx: createVfx({\n profile: quality,\n ...(options.debris?.particles ? { sprites: { kinds: patchSpriteKinds(SPRITE_KINDS, options.debris.particles) } } : {}),\n groundAt,\n }),\n })\n const renderer = createDestructionRenderer(THREE, {\n scene,\n world,\n vfx: vfx.world,\n quality,\n groundAt,\n pointScale,\n ...(options.debris?.fragmentLife !== undefined ? { fragmentLife: options.debris.fragmentLife } : {}),\n ...(options.debris?.maxFragments !== undefined ? { maxFragments: options.debris.maxFragments } : {}),\n eventBudgetMs: options.debris?.eventBudgetMs ?? 8,\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, cause) => {\n const e = entries.get(objectId)\n if (!e) return\n e.piece = piece\n leaveFootprint(objectId)\n rendererPieces.set(objectId, piece)\n action('loosened', t(cause === 'blast' ? 'act.loosened' : 'act.came_apart', { 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\n // the ground is an object of the world: shots, blows, blasts and flames reach it like anything else\n const showGroundBlow = (result: TerrainBlowResult): void => {\n const material = terrain.material(result.removed[0]?.material ?? result.exposed)\n const def = world.materials.get(material.id)\n const size = Math.min(GROUND_BURST_MAX, Math.ceil(result.radius * GROUND_BURST_PER_METRE))\n renderer.emit(material.debris === 'clods' ? 'dust' : material.debris, result.point as Vec3, [0, 1, 0], Math.max(2, size), Math.min(4, 1 + result.radius * 4))\n if (result.radius > GROUND_DUST_RADIUS) renderer.emit('dust', result.point as Vec3, [0, 1, 0], size, 1.4)\n playSound(impactKey(def), result.point as Vec3, Math.min(1, 0.25 + result.radius), impactSoundKeys(material.id, def))\n }\n terrain.onDeform((region) => renderer.wakeRegion(region.x, region.z, region.radius))\n const groundImpl = createTerrainImpl(terrain, { id: GROUND_ID, name: t('ground.name'), onBlow: showGroundBlow })\n const registerGround = (): void => {\n if (!world.has(GROUND_ID)) world.register(groundImpl, { id: GROUND_ID })\n }\n registerGround()\n let groundFireClock = 0\n const showGroundFire = (dt: number): void => {\n groundFireClock += dt\n if (groundFireClock < GROUND_FIRE_EVERY) return\n groundFireClock = 0\n for (const [x, z] of terrain.burningPoints()) {\n const y = terrain.heightAt(x, z)\n renderer.emit('fire', [x, y + 0.05, z], [0, 1, 0], 3, 1.6)\n if (rnd() < 0.25) renderer.emit('smoke', [x, y + 0.2, z], [0, 1, 0], 1, 1)\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(), footfall: 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') {\n emitHost({\n type: 'explosion',\n source: ev.object,\n point: ev.point,\n energy: ev.energy,\n radius: ev.radius,\n cause: 'part',\n ...(ev.effect !== undefined ? { explosive: ev.effect } : {}),\n ...(ev.tnt !== undefined ? { tnt: ev.tnt } : {}),\n ...(ev.lethalRadius !== undefined ? { lethalRadius: ev.lethalRadius } : {}),\n })\n }\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 // the scenery the renderer draws stops the player by what is drawn now (a fallen bookcase is walked onto, not its old footprint); what is\n // too wide for the renderer's boxes (the wall closing the arena) and the tap's post keep their footprint\n const drawnScenery = (i: number): boolean => {\n const c = arena.colliders[i]\n return arena.colliderIds[i] !== null && c[2] - c[0] <= SOLID_SPAN && c[3] - c[1] <= SOLID_SPAN\n }\n // the footprints that still hold: the player and the push read this same list\n const standingColliders: Array<[number, number, number, number]> = []\n const standingIds: Array<string | null> = []\n /** Scenery too wide for the renderer's boxes that came loose: the body stops the player from then on (`inTheWay`), wherever it goes. */\n const footprintsWithBody = new Set<string>()\n /** Every piece of the scenery back where it stands. */\n const standFootprints = (): void => {\n standingColliders.length = 0\n standingIds.length = 0\n footprintsWithBody.clear()\n arena.colliders.forEach((collider, i) => {\n if (drawnScenery(i)) return\n standingColliders.push(collider)\n standingIds.push(arena.colliderIds[i] ?? null)\n })\n }\n standFootprints()\n /** The object is a body now: the footprint it had where it stood no longer means anything. */\n const leaveFootprint = (objectId: string): void => {\n const i = standingIds.indexOf(objectId)\n if (i < 0) return\n standingIds.splice(i, 1)\n standingColliders.splice(i, 1)\n footprintsWithBody.add(objectId)\n }\n /**\n * The footing of the player at (x, z) with the feet at `feet`: what is drawn there and not lighter than `KICK_MASS` (that is kicked, see\n * `kickLight`) is stepped onto when its top is within `STEP_UP` of the feet and stops the player when it is taller and reaches the body.\n */\n const footing = (x: number, z: number, radius: number, feet: number): { floor: number; blocked: boolean } => {\n let floor = -Infinity\n let blocked = false\n for (const s of renderer.solidsNear(x, z, radius)) {\n if ((s.piece?.mass ?? s.loose?.mass ?? Infinity) < KICK_MASS) continue\n const dx = Math.max(s.min[0] - x, 0, x - s.max[0])\n const dz = Math.max(s.min[2] - z, 0, z - s.max[2])\n if (dx * dx + dz * dz > radius * radius) continue\n if (s.max[1] <= feet + STEP_UP) floor = Math.max(floor, s.max[1])\n else if (s.min[1] < feet + BODY_HEIGHT) blocked = true\n }\n return { floor, blocked }\n }\n /** Light pieces at the player's feet (books, boards) are kicked along: away from the player at a little more than the walking speed. */\n const kickFrom = { x: 0, z: 0 }\n const kickLight = (dt: number): void => {\n const x = player.x\n const z = player.z\n // walked by the keys or by a scripted walk: the distance since the last frame\n const speed = dt > 0 ? Math.hypot(x - kickFrom.x, z - kickFrom.z) / dt : 0\n kickFrom.x = x\n kickFrom.z = z\n if (speed < 0.2 || speed > 20) return\n const kicked = new Set<object>()\n for (const s of renderer.solidsNear(x, z, PLAYER_RADIUS)) {\n const pc = s.piece\n const body = pc ?? s.loose\n if (!body || body.mass >= KICK_MASS || kicked.has(body) || s.min[1] > player.feet + KICK_HEIGHT) continue\n kicked.add(body)\n const cx = (s.min[0] + s.max[0]) / 2 - x\n const cz = (s.min[2] + s.max[2]) / 2 - z\n const d = Math.hypot(cx, cz) || 1\n const v = speed * 1.2\n if (!pc) {\n s.loose?.push((cx / d) * v, (cz / d) * v)\n continue\n }\n if (pc.velocity[0] * cx + pc.velocity[2] * cz >= v * d) continue\n pc.velocity = [(cx / d) * v, Math.max(pc.velocity[1], 0.6), (cz / d) * v]\n pc.sleeping = false\n }\n }\n const player = createPlayer(THREE, {\n camera,\n dom,\n colliders: standingColliders,\n footing: (x, z, radius, feet) => footing(x, z, radius, feet),\n blockers,\n limit: arenaSize,\n floorAt: terrain.heightAt,\n start: arena.playerStart,\n crouchKeys: options.crouch?.keys,\n onSlam: (event) => slamPlayer(event),\n onFeet: (event) => {\n const at = player.position\n if (event.type === 'jump') bodySounds.jump(at)\n else {\n bodySounds.land(surfaceUnderFeet(), event.speed, at)\n action('landing_player', t('act.player_land', { speed: num(event.speed, 1) }), { data: { speedMs: Math.round(event.speed * 100) / 100, surface: surfaceUnderFeet() } })\n }\n },\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 /** How far from straight ahead (cosine) something can be and still be what the player leans on. */\n const PUSH_AHEAD = 0.6\n const heaviestMaterial = (id: string): string | undefined => {\n let best: { mass: number; material: string } | undefined\n for (const p of world.state(id)?.parts ?? []) if (p.status !== 'broken' && (!best || p.mass > best.mass)) best = { mass: p.mass, material: p.material }\n return best?.material\n }\n /** What the player stands against when the aim is not on it (from the shoulder the aim of something low falls on the floor beside it): the closest thing ahead within arm's reach. */\n const leanedOn = (): RoomPushTarget | null => {\n const fx = -Math.sin(player.yaw)\n const fz = -Math.cos(player.yaw)\n let best: Entry | null = null\n let bestDistance = PUSH_REACH\n for (const e of entries.values()) {\n if (!e.pushable || (!e.piece && !e.free)) continue\n const b = bodyBox(e)\n if (!b) continue\n const dx = Math.max(b.minX, Math.min(b.maxX, player.x)) - player.x\n const dz = Math.max(b.minZ, Math.min(b.maxZ, player.z)) - player.z\n const distance = Math.hypot(dx, dz)\n if (distance >= bestDistance || (distance > 1e-3 && (dx * fx + dz * fz) / distance < PUSH_AHEAD)) continue\n best = e\n bestDistance = distance\n }\n return best ? { objectId: best.so.objectId, root: best.so.root, name: nameOf(best.so.objectId), piece: best.piece ?? null } : null\n }\n const push = createRoomPush({\n THREE,\n player,\n world,\n arena: { limit: arenaSize, colliders: standingColliders },\n blockers,\n ...(options.push ? { rules: options.push } : {}),\n pick: () => {\n if (heldPiece || (tool.def.category !== 'hand' && toolId !== 'fists')) return null\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n const aimed = r ? (rendererPieces.get(r.object)?.root ?? (entries.get(r.object)?.free ? entries.get(r.object)?.so.root : undefined)) : undefined\n // the eye on something that is not pushed (a can on the floor) is the eye on what the hand takes, even against a sofa\n if (r && aimed) return entries.get(r.object)?.pushable ? { objectId: r.object, root: aimed, name: nameOf(r.object), piece: rendererPieces.get(r.object) ?? null } : null\n return leanedOn()\n },\n massOf: (objectId) => massOfObject(objectId),\n materialOf: heaviestMaterial,\n makePiece: (objectId) => {\n const piece = renderer.makePiece(objectId, { mass: Math.max(0.2, massOfObject(objectId)) })\n const e = entries.get(objectId)\n if (e) e.piece = piece\n rendererPieces.set(objectId, piece)\n leaveFootprint(objectId)\n return piece\n },\n dragSound: (objectId, point, volume) => playSound(dragSoundKey(world.materials.get(heaviestMaterial(objectId) ?? '')), point, volume),\n hitSound: (objectId, point) => {\n const material = heaviestMaterial(objectId) ?? ''\n const def = world.materials.get(material)\n playSound(impactKey(def), point, 0.5, impactSoundKeys(material, def, 'blunt'))\n },\n onEvent: (ev) => {\n const vars = { name: ev.name, kg: num(ev.massKg, 0) }\n action(`push_${ev.type}`, t(`act.push_${ev.type}`, vars), { objectId: ev.objectId, itemId: entryOf(ev.objectId)?.so.itemId, data: { massKg: Math.round(ev.massKg * 10) / 10 } })\n fire('push', ev)\n if (ev.type === 'engaged') say(t('hud.push_on', vars))\n else if (ev.type === 'too_heavy') say(t('hud.push_too_heavy', vars))\n else if (ev.type === 'obstacle') say(t('hud.push_blocked', vars))\n },\n ring: (value) => ui?.holdRing(value),\n hasBody: () => !!avatar?.eye,\n })\n const seatHolder = (objectId: string): SeatHolder | null => {\n const e = entries.get(objectId)\n const seats = e?.item?.seats\n if (!e || !seats?.length || !world.has(objectId)) return null\n return { objectId, root: rendererPieces.get(objectId)?.root ?? e.so.root, seats }\n }\n const seating = createSeating({\n THREE,\n player,\n pick: () => {\n aim()\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], 3.2)\n return r ? seatHolder(r.object) : null\n },\n find: seatHolder,\n hasBody: () => !!avatar?.eye,\n groundAt: (x, z) => groundAt(x, z),\n onSit: (seat) => action('sit', t(seat.pose === 'lie' ? 'act.lie' : 'act.sit', { name: nameOf(seat.objectId) }), { objectId: seat.objectId, itemId: entryOf(seat.objectId)?.so.itemId, data: { seat: seat.seatId, pose: seat.pose } }),\n onStand: (seat) => action('stand', t('act.stand', { name: nameOf(seat.objectId) }), { objectId: seat.objectId, itemId: entryOf(seat.objectId)?.so.itemId, data: { seat: seat.seatId } }),\n })\n /** E was pressed on something that can be pushed, not by a script: letting the key go is letting the piece go. */\n let pushByKey = false\n\n // ----- doors, lids and drawers worked by hand: a tap of E on a leaf (a part an `open_*` clip of the item moves) opens or closes it\n const leafCache = new WeakMap<object, RoomLeaf[]>()\n /** The leaves of an item: each part its `open_*` clips move, with the clip that opens it (a clip of its own wins over one that opens several together). */\n const leavesOf = (objectId: string): RoomLeaf[] => {\n const item = entries.get(objectId)?.item\n if (!item?.animations?.length) return []\n const cached = leafCache.get(item)\n if (cached) return cached\n const byPart = new Map<string, { clip: AnimationClipSpec; n: number }>()\n for (const clip of item.animations) {\n if (!clip.id.startsWith('open_')) continue\n const parts = new Set<string>()\n for (const k of clip.keys) for (const id of Object.keys(k.parts ?? {})) parts.add(id)\n for (const part of parts) {\n const had = byPart.get(part)\n if (!had || parts.size < had.n) byPart.set(part, { clip, n: parts.size })\n }\n }\n const leaves = [...byPart].map(([part, v]) => ({ part, clip: v.clip }))\n leafCache.set(item, leaves)\n return leaves\n }\n /** Locked leaves: `objectId\\0part`, or `objectId\\0*` for every leaf of the object. */\n const lockedLeaves = new Set<string>()\n const doors = createRoomDoors({\n THREE,\n player,\n world,\n camera,\n arena: { limit: arenaSize, colliders: standingColliders, ids: standingIds },\n ...(options.doors ? { rules: options.doors } : {}),\n pick: () => {\n if (heldPiece) return []\n aim()\n const hits: Array<{ objectId: string; part: string; point: Vec3 }> = []\n const r = rayWorld([aimO[0], aimO[1], aimO[2]], [aimD[0], aimD[1], aimD[2]], DOOR_REACH)\n if (r) hits.push({ objectId: r.object, part: r.part, point: r.point as Vec3 })\n // over the shoulder the crosshair can pass by a handle the body hides: what the eye itself faces comes next\n if (thirdActive()) {\n camera.getWorldDirection(tmpV2)\n const e = rayWorld([aimO[0], aimO[1], aimO[2]], [tmpV2.x, tmpV2.y, tmpV2.z], DOOR_REACH)\n if (e) hits.push({ objectId: e.object, part: e.part, point: e.point as Vec3 })\n }\n return hits\n },\n leaves: leavesOf,\n objectOf: (objectId, part) => entries.get(objectId)?.so.root.getObjectByName(part) ?? null,\n pose: (objectId, part, clip, fraction) => {\n const e = entries.get(objectId)\n const obj = e?.so.root.getObjectByName(part)\n if (!e || !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 const rest = restPose.get(obj)!\n const pose = poseAt(clip, part, Math.max(0, Math.min(1, fraction)) * clip.duration)\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 followPart(e, part, obj, rest)\n },\n isLocked: (objectId, part) => lockedLeaves.has(`${objectId}\\0*`) || lockedLeaves.has(`${objectId}\\0${part}`),\n nameOf,\n impactKey: (objectId, part) => impactKey(world.materials.get(world.part(objectId, part)?.material ?? heaviestMaterial(objectId) ?? '')),\n leafSound: (objectId, part, moment) => {\n const spec = specs.get(objectId)\n return spec?.tags?.includes('vehicle') ? vehicleLeafKey(spec, part, moment) : undefined\n },\n sound: playSound,\n // a vehicle's doors, hood and lid have their own sounds in the vehicle bank (game-vehicles-three), not those of the house\n leafFoley: (objectId, part, slides) =>\n specs.get(objectId)?.tags?.includes('vehicle') ? null : leafFoleyOf(entryOf(objectId)?.item?.sounds, part, impactKey(world.materials.get(world.part(objectId, part)?.material ?? heaviestMaterial(objectId) ?? '')), slides),\n onEvent: (ev) => {\n const vars = { name: ev.name, percent: Math.round(ev.opening * 100) }\n action(`door_${ev.type}`, t(`act.door_${ev.type}`, vars), { objectId: ev.objectId, itemId: entryOf(ev.objectId)?.so.itemId, part: ev.part, data: { opening: Math.round(ev.opening * 1000) / 1000, ...(ev.by ? { by: ev.by } : {}) } })\n fire('door', ev)\n if (ev.type === 'locked') say(t('hud.door_locked', vars))\n else if (ev.type === 'blocked') say(t('hud.door_blocked', vars))\n },\n })\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 // the still meshes of an object draw in one batch per material; a mesh that is hit, moved or swung draws on its own again (createStaticBatcher)\n const batchers = new Map<string, StaticBatcher>()\n const batchObject = (objectId: string, root: THREE_NS.Object3D): void => {\n let meshes = 0\n let unbatched = false\n // the owner mark may sit on an inner node (a wrapper around the vehicle's own root)\n root.traverse((object) => {\n if ((object as THREE_NS.Mesh).isMesh) meshes++\n if (UNBATCHED_OWNERS.test((object.userData.kitOrigin as { owner?: string } | undefined)?.owner ?? '')) unbatched = true\n })\n if (!unbatched && meshes >= BATCH_MIN_MESHES) batchers.set(objectId, createStaticBatcher(THREE, root, { budgetMs: BATCH_BUDGET_MS }))\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 batchObject(objectId, root)\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 e.fluidStart = f.container.liters\n e.fluidUsed = 0\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 const e = registerEntry(o.id, o.id, root, o.spec, o.label ?? S.text[`arena.${o.id}`] ?? o.id, undefined, undefined, true, false)\n if (o.free) e.free = true\n if (o.pushable) e.pushable = true\n e.follower = o.follow?.(root, world, o.id) || null\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 // eslint-disable-next-line kit/no-bare-remove -- the inner object belongs to the module that built it, which shows it again; removeEntry frees it when it goes\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 /** The items modules put in the world as scenery (`ModuleHost.addObject`): kept through `clear`; the scenarios run without them (each starts from the seeded room) and they come back after. */\n const sceneryObjects = new Map<string, { item: TestRoomItem; position: Vec3; rotationY: number }>()\n const placeScenery = (objectId: string, item: TestRoomItem, position: Vec3, rotationY: number): Entry => {\n const root = buildRoot(item)\n root.position.set(position[0], position[1], position[2])\n root.rotation.y = rotationY\n root.name = item.id\n scene.add(root)\n root.updateMatrixWorld(true)\n const own = item.impl?.(root, objectId)\n const { spec, parts } = own ? { spec: structuredCloneSpec(own.describe()), parts: undefined } : resolveSpec(item, root)\n root.updateMatrixWorld(true)\n const q = root.getWorldQuaternion(tmpQ)\n if (own) world.register(own, { id: objectId, position, rotation: [q.x, q.y, q.z, q.w] })\n else world.add(spec, { id: objectId, position, rotation: [q.x, q.y, q.z, q.w] })\n const e = registerEntry(objectId, item.id, root, spec, item.name, parts, item, true, false)\n fire('spawn', e.so)\n return e\n }\n const restoreScenery = (): void => {\n for (const [objectId, o] of sceneryObjects) if (!entries.has(objectId)) placeScenery(objectId, o.item, o.position, o.rotationY)\n }\n const addScenery = (itemId: string, position: Vec3, rotationY = 0): { objectId: string; root: unknown; remove(): void } | null => {\n const item = catalogMap.get(itemId)\n if (!item) return null\n const objectId = `${item.id}_scenery_${sceneryObjects.size + 1}`\n sceneryObjects.set(objectId, { item, position: [position[0], position[1], position[2]], rotationY })\n const e = placeScenery(objectId, item, position, rotationY)\n action('spawn', t('act.spawn', { name: item.name, x: num(position[0], 1), z: num(position[2], 1) }), { objectId, itemId: item.id, data: { position, movable: false, scenery: true } })\n return {\n objectId,\n get root() {\n return entries.get(objectId)?.so.root ?? e.so.root\n },\n remove() {\n sceneryObjects.delete(objectId)\n removeEntry(objectId)\n },\n }\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 // (a drawing with no mesh has an empty box: it stays where it was asked, instead of going to minus infinity)\n const box = new THREE.Box3().setFromObject(root)\n const base = Math.max(pos[1], groundAt(pos[0], pos[2]))\n if (!box.isEmpty()) 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 if (item.pushable) e.pushable = 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\n // ---------------------------------------------------------------------------------------------------------------------------------------\n // The player against the objects: what stands on the floor blocks the walk, and the walk pushes what is light enough to slide\n // ---------------------------------------------------------------------------------------------------------------------------------------\n /** Objects lower than this (m) the player steps onto (a can, a concrete block): they do not block, the feet scuff them along. */\n const STEP_OVER = STEP_UP\n /** Things that hang higher than this (m) above the feet pass over the head. */\n const HEADROOM = 1.9\n /**\n * Horizontal force (N) a walking and a running player puts into what is in the way, and the floor's friction coefficient the push has to beat: a 3 kg bin slides off,\n * a 12 kg nightstand moves, a 70 kg fridge only blocks (it would take 0.5 x 70 x 9.8 = 343 N, a shove with the shoulder).\n */\n const PUSH_WALK_N = 250\n const PUSH_RUN_N = 450\n const FLOOR_FRICTION = 0.5\n interface BodyBox { minX: number; maxX: number; minZ: number; maxZ: number; base: number; top: number; stamp: number }\n const bodyBoxes = new Map<string, BodyBox>()\n const bodyBounds = new THREE.Box3()\n let frameStamp = 0\n /** World box of an object the player can bump into, kept until the object moves (a piece that is awake is measured again each frame). */\n const bodyBox = (e: Entry): BodyBox | null => {\n const id = e.so.objectId\n const known = bodyBoxes.get(id)\n if (known && (known.stamp === frameStamp || !e.piece || e.piece.sleeping)) return known\n if (!e.so.root.parent || world.state(id)?.destroyed) {\n bodyBoxes.delete(id)\n return null\n }\n bodyBounds.setFromObject(e.so.root)\n if (bodyBounds.isEmpty()) return null\n const box = { minX: bodyBounds.min.x, maxX: bodyBounds.max.x, minZ: bodyBounds.min.z, maxZ: bodyBounds.max.z, base: bodyBounds.min.y, top: bodyBounds.max.y, stamp: frameStamp }\n bodyBoxes.set(id, box)\n return box\n }\n const footPos = new THREE.Vector3()\n /**\n * Whether `e` stands in the player's way at the floor point (x, z): the arena has its own colliders, a held thing and a low one do not block. A piece that declares its\n * own footprint in `root.userData.collider` (a plant: the trunk as a cylinder, or null for grass the feet walk through) is tested against that instead of its whole box.\n */\n const inTheWay = (e: Entry, x: number, z: number, r: number): BodyBox | null => {\n if ((e.arena && !footprintsWithBody.has(e.so.objectId)) || (e.piece && e.piece.held)) return null\n const ud = e.so.root.userData as { collider?: { kind?: string; radius?: number; height?: number } | null }\n if ('collider' in ud && !ud.collider?.kind) return null\n const b = bodyBox(e)\n if (!b || b.base > player.feet + HEADROOM) return null\n const c = ud.collider\n if (c?.kind === 'cylinder' && c.radius != null) {\n e.so.root.getWorldPosition(footPos)\n const reach = c.radius + r\n return (x - footPos.x) ** 2 + (z - footPos.z) ** 2 < reach * reach ? { ...b, top: Math.min(b.top, footPos.y + (c.height ?? b.top - footPos.y)) } : null\n }\n return x > b.minX - r && x < b.maxX + r && z > b.minZ - r && z < b.maxZ + r ? b : null\n }\n blockers.add((x, z, r) => {\n for (const e of entries.values()) {\n const b = inTheWay(e, x, z, r)\n if (b && b.top - b.base >= STEP_OVER) return true\n }\n return false\n })\n /**\n * The walk pushes what it runs into, by the force of a person leaning on it against the floor's grip: the push brings the object up to the walking speed at most, at the\n * middle of where the body touches it (a waist-high bin slides, a tall light thing can tip), and a low thing the feet step over is scuffed along.\n */\n const pushByPlayer = (dt: number): void => {\n const [wx, wz] = player.takeWish()\n const len = Math.hypot(wx, wz)\n if (dt <= 0 || len < 1e-6) return\n const dx = wx / len\n const dz = wz / len\n const speed = len / dt\n const force = player.running ? PUSH_RUN_N : PUSH_WALK_N\n // where the step tried to go (and a hair more), so what the blocked step stopped against is found\n const ax = player.x + dx * (Math.min(len, 0.5) + 0.03)\n const az = player.z + dz * (Math.min(len, 0.5) + 0.03)\n for (const e of entries.values()) {\n const piece = e.piece\n if (!piece) continue\n const b = inTheWay(e, ax, az, PLAYER_RADIUS)\n if (!b) continue\n const grip = FLOOR_FRICTION * piece.mass * 9.81\n if (force <= grip) continue\n const along = piece.velocity[0] * dx + piece.velocity[2] * dz\n const impulse = Math.min(piece.mass * Math.max(0, speed - along), (force - grip) * dt)\n if (impulse <= 1e-4) continue\n // the body touches it from the floor up to the chest (or its top): the push acts at the middle of that span\n const y = (b.base + Math.max(b.base, Math.min(b.top, player.feet + 1.4))) / 2\n const point: Vec3 = [Math.max(b.minX, Math.min(b.maxX, player.x)), y, Math.max(b.minZ, Math.min(b.maxZ, player.z))]\n piece.sleeping = false\n renderer.impulse(e.so.objectId, [dx * impulse, 0, dz * impulse], point)\n log.coalesce(`bump:${e.so.objectId}`, { channel: 'action', type: 'bump', text: t('act.bump', { name: e.name, kg: num(piece.mass, 1) }), objectId: e.so.objectId, itemId: e.so.itemId, data: { massKg: Math.round(piece.mass * 10) / 10, pushN: force } }, 1)\n }\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 // A removed tree's geometries, materials and textures stay on the GPU (and in three.js's caches) until disposed: everything the room takes out of the scene\n // goes through `dropTree`, released at once or, inside `releasingTogether`, in one pass at its end (one walk of the scene for what is still drawn).\n let releaseBatch: THREE_NS.Object3D[] | null = null\n const dropTree = (root: THREE_NS.Object3D | undefined): void => {\n if (!root) return\n if (releaseBatch) releaseBatch.push(root)\n else releaseObject3D(root, { keep: scene })\n }\n const releasingTogether = (fn: () => void): void => {\n if (releaseBatch) return fn()\n releaseBatch = []\n try {\n fn()\n } finally {\n const roots = releaseBatch\n releaseBatch = null\n releaseObject3D(roots, { keep: scene })\n }\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 e.follower?.dispose?.()\n if (world.has(id)) world.remove(id)\n e.so.root.removeFromParent()\n const inner = wrapped.get(e.so.root)\n letGo(e.so.root)\n // after the renderer let go of it (its restore puts the original meshes back), so the tree released is the one that was drawn\n dropTree(e.so.root)\n dropTree(inner)\n entries.delete(id)\n batchers.get(id)?.dispose()\n batchers.delete(id)\n doors.forget(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 dropTree(p?.root)\n rendererPieces.delete(id)\n splitOf.delete(id)\n }\n loose.length = 0\n }\n\n const clearEverything = (): void => releasingTogether(clearEverythingNow)\n const clearEverythingNow = (): 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 // every fire sound goes with the fires (the renderer's parts are cleared below without their burn_end)\n destructionSound?.reset()\n terrain.setLayout(defaultGround)\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 e.follower?.restore?.()\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 resetListeners = 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 e.follower?.restore?.()\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 seating.release()\n pushByKey = false\n push.end()\n releasingTogether(() => {\n clearEverythingNow()\n for (const id of [...entries.keys()]) removeEntry(id)\n })\n renderer.reset()\n for (const listener of [...resetListeners]) listener()\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 registerGround()\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 filmRandom.seed = 1\n groundFireClock = 0\n counter = 0\n slot = 0\n prevVy.clear()\n lastImpact.clear()\n addArena()\n standFootprints()\n scheduler.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 crouch keys crouch too. */\n let crouchForced = false\n /** Down by a player module (`setAvatarState`: knocked by a zombie, dead); a blast that knocks the player off its feet puts the body down too. */\n let downForced = false\n /** Mass of the player's body for the shove of a blast (kg). */\n const playerMass = options.playerMass ?? bodyMass(1.75)\n /**\n * A blast shoves the player the way it shoves the people of the modules (`knockOf`, the host's `blastShove`), cut by the cover between the centre and the chest: strong\n * enough, it takes the player off its feet, and the body lies a while and gets up.\n */\n /** How far ahead of the body (m, from its axis) a wall it slammed into is looked for, and the height of the shoulder that takes it. */\n const SLAM_REACH = PLAYER_RADIUS + 0.35\n const SLAM_SHOULDER = 1.3\n /**\n * A body thrown into something firm: what it hit takes the blow of its weight (`½ m v²`, blunt, across the shoulder) and answers as its material does (drywall or a board\n * cracks or breaks, brick holds); the body falls with a thud and, when it was hard, cries out.\n */\n const slamPlayer = (event: PlayerSlam): void => {\n const [x, feet, z] = player.position\n const energy = 0.5 * playerMass * event.speed * event.speed\n let hit: RayHit | null = null\n if (event.against === 'obstacle') {\n const from: Vec3 = [x, feet + ((player.knocked?.lying ?? 0) > 0.5 ? 0.3 : SLAM_SHOULDER), z]\n hit = rayWorld(from, event.direction, SLAM_REACH)\n if (hit) world.hitPart(hit.object, hit.part, { type: 'blunt', point: hit.point, direction: event.direction, energy, radius: 0.2, ...(hit.normal ? { normal: hit.normal } : {}) })\n }\n bodySounds.slam(event.speed, [x, feet + 0.5, z])\n action('player_slammed', t(event.against === 'obstacle' ? 'act.player_slammed' : 'act.player_fell', { speed: num(event.speed, 1), what: hit ? nameOf(hit.object) : '' }), {\n ...(hit ? { objectId: hit.object, part: hit.part } : {}),\n data: { against: event.against, speed: event.speed, energy, ...(hit ? { object: hit.object, part: hit.part } : {}) },\n })\n }\n const knockPlayer = (event: Extract<HostEvent, { type: 'explosion' }>): void => {\n if (seating.seat) return\n const feet: Vec3 = [player.x, player.feet, player.z]\n const chest: Vec3 = [feet[0], feet[1] + KNOCK_CHEST, feet[2]]\n const reach = world.blastReach(event.point, chest, event.source ? { ignore: [event.source] } : {})\n const blast = {\n point: event.point,\n energy: event.energy,\n radius: event.radius,\n reach,\n ...(event.tnt !== undefined ? { tnt: event.tnt } : {}),\n ...(event.lethalRadius !== undefined ? { lethalRadius: event.lethalRadius } : {}),\n }\n const knock = knockOf(blast, feet, playerMass, options.blastShove, options.blastImpulse)\n if (!knock) return\n player.knock(knock)\n const speed = Math.hypot(knock.velocity[0], knock.velocity[1], knock.velocity[2])\n const distance = Math.hypot(chest[0] - event.point[0], chest[1] - event.point[1], chest[2] - event.point[2])\n const data = { speed, reach, distance, down: knock.down, wounded: Boolean(knock.wounded), stunSeconds: knock.stunSeconds ?? 0, source: event.source }\n const values = { speed: num(speed, 1), reach: num(reach * 100, 0), distance: num(distance, 1), stun: num(knock.stunSeconds ?? 0, 1) }\n if (knock.wounded) action('player_wounded', t(speed >= KNOCK_DOWN_SPEED ? 'act.player_thrown_wounded' : 'act.player_wounded', values), { data })\n else if (knock.down) action('player_knocked_down', t('act.knocked_down', values), { data })\n else if (speed > 0) action('player_shoved', t('act.player_shoved', values), { data })\n else action('player_stunned', t('act.player_stunned', values), { data })\n }\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 // one body for both views: in first person the camera sits at its eyes and only the head is kept out of that camera\n avatar.root.visible = cameraMode === 'third' || !!avatar.eye\n avatar.setView?.(cameraMode, camera)\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?.setView?.('third', null)\n // eslint-disable-next-line kit/no-bare-remove -- the avatar belongs to the host that set it (the player module), which may set it again or dispose it\n avatar?.root.removeFromParent()\n avatar = next\n feetPrev = null\n if (avatar) {\n // the weapon's contact and laser rays leave from the eye, inside the body: they must not stop at the chest\n avatar.root.userData.viewmodel = true\n scene.add(avatar.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 || push.isBent\n avatarState.down = downForced || Boolean(player.knocked?.down || (player.knocked?.lying ?? 0) > 0.5)\n // a blast falls the body the way it pushed it; a module's own knock-down keeps the avatar's pick\n avatarState.fallForward = downForced ? undefined : player.knockedForward\n avatarState.armed = armedForced ?? tool.def.action.kind === 'firearm'\n avatarState.pitch = player.pitch\n avatarState.holding = heldPiece !== null\n avatarState.push = push.avatarState\n const seat = seating.seat\n avatarState.seat = seat ? { pose: seat.pose, hip: seat.hips[1] - player.feet } : null\n avatarState.door = doors.avatarState\n avatarState.itemUse = useItemPlayer\n ? { id: useItemName, ...useItemPlayer.pose(), ...(twistHand?.gripL !== undefined ? { gripL: twistHand.gripL } : {}) }\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 placeEye()\n }\n /**\n * A view a script asked for (`room.look`: scenarios, the test table, the view an area opens on) is kept exactly until the player moves: the body's eye stands ahead and at the\n * body's own height, and a scripted aim (an axe on a trunk, a punch at a can on the table) is measured from the point it asked for.\n */\n let scriptedAt: [number, number] | null = null\n const lookAt = (eye: Vec3, target: Vec3): void => {\n player.look(eye, target)\n scriptedAt = [player.x, player.z]\n }\n /** How far short of what stands between the player's middle and the body's eyes (a wall, a wardrobe) the eye stops, metres. */\n const EYE_CLEARANCE = 0.1\n const eyeAt = new THREE.Vector3()\n /**\n * The body's eyes are the camera of the first-person view and where the room aims, shoots and reaches from in both views; they are ahead of the player's middle (0.2 m standing,\n * more crouched or down), so they are pulled back toward it out of whatever stands in between.\n */\n const placeEye = (): void => {\n if (!avatar?.eye) return\n if (scriptedAt) {\n const [walkX, walkZ] = player.walkIntent\n if (!walkX && !walkZ && Math.hypot(player.x - scriptedAt[0], player.z - scriptedAt[1]) < 1e-6) return\n scriptedAt = null\n }\n avatar.eye(eyeAt)\n const dx = eyeAt.x - player.x\n const dz = eyeAt.z - player.z\n const ahead = Math.hypot(dx, dz)\n if (ahead > 1e-4) {\n const dir: Vec3 = [dx / ahead, 0, dz / ahead]\n const hit = rayWorld([player.x, eyeAt.y, player.z], dir, ahead + EYE_CLEARANCE)\n if (hit) {\n const keep = Math.max(0, hit.distance - EYE_CLEARANCE)\n eyeAt.set(player.x + dir[0] * keep, eyeAt.y, player.z + dir[2] * keep)\n }\n }\n camera.position.copy(eyeAt)\n camera.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 // 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 /** The body's hands go to the tool the module placed (a carried piece follows the hand instead, a push poses the hands itself, and a door's hand goes to the handle through the same reach). */\n /** How far inside the right shoulder joint, toward the middle of the chest, the pocket a stock rests in sits (m). */\n const SHOULDER_POCKET_IN = 0.1\n const pocketAt = new THREE.Vector3()\n const aimTurn = new THREE.Quaternion()\n const aimEuler = new THREE.Euler(0, 0, 0, 'YXZ')\n /** The pocket of the body's right shoulder, turned to the aim, in both views (`ModuleHost.holdFrame`); null for no body or a body that names no shoulder. */\n const bodyHoldFrame = (): HandPose | null => {\n const shoulder = avatar?.shoulder?.('R')\n if (!shoulder) return null\n shoulder.getWorldPosition(pocketAt)\n // the view's right at this yaw is (cos, 0, -sin): the pocket is that much inside the joint\n pocketAt.x -= Math.cos(player.yaw) * SHOULDER_POCKET_IN\n pocketAt.z += Math.sin(player.yaw) * SHOULDER_POCKET_IN\n aimTurn.setFromEuler(aimEuler.set(player.pitch, player.yaw, 0, 'YXZ'))\n return { position: [pocketAt.x, pocketAt.y, pocketAt.z], quaternion: [aimTurn.x, aimTurn.y, aimTurn.z, aimTurn.w] }\n }\n const reachAvatar = (): void => {\n const doorHand = doors.handTargets()\n const targets = push.active ? null : (doorHand ?? (heldPiece ? twistHand : (handSource?.() ?? null)))\n lastHand = {\n stance: push.active || doorHand ? 'hold' : (handStances[toolId] ?? (targets ? 'hold' : 'relaxed')),\n triggerFinger: targets?.fingers?.index ?? null,\n targets: push.handTargets() ?? targets,\n }\n if (!avatar?.reach) return\n // the camera is the eye here in both views (the shoulder view only moves it for the render): the same reach in both, so switching views moves no hand\n avatar.reach(targets, { camera, keepOutside: { contact: (origin, direction, maxDistance) => rayWorld(origin, direction, maxDistance)?.distance ?? null } })\n }\n /** Moves the camera to the shoulder view for the render that follows, and answers the function that puts it back. */\n const thirdEuler = new THREE.Euler(0, 0, 0, 'YXZ')\n const applyThirdView = (): (() => void) => {\n if (!thirdActive()) return () => undefined\n const home = camera.position.clone()\n const turn = camera.quaternion.clone()\n const pose = thirdPose(0)\n camera.position.set(pose.position[0], pose.position[1], pose.position[2])\n // the view of a body on the floor (turned up, rolled) is the first person's: the camera behind the body keeps the player's own look\n if (player.knocked) camera.quaternion.setFromEuler(thirdEuler.set(player.pitch, player.yaw, 0, 'YXZ'))\n camera.updateMatrixWorld(true)\n return () => {\n camera.position.copy(home)\n camera.quaternion.copy(turn)\n camera.updateMatrixWorld(true)\n }\n }\n\n /** Height of the hip above the feet (m): where a kick leaves from; and how far (rad) below the look it goes, so a level look kicks at the height of a chair seat. */\n const KICK_HIP = 0.9\n const KICK_DROP = 0.35\n /**\n * A kick leaves the hip, not the eye: along the facing, 20 degrees below the look and kept between 50 degrees down (a stomp on what lies on the floor) and 6 up, so a kick\n * at a bin or a chair in front of the feet lands on it, as the leg reaches it, instead of on what the eye ray would find beyond the leg's reach.\n */\n const legAim = (): void => {\n aim()\n // never above the eye: a player low on the ground kicks from where it is, along its look\n const low = aimO[1] < player.feet + KICK_HIP\n const pitch = Math.max(-0.9, Math.min(0.1, player.pitch - (low ? 0 : KICK_DROP)))\n aimO[0] = player.x\n aimO[1] = Math.min(player.feet + KICK_HIP, aimO[1])\n aimO[2] = player.z\n aimD[0] = -Math.sin(player.yaw) * Math.cos(pitch)\n aimD[1] = Math.sin(pitch)\n aimD[2] = -Math.cos(player.yaw) * Math.cos(pitch)\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 /** What the feet stand on, by its sound: the part right under them (a heap of boards, a car roof) or the ground's top layer (a slab, turf, a crater's soil). */\n const surfaceUnderFeet = (): SurfaceId => {\n const [x, feet, z] = player.position\n const under = rayWorld([x, feet + 0.15, z], [0, -1, 0], 0.5)\n if (under && under.object !== GROUND_ID) {\n const material = world.state(under.object)?.parts.find((p) => p.id === under.part)?.material\n if (material) return surfaceOfMaterial(material)\n }\n return surfaceOfMaterial(terrain.columnAt(x, z).material)\n }\n\n // footfalls: the body's walk says when a heel is down; with no body (or one that does not say) the room counts strides along the ground walked\n const strides = createStrideCounter()\n let feetAt: [number, number] | null = null\n const stepFeet = (dt: number): void => {\n const [x, , z] = player.position\n const moved = feetAt && dt > 0 ? Math.hypot(x - feetAt[0], z - feetAt[1]) : 0\n feetAt = [x, z]\n if (dt <= 0 || seating.seat) return\n const gait: GaitId = player.running ? 'run' : 'walk'\n const foot = avatar?.footfall ? avatar.footfall() : moved / dt > MAX_STRIDE_SPEED ? null : strides.advance(moved, gait)\n if (!foot || !player.grounded) return\n emitHost({ type: 'footfall', foot, surface: surfaceUnderFeet(), gait, position: player.position })\n fire('footfall', { foot, gait, time: simTime })\n }\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 // a pool of fuel burning (a molotov's zone, a fuel stain on fire): the fire sound of a liquid, from when it lights to when it goes out\n const poolFire = (point: Vec3, burning: boolean): void => playSound(burning ? 'burn_loop' : 'burn_end', point, 0.5, { fuel: 'liquid' })\n const dropZone = (i: number): void => {\n const [zone] = fireZones.splice(i, 1)\n if (zone) poolFire(zone.point, false)\n }\n const dropStain = (i: number): void => {\n const [stain] = burningStains.splice(i, 1)\n if (stain) poolFire(stain.center, false)\n }\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 poolFire([s.center[0], s.center[1], s.center[2]], true)\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) dropZone(i)\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 dropStain(i)\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 toolDef = (id: string): { readonly category: string } | undefined => arsenal.weapons.get(id)\n /** What a blow met, for its sound: a body (a head apart) or anything else. */\n const blowTarget = (r: RayHit): 'body' | 'head' | 'object' => {\n const part = world.state(r.object)?.parts.find((p) => p.id === r.part)\n if (!part || !(world.materials.get(part.material)?.tags ?? []).includes('body')) return 'object'\n return /head|face|jaw|skull|neck/.test(r.part) ? 'head' : 'body'\n }\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 shotRay = new THREE.Raycaster()\n // batched meshes leave the camera layer (createStaticBatcher), not the world: rays still find them\n shotRay.layers.enableAll()\n /** Metres of water a pistol round crosses to lose 1/e of its speed (a full can takes about a fifth of it in its 6 cm). */\n const LIQUID_SLOWING = 0.25\n /** Share of the momentum along the surface a round leaves in a wall it meets at a slant (the rest goes on with it). */\n const SHOT_GRIP = 0.3\n /**\n * The push a round gives what it hits, at the point of the drawn surface it meets (not the box the world sees): the momentum the round lost there (all of it when\n * it stopped; through a thin shell, only what the wall and the liquid inside took), along the inward normal of that surface plus a little along it. So a round on the\n * right of a can pushes it away and to the left and spins it, as a real one does.\n */\n const shotPush = (s: Shot, objectId: string, results: readonly { readonly object: string; readonly penetrated: boolean; readonly exitEnergy: number }[], fallback: Vec3): { impulse: Vec3; point: Vec3 } => {\n const e = entries.get(objectId)\n const speed = Math.max(80, s.speed)\n const onIt = results.filter((r) => r.object === objectId)\n const last = onIt[onIt.length - 1]\n let kept = last && last.penetrated ? Math.sqrt(Math.max(0, Math.min(1, last.exitEnergy / Math.max(s.energy, 1e-6)))) : 0\n let point = fallback\n let inward: Vec3 = [s.direction[0], s.direction[1], s.direction[2]]\n if (e) {\n shotRay.set(new THREE.Vector3(...s.origin), new THREE.Vector3(...s.direction).normalize())\n shotRay.far = 60\n // sprites (labels, effects) under the object raycast against the camera\n shotRay.camera = camera\n const hit = shotRay.intersectObject(e.so.root, true).find((h) => (h.object as THREE_NS.Mesh).isMesh && !h.object.userData.destructionDebris && h.face)\n if (hit?.face) {\n point = [hit.point.x, hit.point.y, hit.point.z]\n const n = hit.face.normal.clone().transformDirection(hit.object.matrixWorld)\n if (n.x * s.direction[0] + n.y * s.direction[1] + n.z * s.direction[2] > 0) n.negate()\n inward = [-n.x, -n.y, -n.z]\n }\n // the liquid inside slows the round down along the chord it crosses\n const c = kept > 0 && e.containerId ? fluids.container(e.containerId) : null\n if (c && c.liters > 1e-4) {\n const size = new THREE.Box3().setFromObject(e.so.root).getSize(new THREE.Vector3())\n kept *= Math.exp(-(Math.min(size.x, size.z) * 0.9) / LIQUID_SLOWING)\n }\n }\n const momentum = ((2 * s.energy) / speed) * (1 - kept)\n // the momentum of the round, split along the inward normal (all of it) and along the surface (a share)\n const along = s.direction[0] * inward[0] + s.direction[1] * inward[1] + s.direction[2] * inward[2]\n const impulse: Vec3 = [0, 1, 2].map((k) => momentum * (along * inward[k]! + SHOT_GRIP * (s.direction[k]! - along * inward[k]!))) as unknown as Vec3\n return { impulse, point }\n }\n\n /**\n * The push of one trigger pull on what stands free (`free`) and is not a piece yet: when the momentum of every round that hit it is enough to move\n * its mass (`SHOVE_SPEED`: a shotgun's load into a bookcase, not a pistol round), it becomes a piece and takes the push.\n */\n const shoveFree = (pushes: Map<string, { impulse: Vec3; point: Vec3 }>): void => {\n for (const [objectId, push] of pushes) {\n const e = entries.get(objectId)\n if (!e || e.piece || !e.free) continue\n const mass = Math.max(0.2, massOfObject(objectId))\n if (Math.hypot(...push.impulse) / mass < SHOVE_SPEED) continue\n const piece = renderer.makePiece(objectId, { mass })\n e.piece = piece\n rendererPieces.set(objectId, piece)\n leaveFootprint(objectId)\n action('loosened', t('act.shoved', { name: e.name }), { objectId, itemId: e.so.itemId })\n renderer.impulse(objectId, push.impulse, push.point)\n }\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 const pushes = new Map<string, { impulse: Vec3; point: Vec3 }>()\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 blow = shotPush(s, r0.object, results, r0.point)\n if (rendererPieces.has(r0.object)) renderer.impulse(r0.object, blow.impulse, blow.point)\n const push = pushes.get(r0.object) ?? { impulse: [0, 0, 0] as Vec3, point: blow.point }\n for (let k = 0; k < 3; k++) push.impulse[k] += blow.impulse[k]!\n pushes.set(r0.object, push)\n }\n if (shots.length <= 3 || rnd() < 0.34) tracer(m, end)\n }\n })\n shoveFree(pushes)\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 /**\n * A kick leaves the leg, not the eye: level, the way the player faces, at the heights of `kickHeights` above the feet (shin, knee, hip), it finds the nearest\n * thing standing low in front (a chair, a door, a crate) within the tool's reach; when none of those rays finds anything the eye's aim decides, as for any other blow.\n */\n const kickHeights = options.kickHeights ?? [0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85]\n const footRay = (u: Extract<Use, { kind: 'melee' }>): Extract<Use, { kind: 'melee' }> => {\n const flat = Math.hypot(u.direction[0], u.direction[2])\n const direction: Vec3 = flat > 1e-6 ? [u.direction[0] / flat, 0, u.direction[2] / flat] : [-Math.sin(player.yaw), 0, -Math.cos(player.yaw)]\n const feet = player.position\n let best: { origin: Vec3; distance: number } | null = null\n for (const height of kickHeights) {\n const origin: Vec3 = [feet[0], feet[1] + height, feet[2]]\n const hit = rayWorld(origin, direction, u.reach)\n if (hit && (!best || hit.distance < best.distance)) best = { origin, distance: hit.distance }\n }\n return best ? { ...u, origin: best.origin, direction } : u\n }\n const meleeUse = (use: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const w = toolName(id)\n const u = id === 'kick' ? footRay(use) : use\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 const hit = useToHit(u, r.point, r.normal)!\n const result = world.hitPart(r.object, r.part, { ...hit, source: 'player' })\n // a blow that leaves no mark (a punch on solid wood, a kick on the ground) still meets the surface: its impact sounds, by material and blow\n if (!result.events.some((e) => MARK_EVENTS.has(e.type))) {\n const material = world.part(r.object, r.part)?.material ?? heaviestMaterial(r.object) ?? ''\n const def = world.materials.get(material)\n playSound(impactKey(def), r.point, Math.min(0.8, 0.25 + u.energy / 400), impactSoundKeys(material, def, hit.type))\n }\n const blow = blowOfTool(id, toolDef(id)?.category ?? '')\n if (blow) bodySounds.hit(blow, blowTarget(r), r.point as Vec3, u.energy)\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; swing?: () => void; lead?: number }> = []\n /**\n * A melee blow. A tool with a strike clip (`strikeClips`) on an avatar that plays it starts the clip on the body, in both views, 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 punchHand = options.punchHand ?? 'alternate'\n const punchTools = new Set(options.punchTools ?? ['hand', 'fists'])\n let nextHand: 'left' | 'right' = 'right'\n // the combo (an ability the page gives, `strikeCombo`): while it is on, each blow of its tools is its next step, and a pause longer than `reset` starts it over\n const combo = options.strikeCombo\n let comboOn = !!combo && options.strikeComboOn === true\n let comboNext = 0\n let comboAt = -Infinity\n const setStrikeCombo = (on: boolean): void => {\n if (!combo || on === comboOn) return\n comboOn = on\n comboNext = 0\n const name = combo.name?.[locale] ?? combo.id\n action('combo', t(on ? 'act.combo.on' : 'act.combo.off', { name }), { data: { combo: combo.id, on } })\n say(t(on ? 'act.combo.on' : 'act.combo.off', { name }))\n }\n const strikeUse = (u: Extract<Use, { kind: 'melee' }>, id = toolId): void => {\n const stepIndex = comboOn && combo?.tools.includes(id) && combo.steps.length > 0 ? (simTime - comboAt > combo.reset ? 0 : comboNext) : null\n const step = stepIndex === null ? undefined : combo!.steps[stepIndex]\n const clip = step ? step.clip : strikeClips[id]\n // a kick uses the leg the option says (alternating from the right), a punch the hand (the same way) or the one of its combo step, whatever the avatar does with them\n const leg = id === 'kick' ? (kickLeg === 'alternate' ? nextLeg : kickLeg) : undefined\n const hand = step ? step.hand : punchTools.has(id) ? (punchHand === 'alternate' ? nextHand : punchHand) : undefined\n const side = leg ? { leg } : hand ? { hand } : undefined\n const seconds = clip === undefined ? null : (avatar?.strike?.(clip, side) ?? null)\n if (leg && seconds !== null && kickLeg === 'alternate') nextLeg = leg === 'right' ? 'left' : 'right'\n if (!step && hand && seconds !== null && punchHand === 'alternate') nextHand = hand === 'right' ? 'left' : 'right'\n if (step && stepIndex !== null) {\n comboNext = (stepIndex + 1) % combo!.steps.length\n comboAt = simTime\n }\n const blow = blowOfTool(id, toolDef(id)?.category ?? '')\n // the swing's loudest part meets the contact: it starts `swingLead` before the clip's impact (counted in the room's time, so slow motion keeps it), or now\n const lead = blow ? swingLead(blow) : 0\n const swing = blow ? (): void => bodySounds.swing(blow, player.position) : undefined\n if (swing && (seconds === null || seconds <= lead)) swing()\n if (clip === undefined || seconds === null) {\n if (leg) {\n legAim()\n meleeUse({ ...u, origin: [aimO[0], aimO[1], aimO[2]], direction: [aimD[0], aimD[1], aimD[2]] }, id)\n } else meleeUse(u, id)\n return\n }\n const text = leg ? 'act.strike.leg' : hand ? 'act.strike.hand' : 'act.strike'\n action('strike', t(text, { weapon: toolName(id), clip, seconds: num(seconds, 2), leg: leg ? t(`leg.${leg}`) : '', hand: hand ? t(`hand.${hand}`) : '' }), {\n data: { weapon: id, clip, impactIn: seconds, ...(leg ? { leg } : {}), ...(hand ? { hand } : {}), ...(step ? { combo: combo!.id, step: stepIndex } : {}) },\n })\n strikes.push({\n key: id,\n remaining: seconds,\n ...(swing && seconds > lead ? { swing, lead } : {}),\n land: () => {\n if (leg) legAim()\n else 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) {\n strike.remaining -= dt\n if (strike.swing && strike.remaining <= (strike.lead ?? 0)) {\n strike.swing()\n delete strike.swing\n }\n }\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) dropStain(i)\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) dropZone(i)\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 const zone: FireZone = { 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 fireZones.push(zone)\n poolFire(zone.point, true)\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 /** Pulls the trigger of the tool in hand; answers what the trigger said (`drawing` while the draw is not over yet, `ok` when it did something). */\n const useTool = (dt: number, held: boolean): UseStatus => {\n aim()\n const cat = tool.def.category\n if (cat === 'hand') {\n if (strikes.some((strike) => strike.key === 'hand' || strike.key === 'fists')) return 'cooldown'\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 'ok'\n }\n if (strikes.some((strike) => strike.key === toolId)) return 'cooldown' // 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 res.status\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 res.status\n }\n applyUses(res, dt)\n return res.status\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 kick key (K, Shift+V) and the kick button: a kick with the `kick` tool, whatever tool is selected (it keeps its own cooldown). False when there is no kick or it is not ready. */\n const kick = (): boolean => {\n if (!arsenal.weapons.has('kick') || strikes.some((strike) => strike.key === 'kick')) return false\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 false\n for (const u of res.uses) if (u.kind === 'melee') strikeUse(u, 'kick')\n return true\n }\n const kickKeys = options.kick?.keys ?? ['KeyK']\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 const heldVel: Vec3 = [0, 0, 0]\n let useItemPlayer: ItemUsePlayer | null = null\n let useItemName = ''\n /** The use asked for while the seal's opening use (`ModuleItemSeal.openUse`) plays: it starts once the item is open. */\n let afterOpening: string | null = null\n /** The other hand turning the seal's part during the opening use: the stroke and how far the part is off (0..1). */\n let twisting: { stroke: TwistStroke; lift: number } | null = null\n /** The left hand on the part being turned, world space, set by `followHeld` while `twisting`. */\n let twistHand: HandTargets | null = null\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 afterOpening = null\n twisting = null\n twistHand = null\n heldEntry = null\n heldPiece = null\n heldTilt = 0\n }\n\n /**\n * The click with bare hands: a punch (`strikeClips.hand`, the clip plays on the body and the blow lands at its impact). With something in the hands the\n * click lets it go; E grabs and drops, the right button grabs or throws.\n */\n const handUse = (): UseStatus => {\n if (!heldPiece) return useTool(FIXED_DT, false)\n grab()\n return 'ok'\n }\n const grab = (): boolean => {\n if (push.active) return false\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 heldYaw = 0\n heldTilt = 0\n heldVel[0] = heldVel[1] = heldVel[2] = 0\n playSound(pickupSoundOf(heldEntry?.item?.sounds, world.materials.get(heaviestMaterial(r.object) ?? '')), r.point as Vec3, Math.min(1, 0.45 + kg * 0.1))\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 // the hand closing on it: the sound starts as the hold does (criterion C1)\n playSound(impactKey(world.materials.get(heaviestMaterial(r.object) ?? '')).replace('impact_', 'grab_'), v3(piece.root.getWorldPosition(tmpV)), 0.8)\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 playSound('item_throw', [piece.root.position.x, piece.root.position.y, piece.root.position.z], Math.min(1, 0.3 + speed * 0.04))\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 * The left hand on the top of the held item while `twisting`: palm down on the part, the fingers round it, the wrist turned by the stroke about the item's\n * axis and lifted with the part as it comes off. The same pose for the first-person arms and the body.\n */\n const twistTargets = (root: THREE_NS.Object3D, gripQ: THREE_NS.Quaternion): HandTargets | null => {\n if (!twisting) return null\n const { stroke, lift } = twisting\n const up = new THREE.Vector3(0, 1, 0).applyQuaternion(root.quaternion)\n const top = heldLocal\n .clone()\n .applyQuaternion(root.quaternion)\n .add(root.position)\n .addScaledVector(up, heldSize.y * 0.5 + lift * CAP_RISE + stroke.lift * TWIST_LIFT + CARRY_PALM)\n // the fingers point to the right and away from the body (the forearm comes in from the left, not in front of the item), then the wrist turns with the stroke (a cap comes off turning to the left seen from above)\n const knuckles = new THREE.Vector3(0.85, 0, -0.5).normalize().applyQuaternion(gripQ)\n knuckles.addScaledVector(up, -knuckles.dot(up)).normalize().applyAxisAngle(up, stroke.angle)\n const side = new THREE.Vector3().crossVectors(knuckles, up).normalize()\n // the palm sits over the middle of the part, so the middle of the hand is a little back toward the wrist\n const palm = top.addScaledVector(knuckles, -0.025)\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(knuckles, up, side))\n return { L: { position: [palm.x, palm.y, palm.z], quaternion: [q.x, q.y, q.z, q.w] }, gripL: 0.35 + 0.5 * stroke.grip }\n }\n\n const gripQuat = new THREE.Quaternion()\n const followHeld = (dt: number): void => {\n const piece = heldPiece\n twistHand = 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 = avatar?.hand?.('R')\n const isDrink = useItemName === 'drink' || useItemName === 'sip' || useItemName === 'chug'\n if (hand) {\n // with a body the item rides its weapon hand in both views, 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 = 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 // no body to hold it: the item floats in front of the eye\n pos = tmpV.set(0.05, -0.28, -1.15).applyMatrix4(camera.matrixWorld)\n gripQuat.setFromAxisAngle(new THREE.Vector3(0, 1, 0), player.yaw).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 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 twistHand = twistTargets(root, gripQuat)\n }\n\n /** How far (m) from the player an item on the table still counts as at hand (a can opener next to the tin). */\n const TOOL_REACH = 1.6\n /** Ids of what the player could open a seal with: the weapons of the loadout and the items within `TOOL_REACH` (catalogue and item ids). */\n const toolsAtHand = (): string[] => {\n const here = player.position\n const near: string[] = [...loadout]\n for (const other of entries.values()) {\n if (other === heldEntry || other.arena) continue\n const p = other.so.root.position\n if (Math.hypot(p.x - here[0], p.z - here[2]) <= TOOL_REACH) near.push(other.so.itemId)\n }\n return near\n }\n /** Litres a sealed item lost that nobody ate or drank; once it is open, only what it had lost before (a spill from the open mouth spoils nothing). */\n const sealLoss = (e: Entry): number => {\n if (e.sealLoss !== undefined) return e.sealLoss\n const c = e.containerId ? fluids.container(e.containerId) : undefined\n return c && e.fluidStart !== undefined ? Math.max(0, e.fluidStart - c.liters - (e.fluidUsed ?? 0)) : 0\n }\n /** The seal state of an item: opened, holed through (any part) or leaking (it lost contents while sealed). */\n const sealState = (e: Entry): { opened: boolean; breached: boolean; leaked: boolean } => {\n const breached = world.state(e.so.objectId)?.parts.some((p) => p.holes.some((h) => h.through && !h.vent)) ?? false\n const leaked = e.fluidStart !== undefined && sealLoss(e) > Math.max(0.002, e.fluidStart * 0.02)\n return { opened: !!e.opened, breached, leaked }\n }\n /** Opens a sealed item: the container opens, the model is drawn open and the room says with what. False when it needs a tool that is not at hand. */\n const openSeal = (e: Entry): boolean => {\n const seal = e.item?.seal\n if (!seal || e.opened) return true\n const opener = sealOpener(seal, toolsAtHand())\n if (!opener.ok) {\n // the names of the catalogue's items; the arsenal's names only when the catalogue has none of them\n const listed = (seal.openWith ?? []).map((id) => catalogMap.get(id)?.name).filter((n): n is string => !!n)\n const names = [...new Set(listed.length ? listed : (seal.openWith ?? []).filter((id) => arsenal.weapons.has(id)).map((id) => toolName(id)))]\n const why = t('hud.needs_opener', { name: e.name, tools: names.join(', ') })\n say(why)\n action('sealed', why, { objectId: e.so.objectId, itemId: e.so.itemId, data: { openWith: [...(seal.openWith ?? [])] } })\n return false\n }\n e.sealLoss = sealLoss(e)\n e.opened = true\n if (e.containerId) fluids.open(e.containerId)\n seal.open?.(wrapped.get(e.so.root) ?? e.so.root)\n playSound(openSoundOf(e.item?.sounds, world.materials.get(heaviestMaterial(e.so.objectId) ?? '')), v3(e.so.root.getWorldPosition(tmpV)), 0.7)\n const tool = opener.tool ? (catalogMap.get(opener.tool)?.name ?? (arsenal.weapons.has(opener.tool) ? toolName(opener.tool) : opener.tool)) : undefined\n action('open_seal', tool ? t('act.open_with', { name: e.name, tool }) : t('act.open_by_hand', { name: e.name }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { tool: opener.tool ?? 'hand' } })\n return true\n }\n\n /** C crouches unless the page moved the crouch to other keys; while it does, an item's second use is on Shift+F instead of C. */\n const crouchOnC = (options.crouch?.keys ?? ['KeyC']).includes('KeyC')\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 eating = useId === 'drink' || useId === 'sip' || useId === 'chug' || useId === 'eat'\n const consuming = eating || useId === 'pour' || useId === 'pour_out'\n if (useItemPlayer && !useItemPlayer.done) return false\n const seal = e.item?.seal\n if (seal && (consuming || useId === 'open')) {\n const state = sealState(e)\n const spoiled = sealBlock(seal, { ...state, opened: true })\n if (eating && spoiled) {\n say(t(spoiled === 'leaked' ? 'hud.spoiled_leak' : 'hud.spoiled_hole', { name: e.name }))\n action('spoiled', t(spoiled === 'leaked' ? 'hud.spoiled_leak' : 'hud.spoiled_hole', { name: e.name }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { reason: spoiled } })\n return false\n }\n if (!e.opened) {\n const opening = seal.byHand && seal.openUse ? itemUseDefs.find((u) => u.id === seal.openUse) : undefined\n if (opening) {\n // the other hand turns it open first; what was asked for follows once it is open\n useItemPlayer = createItemUse(fluids, e.containerId, opening)\n useItemName = opening.id\n afterOpening = useId === 'open' ? null : useId\n return true\n }\n if (!openSeal(e)) return false\n // a tool opens the tin and that is the whole use; a pull tab opens on the way to the mouth\n if (!seal.byHand || useId === 'open') {\n useItemPlayer = createItemUse(fluids, e.containerId, itemUseDefs.find((u) => u.id === 'open') ?? def)\n useItemName = 'open'\n return true\n }\n } else if (useId === 'open') return false\n }\n if (consuming && c.liters <= 1e-6) {\n say(t('hud.empty_container', { name: e.name }))\n return false\n }\n if (consuming && c.closed) fluids.open(e.containerId)\n useItemPlayer = createItemUse(fluids, e.containerId, def)\n useItemName = def.id\n useSoundIn = 0\n if (eating) useLiters = c.liters\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 /** Litres in the container when an eat or drink use began: what it took out is counted as eaten, not leaked. */\n let useLiters: number | null = null\n /** Seconds until the next sound of the use in progress. */\n let useSoundIn = 0\n\n const updateItemUse = (dt: number): void => {\n if (!useItemPlayer) return\n const e = heldEntry\n const c = e?.containerId ? fluids.container(e.containerId) : undefined\n const before = c?.liters\n useItemPlayer.update(dt)\n // a use that lasts repeats its sound (a gulp, a bite chewed) while the container gives something\n const useSound = e && useLiters !== null ? useSoundOf(e.item?.sounds, useItemName) : undefined\n if (useSound && e) {\n useSoundIn -= dt\n const now = e.containerId ? fluids.container(e.containerId)?.liters : undefined\n if (useSoundIn <= 0 && before !== undefined && now !== undefined && now < before) {\n playSound(useSound, v3(e.so.root.getWorldPosition(tmpV)), 0.6)\n useSoundIn = USE_SOUND_EVERY\n }\n }\n const seal = e?.item?.seal\n twisting = null\n if (e && seal?.openUse === useItemName && !e.opened) {\n twisting = openingProgress(useItemPlayer.def, useItemPlayer.time)\n seal.turn?.(wrapped.get(e.so.root) ?? e.so.root, { turned: twisting.stroke.turned, lift: twisting.lift })\n if (twisting.lift >= 1 || useItemPlayer.done) {\n openSeal(e)\n twisting = null\n }\n }\n if (e && useLiters !== null && before !== undefined) {\n const after = (e.containerId ? fluids.container(e.containerId)?.liters : undefined) ?? before\n e.fluidUsed = (e.fluidUsed ?? 0) + Math.max(0, before - after)\n if (e.opened && e.fluidStart) e.item?.seal?.contents?.(wrapped.get(e.so.root) ?? e.so.root, after / e.fluidStart)\n }\n if (useItemPlayer.done) {\n if (e && useLiters !== null && useItemName === 'eat') {\n const left = (e.containerId ? fluids.container(e.containerId)?.liters : undefined) ?? 0\n action('ate', t(left <= 1e-4 ? 'act.ate_all' : 'act.ate', { name: e.name, grams: Math.round((useLiters - left) * 1000) }), { objectId: e.so.objectId, itemId: e.so.itemId, data: { liters: Math.round((useLiters - left) * 1000) / 1000 } })\n }\n useLiters = null\n useItemPlayer = null\n useItemName = ''\n const next = afterOpening\n afterOpening = null\n if (next && e?.opened) useItem(next)\n }\n }\n\n /**\n * Where the opening use (`ModuleItemSeal.openUse`) is at `time`: the hand's stroke over its `turn` keys (`twistStroke`), then the part rising off until its\n * `open` key (or its end).\n */\n const openingProgress = (def: ItemUseDef, time: number): { stroke: TwistStroke; lift: number } => {\n const keys = [...def.keys].sort((a, b) => a.t - b.t)\n const turning = keys.findIndex((k) => k.action === 'turn')\n const lastTurn = keys.map((k) => k.action).lastIndexOf('turn')\n const start = turning >= 0 ? keys[turning]!.t : 0\n const end = lastTurn >= 0 ? (keys[lastTurn + 1]?.t ?? def.duration) : start\n const openAt = keys.find((k) => k.action === 'open')?.t ?? def.duration\n const share = end > start ? (time - start) / (end - start) : 1\n const lift = time <= end ? 0 : openAt > end ? Math.min(1, (time - end) / (openAt - end)) : 1\n return { stroke: twistStroke(share), lift }\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 || r.object === GROUND_ID) 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 strikeGroundWith = (piece: Piece, energy: number): void => {\n const box = tmpBox.setFromObject(piece.root)\n const centre = box.getCenter(tmpV)\n const size = box.getSize(tmpV2)\n if (sceneryTopAt(centre.x, centre.z) > 0 || restingTopAt(centre.x, centre.z) > 0) return\n const result = terrain.strike('blunt', { x: centre.x, z: centre.z, energy, contactRadius: Math.max(size.x, size.z) / 2 })\n if (result.radius > 0) showGroundBlow(result)\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 strikeGroundWith(piece, energy)\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 if (code === 'KeyE' && pushByKey) {\n pushByKey = false\n // a tap on a leaf opens or closes it; a hold pushed the piece\n if (push.end() && !doors.use()) grab()\n }\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 // the kick has a key of its own (K by default); a weapon module that takes the same key first (the laser of a firearm) wins while that weapon is in hand\n if (kickKeys.includes(code) && !e.ctrlKey && !e.metaKey) {\n kick()\n return\n }\n switch (code) {\n case 'KeyE':\n if (e.repeat) break\n // a tap grabs, a hold against something that stands on the floor pushes it\n pushByKey = !heldPiece && push.begin()\n if (!pushByKey && (heldPiece || !doors.use())) 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 // Shift+F is the second use while C crouches\n const use = heldEntry?.uses[e.shiftKey && crouchOnC ? 1 : 0]\n if (use) useItem(use)\n break\n }\n case 'KeyC':\n if (heldEntry?.uses[1] && !crouchOnC) 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 'KeyN':\n setStrikeCombo(!comboOn)\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 // one aim ray per HUD refresh: the inspect line and the animation panel both read what the eye rests on, and a ray that crosses a vehicle\n // tests its drawn triangles (`surfaceRay`); `undefined` outside a refresh\n let hudAimHit: RayHit | null | undefined\n const inspectTarget = (): RayHit | null => {\n if (hudAimHit !== undefined) return hudAimHit\n aim()\n return rayWorld(aimO, aimD, 14)\n }\n\n /** What E does to the leaf in reach the eye rests on (open, close, locked). */\n const leafNote = (distance: number): string | undefined => {\n if (distance > DOOR_REACH) return undefined\n const leaf = doors.aimed()\n if (!leaf) return undefined\n return t(leaf.locked ? 'hud.door_hint_locked' : leaf.open ? 'hud.door_hint_close' : 'hud.door_hint_open')\n }\n\n /** The floor under the aim: the profile and the layer there, read from the terrain at the point the ray reached (the floor of a crater, not the flat top). */\n const groundInspect = (r: RayHit): InspectInfo => {\n const onFloor = terrain.raycast(aimO, aimD, r.distance + 3)\n const [x, , z] = onFloor?.point ?? r.point\n const column = terrain.columnAt(x, z)\n const materialName = S.text[`material.${column.material}`] ?? dStrings.materialNames[column.material] ?? column.material\n return {\n object: t('ground.name'),\n objectId: GROUND_ID,\n part: column.profile,\n material: materialName,\n status: '',\n hp: 0,\n maxHp: 0,\n temperature: 0,\n burning: false,\n char: column.scorch,\n melt: 0,\n dents: 0,\n holes: 0,\n cracks: 0,\n mass: 0,\n joints: [],\n distance: onFloor?.distance ?? r.distance,\n ground: { surface: terrainProfileName(column.profile, locale), material: materialName, dug: column.depth, remaining: column.remaining, scorch: column.scorch },\n }\n }\n\n const inspectInfo = (): InspectInfo | null => {\n const r = inspectTarget()\n if (!r) return null\n if (r.object === GROUND_ID) return groundInspect(r)\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: leafNote(r.distance) ?? 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 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 let moduleFrameCount = 0\n // the room's frame: 0.05 s is the clamp the loop always had, and 8 ms is the biggest budget of the loose queues of today\n // a system that throws: the display loop logs each id once and keeps going; a headless frame (room.update, a scenario step) holds the errors and throws them after the frame, as the loose loops did\n const headlessErrors = new Map<string, unknown>()\n const loggedErrors = new Set<string>()\n let headlessDepth = 0\n const reportFrameError = (error: unknown, system: { id: string; phase: string }): void => {\n if (headlessDepth > 0) {\n if (!headlessErrors.has(system.id)) headlessErrors.set(system.id, error)\n return\n }\n if (loggedErrors.has(system.id)) return\n loggedErrors.add(system.id)\n console.error(`test-room: ${system.id} (${system.phase}) threw`, error)\n }\n const runHeadless = (run: () => void): void => {\n headlessDepth++\n try {\n run()\n } catch (error) {\n headlessErrors.clear()\n throw error\n } finally {\n headlessDepth--\n }\n if (headlessDepth > 0 || headlessErrors.size === 0) return\n const errors = [...headlessErrors.values()]\n headlessErrors.clear()\n throw errors.length === 1 ? errors[0] : new AggregateError(errors, `${errors.length} systems threw in one frame`)\n }\n const scheduler = createScheduler({ maxFrameSeconds: 0.05, budgetMs: options.frameBudgetMs ?? 8, onError: reportFrameError })\n // the deferred queues share the scheduler's budget: the voices of the sound engine and the events of the destruction renderer\n const audioQueue = audio?.deferredQueue?.()\n if (audioQueue) scheduler.budget.register(audioQueue, DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.AUDIO_VOICES])\n scheduler.budget.register(renderer.deferredQueue(), DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.DESTRUCTION_EVENTS])\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 // CLAUDE.md, \"Memória\": after each clear the GPU counts come back to the scenery; when they keep growing clear after clear the room says so on screen\n const MEMORY_CLEARS = 4\n const memoryWatch = createMemoryWatch({\n clears: MEMORY_CLEARS,\n read: () => {\n const memory = (gl as { info?: { memory?: { geometries: number; textures: number } } }).info?.memory\n const heap = heapMB()\n return memory ? { geometries: memory.geometries, textures: memory.textures, ...(heap === undefined ? {} : { heapMB: heap }) } : undefined\n },\n })\n clearListeners.add(() => {\n const verdict = memoryWatch.cleared(activeBench ?? undefined)\n if (!verdict) return\n if (!verdict.leaking) {\n ui?.alert(null)\n return\n }\n const text = t('memory.leak', { geometries: verdict.grew.geometries, textures: verdict.grew.textures, clears: MEMORY_CLEARS })\n log.add({ channel: 'event', type: 'memory_leak', text, data: { ...verdict.after, grew: verdict.grew } })\n ui?.alert(`⚠ ${text}`)\n })\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 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 // lateSimulate, before the modules' frame callbacks: `dt` is simulated seconds; real time only drives input\n const simulateBeforeModules = (dt: number): void => {\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 destructionSound?.update(dt)\n for (const e of entries.values()) e.follower?.update?.()\n terrainView.sync(camera.position)\n showGroundFire(dt)\n vfx.update(dt)\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 }\n\n // lateSimulate, after the modules' frame callbacks\n const simulateAfterModules = (dt: number): void => {\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 // input: real time, what the player does (the world is paused or slowed without touching it)\n const updateInput = (dt: number, isPaused: boolean): void => {\n if (!ownsLoop) roomMetrics.frame(dt)\n frameStamp++\n seating.update()\n player.update(dt)\n if (pushByKey && !player.keys.has('KeyE')) {\n // the window lost the key without a key up\n pushByKey = false\n push.end()\n }\n push.step(isPaused ? 0 : dt)\n doors.step(isPaused ? 0 : dt)\n if (!isPaused) kickLight(dt)\n if (!isPaused) pushByPlayer(dt)\n else player.takeWish()\n stepAvatar(isPaused ? 0 : dt)\n stepFeet(isPaused ? 0 : dt)\n if (tiltKey || heldTilt > 0) {\n heldTilt = Math.max(0, Math.min(2.4, heldTilt + (tiltKey ? 2.2 : -3) * dt))\n }\n // a click that was pressed and let go between two frames still counts (useFirst stays until a frame reads it)\n if ((useHeld || useFirst) && !isPaused && !push.active) {\n if (tool.def.category === 'hand') {\n if (useFirst) handUse()\n } else if (useHeld) useTool(dt, !useFirst)\n useFirst = false\n }\n if (!isPaused) followHeld(dt)\n }\n\n // present: what the player reads (HUD, progress, log, bench metrics), by real time\n const updatePresent = (dt: number): void => {\n reachAvatar()\n if (progress && simTime - progress.at > 0.25) progress = null\n // the log first: it scrolls before anything of this frame touches the DOM, so reading its height lays nothing out\n ui?.flushLog()\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 hudAimHit = inspectTarget()\n try {\n return readHudState()\n } finally {\n hudAimHit = undefined\n }\n }\n const readHudState = (): 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', crouchOnC ? 'Shift+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: scheduler.timeScale,\n fast: fastForward,\n tap: isTapOn(),\n combo: combo ? comboOn : null,\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\n if (id !== '') followPart(pl.entry, id, obj, rest)\n }\n }\n const fpRest = new THREE.Matrix4()\n const fpNow = new THREE.Matrix4()\n const fpRoot = new THREE.Matrix4()\n const fpPart = new THREE.Matrix4()\n const fpPos = new THREE.Vector3()\n const fpQuat = new THREE.Quaternion()\n const fpScale = new THREE.Vector3()\n const fpEuler = new THREE.Euler()\n /**\n * Moves a part's collision shape the way its drawn group moved from rest: a door group turns on its hinge (its origin), so the shape goes round the hinge with it and does\n * not spin on its own centre into the body next to it.\n */\n const followPart = (e: Entry, id: string, obj: THREE_NS.Object3D, rest: { p: Vec3; r: Vec3 }): void => {\n const ps = specs.get(e.so.objectId)?.parts.find((p) => p.id === id)\n if (!ps || !obj.parent) return\n const root = e.so.root\n root.updateMatrixWorld(true)\n fpRoot.copy(root.matrixWorld).invert()\n fpNow.multiplyMatrices(fpRoot, obj.matrixWorld)\n fpEuler.set(rest.r[0], rest.r[1], rest.r[2])\n fpRest.compose(fpPos.set(rest.p[0], rest.p[1], rest.p[2]), fpQuat.setFromEuler(fpEuler), obj.scale)\n fpRest.premultiply(obj.parent.matrixWorld).premultiply(fpRoot)\n // the move of the group since rest, in the item's frame, carried onto the spec's pose of the part\n fpNow.multiply(fpRest.invert())\n const r0 = ps.rotation ?? ZERO\n fpPart.compose(fpPos.set(ps.position[0], ps.position[1], ps.position[2]), fpQuat.setFromEuler(fpEuler.set(r0[0], r0[1], r0[2])), fpScale.set(1, 1, 1))\n fpPart.premultiply(fpNow).decompose(fpPos, fpQuat, fpScale)\n fpEuler.setFromQuaternion(fpQuat)\n world.setPartPose(e.so.objectId, id, [fpPos.x, fpPos.y, fpPos.z], [fpEuler.x, fpEuler.y, fpEuler.z])\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: MetricRow[] = roomMetricIds.flatMap((id): MetricRow[] => {\n const value = sampled[id]\n return value === undefined ? [] : [{ id, name: t(`metric.${id}`), text: num(value, id === 'frame_ms' ? 1 : 0) }]\n })\n // stays on the counters line until a clear finds the memory back down\n const leak = memoryWatch.last\n if (leak?.leaking) room.push({ id: 'memory_leak', name: '⚠', text: t('memory.leak_short', { geometries: leak.grew.geometries, textures: leak.grew.textures, clears: MEMORY_CLEARS }) })\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 listenerDirection = new THREE.Vector3()\n const environment = options.environment ?? createEnvironmentBus()\n const audioSink = audio ? createAudioSink(audio) : undefined\n function emitHost(event: HostEvent): void {\n if (event.type === 'explosion') knockPlayer(event)\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 ...(graphics ? { graphics: graphics.host } : {}),\n ...(audioSink ? { audio: audioSink } : {}),\n environment,\n groundAt,\n // the terrain's material where the floor is the top; a table or a counter answers undefined (the module's default)\n surfaceAt: (x, z) => (Math.max(sceneryTopAt(x, z), restingTopAt(x, z)) > terrain.heightAt(x, z) ? undefined : terrain.columnAt(x, z).material),\n effects: vfx,\n particleLimit: () => options.debris?.particleLimit ?? DEFAULT_PARTICLE_LIMIT,\n lights,\n pools,\n loading,\n addView: (view) => moduleViews.add(view),\n setViewCamera: (view) => moduleViews.setMain((view as THREE_NS.Camera | null) ?? null),\n holdPlayer: (held) => player.setWalkHeld(held),\n ...(options.blastShove ? { blastShove: options.blastShove } : {}),\n blastReach: (point, target, ignore) => world.blastReach(point, target, ignore ? { ignore } : {}),\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 defer: (queue, queueOptions) => scheduler.budget.register(queue, queueOptions),\n onFrame(update, frameOptions) {\n return scheduler.add((ctx) => update(ctx.dt), { phase: frameOptions?.phase ?? 'lateSimulate', order: frameOptions?.order ?? 0, id: `module.frame#${moduleFrameCount++}` })\n },\n holdFrame: () => bodyHoldFrame(),\n reachFor(reach) {\n if (!avatar) {\n reach.onGrip?.()\n return\n }\n doors.reachFor(reach)\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 onReset(listener) {\n resetListeners.add(listener)\n return () => resetListeners.delete(listener)\n },\n addObject(itemId, place) {\n return addScenery(itemId, place.position, place.rotationY)\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 /** Every material a probe group draws: they go to the warmup's anchors, which keep them alive (a program is freed when the last material that uses it is disposed). */\n const materialsOf = (group: THREE_NS.Object3D): THREE_NS.Material[] => {\n const found = new Set<THREE_NS.Material>()\n group.traverse((object) => {\n const material = (object as THREE_NS.Mesh).material as THREE_NS.Material | THREE_NS.Material[] | undefined\n for (const each of Array.isArray(material) ? material : material ? [material] : []) found.add(each)\n })\n return [...found]\n }\n // the materials that decals, effects and liquids make on demand: each adapter's probes are drawn once at load (every light count is another set of programs), and their materials stay as anchors\n const probeOf = (id: string, adapter: { warmUpProbes(): { readonly group: unknown; dispose(): void } }): WarmupProbe => ({\n id,\n build() {\n const probe = adapter.warmUpProbes()\n const group = probe.group as THREE_NS.Object3D\n return { group, materials: materialsOf(group), dispose: () => probe.dispose() }\n },\n })\n warmup.register(probeOf('destruction', renderer))\n warmup.register(probeOf('vfx', vfx))\n warmup.register(probeOf('fluids', fluidView))\n warmup.register(spriteProbes(THREE))\n // a blast of every explosive and a flame, drawn a few frames at load: their programs link and their buffers reach the GPU before the first one goes off; nothing stays in the world, the log or the sound\n const warmedEffect = (id: string): EffectWarmup => {\n let handle: number | null = null\n return {\n id: `vfx:${id}`,\n // the room was drawn in every fog state just before: each frame of a blast draws the effects alone\n root: () => vfx.root,\n play() {\n handle = vfx.play({ effect: id, point: [0, 0.1, -4], direction: [0, 1, 0], normal: [0, 1, 0] })\n },\n step: (dt) => vfx.update(dt),\n stop() {\n if (handle !== null) vfx.stop(handle)\n vfx.world.clear()\n vfx.update(0)\n },\n }\n }\n const catalogIds = vfx.catalog?.() ?? []\n for (const id of [...EXPLOSIVE_EFFECT_IDS, ...catalogIds.filter((id) => /fire|flame/i.test(id)).slice(0, 1)]) if (catalogIds.includes(id)) warmup.registerEffect(warmedEffect(id))\n let warmedUp = false\n const warmUp = (): void => {\n warmup.warmUp(gl, scene, camera, { lights, fogStates: WARMED_FOG_STATES, materials: pools.materials.registeredMaterials?.() ?? [] })\n warmedUp = true\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 pushable: ti.pushable,\n slow: ti.slow,\n fluid: ti.fluid,\n seal: ti.seal,\n weapon: ti.weapon,\n impl: ti.impl as TestRoomItem['impl'],\n animations: ti.animations,\n seats: ti.seats,\n sounds: ti.sounds,\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 let reportedState = bench.encode()\n bench.watch(() => {\n const encoded = bench.encode()\n if (encoded !== reportedState) {\n reportedState = encoded\n options.bench?.onChange?.(mod.id, encoded)\n }\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 // a scenario steps the world through the scheduler: input and present know they are scripted (ctx.scripted) and keep to what the step always did\n const step = (seconds: number): void => runHeadless(() => scheduler.advance(seconds, { dt: seconds > 6 ? 1 / 30 : FIXED_DT }))\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 = scheduler.paused\n scheduler.resume()\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 if (wasPaused) scheduler.pause()\n restoreScenery()\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 if (mod?.ground) terrain.setLayout(mod.ground)\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 // ----- the test table: a group of the catalogue laid on the `test_table` piece a page at a time, and the trials on one of its items\n const catalogGroups = (): 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 const tableOptions = options.testTable === false ? {} : (options.testTable ?? {})\n const tableScenery = tableOptions.scenery ?? 'test_table'\n const measured = new Map<string, { w: number; d: number }>()\n const testTable = createTestTable(\n {\n groups: catalogGroups,\n top: () => {\n const top = arena.tops.find((x) => x.id === tableScenery)\n return top && topOk(top) ? top : null\n },\n measure: (itemId) => {\n let size = measured.get(itemId)\n if (!size) {\n const item = catalogMap.get(itemId)\n const box = item ? new THREE.Box3().setFromObject(buildRoot(item)) : null\n size = box && !box.isEmpty() ? { w: box.max.x - box.min.x, d: box.max.z - box.min.z } : { w: 0.3, d: 0.3 }\n measured.set(itemId, size)\n }\n return size\n },\n spawn: (itemId, position) => spawn(itemId, position, 0),\n clear,\n resetAll,\n box: (objectId) => {\n const e = entries.get(objectId)\n if (!e || !world.has(objectId)) return null\n const box = new THREE.Box3().setFromObject(e.so.root)\n return box.isEmpty() ? null : { min: [box.min.x, box.min.y, box.min.z], max: [box.max.x, box.max.y, box.max.z] }\n },\n equip: (weapon) => {\n if (!arsenal.weapons.has(weapon)) return false\n if (heldEntry) releaseHeld()\n equip(weapon)\n room.waitUntilReady()\n return true\n },\n look: (eye, target) => lookAt(eye, target),\n use: (hold) => room.use(hold),\n blastAt: (weapon, point) => {\n const def = arsenal.weapons.get(weapon)\n const explosive = def?.action.kind === 'throwable' ? def.action.explosive : def?.action.kind === 'launcher' ? def.action.projectile : undefined\n return explosive !== undefined && explosives.blastAt(weapon, explosive, point)\n },\n log: (type, text, data) => action(type, text, { data }),\n translate: t,\n },\n tableOptions,\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 setStrikeCombo(on: boolean): void\n readonly strikeCombo: boolean | null\n kick(): boolean\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 testTable,\n spawn,\n clear,\n resetAll,\n setTool,\n useItem,\n use(hold = 0) {\n if (tool.def.category === 'hand') {\n const status = handUse()\n flush()\n return status\n }\n const status = useTool(FIXED_DT, false)\n flush()\n let t0 = 0\n while (t0 < hold) {\n useTool(FIXED_DT, true)\n directStep = true\n try {\n runHeadless(() => scheduler.advance(FIXED_DT))\n } finally {\n directStep = false\n }\n t0 += FIXED_DT\n }\n releaseTrigger()\n return status\n },\n grab,\n throwHeld,\n look(position, target) {\n lookAt(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: (dt: number): void => runHeadless(() => scheduler.frame(dt, { render: false, exact: true })),\n waitUntilReady(maxSeconds = 5) {\n let waited = 0\n while (tool.phase && waited < maxSeconds) {\n room.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 room.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 scheduler.pause()\n },\n resume() {\n scheduler.resume()\n },\n get paused() {\n return scheduler.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 scheduler.timeScale = on ? 0.25 : 1\n },\n setFastForward(on) {\n fastForward = on\n },\n setStrikeCombo,\n kick,\n get strikeCombo() {\n return combo ? comboOn : null\n },\n equip,\n terrain,\n openArea,\n modules: () => [...modules.values()].map((m) => ({ id: m.id, name: m.name, group: m.group, hasArea: typeof m.area === 'function' })),\n openAreaAsync: (area) => loading.busy(t('loading.open_area', { area: areaLabel(area) }), () => openArea(area)),\n loading,\n graphics: graphics?.controller ?? null,\n graphicsScreen: graphics?.screen ?? null,\n busy: (label, work, busyOptions) => loading.busy(label, work, busyOptions),\n loadModule,\n warmUp: () => {\n audio?.warmUp()\n warmUp()\n },\n animations: animationsOf,\n playAnimation,\n useLeaf: (objectId, part) => doors.useLeaf(objectId, part),\n leafOpening: (objectId, part) => doors.opening(objectId, part ?? leavesOf(objectId)[0]?.part ?? ''),\n leaves: (objectId) => leavesOf(objectId).map((l) => l.part),\n lockLeaf(objectId, locked = true, part) {\n const k = `${objectId}\\0${part ?? '*'}`\n if (locked) lockedLeaves.add(k)\n else lockedLeaves.delete(k)\n },\n get door() {\n return doors.state\n },\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) {\n downForced = state.down\n avatarState.down = state.down || Boolean(player.knocked?.down)\n }\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 get playerPosition() {\n return player.position\n },\n get playerKnock() {\n return player.knocked\n },\n sit: (objectId, seatId) => seating.sit(objectId, seatId),\n stand: () => seating.stand(),\n get seat() {\n return seating.seat\n },\n push: { begin: () => push.begin(), end: () => push.end(), setWalk: (walk) => push.setWalk(walk), get state() { return push.state } },\n setCameraMode,\n get cameraMode() {\n return cameraMode\n },\n metrics() {\n return { room: roomMetrics.sample(), module: moduleMetrics() }\n },\n frameStats: () => scheduler.stats(),\n lights,\n webgl: gl,\n dispose() {\n destructionSound?.dispose()\n if (ownAudio) audio?.dispose()\n for (const detach of detachers.values()) detach()\n detachers.clear()\n moduleViews.dispose()\n for (const store of benches.values()) store.dispose()\n benches.clear()\n stopLoop?.()\n disposePacer?.()\n scheduler.dispose()\n window.removeEventListener('resize', onResize)\n player.dispose()\n ui?.dispose()\n graphics?.dispose()\n loading.dispose()\n renderer.dispose()\n vfx.dispose()\n lights.dispose()\n pools.materials.dispose()\n pools.geometries.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 ...(graphics?.screen ? { onGraphics: () => graphics.screen?.open() } : {}),\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 ...(combo ? { combo: { label: combo.name?.[locale] ?? combo.id, onToggle: () => setStrikeCombo(!comboOn) } } : {}),\n ...(arsenal.weapons.has('kick') ? { kick: { label: `${t('ui.kick')} (${kickKeys.map((key) => key.replace(/^Key/, '')).join('/')})`, onKick: () => void kick() } } : {}),\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 ...(options.testTable !== false && arena.tops.some((x) => x.id === tableScenery) ? { testTable } : {}),\n })\n ui.hud(hudState())\n showBench()\n }\n\n let directStep = false\n scheduler.add(\n (ctx) => {\n if (directStep) return\n if (!ctx.scripted) return updateInput(ctx.dt, ctx.paused)\n seating.update()\n player.update(0)\n push.step(ctx.dt)\n doors.step(ctx.dt)\n followHeld(ctx.dt)\n },\n { phase: 'input', id: 'room.input' },\n )\n scheduler.add((ctx) => simulateBeforeModules(ctx.dt), { phase: 'lateSimulate', order: -1000, id: 'room.simulate' })\n scheduler.add((ctx) => simulateAfterModules(ctx.dt), { phase: 'lateSimulate', order: 1000, id: 'room.simulate-end' })\n scheduler.add(\n (ctx) => {\n if (ctx.simulated && !ctx.scripted) updatePresent(ctx.realDt)\n },\n { phase: 'present', id: 'room.present' },\n )\n scheduler.add((ctx) => lights.present([camera.position.x, camera.position.y, camera.position.z], ctx.realDt), { phase: 'present', order: 10, id: 'room.lights' })\n let stopLoop: (() => void) | undefined\n let disposePacer: (() => void) | undefined\n if (ownRenderer) {\n let nextLightsCheck = 0\n let warnedState = ''\n // modules that add a light of their own after the load (or change the fog, the tone mapping...) change the program key of every lit material: warm again when the sealed state breaks\n scheduler.add(\n (ctx) => {\n if (ctx.scripted) return\n const now = performance.now()\n if (now < nextLightsCheck) return\n nextLightsCheck = now + LIGHTS_CHECK_MS\n const state = lights.check(gl, scene)\n if (warmedUp && (state.ok || state.actual === warnedState)) return\n warnedState = state.actual\n warmUp()\n },\n { phase: 'render', order: -1000, id: 'room.lights-check' },\n )\n // a GPU slower than the CPU fills the driver queue and stalls the compositor for the whole queue: keep it a few frames behind at most\n const pacer = createFramePacer(typeof gl.getContext === 'function' ? (gl.getContext() as unknown as WebGL2RenderingContext) : null, options.framesInFlight === undefined ? {} : { framesInFlight: options.framesInFlight })\n disposePacer = () => pacer.dispose()\n scheduler.add(\n (ctx) => {\n if (!ctx.scripted && !pacer.ready()) return\n for (const batcher of batchers.values()) batcher.update()\n const restoreCamera = room.applyCamera()\n graphics?.beforeRender(camera)\n gl.render(scene, debugView ?? moduleViews.main(camera))\n moduleViews.render(scene)\n graphics?.afterRender()\n restoreCamera()\n pacer.submitted()\n roomMetrics.rendered()\n if (!ctx.scripted) graphics?.frameEnd()\n },\n { phase: 'render', id: 'room.render' },\n )\n try {\n stopLoop = startLoop(scheduler, {\n onFrame: (realSeconds) => {\n graphics?.frameStart()\n roomMetrics.frame(realSeconds)\n },\n skipSimulation: () => scenarioRunning,\n // the player's frame cap (Gráficos → Limite de FPS)\n ...(graphics ? { minFrameMs: () => graphics.controller.minFrameMs() } : {}),\n })\n ownsLoop = true\n } catch {\n // no display frames here (a worker): the host calls room.update\n }\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 { BODY_FOLEY_BANK } from '@adatechnology/game-audio'\nimport type { AudioEngine } from '@adatechnology/game-audio'\nimport { SWING_LEAD_SECONDS, hitSoundId, landSoundId, swingSoundId } from '@adatechnology/game-contracts'\nimport type { BlowId, BlowTarget, GaitId, SurfaceId, Vec3 } from '@adatechnology/game-contracts'\n\n/** How each melee tool of the arsenal strikes, by tool id; a tool not here goes by its category (`melee_blade` cuts, `melee_blunt` and `hand` knock). */\nexport const DEFAULT_TOOL_BLOWS: Readonly<Record<string, BlowId>> = {\n hand: 'punch',\n fists: 'punch',\n kick: 'kick',\n shove: 'shove',\n knife: 'blade',\n machete: 'blade',\n utility_knife: 'blade',\n axe: 'chop',\n hammer: 'blunt',\n claw_hammer: 'blunt',\n sledgehammer: 'blunt',\n baseball_bat: 'blunt',\n crowbar: 'blunt',\n wrench: 'blunt',\n}\n\n/** The blow a tool strikes with, or null when it is not a melee tool. */\nexport function blowOfTool(id: string, category: string, table: Readonly<Record<string, BlowId>> = DEFAULT_TOOL_BLOWS): BlowId | null {\n const listed = table[id]\n if (listed) return listed\n if (category === 'melee_blade') return 'blade'\n if (category === 'melee_blunt' || category === 'hand') return id === 'kick' ? 'kick' : 'blunt'\n return null\n}\n\n/** Joules of a blow to its level: a jab (about 40 J) is 0.6, a full swing of a sledgehammer (400 J and up) is 1. */\nconst levelOf = (energyJ: number): number => Math.max(0.5, Math.min(1, 0.5 + energyJ / 800))\n\n/** Metres of ground per footfall when no body says where its feet are: a walking stride, a running one. */\nexport const STRIDE_METRES: Readonly<Record<GaitId, number>> = { walk: 0.72, run: 1.05 }\n\nexport type BodySounds = {\n /** The swing of a blow through the air, `delay` seconds from now (its loudest part `SWING_LEAD_SECONDS` later); nothing for a blow without one. */\n swing(blow: BlowId, position: Vec3, delay?: number): void\n /** The body's side of a blow that landed (knuckles, sole, blade, club) on a body, a head or an object; the material's own impact plays beside it. */\n hit(blow: BlowId, target: Exclude<BlowTarget, 'air'>, position: Vec3, energyJ: number): void\n jump(position: Vec3): void\n /** The feet meet the floor after a fall of `speed` m/s on `surface`. */\n land(surface: SurfaceId, speed: number, position: Vec3): void\n /** A thrown body hits a wall or the floor at `speed` m/s: the fall of the body, and the hurt cry when it was hard (`SLAM_HURT_SPEED`). */\n slam(speed: number, position: Vec3): void\n /** Ids played, oldest first, for the room's checks (the last 64). */\n readonly played: readonly string[]\n}\n\n/** From this speed (m/s) a body thrown into a wall or onto the floor is hurt: it cries out. */\nexport const SLAM_HURT_SPEED = 3.5\n\n/** The test room's body sounds on its engine (the bank is registered in it); with no engine every call does nothing. */\nexport function createBodySounds(audio: AudioEngine | null): BodySounds {\n audio?.register(BODY_FOLEY_BANK)\n const played: string[] = []\n const play = (id: string, position: Vec3, volume: number, delay = 0): void => {\n played.push(id)\n if (played.length > 64) played.shift()\n audio?.play(id, { position, volume, urgent: true, ...(delay > 0 ? { delay } : {}) })\n }\n return {\n swing(blow, position, delay = 0) {\n const id = swingSoundId(blow)\n if (id) play(id, position, 0.8, delay)\n },\n hit(blow, target, position, energyJ) {\n play(hitSoundId(blow, target), position, levelOf(energyJ))\n },\n jump: (position) => play('jump', position, 0.6),\n land: (surface, speed, position) => play(landSoundId(surface, speed), position, Math.min(1, 0.45 + speed / 8)),\n slam(speed, position) {\n play('body_fall', position, Math.min(1, 0.4 + speed / 8))\n if (speed >= SLAM_HURT_SPEED) play('player_hurt', position, Math.min(1, 0.5 + speed / 12))\n },\n played,\n }\n}\n\n/** Seconds before the contact the swing of `blow` starts, so its loudest part meets the hit. */\nexport const swingLead = (blow: BlowId): number => SWING_LEAD_SECONDS[blow]\n\n/** Counts strides along the ground the player walked, for a room with no body to put the feet down: one footfall per stride, the feet alternating. */\nexport function createStrideCounter(stride: Readonly<Record<GaitId, number>> = STRIDE_METRES): { advance(metres: number, gait: GaitId): 'left' | 'right' | null; reset(): void } {\n // the first footfall comes after half a stride: starting to walk is a step\n let left = stride.walk / 2\n let next: 'left' | 'right' = 'right'\n return {\n advance(metres, gait) {\n left -= metres\n if (left > 0) return null\n left += stride[gait]\n const foot = next\n next = next === 'right' ? 'left' : 'right'\n return foot\n },\n reset() {\n left = stride.walk / 2\n next = 'right'\n },\n }\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 { markKitOrigin } from '@adatechnology/game-contracts'\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 follow?: SceneryObject['follow']\n label?: string\n top?: SceneryObject['top']\n spout?: SceneryObject['spout']\n free?: boolean\n pushable?: boolean\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 /** A top made of boards (`SceneryObject.top.parts`): each holds what is over it while it stands; `topPart` is one of them. */\n boards?: ReadonlyArray<{ part: string; minX: number; maxX: number; minZ: number; maxZ: number }>\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 /** The object of each collider (`colliders[i]`), `null` for what is not an object of the world (the tap's post). */\n colliderIds: Array<string | null>\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, follow: o.follow, label: o.label, top: o.top, spout: o.spout, free: o.free, pushable: o.pushable }))\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 // the room's own floor, grid and ruler (not a piece: the pieces in the room come from their packages)\n const group = markKitOrigin(new THREE.Group(), { owner: 'game-test-room', kind: 'room' })\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 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 boards = (o.top.parts ?? []).flatMap((part) => {\n const f = specBounds(THREE, o.spec, o.position, o.rotationY, { onlyPart: part })\n return f ? [{ part, minX: f.minX, maxX: f.maxX, minZ: f.minZ, maxZ: f.maxZ }] : []\n })\n const whole = specBounds(THREE, o.spec, o.position, o.rotationY, { onlyPart: o.top.part })\n if (!whole) continue\n const b = boards.length === 0 ? whole : { minX: Math.min(...boards.map((f) => f.minX)), maxX: Math.max(...boards.map((f) => f.maxX)), minZ: Math.min(...boards.map((f) => f.minZ)), maxZ: Math.max(...boards.map((f) => f.maxZ)) }\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, ...(boards.length > 0 ? { boards } : {}) })\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 const colliderIds: Array<string | null> = []\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 colliderIds.push(o.id)\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 colliderIds.push(null)\n }\n }\n\n return {\n group,\n objects: sceneryObjects,\n surfaces,\n colliders,\n colliderIds,\n playerStart,\n wallZ,\n tops,\n tapSpout,\n sun,\n }\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","/**\n * Which sound the hand makes with what it works: the item's own choice (`TestableItem.sounds`) first, else what its material says. The ids are those of the\n * foley bank of game-audio (`FOLEY_BANK`), named after the sound list, so a recorded take under the same id replaces the synthesised one.\n */\nimport { LEAF_FOLEY_SETS } from '@adatechnology/game-audio'\nimport type { LeafFoley, PickupClass } from '@adatechnology/game-audio'\nimport type { ItemSounds } from '@adatechnology/game-contracts'\nimport type { MaterialDef } from '@adatechnology/game-destruction'\n\n/** The pickup class of a material: by its tags (metal, glass and ceramic, plastic and rubber, wood, cloth, plants), paper by its id; plastic when nothing says. */\nexport function pickupClassOf(def: MaterialDef | undefined): PickupClass {\n if (!def) return 'plastic'\n const tags = def.tags ?? []\n if (def.id === 'paper') return 'paper'\n if (tags.includes('metal')) return 'metal'\n if (tags.includes('glass') || tags.includes('ceramic')) return 'glass'\n if (tags.includes('plastic') || tags.includes('rubber')) return 'plastic'\n if (tags.includes('wood')) return 'wood'\n if (tags.includes('fabric')) return 'fabric'\n if (tags.includes('plant')) return 'food'\n return 'plastic'\n}\n\n/** The sound of picking the item up. */\nexport const pickupSoundOf = (sounds: ItemSounds | undefined, def: MaterialDef | undefined): string => `item_pickup_${sounds?.handling ?? pickupClassOf(def)}`\n\n/**\n * The sound set of a leaf: the one the item names for this part (or for `*`), else a drawer for a leaf that slides, else a metal or a wooden door by the\n * sound class of its material (`impact_metal`, `impact_glass` ring like metal). An unknown set name falls back the same way.\n */\nexport function leafFoleyOf(sounds: ItemSounds | undefined, part: string, impactKey: string, slides: boolean): LeafFoley {\n const named = sounds?.leaves?.[part] ?? sounds?.leaves?.['*']\n const set = named ? LEAF_FOLEY_SETS[named] : undefined\n if (set) return set\n if (slides) return LEAF_FOLEY_SETS.drawer\n return /metal|glass/.test(impactKey) ? LEAF_FOLEY_SETS.metal_door : LEAF_FOLEY_SETS.wood_door\n}\n\n/** The sound of opening the item's seal: the item's own, else a metal seal is a can's tab and anything else a screw cap. */\nexport const openSoundOf = (sounds: ItemSounds | undefined, def: MaterialDef | undefined): string => sounds?.open ?? (pickupClassOf(def) === 'metal' ? 'can_open' : 'bottle_open')\n\n/** The sound each use repeats while it lasts, when the item does not name its own. */\nexport const USE_SOUNDS: Readonly<Record<string, string>> = {\n drink: 'drink_gulp',\n sip: 'drink_gulp',\n chug: 'drink_gulp',\n eat: 'eat_chew',\n}\n/** Seconds between two sounds of a use that lasts (a gulp, a bite chewed). */\nexport const USE_SOUND_EVERY = 0.55\n\n/** The sound a use repeats, if any. */\nexport const useSoundOf = (sounds: ItemSounds | undefined, useId: string): string | undefined => sounds?.uses?.[useId] ?? USE_SOUNDS[useId]\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 { releaseObject3D } from '@adatechnology/game-shapes-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 { ExplosiveBody, backblastEffect, blastEffect, createExplosiveBody, tripwireSegment } from '@adatechnology/game-weapons'\nimport type { Arsenal, Detonation, 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 /** Sets the explosive `explosive` off at `point` at once, as if `weapon` had put it there (the test table's blast); false for an unknown explosive. */\n blastAt: (weapon: string, explosive: string, point: Vec3) => boolean\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 // a projectile's mesh is its own (geometry, material, the model the host built for it): freed when it leaves the scene, keeping what the scene still draws\n const drop = (objects: THREE_NS.Object3D[]): void => {\n for (const object of objects) object.removeFromParent()\n releaseObject3D(objects, { keep: scene })\n }\n\n const clear = (): void => {\n projectiles.length = 0\n drop(meshes)\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 const extraAt = meshes.indexOf(extra)\n if (extraAt >= 0) meshes.splice(extraAt, 1)\n }\n const meshAt = meshes.indexOf(projectile.mesh)\n if (meshAt >= 0) meshes.splice(meshAt, 1)\n drop([...(projectile.attached ?? []), projectile.mesh])\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, effect: detonation.explosive })\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({\n type: 'explosion',\n source: projectile.weapon,\n point: detonation.point,\n energy: detonation.energy,\n radius: reach,\n cause: detonation.cause,\n explosive: detonation.explosive,\n lethalRadius: detonation.lethalRadius,\n ...(detonation.tnt !== undefined ? { tnt: detonation.tnt } : {}),\n })\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 blastAt = (weapon: string, explosive: string, point: Vec3): boolean => {\n const def = arsenal.explosives.get(explosive)\n if (!def) return false\n const event = new ExplosiveBody({ explosive: def, origin: point, triggers: ['remote'], rules: arsenal.rules.explosives }).trigger('remote')\n if (event?.type !== 'detonate') return false\n detonate({ weapon } as Projectile, event.detonation)\n return true\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, blastAt, 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 { Vec3 } from '@adatechnology/game-contracts'\n\n/**\n * What a trial does to one object: a shot, a punch, a knife blow, a flame on it or a blast beside it. The test table runs one on the object it has picked, so every item of the\n * catalogue can be tried one by one with the same hit.\n */\nexport type TrialKind = 'shot' | 'punch' | 'stab' | 'fire' | 'blast'\n\nexport const TRIAL_KINDS: readonly TrialKind[] = ['shot', 'punch', 'stab', 'fire', 'blast']\n\n/**\n * How the room runs a trial: the tool (an id of the arsenal), where the player stands and how long the trigger is held.\n * `distance` is metres from the front face of the object (the side the player comes from) to the eye, `lift` metres the eye is above the object's centre, `hold` seconds the\n * trigger stays down (a flame). For `blast` the explosive of `weapon` goes off `distance` metres behind the object, and the player watches from `watch` metres in front.\n */\nexport interface TrialTool {\n readonly weapon: string\n readonly distance: number\n readonly lift: number\n readonly hold?: number\n readonly watch?: number\n}\n\n/** The tools of the trials: a 9 mm pistol, the fists, a knife, a flamethrower and a fragmentation grenade, all of the default arsenal. */\nexport const DEFAULT_TRIALS: Readonly<Record<TrialKind, TrialTool>> = {\n shot: { weapon: 'pistol_9mm', distance: 2.5, lift: 0.5 },\n punch: { weapon: 'fists', distance: 0.3, lift: 0.15 },\n stab: { weapon: 'knife', distance: 0.22, lift: 0.1 },\n fire: { weapon: 'flamethrower', distance: 1.6, lift: 0.4, hold: 0.8 },\n blast: { weapon: 'frag_grenade', distance: 0.3, lift: 1, watch: 6 },\n}\n\n/** The test table: which piece of the arena it is, the gap between the things laid on it and the trial tools (each one replaces the default's fields it gives). */\nexport interface TestTableOptions {\n /** Id of the `scenery` piece with a `top` the items are laid on (default `test_table`). */\n readonly scenery?: string\n /** Metres between two items on the table (default 0.12). */\n readonly gap?: number\n /** Metres kept free at each end of the table (default 0.1). */\n readonly margin?: number\n readonly trials?: Partial<Record<TrialKind, Partial<TrialTool>>>\n}\n\n/** One item laid on the table. */\nexport interface TestTableObject {\n readonly objectId: string\n readonly itemId: string\n readonly name: string\n}\n\n/** The page of a group that lies on the table now. */\nexport interface TestTablePage {\n /** The catalogue group (its translated name, as the catalogue tabs show it). */\n readonly group: string\n /** Index of the page, from 0. */\n readonly page: number\n /** Index in the group of the first item on the table, and how many the group has. */\n readonly first: number\n readonly total: number\n readonly objects: readonly TestTableObject[]\n /** The object the trials hit (the first one until another is picked). */\n readonly selected: string | null\n readonly hasPrev: boolean\n readonly hasNext: boolean\n}\n\n/** The test table of the room: lays a group of the catalogue on the table a page at a time, picks one object and runs the trials on it. */\nexport interface TestTable {\n /** The groups of the catalogue that can be laid (every group with items). */\n groups(): string[]\n /** Every item that can be laid, with its group (what a search looks in). */\n items(): Array<{ id: string; name: string; group: string }>\n /** Clears the room and lays page `page` (default 0) of `group`; null when the room has no table or the group no items. */\n open(group: string, page?: number): TestTablePage | null\n next(): TestTablePage | null\n prev(): TestTablePage | null\n /** Lays the page of the group that holds `itemId` and picks it; null when no group has it (or the room has no table). */\n find(itemId: string): TestTablePage | null\n /** Puts the table and the page back as they were before the trials: everything is restored and laid again. */\n relay(): TestTablePage | null\n state(): TestTablePage | null\n /** Picks the object the trials hit; false when it is not on the table. */\n select(objectId: string): boolean\n /** Runs a trial on the picked object (or on `objectId`): the room equips the tool, puts the player in front of it, aims and uses it. False when there is nothing to hit. */\n trial(kind: TrialKind, objectId?: string): boolean\n /** Follow the table: a page laid, an object picked, a trial run. Returns the unsubscribe function. */\n on(listener: (page: TestTablePage | null) => void): () => void\n}\n\nexport const resolveTrials = (overrides: TestTableOptions['trials'] = {}): Record<TrialKind, TrialTool> =>\n Object.fromEntries(TRIAL_KINDS.map((kind) => [kind, { ...DEFAULT_TRIALS[kind], ...overrides[kind] }])) as Record<TrialKind, TrialTool>\n\n/**\n * How many items, from `start`, fit side by side along a table of `length` metres with `gap` between them (`width(i)` is the width of item i). At least one, so an item longer\n * than the table still gets a page of its own. Pure.\n */\nexport function fitRow(width: (index: number) => number, start: number, total: number, length: number, gap: number): number {\n let used = 0\n let count = 0\n for (let i = start; i < total; i++) {\n const w = width(i)\n const next = count === 0 ? w : used + gap + w\n if (count > 0 && next > length) break\n used = next\n count++\n }\n return count\n}\n\n/** The x of the centre of each item of a row laid side by side, centred on `centreX`, with `gap` between them. Pure. */\nexport function rowCentres(widths: readonly number[], centreX: number, gap: number): number[] {\n const length = widths.reduce((sum, w) => sum + w, 0) + gap * Math.max(0, widths.length - 1)\n let x = centreX - length / 2\n return widths.map((w) => {\n const centre = x + w / 2\n x += w + gap\n return centre\n })\n}\n\n/**\n * Where the player's eye goes for a trial on an object whose box is `min`..`max` (world), and where it looks. The player comes from +z (the side of the room the table faces),\n * so a melee blow lands on the front face. A blast is watched from `watch` metres. Pure.\n */\nexport function trialView(tool: TrialTool, kind: TrialKind, min: Vec3, max: Vec3): { eye: Vec3; target: Vec3 } {\n const target: Vec3 = [(min[0] + max[0]) / 2, (min[1] + max[1]) / 2, (min[2] + max[2]) / 2]\n const away = kind === 'blast' ? (tool.watch ?? 6) : tool.distance\n return { eye: [target[0], target[1] + tool.lift, max[2] + away], target }\n}\n\n/** What the test table needs of the room. */\nexport interface TestTableContext {\n /** The catalogue by group: the ids and names of the items of each one. */\n readonly groups: () => ReadonlyMap<string, ReadonlyArray<{ readonly id: string; readonly name: string }>>\n /** The top of the table in the world (null: the room has no such piece, or its top is broken). */\n readonly top: () => { readonly minX: number; readonly maxX: number; readonly minZ: number; readonly maxZ: number; readonly top: number } | null\n /** Width (x) and depth (z) of an item's model at rotation 0, metres. */\n readonly measure: (itemId: string) => { readonly w: number; readonly d: number }\n readonly spawn: (itemId: string, position: Vec3) => { readonly objectId: string }\n readonly clear: () => void\n readonly resetAll: () => void\n /** The world box of an object still in the room, else null. */\n readonly box: (objectId: string) => { readonly min: Vec3; readonly max: Vec3 } | null\n /** Puts the tool in hand (added to the hotbar) and waits for its draw. False for an id the arsenal does not have. */\n readonly equip: (weapon: string) => boolean\n readonly look: (eye: Vec3, target: Vec3) => void\n readonly use: (hold: number) => void\n /** Sets off the explosive of `weapon` at `point`. False when the weapon throws or places no explosive. */\n readonly blastAt: (weapon: string, point: Vec3) => boolean\n readonly log: (type: string, text: string, data: Record<string, unknown>) => void\n readonly translate: (key: string, vars?: Record<string, string | number>) => string\n}\n\n/** The test table over a room (see `TestTable`). */\nexport function createTestTable(context: TestTableContext, options: TestTableOptions = {}): TestTable {\n const gap = options.gap ?? 0.12\n const margin = options.margin ?? 0.1\n const trials = resolveTrials(options.trials)\n const listeners = new Set<(page: TestTablePage | null) => void>()\n let current: { group: string; page: number; first: number; objects: TestTableObject[]; selected: string | null } | null = null\n\n const itemsOf = (group: string) => context.groups().get(group) ?? []\n const emit = (): TestTablePage | null => {\n const page = state()\n for (const listener of [...listeners]) listener(page)\n return page\n }\n const state = (): TestTablePage | null => {\n if (!current) return null\n const total = itemsOf(current.group).length\n const live = current.objects.filter((o) => context.box(o.objectId))\n return {\n group: current.group,\n page: current.page,\n first: current.first,\n total,\n objects: live,\n selected: current.selected,\n hasPrev: current.page > 0,\n hasNext: current.first + current.objects.length < total,\n }\n }\n\n // the bounds of each page of each group: page n is [bounds[n], bounds[n + 1]), found one after the other (a page holds what fits on the table), up to the group's length\n const bounds = new Map<string, number[]>()\n const widthOf = (itemId: string): number => context.measure(itemId).w\n /** The bounds of `group` known at least up to the page that holds item `index` (or page `page`). */\n const boundsUntil = (group: string, length: number, until: (bound: number[]) => boolean): number[] => {\n const items = itemsOf(group)\n const known = bounds.get(group) ?? [0]\n bounds.set(group, known)\n while (known[known.length - 1] < items.length && !until(known)) {\n const first = known[known.length - 1]\n known.push(first + fitRow((i) => widthOf(items[i].id), first, items.length, length, gap))\n }\n return known\n }\n const lengthOf = (top: NonNullable<ReturnType<TestTableContext['top']>>): number => top.maxX - top.minX - 2 * margin\n\n const lay = (group: string, page: number, top: NonNullable<ReturnType<TestTableContext['top']>>): TestTablePage | null => {\n const items = itemsOf(group)\n const known = boundsUntil(group, lengthOf(top), (b) => b.length > page + 1)\n const index = Math.max(0, Math.min(page, known.length - 2))\n const first = known[index]\n const laid = items.slice(first, known[index + 1])\n context.clear()\n const sizes = laid.map((item) => context.measure(item.id))\n const centres = rowCentres(sizes.map((size) => size.w), (top.minX + top.maxX) / 2, gap)\n // along the front edge of the table (the player's side), so a blow from in front reaches each one\n const objects = laid.map((item, i) => {\n const d = Math.min(sizes[i].d, top.maxZ - top.minZ)\n const { objectId } = context.spawn(item.id, [centres[i], top.top, top.maxZ - margin / 2 - d / 2])\n return { objectId, itemId: item.id, name: item.name }\n })\n current = { group, page: index, first, objects, selected: objects[0]?.objectId ?? null }\n context.log('test_table', context.translate('act.test_table', { group, from: first + 1, to: first + laid.length, total: items.length }), { group, page: index, items: laid.map((i) => i.id) })\n return emit()\n }\n\n const open = (group: string, page = 0): TestTablePage | null => {\n const top = context.top()\n if (!itemsOf(group).length || !top) return null\n return lay(group, page, top)\n }\n\n const find = (itemId: string): TestTablePage | null => {\n const top = context.top()\n const group = [...context.groups()].find(([, items]) => items.some((i) => i.id === itemId))?.[0]\n if (group === undefined || !top) return null\n const index = itemsOf(group).findIndex((i) => i.id === itemId)\n // only the widths are measured on the way: nothing is laid until the page that holds the item\n const known = boundsUntil(group, lengthOf(top), (b) => b[b.length - 1] > index)\n lay(group, known.findIndex((bound, i) => bound <= index && index < known[i + 1]), top)\n const target = current?.objects.find((o) => o.itemId === itemId)\n if (current && target) current.selected = target.objectId\n return emit()\n }\n\n const selected = (objectId?: string): string | null => {\n const id = objectId ?? current?.selected ?? null\n return id && context.box(id) ? id : null\n }\n\n const trial = (kind: TrialKind, objectId?: string): boolean => {\n const id = selected(objectId)\n const box = id ? context.box(id) : null\n if (!id || !box) return false\n const tool = trials[kind]\n if (!context.equip(tool.weapon)) return false\n const view = trialView(tool, kind, box.min, box.max)\n context.look(view.eye, view.target)\n const name = current?.objects.find((o) => o.objectId === id)?.name ?? id\n context.log('trial', context.translate(`act.trial.${kind}`, { name }), { kind, objectId: id, weapon: tool.weapon })\n if (kind === 'blast') {\n const point: Vec3 = [view.target[0], box.min[1] + 0.05, box.min[2] - tool.distance]\n return context.blastAt(tool.weapon, point)\n }\n context.use(tool.hold ?? 0)\n emit()\n return true\n }\n\n return {\n groups: () => [...context.groups()].filter(([, items]) => items.length > 0).map(([group]) => group),\n items: () => [...context.groups()].flatMap(([group, items]) => items.map((item) => ({ id: item.id, name: item.name, group }))),\n open,\n find,\n next: () => {\n const page = state()\n return page?.hasNext ? open(page.group, page.page + 1) : page\n },\n prev: () => {\n const page = state()\n return page?.hasPrev ? open(page.group, page.page - 1) : page\n },\n relay: () => {\n if (!current) return null\n context.resetAll()\n return open(current.group, current.page)\n },\n state,\n select: (objectId) => {\n if (!current || !current.objects.some((o) => o.objectId === objectId) || !context.box(objectId)) return false\n current.selected = objectId\n emit()\n return true\n },\n trial,\n on: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\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 * as THREE_NS from 'three'\nimport type { BusySink, BusyTask, HostGraphics } from '@adatechnology/game-contracts'\nimport { createGraphicsController, frameLoad, targetFrameMs } from '@adatechnology/game-graphics'\nimport type { GraphicsController, StorageLike } from '@adatechnology/game-graphics'\nimport { createFpsOverlay, createGraphicsScreen } from '@adatechnology/game-graphics/screen'\nimport type { FpsOverlay, GraphicsScreen } from '@adatechnology/game-graphics/screen'\nimport { createGpuFrameTimer, createGraphicsView, gpuName } from '@adatechnology/game-graphics-three'\nimport type { GpuFrameTimer, GraphicsView } from '@adatechnology/game-graphics-three'\n\nconst QUIET_FRAMES = 10\n\n/** The room's graphics settings (`TestRoomOptions.graphics`). */\nexport interface RoomGraphicsOptions {\n /** Where the player's choice is kept (default `localStorage`; null keeps it in memory). */\n readonly storage?: StorageLike | null\n /** The key it is kept under (default `adatechnology.graphics`). */\n readonly key?: string\n /** The short test of the first load, seconds (default 3; 0 skips it and starts the automatic mode at Alta). */\n readonly calibrationSeconds?: number\n /**\n * When the calibration of a first run starts: `idle` (default) after a few drawn frames with nothing on the loading indicator, or `manual`, where the page calls\n * `room.graphics.calibrateIfNeeded()` once its content is in (a page that loads its content before it shows the room).\n */\n readonly calibrate?: 'idle' | 'manual'\n}\n\nexport interface RoomGraphics {\n readonly controller: GraphicsController\n readonly view: GraphicsView\n readonly screen: GraphicsScreen | null\n /** What modules get as `host.graphics`. */\n readonly host: HostGraphics\n /** Marks the start of a display frame (before the scheduler runs it). */\n frameStart(): void\n /** Around the draw call of the frame: the GPU timer and the near shadow box that follows the camera. */\n beforeRender(camera: THREE_NS.Camera): void\n afterRender(): void\n /** The end of a frame that was drawn: what it cost goes to the automatic mode, with the wall time since the last drawn frame (a frame the pacer skipped is in it). */\n frameEnd(): void\n dispose(): void\n}\n\n/**\n * The graphics settings on the test room: the controller of `game-graphics` (choice in the browser, calibration, automatic mode), the three.js view of\n * `game-graphics-three` on the room's renderer, camera and sun, the settings screen and the frame counter, and the calibration shown on the loading indicator.\n */\nexport function createRoomGraphics(o: {\n readonly gl: THREE_NS.WebGLRenderer\n readonly camera: THREE_NS.PerspectiveCamera\n readonly sun: THREE_NS.DirectionalLight\n readonly container: HTMLElement\n readonly locale: string\n readonly loading: BusySink & { readonly active: boolean }\n readonly label: string\n readonly ui: boolean\n readonly options: RoomGraphicsOptions\n}): RoomGraphics {\n const view = createGraphicsView({ renderer: o.gl, camera: o.camera, sun: o.sun })\n const seconds = o.options.calibrationSeconds ?? 3\n const controller = createGraphicsController({\n store: { ...(o.options.storage !== undefined ? { storage: o.options.storage } : {}), ...(o.options.key ? { key: o.options.key } : {}) },\n gpu: gpuName(o.gl),\n benchmark: seconds > 0 ? { durationS: seconds } : false,\n // the room measures its own frames once it is up, not the loading of its content\n calibrate: 'manual',\n apply: (e) => view.apply(e),\n })\n const timer: GpuFrameTimer = createGpuFrameTimer(o.gl)\n const screen = o.ui ? createGraphicsScreen({ container: o.container, controller, locale: o.locale }) : null\n const overlay: FpsOverlay | null = o.ui ? createFpsOverlay({ container: o.container, controller, locale: o.locale }) : null\n const listeners = new Set<() => void>()\n let lastHorde = controller.settings.hordeDetail\n const unsubscribe = controller.subscribe(() => {\n if (controller.settings.hordeDetail === lastHorde) return\n lastHorde = controller.settings.hordeDetail\n for (const l of listeners) l()\n })\n\n // the calibration is a task of the loading indicator, with its bar\n let task: BusyTask | null = null\n const syncTask = (): void => {\n if (controller.phase === 'calibrating') {\n task ??= o.loading.begin(o.label, { total: 100 })\n task.step(`${Math.round(controller.calibrationProgress * 100)}%`, Math.round(controller.calibrationProgress * 100))\n } else if (task) {\n task.end()\n task = null\n }\n }\n syncTask()\n\n let started = 0\n // drawn frames in a row with nothing loading: the calibration waits for a few (the first frames after a load compile and upload)\n let quiet = 0\n let lastEnd = 0\n return {\n controller,\n view,\n screen,\n host: {\n hordeDetail: () => controller.settings.hordeDetail,\n onChange(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n report: (key, value) => controller.report(key, value),\n },\n frameStart() {\n started = performance.now()\n },\n beforeRender(camera) {\n view.hold()\n view.follow(camera.position.x, camera.position.z)\n timer.begin()\n },\n afterRender() {\n timer.end()\n },\n frameEnd() {\n const now = performance.now()\n const realSeconds = lastEnd > 0 ? (now - lastEnd) / 1000 : 0\n lastEnd = now\n if (!(realSeconds > 0)) return\n const cpuMs = started > 0 ? now - started : realSeconds * 1000\n controller.frame(realSeconds, frameLoad({ cpuMs, gpuMs: timer.ms, intervalMs: realSeconds * 1000, targetMs: targetFrameMs(controller.settings.fpsCap) }))\n quiet = o.loading.active && !task ? 0 : quiet + 1\n if (o.options.calibrate !== 'manual' && quiet >= QUIET_FRAMES) controller.calibrateIfNeeded()\n syncTask()\n },\n dispose() {\n task?.end()\n unsubscribe()\n listeners.clear()\n timer.dispose()\n screen?.dispose()\n overlay?.dispose()\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', 'geometries', 'textures', 'heap_mb']\n\nconst WINDOW_S = 0.5\n\ninterface RenderInfo {\n info?: { render?: { calls: number; triangles: number }; memory?: { geometries: number; textures: 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\n/** The JS heap in MB where the browser tells it (Chrome's `performance.memory`), undefined elsewhere. */\nexport function heapMB(): number | undefined {\n const memory = (globalThis.performance as { memory?: { usedJSHeapSize?: number } } | undefined)?.memory\n return typeof memory?.usedJSHeapSize === 'number' ? memory.usedJSHeapSize / 1048576 : undefined\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 put('geometries', gl.info?.memory?.geometries)\n put('textures', gl.info?.memory?.textures)\n put('heap_mb', heapMB())\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","/**\n * Watches what the room keeps after each clear (CLAUDE.md, \"Memória\"). Right after a clear the scene holds only the scenery, so the GPU counts of three\n * (geometries and textures alive, `renderer.info.memory`) should come back to the same level every time. A cache fills once (the first use of a\n * model, a palette); a leak grows on every clear. The watch warns when the counts grew on each of the last clears and, over them, by more than the\n * budget: something taken out of the scene was not released (`discardObject3D` / `releaseObject3D` of game-shapes-three) or a list still holds it.\n */\nexport interface MemorySample {\n readonly geometries: number\n readonly textures: number\n /** JS heap in MB, where the browser tells it (Chrome). Shown, never used to warn: without a forced GC it moves with the garbage. */\n readonly heapMB?: number\n}\n\nexport interface MemoryWatchOptions {\n /** Reads the counts now. */\n readonly read: () => MemorySample | undefined\n /** How many clears in a row must each grow before the watch warns (default 4). */\n readonly clears?: number\n /** Growth over those clears that is a leak and not a cache (defaults: 40 geometries, 4 textures). */\n readonly budget?: { readonly geometries?: number; readonly textures?: number }\n}\n\nexport interface MemoryVerdict {\n /** The counts right after the last clear. */\n readonly after: MemorySample\n /** Growth over the watched clears (last minus first). */\n readonly grew: { readonly geometries: number; readonly textures: number }\n /** True when the counts keep growing clear after clear past the budget. */\n readonly leaking: boolean\n}\n\nexport interface MemoryWatch {\n /**\n * Call right after the room clears; returns the verdict, or undefined when the counts are not readable. `context` names what was on the table\n * (the area or bench): clears are compared only with clears of the same context, so visiting a new area (its caches filling) is not a leak.\n */\n cleared(context?: string): MemoryVerdict | undefined\n /** The last verdict (none before the first clear). */\n readonly last: MemoryVerdict | undefined\n /** Forgets every history. */\n reset(): void\n}\n\nexport function createMemoryWatch(options: MemoryWatchOptions): MemoryWatch {\n const clears = Math.max(2, options.clears ?? 4)\n const budget = { geometries: options.budget?.geometries ?? 40, textures: options.budget?.textures ?? 4 }\n const histories = new Map<string, MemorySample[]>()\n let last: MemoryVerdict | undefined\n return {\n cleared(where) {\n const now = options.read()\n if (!now) return undefined\n const key = where ?? ''\n const history = histories.get(key) ?? []\n histories.set(key, history)\n history.push(now)\n if (history.length > clears + 1) history.shift()\n const first = history[0]\n const grew = { geometries: now.geometries - first.geometries, textures: now.textures - first.textures }\n let growing = history.length === clears + 1\n for (let i = 1; growing && i < history.length; i++) {\n const before = history[i - 1]\n const after = history[i]\n growing = after.geometries > before.geometries || after.textures > before.textures\n }\n const leaking = growing && (grew.geometries > budget.geometries || grew.textures > budget.textures)\n last = { after: now, grew, leaking }\n return last\n },\n get last() {\n return last\n },\n reset() {\n histories.clear()\n last = undefined\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 // food eaten with its liquid: the host says what was eaten, not what was drunk\n if (ev.eaten) break\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 { stepKnock } from '@adatechnology/game-contracts'\nimport type { Knock } from '@adatechnology/game-contracts'\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 /**\n * What stands where the body would be, asked on every step with the feet height: `floor` is the highest top it can step onto there (a low\n * heap of debris; 0 is the floor), `blocked` that something taller is in the way. Without it the floor is flat and only the colliders stop.\n */\n footing?: (x: number, z: number, radius: number, feet: number) => { floor: number; blocked: boolean }\n /** Half size of the arena. */\n limit: number\n start: Vec3\n hooks: PlayerHooks\n /** `KeyboardEvent.code`s that crouch (default `['KeyC']`): a tap stays crouched until the next tap, a longer press crouches while held. Ctrl is not one by default: Ctrl+W closes the tab and no page can stop it. */\n crouchKeys?: readonly string[]\n /** Height of the ground the player walks on (a crater, a heap). Default flat at 0. */\n floorAt?: (x: number, z: number) => number\n /** The feet leave the floor on a jump, or meet it again after a fall (`speed`: m/s downward at the touch). For the body's sounds. */\n /**\n * A body thrown by a knock hit something on its way (`obstacle`: a wall, a car, a cupboard, which stopped it) or the floor (`ground`, falling): `speed` m/s into it,\n * `direction` the unit way it was going. For the impact on what it hit, the sound and the hurt.\n */\n onSlam?(event: PlayerSlam): void\n onFeet?: (event: PlayerFeetEvent) => void\n}\n\n/** What the feet did this frame: a jump, or a landing with the speed of the fall (a jump on the spot comes down at about 4.6 m/s). */\nexport type PlayerFeetEvent = { readonly type: 'jump' } | { readonly type: 'land'; readonly speed: number }\n\n/** A thrown body meeting a wall or the floor (`PlayerOptions.onSlam`). */\nexport interface PlayerSlam {\n readonly against: 'obstacle' | 'ground'\n readonly speed: number\n readonly direction: Vec3\n}\n\n/** Slower than this (m/s) a thrown body meeting something only stops: no slam. */\nexport const SLAM_MIN_SPEED = 1.5\n\n/** Below this fall speed (m/s) a touch of the floor is a step down, not a landing. */\nexport const LANDING_MIN_SPEED = 1\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 /** The feet are on the floor (not in a jump or a fall). */\n readonly grounded: boolean\n /** Whether the player is crouched (a crouch key tapped or 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 /** Where the keys ask to go on the floor: a unit `[x, z]`, or `[0, 0]`. */\n readonly walkIntent: readonly [number, number]\n /** Whether a body can stand at this point (arena, colliders, blockers). */\n canStand(x: number, z: number): boolean\n /** While held the keys do not walk or jump: whoever holds it moves the player with `moveBy` (pushing a piece of furniture). */\n setWalkHeld(held: boolean): void\n /** Seated, the body stays at the height its pose set: what it sits on is not a step to climb and it does not fall. */\n setSeated(seated: boolean): void\n /** Lowers the eye by this many metres, eased (bending over something low); 0 stands up. */\n setBend(metres: number): void\n /** Keeps the view within `range` radians of `yaw`; null frees it. */\n setLookLimit(limit: { readonly yaw: number; readonly range: number } | null): void\n /** The floor offset the player tried to walk (keys, `moveBy`, `walk`) since the last call, blocked or not; the call resets it. */\n takeWish(): [number, number]\n /** Walk by hand (tests): moves the player `forward` and `right` metres along its facing. */\n walk(forward: number, right: number): void\n /**\n * A blast's shove (`knockOf` of game-contracts): the body is thrown with its velocity, slides and stops against what is in the way, and, when the knock takes it off\n * its feet, falls, lies a while and gets up. The keys do nothing until it stands again. A second knock while one is on adds its velocity.\n */\n knock(knock: Knock): void\n /** The knock on now, or null: `lying` 0..1 says how far down the body is. */\n readonly knocked: Readonly<Knock> | null\n /** Whether the knock that put the body down pushed it toward its facing (falls face down) rather than from the front (falls on its back). */\n readonly knockedForward: boolean\n /** Seconds of stun left from a blast (the view sways), 0 when clear. */\n readonly stunned: number\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\n/** Share of the radius the feet stand on: at the edge of a heap the player steps down instead of hovering on its corner. */\nconst FOOT = 0.5\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 BEND_RATE = 7\n/** The widths of the body, against its full width, that say how deep something has come into it. */\nconst CLEAR_SHARES = [1, 0.75, 0.5, 0.25]\n/** A crouch key released within this many seconds was a tap, which stays crouched; a longer press was a hold. */\nconst CROUCH_TAP = 0.25\nconst RUN = 6.2\nconst JUMP = 4.6\nconst GRAVITY = 13\nconst FLOOR_CLIMB_SPEED = 3\nconst FLOOR_FALL_SPEED = 6\nconst LOOK = 0.0022\n/** Height of the eye (m above the floor) of a body lying on its back, where the view turns up to (radians above the level), and how far it rolls to one side. */\nconst LYING_EYE = 0.3\nconst LYING_PITCH = 1.05\nconst LYING_ROLL = 0.35\n/** Where the view of a body fallen face down turns to: below the level, at the ground under the face (radians). */\nconst LYING_PITCH_FACE_DOWN = -1.05\n/** The sway of a stunned view: radians of pitch and roll at full stun, reached with `STUN_FULL` seconds or more left. */\nconst STUN_PITCH = 0.05\nconst STUN_ROLL = 0.08\nconst STUN_FULL = 2\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 bend = 0\n let bendTarget = 0\n let vy = 0\n /** The floor under the feet at the last update (0 before the first). */\n let floorUnder = 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 let crouchLatched = false\n let crouchPress: { held: number; latched: boolean } | null = null\n const isCrouched = (): boolean => crouchLatched || isCrouchHeld()\n const pressCrouch = (code: string): void => {\n if (crouchKeys.includes(code) && !isCrouchHeld()) crouchPress = { held: 0, latched: crouchLatched }\n }\n const releaseCrouch = (code: string): void => {\n if (!crouchKeys.includes(code) || !crouchPress || isCrouchHeld()) return\n crouchLatched = crouchPress.held < CROUCH_TAP ? !crouchPress.latched : false\n crouchPress = null\n }\n const euler = new THREE.Euler(0, 0, 0, 'YXZ')\n const floorHere = (): number => o.floorAt?.(px.x, px.z) ?? 0\n let floorLevel = 0\n // the eye eases over a rim and falls into a hole instead of jumping with every cell of the ground\n const followFloor = (dt: number): void => {\n const gap = floorHere() - floorLevel\n const reach = (gap > 0 ? FLOOR_CLIMB_SPEED : FLOOR_FALL_SPEED) * dt\n floorLevel += Math.max(-reach, Math.min(reach, gap))\n }\n\n /** The knock of a blast on the body, while it lasts. */\n let knocked: Knock | null = null\n let knockedForward = false\n /** Seconds of stun left, and the phase of the sway it gives the view. */\n let stunLeft = 0\n let stunPhase = 0\n /** Which way the view rolls when the body falls: toward the side the shove came from. */\n let rollSide = 1\n const apply = (): void => {\n const lying = knocked?.lying ?? 0\n // a fall eases in: the eye goes down to the floor and the view turns up to the sky, a little onto one side (on its back, thrown away from the blast)\n const fallen = lying * lying * (3 - 2 * lying)\n // a stunned head sways: slow, uneven, fading as the stun wears off\n const sway = Math.min(1, stunLeft / STUN_FULL)\n const swayPitch = STUN_PITCH * sway * Math.sin(stunPhase * 1.3)\n const swayRoll = STUN_ROLL * sway * Math.sin(stunPhase * 0.9 + 1)\n euler.set(pitch + ((knockedForward ? LYING_PITCH_FACE_DOWN : LYING_PITCH) - pitch) * fallen + swayPitch, yaw, LYING_ROLL * rollSide * fallen + swayRoll, 'YXZ')\n cam.quaternion.setFromEuler(euler)\n const standing = eye - CROUCH_DROP * crouch - bend\n cam.position.set(px.x, floorLevel + y + standing + (LYING_EYE - standing) * fallen, px.z)\n cam.updateMatrixWorld(true)\n }\n apply()\n\n const outside = (x: number, z: number): boolean => Math.abs(x) > o.limit - PLAYER_RADIUS || Math.abs(z) > o.limit - PLAYER_RADIUS\n const blocked = (x: number, z: number, radius = PLAYER_RADIUS): boolean => {\n if (outside(x, z)) return true\n for (const c of o.colliders) if (x > c[0] - radius && x < c[2] + radius && z > c[1] - radius && z < c[3] + radius) return true\n if (o.blockers) for (const isBlocked of o.blockers) if (isBlocked(x, z, radius)) return true\n return o.footing ? o.footing(x, z, radius, y).blocked : false\n }\n /** The widest body that fits where the player is, or null when not even the narrowest does: how deep something has come into the player. */\n const clearRadius = (): number | null => {\n for (const share of CLEAR_SHARES) if (!blocked(px.x, px.z, PLAYER_RADIUS * share)) return PLAYER_RADIUS * share\n return null\n }\n // what the player tried to walk since the last `takeWish` (blocked or not): the room pushes what stands in the way by it\n const wish = { x: 0, z: 0 }\n const move = (dx: number, dz: number): void => {\n wish.x += dx\n wish.z += dz\n // caught in something (a piece fell on the spot, a piece settling touches the body) the player walks out of it, and never deeper; right inside, every way is out\n const radius = clearRadius()\n const free = (x: number, z: number): boolean => (radius === null ? !outside(x, z) : !blocked(x, z, radius))\n // in steps no longer than a third of the body's width, so a long move (a slow frame, the end of a scripted walk) cannot jump over a thin obstacle\n const steps = Math.max(1, Math.ceil(Math.hypot(dx, dz) / (PLAYER_RADIUS / 3)))\n const sx = dx / steps\n const sz = dz / steps\n for (let i = 0; i < steps; i++) {\n if (free(px.x + sx, px.z)) px.x += sx\n if (free(px.x, px.z + sz)) px.z += sz\n }\n }\n\n const walkKeys = (): readonly [number, number] => {\n const f = (keys.has('KeyW') || keys.has('ArrowUp') ? 1 : 0) - (keys.has('KeyS') || keys.has('ArrowDown') ? 1 : 0)\n const r = (keys.has('KeyD') || keys.has('ArrowRight') ? 1 : 0) - (keys.has('KeyA') || keys.has('ArrowLeft') ? 1 : 0)\n if (!f && !r) return [0, 0]\n const len = Math.hypot(f, r)\n return [(-Math.sin(yaw) * f + Math.cos(yaw) * r) / len, (-Math.cos(yaw) * f - Math.sin(yaw) * r) / len]\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 let walkHeld = false\n let seated = false\n let lookLimit: { readonly yaw: number; readonly range: number } | null = null\n const look = (dx: number, dy: number): void => {\n yaw -= dx * LOOK\n if (lookLimit) {\n const off = Math.atan2(Math.sin(yaw - lookLimit.yaw), Math.cos(yaw - lookLimit.yaw))\n yaw = lookLimit.yaw + Math.max(-lookLimit.range, Math.min(lookLimit.range, off))\n }\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) {\n pressCrouch(e.code)\n keys.add(e.code)\n }\n o.hooks.key(e.code, true, e)\n }\n const onKeyUp = (e: KeyboardEvent): void => {\n keys.delete(e.code)\n releaseCrouch(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 => {\n keys.clear()\n crouchPress = null\n }\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 /** One step of a knock: the body flies and slides, stopped by the colliders like a walk, falls, lies and gets up; the keys wait. */\n const stepKnocked = (dt: number): void => {\n const k = knocked\n if (!k) return\n const floor = Math.max(floorHere(), o.footing?.(px.x, px.z, PLAYER_RADIUS * FOOT, y).floor ?? -Infinity)\n floorUnder = floor\n const at = { x: px.x, y, z: px.z }\n const fromY = y\n const fallSpeed = Math.max(0, -k.velocity[1])\n const done = stepKnock(k, at, dt, () => floor, true)\n const wantX = at.x - px.x\n const wantZ = at.z - px.z\n const fromX = px.x\n const fromZ = px.z\n const vx = k.velocity[0]\n const vz = k.velocity[2]\n move(wantX, wantZ)\n // what stopped the body takes the speed that went into it, and the body slams into it\n const stoppedX = Math.abs(wantX) > 1e-6 && Math.abs(px.x - fromX) < Math.abs(wantX) * 0.5\n const stoppedZ = Math.abs(wantZ) > 1e-6 && Math.abs(px.z - fromZ) < Math.abs(wantZ) * 0.5\n if (stoppedX) k.velocity[0] = 0\n if (stoppedZ) k.velocity[2] = 0\n const into = Math.hypot(stoppedX ? vx : 0, stoppedZ ? vz : 0)\n if (into >= SLAM_MIN_SPEED) o.onSlam?.({ against: 'obstacle', speed: into, direction: [stoppedX ? vx / into : 0, 0, stoppedZ ? vz / into : 0] })\n y = at.y\n if (fromY > floor && y <= floor) {\n const speed = Math.max(fallSpeed, (fromY - y) / Math.max(dt, 1e-6))\n if (k.down && speed >= SLAM_MIN_SPEED * 0.5) o.onSlam?.({ against: 'ground', speed: Math.hypot(speed, Math.hypot(vx, vz) * 0.5), direction: [0, -1, 0] })\n else if (speed >= LANDING_MIN_SPEED) o.onFeet?.({ type: 'land', speed })\n }\n vy = 0\n walked = dt > 0 ? Math.hypot(px.x - fromX, px.z - fromZ) / dt : 0\n running = false\n if (done) knocked = null\n followFloor(dt)\n apply()\n }\n\n return {\n get walkIntent() {\n return walkKeys()\n },\n canStand(x, z) {\n return !blocked(x, z)\n },\n setWalkHeld(held) {\n walkHeld = held\n },\n setSeated(value) {\n seated = value\n y = 0\n vy = 0\n },\n setBend(metres) {\n bendTarget = metres\n },\n setLookLimit(limit) {\n lookLimit = limit\n },\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 floorLevel + y\n },\n get position() {\n return [px.x, floorLevel + y, px.z] as Vec3\n },\n get speed() {\n return walked\n },\n get running() {\n return running\n },\n get grounded() {\n return y <= floorUnder + 1e-3 && vy <= 0\n },\n get crouching() {\n return isCrouched()\n },\n keys,\n knock(next) {\n if (seated) return\n if (knocked) {\n knocked.velocity = [knocked.velocity[0] + next.velocity[0], knocked.velocity[1] + next.velocity[1], knocked.velocity[2] + next.velocity[2]]\n knocked.airborne ||= next.airborne\n knocked.down ||= next.down\n knocked.wounded ||= next.wounded\n knocked.lieLeft = Math.max(knocked.lieLeft, next.lieLeft)\n } else knocked = { ...next, velocity: [...next.velocity] }\n stunLeft = Math.max(stunLeft, next.stunSeconds ?? 0)\n if (next.down) {\n // the way away from the blast, even when the push is too weak to move the body (felled by wounds where it stands)\n const away = next.away && (next.away[0] !== 0 || next.away[2] !== 0) ? next.away : next.velocity\n // the view rolls to the side the shove pushes toward, seen from the facing\n const right = Math.cos(yaw) * away[0] - Math.sin(yaw) * away[2]\n rollSide = right >= 0 ? -1 : 1\n // pushed from behind the body pitches onto its face; from the front (the blast seen) onto its back\n knockedForward = -Math.sin(yaw) * away[0] - Math.cos(yaw) * away[2] > 0\n crouchLatched = false\n }\n if (knocked.airborne) vy = Math.max(vy, knocked.velocity[1])\n },\n get knocked() {\n return knocked\n },\n get knockedForward() {\n return knockedForward\n },\n get stunned() {\n return stunLeft\n },\n update(dt) {\n if (stunLeft > 0) {\n stunLeft = Math.max(0, stunLeft - dt)\n stunPhase += dt * 2.4\n }\n if (knocked) {\n stepKnocked(dt)\n return\n }\n if (crouchPress) crouchPress.held += dt\n const crouched = isCrouched()\n crouch += ((crouched ? 1 : 0) - crouch) * Math.min(1, dt * CROUCH_RATE)\n if (!crouched && crouch < 1e-3) crouch = 0\n bend += (bendTarget - bend) * Math.min(1, dt * BEND_RATE)\n const run = !crouched && !walkHeld && (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 const [walkX, walkZ] = walkKeys()\n if ((walkX || walkZ || keys.has('Space')) && eye !== EYE) eye = EYE\n if ((walkX || walkZ) && !walkHeld) move(walkX * speed * dt, walkZ * speed * dt)\n walked = dt > 0 ? Math.hypot(px.x - fromX, px.z - fromZ) / dt : 0\n running = run && walked > 0\n if (seated) {\n followFloor(dt)\n apply()\n return\n }\n // the floor under the feet: a step up is taken at once, a drop is a fall\n const floor = Math.max(floorHere(), o.footing?.(px.x, px.z, PLAYER_RADIUS * FOOT, y).floor ?? -Infinity)\n floorUnder = floor\n if (y < floor && vy <= 0) y = floor\n if (y <= floor && keys.has('Space') && !walkHeld) {\n vy = JUMP\n o.onFeet?.({ type: 'jump' })\n }\n if (y > floor || vy > 0) {\n vy -= GRAVITY * dt\n y += vy * dt\n if (y <= floor) {\n y = floor\n if (-vy >= LANDING_MIN_SPEED) o.onFeet?.({ type: 'land', speed: -vy })\n vy = 0\n }\n }\n followFloor(dt)\n apply()\n },\n setPose(position, yw, pt) {\n knocked = null\n px.x = position[0]\n px.z = position[2]\n floorLevel = floorHere()\n eye = position[1] - floorLevel\n y = 0\n vy = 0\n yaw = yw\n pitch = pt\n apply()\n },\n look(position, target) {\n knocked = null\n px.x = position[0]\n px.z = position[2]\n floorLevel = floorHere()\n eye = position[1] - floorLevel\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 takeWish() {\n const out: [number, number] = [wish.x, wish.z]\n wish.x = 0\n wish.z = 0\n return out\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 room's side of pushing furniture: finds what the player leans on, asks `createFurniturePush` (game-player) how it goes, tests the volume of the piece before each\n * step (the world, the walls of the arena, the blockers of the modules) and moves it with the player. The animations read `avatarState` and `handTargets`.\n */\nimport type * as THREE_NS from 'three'\nimport type { DestructionWorld, Vec3 } from '@adatechnology/game-destruction'\nimport type { Piece } from '@adatechnology/game-destruction-three'\nimport type { HandTargets } from '@adatechnology/game-contracts'\nimport { createFurniturePush } from '@adatechnology/game-player'\nimport type { FurniturePushBlock, FurniturePushPhase, FurniturePushRules } from '@adatechnology/game-player'\nimport type { Player } from './player'\n\n/** How close to the piece the player must be to lean on it, metres from the feet to its box. */\nexport const PUSH_REACH = 1.1\n/** Where the player ends up from the face, for the arms to be straight but not stretched. */\nconst STANDOFF = 0.58\n/** Lower than this the hands go on top of the piece and the player bends over it, closer. */\nconst LOW_TOP = 0.95\nconst LOW_STANDOFF = 0.42\nconst LOW_HAND_ON_TOP = 0.07\n/** How far above the top of a low piece the eye stays, and the most the player bends. */\nconst LOW_EYE_OVER_TOP = 0.62\nconst MAX_BEND = 0.8\nconst STANDING_EYE = 1.7\nconst APPROACH_SPEED = 1.2\n/** A piece whose base is higher than this is on something, not on the floor. */\nconst MAX_BASE_HEIGHT = 0.12\nconst FLOOR_CLEARANCE = 0.06\nconst SWEEP_SKIN = 0.015\n/** Hands: half the gap between them, the highest they go, how far under the top of the piece. */\nconst HAND_SPREAD = 0.2\nconst HAND_TOP = 1.35\nconst HAND_UNDER_TOP = 0.05\nconst LOOK_RANGE = 0.9\nconst DRAG_GRAIN_METRES = 0.3\nconst RING_DELAY_S = 0.1\n\nexport type RoomPushTarget = {\n readonly objectId: string\n readonly root: THREE_NS.Object3D\n readonly name: string\n /** The body it already has, or null when it stands free and only becomes one when it moves. */\n readonly piece: Piece | null\n}\n\nexport type RoomPushOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n readonly world: DestructionWorld\n readonly arena: { readonly limit: number; readonly colliders: ReadonlyArray<readonly [number, number, number, number]> }\n readonly blockers: ReadonlySet<(x: number, z: number, radius: number) => boolean>\n readonly rules?: Partial<FurniturePushRules>\n /** What the eye rests on and could be pushed, or null. */\n pick(): RoomPushTarget | null\n massOf(objectId: string): number\n materialOf(objectId: string): string | undefined\n /** Turns a free-standing object into a body (the first step it takes). */\n makePiece(objectId: string): Piece\n dragSound(objectId: string, point: Vec3, volume: number): void\n hitSound(objectId: string, point: Vec3): void\n onEvent(event: RoomPushEvent): void\n ring(value: number | null): void\n /** The room draws a body whose pose bends over a low piece: the player's own eye is not lowered (without a body the eye is the camera and bends). */\n hasBody?(): boolean\n}\n\nexport type RoomPushEvent =\n | { readonly type: 'grip' | 'release'; readonly objectId: string; readonly name: string; readonly massKg: number }\n | { readonly type: 'engaged' | 'too_heavy' | 'obstacle'; readonly objectId: string; readonly name: string; readonly massKg: number }\n\nexport type RoomPushState = {\n readonly objectId: string\n readonly phase: FurniturePushPhase\n readonly progress: number\n readonly block: FurniturePushBlock\n readonly massKg: number\n}\n\nexport interface RoomPush {\n readonly active: boolean\n readonly state: RoomPushState | null\n /** What the body does this frame, for the avatar. */\n /** The piece is low: the body bends over it. */\n readonly isBent: boolean\n readonly avatarState: { readonly phase: Exclude<FurniturePushPhase, 'idle'>; readonly progress: number } | null\n /** Starts leaning on what the eye rests on; false when there is nothing to lean on. */\n begin(): boolean\n /** Lets go. Answers true when the press was short enough to be a tap (the room then grabs). */\n end(): boolean\n /** Scripted walk (scenarios), world `[x, z]`; null gives the walk back to the keys. */\n setWalk(walk: readonly [number, number] | null): void\n step(dt: number): void\n handTargets(): HandTargets | null\n}\n\ntype Leaning = {\n readonly target: RoomPushTarget\n readonly massKg: number\n piece: Piece | null\n readonly min: [number, number, number]\n readonly max: [number, number, number]\n /** The point of the near face the hands go to, and the way into the face (unit, on the floor). */\n readonly contact: [number, number]\n readonly into: [number, number]\n readonly isLow: boolean\n readonly palm: [number, number, number, number]\n}\n\n/** The closest point of a box (on the floor plane) to a point; the way in when the point is inside the box is the way the player faces. */\nfunction contactOf(box: { min: readonly number[]; max: readonly number[] }, player: Player): { contact: [number, number]; into: [number, number]; distance: number } {\n const x = Math.max(box.min[0] ?? 0, Math.min(box.max[0] ?? 0, player.x))\n const z = Math.max(box.min[2] ?? 0, Math.min(box.max[2] ?? 0, player.z))\n const dx = x - player.x\n const dz = z - player.z\n const distance = Math.hypot(dx, dz)\n if (distance < 1e-3) return { contact: [x, z], into: [-Math.sin(player.yaw), -Math.cos(player.yaw)], distance: 0 }\n return { contact: [x, z], into: [dx / distance, dz / distance], distance }\n}\n\nexport function createRoomPush(options: RoomPushOptions): RoomPush {\n const { THREE, player, world, arena, blockers } = options\n const control = createFurniturePush(options.rules)\n const box3 = new THREE.Box3()\n let leaning: Leaning | null = null\n let scriptedWalk: readonly [number, number] | null = null\n let dragged = 0\n\n const event = (type: RoomPushEvent['type'], lean: Leaning): void => options.onEvent({ type, objectId: lean.target.objectId, name: lean.target.name, massKg: lean.massKg })\n\n const standsClear = (lean: Leaning, dx: number, dz: number): boolean => {\n const minX = lean.min[0] + dx\n const maxX = lean.max[0] + dx\n const minZ = lean.min[2] + dz\n const maxZ = lean.max[2] + dz\n if (Math.max(Math.abs(minX), Math.abs(maxX)) > arena.limit || Math.max(Math.abs(minZ), Math.abs(maxZ)) > arena.limit) return false\n for (const c of arena.colliders) {\n // what the piece already stands in does not hold it: it can always back out\n if (lean.max[0] > c[0] && lean.min[0] < c[2] && lean.max[2] > c[1] && lean.min[2] < c[3]) continue\n if (maxX > c[0] && minX < c[2] && maxZ > c[1] && minZ < c[3]) return false\n }\n if (blockers.size === 0) return true\n const midX = (minX + maxX) / 2\n const midZ = (minZ + maxZ) / 2\n for (const [x, z] of [[minX, minZ], [maxX, minZ], [minX, maxZ], [maxX, maxZ], [midX, minZ], [midX, maxZ], [minX, midZ], [maxX, midZ]] as const) {\n for (const isBlocked of blockers) if (isBlocked(x, z, 0)) return false\n }\n return true\n }\n\n const isFree = (lean: Leaning, dx: number, dz: number): boolean => {\n if (!standsClear(lean, dx, dz) || !player.canStand(player.x + dx, player.z + dz)) return false\n const distance = Math.hypot(dx, dz)\n const box = { min: [lean.min[0], lean.min[1] + FLOOR_CLEARANCE, lean.min[2]] as Vec3, max: [lean.max[0], lean.max[1], lean.max[2]] as Vec3 }\n return world.sweepBox(box, [dx / distance, 0, dz / distance], distance + SWEEP_SKIN, { ignore: lean.target.objectId }) === null\n }\n\n const release = (): void => {\n const lean = leaning\n if (!lean) return\n leaning = null\n if (lean.piece) {\n lean.piece.held = false\n lean.piece.sleeping = false\n lean.piece.velocity = [0, 0, 0]\n }\n control.release()\n player.setWalkHeld(false)\n if (!options.hasBody?.()) player.setBend(0)\n player.setLookLimit(null)\n options.ring(null)\n event('release', lean)\n }\n\n const approach = (lean: Leaning, dt: number): void => {\n const off = Math.hypot(lean.contact[0] - player.x, lean.contact[1] - player.z) - (lean.isLow ? LOW_STANDOFF : STANDOFF)\n const move = Math.sign(off) * Math.min(Math.abs(off), APPROACH_SPEED * dt)\n if (move !== 0) player.moveBy(lean.into[0] * move, lean.into[1] * move)\n }\n\n const moveWith = (lean: Leaning, dx: number, dz: number): void => {\n lean.target.root.position.x += dx\n lean.target.root.position.z += dz\n lean.target.root.updateMatrixWorld(true)\n player.moveBy(dx, dz)\n lean.min[0] += dx\n lean.max[0] += dx\n lean.min[2] += dz\n lean.max[2] += dz\n lean.contact[0] += dx\n lean.contact[1] += dz\n dragged += Math.hypot(dx, dz)\n if (dragged < DRAG_GRAIN_METRES) return\n dragged = 0\n options.dragSound(lean.target.objectId, [lean.contact[0], lean.min[1], lean.contact[1]], 0.3 + 0.5 * Math.min(1, lean.massKg / 100))\n }\n\n return {\n get active() {\n return leaning !== null\n },\n get state() {\n return leaning ? { objectId: leaning.target.objectId, phase: control.phase, progress: control.progress, block: control.block, massKg: leaning.massKg } : null\n },\n get isBent() {\n return leaning?.isLow ?? false\n },\n get avatarState() {\n return leaning && control.phase !== 'idle' ? { phase: control.phase, progress: control.progress } : null\n },\n begin() {\n if (leaning) return true\n const target = options.pick()\n if (!target || !world.has(target.objectId)) return false\n box3.setFromObject(target.root)\n if (box3.min.y > player.feet + MAX_BASE_HEIGHT) return false\n const min: [number, number, number] = [box3.min.x, box3.min.y, box3.min.z]\n const max: [number, number, number] = [box3.max.x, box3.max.y, box3.max.z]\n const { contact, into, distance } = contactOf({ min, max }, player)\n if (distance > PUSH_REACH) return false\n const massKg = options.massOf(target.objectId)\n const material = options.materialOf(target.objectId)\n const isLow = max[1] - player.feet < LOW_TOP\n // the palms lie flat on the face that takes the push (HandPose of game-contracts): on a tall piece fingers up and backs to the player, on a low one fingers ahead and backs up\n const side = new THREE.Vector3(-into[1], 0, into[0])\n const way = new THREE.Vector3(into[0], 0, into[1])\n const up = new THREE.Vector3(0, 1, 0)\n const basis = isLow ? new THREE.Matrix4().makeBasis(way, up, side) : new THREE.Matrix4().makeBasis(up, way.clone().negate(), side)\n const palm = new THREE.Quaternion().setFromRotationMatrix(basis)\n leaning = { target, massKg, piece: target.piece, min, max, contact, into, isLow, palm: [palm.x, palm.y, palm.z, palm.w] }\n if (target.piece) target.piece.held = true\n control.begin(material === undefined ? { massKg } : { massKg, material })\n dragged = 0\n player.setWalkHeld(true)\n if (isLow && !options.hasBody?.()) player.setBend(Math.min(MAX_BEND, Math.max(0, STANDING_EYE - (max[1] - player.feet + LOW_EYE_OVER_TOP))))\n player.setLookLimit({ yaw: Math.atan2(-into[0], -into[1]), range: LOOK_RANGE })\n event('grip', leaning)\n return true\n },\n end() {\n if (!leaning) return false\n const tap = control.isTap\n release()\n return tap\n },\n setWalk(walk) {\n scriptedWalk = walk\n },\n step(dt) {\n const lean = leaning\n if (!lean) return\n if (!world.has(lean.target.objectId)) {\n release()\n return\n }\n const gripping = control.phase === 'grip'\n if (gripping) approach(lean, dt)\n const result = control.update(dt, { walk: scriptedWalk ?? player.walkIntent, isFree: (dx, dz) => isFree(lean, dx, dz) })\n if (result.engaged) {\n // a body from here on: held, the room's collision of the player and of this sweep no longer sees it as something in the way\n if (control.block !== 'too_heavy') {\n lean.piece ??= options.makePiece(lean.target.objectId)\n lean.piece.held = true\n }\n event(control.block === 'too_heavy' ? 'too_heavy' : 'engaged', lean)\n }\n if (result.hitObstacle) {\n options.hitSound(lean.target.objectId, [lean.contact[0], lean.min[1] + 0.3, lean.contact[1]])\n event('obstacle', lean)\n }\n if (result.dx !== 0 || result.dz !== 0) moveWith(lean, result.dx, result.dz)\n options.ring(control.phase === 'grip' && control.heldSeconds >= RING_DELAY_S ? control.progress : null)\n },\n handTargets() {\n const lean = leaning\n if (!lean) return null\n const strain = control.phase === 'strain'\n const y = lean.isLow ? lean.max[1] + 0.01 : Math.min(HAND_TOP, lean.max[1] - HAND_UNDER_TOP)\n // the arms give a little under the effort, and shake\n const shake = strain ? Math.sin(performance.now() * 0.045) * 0.006 : 0\n const inset = lean.isLow ? -LOW_HAND_ON_TOP + shake : (strain ? 0.05 : 0.02) + shake\n const px = lean.contact[0] - lean.into[0] * inset\n const pz = lean.contact[1] - lean.into[1] * inset\n const sideX = -lean.into[1] * HAND_SPREAD\n const sideZ = lean.into[0] * HAND_SPREAD\n const grip = 0.05 + 0.2 * control.progress\n return {\n R: { position: [px + sideX, y, pz + sideZ], quaternion: lean.palm },\n L: { position: [px - sideX, y, pz - sideZ], quaternion: lean.palm },\n grip,\n gripL: grip,\n }\n },\n }\n}\n","/**\n * The room's seats: puts the player on a seat an item brings (`TestRoomItem.seats`, the shape of a `game-interactables` seat) and back on its feet at the seat's exit.\n * Seated, the keys do not walk and the view stays within reach of the seat's facing; a walk key or a jump gets up, and so does losing the seat (the item is gone).\n */\nimport type * as THREE_NS from 'three'\nimport type { ItemSeat, Vec3 } from '@adatechnology/game-contracts'\nimport type { Player } from './player'\n\nconst SIT_EYE = 0.62\nconst LIE_EYE = 0.18\nconst STANDING_EYE = 1.7\n/** How far (radians) the view turns away from the seat's facing, either side. */\nconst LOOK_RANGE = 1.6\n\n/** Something the player can sit on: where its object is drawn now and the seats it brings. */\nexport type SeatHolder = {\n readonly objectId: string\n readonly root: THREE_NS.Object3D\n readonly seats: readonly ItemSeat[]\n}\n\n/** The seat the player is on. */\nexport type RoomSeat = {\n readonly objectId: string\n readonly seatId: string\n readonly pose: ItemSeat['pose']\n /** Where the hips (sit) or the pelvis (lie) are, in the world. */\n readonly hips: Vec3\n}\n\nexport type SeatingOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n /** The aimed thing that has seats, or null. */\n pick(): SeatHolder | null\n /** The thing with that object id, or null when it is gone. */\n find(objectId: string): SeatHolder | null\n /** Height of the ground at a point, where the player stands when getting up. */\n groundAt(x: number, z: number): number\n onSit?(seat: RoomSeat): void\n onStand?(seat: RoomSeat): void\n /** The room draws a body that sits by its pose: the player's own eye does not drop to the seat (without a body the eye is the camera). */\n hasBody?(): boolean\n}\n\nexport type Seating = {\n /** Sits on `objectId` (default: the aimed thing), on `seatId` (default: the seat nearest the player). Null when there is no seat there. */\n sit(objectId?: string, seatId?: string): RoomSeat | null\n /** Gets up at the seat's exit; false when not seated or the exit is blocked. */\n stand(): boolean\n /** Once a frame, before the player moves: a walk key or a jump gets up. */\n update(): void\n /** Lets go of the seat without moving the player (the room is reset). */\n release(): void\n readonly seat: RoomSeat | null\n}\n\nexport function createSeating(o: SeatingOptions): Seating {\n const { THREE, player } = o\n const v = new THREE.Vector3()\n const q = new THREE.Quaternion()\n const e = new THREE.Euler()\n let current: RoomSeat | null = null\n let facing = 0\n\n const toWorld = (root: THREE_NS.Object3D, local: Vec3): Vec3 => {\n root.updateWorldMatrix(true, false)\n v.set(local[0], local[1], local[2]).applyMatrix4(root.matrixWorld)\n return [v.x, v.y, v.z]\n }\n const yawOf = (root: THREE_NS.Object3D): number => {\n root.getWorldQuaternion(q)\n return e.setFromQuaternion(q, 'YXZ').y\n }\n const nearest = (holder: SeatHolder): ItemSeat | undefined => {\n let best: ItemSeat | undefined\n let bestDistance = Infinity\n for (const seat of holder.seats) {\n const [x, , z] = toWorld(holder.root, seat.pos)\n const distance = Math.hypot(x - player.x, z - player.z)\n if (distance < bestDistance) {\n best = seat\n bestDistance = distance\n }\n }\n return best\n }\n const hold = (): void => {\n player.setSeated(true)\n player.setWalkHeld(true)\n player.setLookLimit({ yaw: facing, range: LOOK_RANGE })\n }\n const release = (): void => {\n player.setSeated(false)\n player.setWalkHeld(false)\n player.setLookLimit(null)\n current = null\n }\n\n const seating: Seating = {\n sit(objectId, seatId) {\n const holder = objectId ? o.find(objectId) : o.pick()\n if (!holder) return null\n const seat = seatId ? holder.seats.find((s) => s.id === seatId) : nearest(holder)\n if (!seat) return null\n const [x, y, z] = toWorld(holder.root, seat.pos)\n const eye = o.hasBody?.() ? STANDING_EYE : (seat.eye ?? (seat.pose === 'lie' ? LIE_EYE : SIT_EYE))\n // a seat faces the front of its item (+z); the player looks down -z at yaw 0\n facing = yawOf(holder.root) + seat.ry + Math.PI\n player.setPose([x, y + eye, z], facing, 0)\n current = { objectId: holder.objectId, seatId: seat.id, pose: seat.pose, hips: [x, y, z] }\n hold()\n o.onSit?.(current)\n return current\n },\n stand() {\n if (!current) return false\n const holder = o.find(current.objectId)\n const seat = holder?.seats.find((s) => s.id === current?.seatId)\n if (holder && seat) {\n const [x, , z] = toWorld(holder.root, seat.exit)\n if (!player.canStand(x, z)) return false\n player.setPose([x, o.groundAt(x, z) + STANDING_EYE, z], player.yaw, 0)\n } else player.setPose([player.x, o.groundAt(player.x, player.z) + STANDING_EYE, player.z], player.yaw, 0)\n const left = current\n release()\n o.onStand?.(left)\n return true\n },\n update() {\n if (!current) return\n if (!o.find(current.objectId)) {\n seating.stand()\n return\n }\n const [walkX, walkZ] = player.walkIntent\n if (walkX || walkZ || player.keys.has('Space')) {\n seating.stand()\n return\n }\n // pushing or carrying lets the walk go when it ends: the seat holds it again\n hold()\n },\n release,\n get seat() {\n return current\n },\n }\n return seating\n}\n","/**\n * The room's side of opening and closing by hand: finds the leaf the eye rests on (a door, a lid, a drawer of furniture or of a vehicle: a part an `open_*` clip of the item moves),\n * asks `createDoorUse` (game-player) how far it goes, tests the sweep of the leaf against what is around before each step and puts the hand on the handle.\n * The leaf is posed along its item's own open clip, so the same opening the item's animation shows is the one the hand drives.\n */\nimport type * as THREE_NS from 'three'\nimport type { DestructionWorld, Vec3 } from '@adatechnology/game-destruction'\nimport type { AnimationClipSpec, HandTargets, HostReach } from '@adatechnology/game-contracts'\nimport { createDoorUse, DOOR_USE_DEFAULTS } from '@adatechnology/game-player'\nimport type { DoorUsePhase, DoorUseRules } from '@adatechnology/game-player'\nimport type { LeafFoley } from '@adatechnology/game-audio'\nimport { PLAYER_RADIUS } from './player'\nimport type { Player } from './player'\n\n/** How far the hand reaches a handle, metres from the eye. */\nexport const DOOR_REACH = 2.2\n/** A hit this close to a leaf (the handle, the glass of the door) counts as on the leaf. */\nconst NEAR_LEAF = 0.25\n/** Looking into an open fridge or wardrobe, the open leaf this close to the point is the one E closes. */\nconst NEAR_OPEN_LEAF = 0.9\nconst BODY_HEIGHT = 1.8\n/** The hand at rest in front of the chest, in the eye's space (x right, y up, -z ahead). */\nconst HAND_REST: Vec3 = [0.22, -0.42, -0.32]\nconst SKIN = 0.01\n/** How far in from the free edge of a leaf its handle is, metres. */\nconst HANDLE_INSET = 0.06\n/** Where the feet stop in front of a handle (a drawer, a leaf with no hinge known) for the hand to hold it with a bent arm, metres on the floor, and how fast the player steps up. */\nconst STANDOFF = 0.55\n/** A drawer comes out about this far toward the player. */\nconst DRAWER_TRAVEL = 0.3\n/** Standing by a turning leaf: this far past the arc of its free edge, and this far out in front of its face. */\nconst CLEAR_OF_ARC = 0.3\nconst OUT_IN_FRONT = 0.42\n/** Close enough to the place, metres; the longest walk to it before the hand goes anyway, seconds. */\nconst ARRIVED = 0.05\n/** How fast the head turns to the handle (share per second). */\nconst TURN_RATE = 8\nconst MAX_WALK_SECONDS = 1.5\nconst APPROACH_SPEED = 3\n/** How far over the floor a leaf swings (the gap under a door). */\nconst FLOOR_GAP = 0.03\n\n/** A leaf an item can open: the part, and the clip that opens it (the pose at the end of the clip is the leaf open). */\nexport type RoomLeaf = { readonly part: string; readonly clip: AnimationClipSpec }\n\nexport type RoomDoorOptions = {\n readonly THREE: typeof THREE_NS\n readonly player: Player\n readonly world: DestructionWorld\n readonly camera: THREE_NS.Object3D\n readonly arena: { readonly limit: number; readonly colliders: ReadonlyArray<readonly [number, number, number, number]>; readonly ids: ReadonlyArray<string | null> }\n readonly rules?: Partial<DoorUseRules>\n /** What the eye rests on within reach, best first (the crosshair, then what the eye faces over the shoulder). */\n pick(): ReadonlyArray<{ readonly objectId: string; readonly part: string; readonly point: Vec3 }>\n /** The leaves of an object (none when it has nothing to open). */\n leaves(objectId: string): readonly RoomLeaf[]\n /** The drawn part of a leaf. */\n objectOf(objectId: string, part: string): THREE_NS.Object3D | null\n /** Poses the leaf at `fraction` of its clip (0 closed, 1 open), drawing and collision both. */\n pose(objectId: string, part: string, clip: AnimationClipSpec, fraction: number): void\n isLocked(objectId: string, part: string): boolean\n nameOf(objectId: string): string\n /** The sound class of what the leaf is made of (`impact_wood`, `impact_metal`...). */\n impactKey(objectId: string, part: string): string\n /**\n * The leaf's own sound key for a moment, when it has one (a car door is a padded thump with a latch, not the hollow metal of a fridge): `open` as\n * the leaf leaves the frame, `shut` as it meets it. Left out or `undefined`, the latch, the hinge and the shut of the leaf's material play.\n */\n leafSound?(objectId: string, part: string, moment: 'open' | 'shut'): string | undefined\n sound(key: string, point: Vec3, volume: number): void\n /**\n * The sound set of a leaf (a car door, a fridge, a wooden door: `LEAF_FOLEY_SETS` of game-audio), from its item or its material; `null` keeps the\n * material keys of the destruction renderer (`leaf_latch`, `leaf_creak_*`, `leaf_shut_*`).\n */\n leafFoley?(objectId: string, part: string, slides: boolean): LeafFoley | null\n onEvent(event: RoomDoorEvent): void\n}\n\n/** At or above this volume (a heavy leaf, see `shutVolume`) a leaf with a `slam` sound slams instead of closing gently. */\nexport const LEAF_SLAM_VOLUME = 0.85\n/** The volume a leaf meets its frame with: heavier leaves are louder. */\nexport const shutVolume = (massKg: number): number => Math.min(1, 0.3 + massKg * 0.03)\n\nexport type RoomDoorEventType = 'reach' | 'opened' | 'closed' | 'blocked' | 'locked' | 'stepped_back'\n\nexport type RoomDoorEvent = {\n readonly type: RoomDoorEventType\n readonly objectId: string\n readonly part: string\n readonly name: string\n /** How open the leaf is, 0 to 1. */\n readonly opening: number\n /** What stopped it (`blocked`): another object, the wall of the room, the player. */\n readonly by?: string\n}\n\nexport type RoomDoorState = { readonly objectId: string; readonly part: string; readonly phase: DoorUsePhase; readonly opening: number; readonly goal: 0 | 1 }\n\nexport interface RoomDoors {\n readonly active: boolean\n readonly state: RoomDoorState | null\n /** What the body does this frame, for the avatar: the hand height (metres over the feet) and the phase. */\n readonly avatarState: { readonly phase: Exclude<DoorUsePhase, 'idle'>; readonly progress: number; readonly height: number; readonly pull: boolean } | null\n /** Whether the eye rests on a leaf in reach (the prompt). */\n aimed(): { readonly objectId: string; readonly part: string; readonly open: boolean; readonly locked: boolean } | null\n /** Uses the leaf the eye rests on; false when there is none. */\n use(): boolean\n /** Opens or closes a leaf by its ids, as if the hand did it (scenarios). Answers false when the object has no such leaf. */\n useLeaf(objectId: string, part?: string): boolean\n /** How open a leaf is, 0 to 1. */\n opening(objectId: string, part: string): number\n step(dt: number): void\n handTargets(): HandTargets | null\n /** Puts the hand on a leaf a module moves itself (`ModuleHost.reachFor`): reach, grip (`onGrip`), hold it while it moves, let go. */\n reachFor(reach: HostReach): void\n /** Forgets an object (it was removed). */\n forget(objectId: string): void\n}\n\ntype Using = {\n readonly objectId: string\n readonly leaf: RoomLeaf\n readonly obj: THREE_NS.Object3D\n /** Where the hand holds the leaf, in the leaf's own space. */\n readonly grip: THREE_NS.Vector3\n readonly pull: boolean\n phase: DoorUsePhase\n progress: number\n /** Seconds walked to the handle, and whether the player got there. */\n walked: number\n there: boolean\n}\n\nconst key = (objectId: string, part: string): string => `${objectId}\\0${part}`\n\n/** Whether a clip slides its part (a drawer) rather than turning it. */\nconst slides = (clip: AnimationClipSpec, part: string): boolean => {\n const last = clip.keys[clip.keys.length - 1]?.parts?.[part]\n const r = last?.rotation ?? [0, 0, 0]\n return Math.abs(r[0]) + Math.abs(r[1]) + Math.abs(r[2]) < 1e-3\n}\n\nexport function createRoomDoors(options: RoomDoorOptions): RoomDoors {\n const { THREE, player, world, camera, arena } = options\n const control = createDoorUse(options.rules)\n const openings = new Map<string, number>()\n const box = new THREE.Box3()\n const before = new THREE.Box3()\n const tmp = new THREE.Vector3()\n const centre = new THREE.Vector3()\n let using: Using | null = null\n /** A module's own leaf under the hand (a house door). */\n let reaching: { readonly reach: HostReach; phase: Exclude<DoorUsePhase, 'idle'>; time: number; progress: number; walked: number; there: boolean } | null = null\n const rules = { ...DOOR_USE_DEFAULTS, ...options.rules }\n\n /** Where the hand is going or holding now, and how: the leaf in use or the module's leaf. */\n const holding = (): { phase: Exclude<DoorUsePhase, 'idle'>; progress: number; at: THREE_NS.Vector3; pull: boolean } | null => {\n if (reaching) {\n const h = reaching.reach.handle()\n return { phase: reaching.phase, progress: reaching.progress, at: new THREE.Vector3(h[0], h[1], h[2]), pull: reaching.reach.pull ?? true }\n }\n if (!using || control.phase === 'idle') return null\n using.obj.updateMatrixWorld(true)\n return { phase: control.phase, progress: using.progress, at: using.obj.localToWorld(new THREE.Vector3().copy(using.grip)), pull: using.pull }\n }\n /**\n * Where the player takes the handle from. A turning leaf: beside its free edge, past the arc it sweeps and a little out in front, on the side the player is on, so the leaf\n * swings by and not into the body (a person opens a fridge standing by the handle side). A drawer or a leaf with no hinge known: straight in front of the handle.\n */\n const standFor = (handle: THREE_NS.Vector3, hinge: THREE_NS.Vector3 | null, slide: boolean): [number, number] => {\n if (!hinge || slide) {\n const dx = handle.x - player.x\n const dz = handle.z - player.z\n const d = Math.hypot(dx, dz) || 1\n const off = slide ? STANDOFF + DRAWER_TRAVEL : STANDOFF\n return [handle.x - (dx / d) * off, handle.z - (dz / d) * off]\n }\n let ax = handle.x - hinge.x\n let az = handle.z - hinge.z\n const width = Math.hypot(ax, az)\n if (width < 0.05) return standFor(handle, null, false)\n ax /= width\n az /= width\n // out of the face, toward the player\n let nx = -az\n let nz = ax\n if ((player.x - handle.x) * nx + (player.z - handle.z) * nz < 0) {\n nx = -nx\n nz = -nz\n }\n const x = hinge.x + ax * (width + CLEAR_OF_ARC) + nx * OUT_IN_FRONT\n const z = hinge.z + az * (width + CLEAR_OF_ARC) + nz * OUT_IN_FRONT\n // something stands there (the next cabinet, a nightstand): in front of the handle, and the leaf will make the player step back\n return player.canStand(x, z) ? [x, z] : standFor(handle, null, false)\n }\n /** The head turns to the handle as the player goes for it. */\n const face = (handle: THREE_NS.Vector3, dt: number): void => {\n camera.updateMatrixWorld(true)\n const eye = camera.getWorldPosition(new THREE.Vector3())\n const dx = handle.x - player.x\n const dz = handle.z - player.z\n const flat = Math.hypot(dx, dz)\n if (flat < 0.05) return\n const yaw = Math.atan2(-dx, -dz)\n const pitch = Math.atan2(handle.y - eye.y, flat)\n let dYaw = yaw - player.yaw\n dYaw = Math.atan2(Math.sin(dYaw), Math.cos(dYaw))\n const k = Math.min(1, dt * TURN_RATE)\n player.setPose([player.x, eye.y, player.z], player.yaw + dYaw * k, player.pitch + (pitch - player.pitch) * k)\n }\n /** The player steps toward where the handle is taken from. Answers true once there, or when nothing more can be gained (in the way, or walking too long). */\n const approach = (handle: THREE_NS.Vector3, hinge: THREE_NS.Vector3 | null, slide: boolean, dt: number, walked: number): boolean => {\n const [x, z] = standFor(handle, hinge, slide)\n const dx = x - player.x\n const dz = z - player.z\n const d = Math.hypot(dx, dz)\n if (d < ARRIVED || walked > MAX_WALK_SECONDS) return true\n const go = Math.min(d, APPROACH_SPEED * dt)\n if (go < 1e-4) return false\n const x0 = player.x\n const z0 = player.z\n player.moveBy((dx / d) * go, (dz / d) * go)\n return Math.hypot(player.x - x0, player.z - z0) < go * 0.2\n }\n\n const openingOf = (objectId: string, part: string): number => openings.get(key(objectId, part)) ?? 0\n\n /** Where the last use sent each leaf (`objectId|part`), for the next use to turn it round. */\n const lastGoals = new Map<string, 0 | 1>()\n\n const leafAt = (objectId: string, part: string, point: Vec3): RoomLeaf | null => {\n const leaves = options.leaves(objectId)\n if (leaves.length === 0) return null\n const exact = leaves.find((l) => l.part === part)\n if (exact) return exact\n // the ray found the handle, a pane or the frame next to the leaf: the closest leaf to the point, if it is close enough;\n // looking into what an open leaf opened (the shelves of an open fridge), the closest open leaf\n let best: RoomLeaf | null = null\n let bestD = NEAR_LEAF\n let open: RoomLeaf | null = null\n let openD = NEAR_OPEN_LEAF\n for (const l of leaves) {\n const obj = options.objectOf(objectId, l.part)\n if (!obj) continue\n box.setFromObject(obj)\n const d = box.distanceToPoint(tmp.set(point[0], point[1], point[2]))\n if (d < bestD) {\n bestD = d\n best = l\n }\n if (openingOf(objectId, l.part) > 0.5 && d < openD) {\n openD = d\n open = l\n }\n }\n return best ?? open\n }\n\n /** The first thing the eye rests on that has a leaf there. */\n const picked = (): { hit: { objectId: string; part: string; point: Vec3 }; leaf: RoomLeaf } | null => {\n for (const hit of options.pick()) {\n const leaf = leafAt(hit.objectId, hit.part, hit.point)\n if (leaf) return { hit, leaf }\n }\n return null\n }\n\n const massOf = (objectId: string, part: string): number => world.part(objectId, part)?.mass ?? 10\n\n const event = (type: RoomDoorEventType, u: Using, by?: string): void =>\n options.onEvent({ type, objectId: u.objectId, part: u.leaf.part, name: options.nameOf(u.objectId), opening: openingOf(u.objectId, u.leaf.part), ...(by ? { by } : {}) })\n\n const overlaps2d = (b: THREE_NS.Box3, c: readonly [number, number, number, number]): boolean => b.max.x > c[0] && b.min.x < c[2] && b.max.z > c[1] && b.min.z < c[3]\n\n /** The player's body against the leaf at `b`: the overlap on the floor, or null. */\n const bodyOverlap = (b: THREE_NS.Box3): [number, number] | null => {\n if (b.min.y > player.feet + BODY_HEIGHT || b.max.y < player.feet + 0.05) return null\n const cx = Math.max(b.min.x, Math.min(b.max.x, player.x))\n const cz = Math.max(b.min.z, Math.min(b.max.z, player.z))\n const dx = player.x - cx\n const dz = player.z - cz\n const d = Math.hypot(dx, dz)\n if (d >= PLAYER_RADIUS) return null\n if (d < 1e-4) {\n // the centre is inside the leaf's box: out the shortest way\n const outs: Array<[number, number, number]> = [\n [b.max.x - player.x, 1, 0],\n [player.x - b.min.x, -1, 0],\n [b.max.z - player.z, 0, 1],\n [player.z - b.min.z, 0, -1],\n ]\n outs.sort((a, c) => a[0] - c[0])\n const o = outs[0]!\n return [o[1] * (o[0] + PLAYER_RADIUS), o[2] * (o[0] + PLAYER_RADIUS)]\n }\n const push = PLAYER_RADIUS - d + SKIN\n return [(dx / d) * push, (dz / d) * push]\n }\n\n /** Can the leaf go from one opening to the other: poses it there and looks at what it would go through. Leaves it where it can be. */\n const isFree = (u: Using, from: number, to: number): boolean => {\n const { objectId, leaf, obj } = u\n obj.updateMatrixWorld(true)\n before.setFromObject(obj)\n options.pose(objectId, leaf.part, leaf.clip, to)\n obj.updateMatrixWorld(true)\n box.setFromObject(obj)\n box.expandByScalar(-SKIN)\n let by: string | null = null\n // the walls and the furniture of the room that stand on the floor (not the object's own footprint)\n if (Math.max(Math.abs(box.min.x), Math.abs(box.max.x), Math.abs(box.min.z), Math.abs(box.max.z)) > arena.limit) by = 'wall'\n else\n for (let i = 0; i < arena.colliders.length; i++) {\n const c = arena.colliders[i]!\n if (arena.ids[i] === objectId) continue\n if (overlaps2d(box, c) && !overlaps2d(before, c)) {\n by = arena.ids[i] ?? 'wall'\n break\n }\n }\n // anything of the destruction world between the two poses\n if (!by) {\n before.getCenter(centre)\n box.getCenter(tmp)\n const dir: Vec3 = [tmp.x - centre.x, tmp.y - centre.y, tmp.z - centre.z]\n const len = Math.hypot(dir[0], dir[1], dir[2])\n // the far edge of a turning leaf moves about twice as far as its middle\n if (len > 1e-5) {\n // a leaf clears the floor it stands over (and what it rests on): only what stands up in its way stops it\n const hit = world.sweepBox({ min: [before.min.x + SKIN, before.min.y + FLOOR_GAP, before.min.z + SKIN], max: [before.max.x - SKIN, before.max.y - SKIN, before.max.z - SKIN] }, dir, len * 2, { ignore: objectId, spacing: 0.12 })\n if (hit && hit.normal[1] < 0.7) by = hit.object\n }\n }\n // the player: steps back out of the way of the leaf, or holds it when there is no room behind\n if (!by) {\n const out = bodyOverlap(box)\n if (out) {\n const x0 = player.x\n const z0 = player.z\n player.moveBy(out[0], out[1])\n if (Math.hypot(player.x - x0, player.z - z0) < Math.hypot(out[0], out[1]) * 0.5) by = 'player'\n else if (u.phase !== 'swing' || from === 0) event('stepped_back', u)\n }\n }\n if (by) {\n options.pose(objectId, leaf.part, leaf.clip, from)\n const at: Vec3 = [box.getCenter(tmp).x, tmp.y, tmp.z]\n options.sound(options.impactKey(objectId, leaf.part), at, Math.min(0.6, 0.15 + massOf(objectId, leaf.part) * 0.02))\n event('blocked', u, by)\n return false\n }\n return true\n }\n\n /**\n * Where the hand takes the leaf, in the leaf's own space: a turning leaf by its free edge (the handle side, away from the hinge, at the height the eye was or at a handle's height),\n * a drawer by the middle of its front where the eye was.\n */\n const handleOf = (obj: THREE_NS.Object3D, leaf: RoomLeaf, point: Vec3 | null): THREE_NS.Vector3 => {\n obj.updateMatrixWorld(true)\n box.setFromObject(obj)\n const lo = new THREE.Vector3(Infinity, Infinity, Infinity)\n const hi = new THREE.Vector3(-Infinity, -Infinity, -Infinity)\n for (let i = 0; i < 8; i++) {\n tmp.set(i & 1 ? box.max.x : box.min.x, i & 2 ? box.max.y : box.min.y, i & 4 ? box.max.z : box.min.z)\n obj.worldToLocal(tmp)\n lo.min(tmp)\n hi.max(tmp)\n }\n const aimed = point ? obj.worldToLocal(new THREE.Vector3(point[0], point[1], point[2])) : lo.clone().add(hi).multiplyScalar(0.5)\n if (!point) {\n // no eye on it (a script): the hand at the height of a handle, about a metre over the feet\n const local = obj.worldToLocal(obj.getWorldPosition(new THREE.Vector3()).setY(player.feet + 1.0))\n aimed.y = local.y\n }\n aimed.clamp(lo, hi)\n if (slides(leaf.clip, leaf.part)) return aimed\n // the hinge is the leaf's own origin; the free edge is the far end of the leaf across the axis it turns about\n const last = leaf.clip.keys[leaf.clip.keys.length - 1]?.parts?.[leaf.part]?.rotation ?? [0, 1, 0]\n const axis = Math.abs(last[0]) >= Math.abs(last[1]) && Math.abs(last[0]) >= Math.abs(last[2]) ? 0 : Math.abs(last[1]) >= Math.abs(last[2]) ? 1 : 2\n const size = [hi.x - lo.x, hi.y - lo.y, hi.z - lo.z]\n const reachOf = (k: number): number => Math.max(Math.abs(lo.getComponent(k)), Math.abs(hi.getComponent(k)))\n let across = -1\n for (let k = 0; k < 3; k++) {\n if (k === axis || size[k]! < Math.min(size[0]!, size[1]!, size[2]!) + 1e-6) continue\n if (across < 0 || reachOf(k) > reachOf(across)) across = k\n }\n if (across < 0) return aimed\n const far = Math.abs(hi.getComponent(across)) >= Math.abs(lo.getComponent(across)) ? hi.getComponent(across) : lo.getComponent(across)\n aimed.setComponent(across, far - Math.sign(far) * Math.min(HANDLE_INSET, size[across]! * 0.25))\n return aimed\n }\n\n const start = (objectId: string, leaf: RoomLeaf, point: Vec3 | null): boolean => {\n reaching = null\n const obj = options.objectOf(objectId, leaf.part)\n if (!obj) return false\n if (using && (using.objectId !== objectId || using.leaf.part !== leaf.part)) control.cancel()\n obj.updateMatrixWorld(true)\n // the hand goes where the eye was, else to the middle of the free edge of the leaf at the height of a handle\n const grip = handleOf(obj, leaf, point)\n const opening = openingOf(objectId, leaf.part)\n const key = `${objectId}|${leaf.part}`\n const lastGoal = lastGoals.get(key)\n const goal = control.begin({ opening, massKg: massOf(objectId, leaf.part), locked: options.isLocked(objectId, leaf.part), ...(lastGoal !== undefined ? { lastGoal } : {}) })\n if (goal !== null) lastGoals.set(key, goal)\n // a leaf that comes toward the body is pulled, one that goes away is pushed: compare the leaf open and closed with where the player stands\n let pull = true\n if (goal !== null) {\n obj.updateMatrixWorld(true)\n options.pose(objectId, leaf.part, leaf.clip, 1)\n obj.updateMatrixWorld(true)\n const openAt = obj.localToWorld(grip.clone())\n options.pose(objectId, leaf.part, leaf.clip, 0)\n obj.updateMatrixWorld(true)\n const shutAt = obj.localToWorld(grip.clone())\n options.pose(objectId, leaf.part, leaf.clip, opening)\n const dOpen = Math.hypot(openAt.x - player.x, openAt.z - player.z)\n const dShut = Math.hypot(shutAt.x - player.x, shutAt.z - player.z)\n pull = goal === 1 ? dOpen <= dShut : dShut <= dOpen\n }\n using = { objectId, leaf, obj, grip, pull, phase: control.phase, progress: 0, walked: 0, there: goal === null }\n const at = obj.localToWorld(grip.clone())\n if (goal === null) {\n options.sound(options.leafFoley?.(objectId, leaf.part, slides(leaf.clip, leaf.part))?.locked ?? 'leaf_rattle', [at.x, at.y, at.z], 0.6)\n event('locked', using)\n } else event('reach', using)\n return true\n }\n\n return {\n get active() {\n return reaching !== null || (using !== null && control.phase !== 'idle')\n },\n get state() {\n return using ? { objectId: using.objectId, part: using.leaf.part, phase: control.phase, opening: openingOf(using.objectId, using.leaf.part), goal: control.goal } : null\n },\n get avatarState() {\n const h = holding()\n return h ? { phase: h.phase, progress: h.progress, height: h.at.y - player.feet, pull: h.pull } : null\n },\n aimed() {\n const found = picked()\n if (!found) return null\n const { hit, leaf } = found\n return { objectId: hit.objectId, part: leaf.part, open: openingOf(hit.objectId, leaf.part) > 0.5, locked: options.isLocked(hit.objectId, leaf.part) }\n },\n use() {\n const found = picked()\n return found ? start(found.hit.objectId, found.leaf, found.hit.point) : false\n },\n useLeaf(objectId, part) {\n const leaves = options.leaves(objectId)\n const leaf = part === undefined ? leaves[0] : leaves.find((l) => l.part === part)\n return leaf ? start(objectId, leaf, null) : false\n },\n opening: openingOf,\n step(dt) {\n const r = reaching\n if (r) {\n r.time += dt\n if (r.phase === 'reach' && !r.there) {\n const h = r.reach.handle()\n const hinge = r.reach.hinge?.()\n r.walked += dt\n const g = new THREE.Vector3(h[0], h[1], h[2])\n r.there = approach(g, hinge ? new THREE.Vector3(hinge[0], hinge[1], hinge[2]) : null, false, dt, r.walked)\n face(g, dt)\n if (r.there) r.time = 0\n } else if (r.phase === 'reach') {\n r.progress = Math.min(1, r.time / rules.reachSeconds)\n if (r.progress >= 1) {\n r.reach.onGrip?.()\n r.phase = r.reach.locked ? 'rattle' : 'swing'\n r.time = 0\n r.progress = 0\n }\n } else if (r.phase === 'swing' || r.phase === 'rattle') {\n r.progress = Math.min(1, r.time / (r.phase === 'rattle' ? rules.rattleSeconds : Math.max(0.05, r.reach.seconds)))\n if (r.progress >= 1) {\n r.phase = 'release'\n r.time = 0\n r.progress = 0\n }\n } else {\n r.progress = Math.min(1, r.time / rules.releaseSeconds)\n if (r.progress >= 1) reaching = null\n }\n return\n }\n const u = using\n if (!u || control.phase === 'idle') return\n const was = openingOf(u.objectId, u.leaf.part)\n const wasPhase = control.phase\n // the player walks to the handle first; the hand goes out once there\n if (wasPhase === 'reach' && !u.there) {\n u.obj.updateMatrixWorld(true)\n u.walked += dt\n const g = u.obj.localToWorld(new THREE.Vector3().copy(u.grip))\n u.there = approach(g, u.obj.getWorldPosition(new THREE.Vector3()), slides(u.leaf.clip, u.leaf.part), dt, u.walked)\n face(g, dt)\n if (!u.there) return\n }\n const s = control.step(dt, (from, to) => isFree(u, from, to))\n u.phase = s.phase\n u.progress = s.progress\n openings.set(key(u.objectId, u.leaf.part), s.opening)\n u.obj.updateMatrixWorld(true)\n const at = u.obj.localToWorld(tmp.copy(u.grip))\n const point: Vec3 = [at.x, at.y, at.z]\n const slide = slides(u.leaf.clip, u.leaf.part)\n const foley = options.leafFoley?.(u.objectId, u.leaf.part, slide) ?? null\n const own = (moment: 'open' | 'shut'): string | undefined => options.leafSound?.(u.objectId, u.leaf.part, moment)\n const shut = own('shut') ?? options.impactKey(u.objectId, u.leaf.part).replace('impact_', 'leaf_shut_')\n // the latch gives as the leaf leaves the frame, the hinge sounds while it turns, the leaf meets the frame closing\n if (wasPhase === 'reach' && s.phase !== 'reach') {\n const opening = foley ? undefined : own('open')\n if (foley) {\n // a closed leaf lets go of its latch or seal; one already ajar only turns\n if (was < 0.02) options.sound(foley.open, point, 0.5)\n if (foley.turn) options.sound(foley.turn, point, 0.35)\n } else if (slide) options.sound('leaf_slide', point, 0.5)\n else if (opening) {\n if (was < 0.02) options.sound(opening, point, 0.5)\n } else {\n if (was < 0.02) options.sound('leaf_latch', point, 0.5)\n options.sound(/metal|glass/.test(shut) ? 'leaf_creak_metal' : 'leaf_creak_wood', point, 0.35)\n }\n }\n if (s.arrived) {\n if (s.opening <= 0) {\n const volume = shutVolume(massOf(u.objectId, u.leaf.part))\n if (foley) options.sound(foley.slam && volume >= LEAF_SLAM_VOLUME ? foley.slam : foley.close, point, volume)\n else options.sound(slide ? 'leaf_slide' : shut, point, volume)\n event('closed', u)\n } else event('opened', u)\n }\n if (s.phase === 'idle') using = null\n },\n handTargets() {\n const h = holding()\n if (!h || (h.phase === 'rattle' && h.progress > 0.92)) return null\n const { at, phase, progress } = h\n // the rattle shakes the handle under the hand\n if (phase === 'rattle') at.y += Math.sin(progress * 60) * 0.012\n camera.updateMatrixWorld(true)\n const rest = camera.localToWorld(new THREE.Vector3(HAND_REST[0], HAND_REST[1], HAND_REST[2]))\n // reach: the hand travels to the handle; release: back to the chest\n const k = phase === 'reach' ? progress : phase === 'release' ? 1 - progress : 1\n const ease = k * k * (3 - 2 * k)\n const pos = rest.lerp(at, ease)\n // a hand round a vertical handle: fingers away from the player, thumb up (HandPose of game-contracts: +x to the knuckles, +z to the little finger)\n const way = new THREE.Vector3(at.x - player.x, 0, at.z - player.z)\n if (way.lengthSq() < 1e-6) way.set(-Math.sin(player.yaw), 0, -Math.cos(player.yaw))\n way.normalize()\n const down = new THREE.Vector3(0, -1, 0)\n const back = new THREE.Vector3().crossVectors(down, way)\n const q = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().makeBasis(way, back, down))\n const grip = phase === 'reach' ? 0.15 + 0.75 * progress : phase === 'release' ? 0.9 * (1 - progress) : 0.9\n return { R: { position: [pos.x, pos.y, pos.z], quaternion: [q.x, q.y, q.z, q.w] }, L: null, grip }\n },\n reachFor(reach) {\n if (using) {\n control.cancel()\n using = null\n }\n reaching = { reach, phase: 'reach', time: 0, progress: 0, walked: 0, there: false }\n },\n forget(objectId) {\n for (const k of [...openings.keys()]) if (k.startsWith(`${objectId}\\0`)) openings.delete(k)\n if (using?.objectId === objectId) {\n control.cancel()\n using = null\n }\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 /** How closed the other hand is when it works on the item (turning a cap off); the room brings it there with `reach`. */\n readonly gripL?: 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 /** Which way the body falls while `down`: true face down, false on its back; left out, the avatar picks. A blast falls it the way it pushed. */\n fallForward?: 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 /** Hands on a piece of furniture: `grip` while the hold timer fills (`progress`), `push` walking with it, `strain` straining against what does not give. */\n push?: { readonly phase: 'grip' | 'push' | 'strain'; readonly progress: number } | null\n /** On a seat: the pose and how high the hips (or the pelvis) are above the feet. */\n seat?: { readonly pose: 'sit' | 'lie'; readonly hip: number } | null\n /** A hand on a door, lid or drawer: `reach` to the handle, `swing` with it (`pull` toward the body or pushed away), `release`, `rattle` on a locked one; `height` of the hand over the feet, metres. */\n door?: { readonly phase: 'reach' | 'swing' | 'release' | 'rattle'; readonly progress: number; readonly height: number; readonly pull: boolean } | 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 /** The joint of a shoulder: in third person the room rests a long gun's stock in the pocket just inside the right one (`ModuleHost.holdFrame`). */\n shoulder?(side: 'R' | 'L'): THREE_NS.Object3D\n /**\n * Where the body's eyes are after its pose (world space), sampled before `reach`: with it the room draws the body in both views, puts the first-person camera there (pulled back out of\n * walls) and shoots, aims and reaches from there in both views. Without it the room keeps the player's own eye.\n */\n eye?(out?: THREE_NS.Vector3): THREE_NS.Vector3\n /** Hides the head and neck from `camera` while the view is `first` (shadows, mirrors and other cameras keep seeing them). */\n setView?(mode: CameraMode, camera: THREE_NS.Object3D | null): void\n /**\n * Plays the strike `clipId` (on the body, in both views) 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'; hand?: 'left' | 'right' }): number | null\n /**\n * The foot the body put down since the last call (its walk cycle reached a heel strike), or null. The room asks after each `update` and sends the footfall to the\n * modules (`HostEvent` `footfall`), so the step is heard on the frame the foot is seen on the ground. Without it the room counts strides by distance.\n */\n footfall?(): 'left' | 'right' | null\n /**\n * Brings the body's hands to the tool in them (`HandTargets`, world space: the module's). The room calls it in both views every frame, after the modules have placed the tool and\n * before the render, with `view` (the eye's camera, and `contact` to keep the hands out of walls) in both views. An avatar without it keeps the hands where its own pose puts them.\n */\n reach?(targets: HandTargets | null, view?: RoomReachView): void\n}\n\n/** The first-person view the body's hands keep to: the camera, and the room's ray (`contact`) so a hand stops before a wall. */\nexport interface RoomReachView {\n camera: THREE_NS.Object3D\n keepOutside?: { contact(origin: [number, number, number], direction: [number, number, number], maxDistance: number): number | null }\n}\n\n/** Which leg a kick uses: `alternate` swaps at each kick (right first). */\nexport type KickLeg = 'alternate' | 'left' | 'right'\n/** Which hand a punch uses: `alternate` swaps at each punch (right first). */\nexport type PunchHand = '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 'metric.geometries': 'Geometries',\n 'metric.textures': 'Textures',\n 'metric.heap_mb': 'Heap MB',\n 'memory.leak_short': 'memory leak: +{geometries} geometries, +{textures} textures per {clears} clears',\n 'memory.leak': 'Memory keeps growing after each clear: +{geometries} geometries and +{textures} textures over the last {clears} clears. Something removed from the scene was not released (discardObject3D).',\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.strike.hand': '{weapon}: {clip} with the {hand} hand begins, impact in {seconds} s',\n 'hand.left': 'left',\n 'hand.right': 'right',\n 'act.combo.on': '{name}: on (each blow follows the sequence)',\n 'act.combo.off': '{name}: off',\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.bump': 'Pushed {name} ({kg} kg) walking into it',\n 'act.drop': 'Dropped {name}',\n 'act.throw': 'Threw {name} at {speed} m/s',\n 'ground.name': 'Ground',\n 'act.landing': '{name} landed at {speed} m/s: {energy} J',\n 'act.player_land': 'You landed at {speed} m/s',\n 'act.bench_failed': '{name} failed: {error}',\n 'loading.working': 'Working…',\n 'loading.graphics': 'Calibrating graphics…',\n 'ui.graphics': 'Graphics',\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.knocked_down': 'The blast threw the player off their feet at {speed} m/s ({reach}% got through the cover)',\n 'act.player_slammed': 'The player was thrown into {what} at {speed} m/s',\n 'act.player_fell': 'The player hit the floor at {speed} m/s',\n 'act.player_shoved': 'The blast pushed the player at {speed} m/s ({reach}% got through the cover)',\n 'act.player_wounded': 'The blast felled the player where they stood, {distance} m from it: badly wounded, stunned for {stun} s ({reach}% got through the cover)',\n 'act.player_thrown_wounded': 'The blast threw the player at {speed} m/s, {distance} m from it: badly wounded, stunned for {stun} s ({reach}% got through the cover)',\n 'act.player_stunned': 'The blast stunned the player for {stun} s, {distance} m from it: dizzy, ears ringing',\n 'act.came_apart': '{name} came apart: what stayed is loose and falls',\n 'act.shoved': '{name} stands free: the shots 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.open_with': 'Opened {name} with {tool}',\n 'act.open_by_hand': 'Opened {name} by hand',\n 'act.ate': 'Ate {grams} g of {name}',\n 'act.ate_all': 'Ate all of {name} ({grams} g): the packaging is empty',\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.eat': 'eat',\n 'use.pour': 'pour',\n 'use.pour_out': 'pour out',\n 'use.open': 'open',\n 'use.unscrew': 'unscrew',\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.door_locked': '{name} is locked',\n 'hud.door_blocked': '{name} hits something and stops ({percent}% open)',\n 'hud.door_hint_open': 'E: open',\n 'hud.door_hint_close': 'E: close',\n 'hud.door_hint_locked': 'Locked',\n 'act.door_reach': 'reaches for the handle of {name}',\n 'act.door_opened': 'opens {name}',\n 'act.door_closed': 'closes {name}',\n 'act.door_blocked': '{name} hits something and stops at {percent}%',\n 'act.door_locked': 'tries {name}: locked, it only rattles',\n 'act.door_stepped_back': 'steps back out of the way of {name}',\n 'hud.push_on': 'Pushing {name}: W pushes, S pulls, let go of E to stop',\n 'hud.push_too_heavy': '{name} does not budge ({kg} kg)',\n 'hud.push_blocked': '{name} is stuck: there is something in the way',\n 'act.push_grip': 'leans on {name} ({kg} kg)',\n 'act.push_engaged': 'starts pushing {name} ({kg} kg)',\n 'act.sit': 'sits on {name}',\n 'act.lie': 'lies down on {name}',\n 'act.stand': 'gets up from {name}',\n 'act.push_too_heavy': 'strains against {name}: {kg} kg is too much',\n 'act.push_obstacle': '{name} hits something and locks',\n 'act.push_release': 'lets go of {name}',\n 'hud.empty_container': '{name} is empty',\n 'hud.needs_opener': 'Opening {name} needs {tools} (put one within reach or in the loadout)',\n 'hud.spoiled_hole': '{name}: the packaging is holed through, what is inside is contaminated; do not eat or drink it',\n 'hud.spoiled_leak': '{name} leaked: what is left is contaminated; do not eat or drink it',\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 (tap stays, hold while pressed) · Space: jump · 1-0 / wheel: tool · LMB: use (bare hands: punch) · E: grab/drop (hold against furniture: push) · G or RMB: throw · R: reload · Q: fire mode · X: clear a jam · B: safety · Y: detonate charges set down · K: kick · N: strike combo on/off · 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.test_table': 'Test table',\n 'ui.test_table.group': 'Group to lay on the table',\n 'ui.test_table.lay': 'Lay',\n 'ui.test_table.prev': 'Previous items',\n 'ui.test_table.next': 'Next items',\n 'ui.test_table.relay': 'Put back',\n 'ui.test_table.search': 'Find an item to put on the table',\n 'ui.test_table.hint': 'Pick a group and lay it on the table, then pick an item and try it.',\n 'ui.test_table.page': 'Items {from}–{to} of {total}. Pick one, then a trial:',\n 'ui.trial.shot': 'Shot',\n 'ui.trial.punch': 'Punch',\n 'ui.trial.stab': 'Knife',\n 'ui.trial.fire': 'Fire',\n 'ui.trial.blast': 'Blast',\n 'ui.trial.shot.hint': 'A 9 mm round from 2.5 m',\n 'ui.trial.punch.hint': 'A punch, up close',\n 'ui.trial.stab.hint': 'A knife blow, up close',\n 'ui.trial.fire.hint': 'A flamethrower burst from 1.6 m',\n 'ui.trial.blast.hint': 'A fragmentation grenade goes off just behind it (it reaches the neighbours too)',\n 'act.test_table': 'Test table: {group}, items {from}–{to} of {total}',\n 'act.trial.shot': 'Trial: shooting {name}',\n 'act.trial.punch': 'Trial: punching {name}',\n 'act.trial.stab': 'Trial: stabbing {name}',\n 'act.trial.fire': 'Trial: setting fire to {name}',\n 'act.trial.blast': 'Trial: a blast beside {name}',\n 'arena.test_table': 'Test table',\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.kick': 'Kick',\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.dug': 'Dug',\n 'ins.dig_limit': 'Ground left to dig',\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 'metric.geometries': 'Geometrias',\n 'metric.textures': 'Texturas',\n 'metric.heap_mb': 'Heap MB',\n 'memory.leak_short': 'vazamento de memória: +{geometries} geometrias, +{textures} texturas em {clears} limpezas',\n 'memory.leak': 'A memória continua subindo a cada limpeza: +{geometries} geometrias e +{textures} texturas nas últimas {clears} limpezas. Algo tirado da cena não foi liberado (discardObject3D).',\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.strike.hand': '{weapon}: {clip} com a mão {hand} começa, impacto em {seconds} s',\n 'hand.left': 'esquerda',\n 'hand.right': 'direita',\n 'act.combo.on': '{name}: ligada (cada golpe segue a sequência)',\n 'act.combo.off': '{name}: desligada',\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.bump': 'Empurrou {name} ({kg} kg) ao esbarrar',\n 'act.drop': 'Soltou {name}',\n 'act.throw': 'Arremessou {name} a {speed} m/s',\n 'ground.name': 'Chão',\n 'act.landing': '{name} caiu a {speed} m/s: {energy} J',\n 'act.player_land': 'Você aterrissou a {speed} m/s',\n 'act.bench_failed': '{name} falhou: {error}',\n 'loading.working': 'Trabalhando…',\n 'loading.graphics': 'Calibrando os gráficos…',\n 'ui.graphics': 'Gráficos',\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.knocked_down': 'A explosão derrubou o jogador a {speed} m/s ({reach}% passou pela cobertura)',\n 'act.player_slammed': 'O jogador foi arremessado contra {what} a {speed} m/s',\n 'act.player_fell': 'O jogador bateu no chão a {speed} m/s',\n 'act.player_shoved': 'A explosão empurrou o jogador a {speed} m/s ({reach}% passou pela cobertura)',\n 'act.player_wounded': 'A explosão derrubou o jogador onde estava, a {distance} m dela: ferido gravemente, atordoado por {stun} s ({reach}% passou pela cobertura)',\n 'act.player_thrown_wounded': 'A explosão arremessou o jogador a {speed} m/s, a {distance} m dela: ferido gravemente, atordoado por {stun} s ({reach}% passou pela cobertura)',\n 'act.player_stunned': 'A explosão atordoou o jogador por {stun} s, a {distance} m dela: tonto, com os ouvidos zumbindo',\n 'act.came_apart': '{name} se desmontou: o que ficou está solto e cai',\n 'act.shoved': '{name} estava solto no chão: os tiros o moveram',\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.open_with': 'Abriu {name} com {tool}',\n 'act.open_by_hand': 'Abriu {name} com a mão',\n 'act.ate': 'Comeu {grams} g de {name}',\n 'act.ate_all': 'Comeu todo o conteúdo de {name} ({grams} g): a embalagem ficou vazia',\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.eat': 'comer',\n 'use.pour': 'despejar',\n 'use.pour_out': 'esvaziar',\n 'use.open': 'abrir',\n 'use.unscrew': 'desenroscar',\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.door_locked': '{name} está trancado(a)',\n 'hud.door_blocked': '{name} bateu em algo e parou ({percent}% aberto)',\n 'hud.door_hint_open': 'E: abrir',\n 'hud.door_hint_close': 'E: fechar',\n 'hud.door_hint_locked': 'Trancado',\n 'act.door_reach': 'leva a mão à maçaneta de {name}',\n 'act.door_opened': 'abre {name}',\n 'act.door_closed': 'fecha {name}',\n 'act.door_blocked': '{name} bate em algo e para em {percent}%',\n 'act.door_locked': 'tenta abrir {name}: trancado, só chacoalha',\n 'act.door_stepped_back': 'dá um passo para trás para {name} passar',\n 'hud.push_on': 'Empurrando {name}: W empurra, S puxa, solte o E para parar',\n 'hud.push_too_heavy': '{name} não se mexe ({kg} kg)',\n 'hud.push_blocked': '{name} travou: tem algo no caminho',\n 'act.push_grip': 'encosta em {name} ({kg} kg)',\n 'act.push_engaged': 'começa a empurrar {name} ({kg} kg)',\n 'act.sit': 'senta em {name}',\n 'act.lie': 'deita em {name}',\n 'act.stand': 'levanta de {name}',\n 'act.push_too_heavy': 'faz força contra {name}: {kg} kg é demais',\n 'act.push_obstacle': '{name} bate em algo e trava',\n 'act.push_release': 'solta {name}',\n 'hud.empty_container': '{name} está vazio',\n 'hud.needs_opener': 'Para abrir {name} precisa de {tools} (deixe um ao alcance ou no inventário)',\n 'hud.spoiled_hole': '{name}: a embalagem furou, o conteúdo está contaminado; não dá para comer nem beber',\n 'hud.spoiled_leak': '{name} vazou: o que sobrou está contaminado; não dá para comer nem beber',\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 (toque fixa, segurar só enquanto aperta) · Espaço: pular · 1-0 / roda: ferramenta · botão esquerdo: usar (mão livre: soco) · E: pegar/soltar (segurar encostado no móvel: empurrar) · G ou botão direito: arremessar · R: recarregar · Q: modo de tiro · X: destravar · B: trava · Y: detonar cargas postas · K: chute · N: liga/desliga a sequência de golpes · 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.test_table': 'Mesa de testes',\n 'ui.test_table.group': 'Grupo para pôr na mesa',\n 'ui.test_table.lay': 'Pôr na mesa',\n 'ui.test_table.prev': 'Itens anteriores',\n 'ui.test_table.next': 'Próximos itens',\n 'ui.test_table.relay': 'Repor',\n 'ui.test_table.search': 'Buscar item para pôr na mesa',\n 'ui.test_table.hint': 'Escolha um grupo e ponha na mesa; depois escolha um item e teste.',\n 'ui.test_table.page': 'Itens {from}–{to} de {total}. Escolha um e um teste:',\n 'ui.trial.shot': 'Tiro',\n 'ui.trial.punch': 'Soco',\n 'ui.trial.stab': 'Faca',\n 'ui.trial.fire': 'Fogo',\n 'ui.trial.blast': 'Explosão',\n 'ui.trial.shot.hint': 'Um tiro de 9 mm a 2,5 m',\n 'ui.trial.punch.hint': 'Um soco, de perto',\n 'ui.trial.stab.hint': 'Um golpe de faca, de perto',\n 'ui.trial.fire.hint': 'Uma rajada de lança-chamas a 1,6 m',\n 'ui.trial.blast.hint': 'Uma granada de fragmentação explode logo atrás dele (pega os vizinhos também)',\n 'act.test_table': 'Mesa de testes: {group}, itens {from}–{to} de {total}',\n 'act.trial.shot': 'Teste: tiro em {name}',\n 'act.trial.punch': 'Teste: soco em {name}',\n 'act.trial.stab': 'Teste: faca em {name}',\n 'act.trial.fire': 'Teste: fogo em {name}',\n 'act.trial.blast': 'Teste: explosão ao lado de {name}',\n 'arena.test_table': 'Mesa de testes',\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.kick': 'Chute',\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.dug': 'Escavado',\n 'ins.dig_limit': 'Chão até o limite',\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 { TRIAL_KINDS } from './test-table'\nimport type { TestTable, TestTablePage } from './test-table'\n\n/** The CSS of the test table panel (the room's panel look: `.tr-panel`, `.tr-btn`, `.tr-row`). */\nexport const TEST_TABLE_CSS = `\n.tr-table{flex:0 0 auto;max-height:42%}\n.tr-table .sub{color:#9aa3b2;margin:4px 0}\n.tr-table .list{display:flex;flex-wrap:wrap;gap:3px}\n.tr-table .list .tr-btn{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.tr-table select{flex:1;min-width:0;max-width:55%}\n.tr-table .tr-search{margin:6px 0 0}\n.tr-root .tr-table button.tr-btn.on{background:#3b3a14;border-color:#ffd23f;color:#fff}\n`\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/**\n * The panel of the test table: a group, its pages (◀ ▶), the items on the table (a click picks the one the trials hit) and one button per trial, plus one that puts the table back.\n */\nexport function createTestTablePanel(table: TestTable, t: (key: string, vars?: Record<string, string | number>) => string): { element: HTMLElement; refresh(): void; dispose(): void } {\n const element = mk('div', 'tr-panel tr-table')\n element.appendChild(mk('h3', undefined, t('ui.test_table')))\n const head = mk('div', 'tr-row')\n const select = mk('select')\n select.setAttribute('aria-label', t('ui.test_table.group'))\n const lay = mk('button', 'tr-btn', t('ui.test_table.lay'))\n const prev = mk('button', 'tr-btn', '◀')\n const next = mk('button', 'tr-btn', '▶')\n prev.title = t('ui.test_table.prev')\n next.title = t('ui.test_table.next')\n for (const b of [lay, prev, next]) b.type = 'button'\n head.append(select, lay, prev, next)\n // a group has hundreds of items: the search lays the page that holds the one asked for\n const search = mk('input', 'tr-search')\n search.type = 'search'\n search.placeholder = t('ui.test_table.search')\n const found = mk('div', 'list')\n const sub = mk('div', 'sub', t('ui.test_table.hint'))\n const list = mk('div', 'list')\n const trials = mk('div', 'tr-row')\n const trialButtons = TRIAL_KINDS.map((kind) => {\n const b = mk('button', 'tr-btn', t(`ui.trial.${kind}`))\n b.type = 'button'\n b.dataset.trial = kind\n b.title = t(`ui.trial.${kind}.hint`)\n b.onclick = () => table.trial(kind)\n trials.appendChild(b)\n return b\n })\n const relay = mk('button', 'tr-btn', t('ui.test_table.relay'))\n relay.type = 'button'\n relay.onclick = () => table.relay()\n trials.appendChild(relay)\n // the trial buttons stay over the list: a page of small things is a long list, and the buttons must not scroll away under it\n element.append(head, search, found, sub, trials, list)\n\n const groups = (): void => {\n const keep = select.value\n select.textContent = ''\n for (const group of table.groups()) {\n const op = mk('option', undefined, group)\n op.value = group\n select.appendChild(op)\n }\n if ([...select.options].some((o) => o.value === keep)) select.value = keep\n }\n const render = (page: TestTablePage | null): void => {\n list.textContent = ''\n prev.disabled = !page?.hasPrev\n next.disabled = !page?.hasNext\n for (const b of [...trialButtons, relay]) b.disabled = !page?.selected\n if (!page) {\n sub.textContent = t('ui.test_table.hint')\n return\n }\n if (select.value !== page.group) select.value = page.group\n sub.textContent = t('ui.test_table.page', { from: page.first + 1, to: page.first + page.objects.length, total: page.total })\n for (const o of page.objects) {\n const b = mk('button', o.objectId === page.selected ? 'tr-btn on' : 'tr-btn', o.name)\n b.type = 'button'\n b.title = o.itemId\n b.onclick = () => table.select(o.objectId)\n list.appendChild(b)\n }\n }\n const fold = (text: string): string => text.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '').toLowerCase()\n search.oninput = () => {\n found.textContent = ''\n const term = fold(search.value.trim())\n if (!term) return\n const hits = table.items().filter((item) => fold(`${item.name} ${item.id}`).includes(term)).slice(0, 8)\n for (const item of hits) {\n const b = mk('button', 'tr-btn', item.name)\n b.type = 'button'\n b.title = `${item.group} · ${item.id}`\n b.onclick = () => {\n search.value = ''\n found.textContent = ''\n table.find(item.id)\n }\n found.appendChild(b)\n }\n if (!hits.length) found.appendChild(mk('div', 'sub', t('ui.no_results')))\n }\n lay.onclick = () => table.open(select.value)\n prev.onclick = () => table.prev()\n next.onclick = () => table.next()\n select.onchange = () => table.open(select.value)\n // typing in the select must not move the player or switch tools\n for (const box of [select, search]) box.addEventListener('keydown', (e) => e.stopPropagation())\n const off = table.on(render)\n groups()\n render(table.state())\n return {\n element,\n refresh: () => {\n groups()\n render(table.state())\n },\n dispose: off,\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 { createTestTablePanel, TEST_TABLE_CSS } from './test-table-panel'\nimport type { TestTable } from './test-table'\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 /** Set when the aim rests on the floor: what the ground is there (the room's terrain) instead of an object's part. */\n ground?: GroundInspect\n}\n\n/** The floor under the aim: its profile, the layer a blow reaches now and what has been done to it. */\nexport interface GroundInspect {\n /** Name of the ground profile (Dirt, Concrete slab). */\n surface: string\n /** Name of the material exposed at that point (the turf, or the soil under it once dug). */\n material: string\n /** Metres dug out under the untouched surface. */\n dug: number\n /** Metres left before the digging limit (bedrock, or the bottom of a slab). */\n remaining: number\n /** 0..1, how burnt the surface is. */\n scorch: 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 strike combo (`strikeCombo`) is on; null when the room has none. */\n combo?: boolean | null\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 /** Opens the graphics screen: the button takes the place of the quality select. Absent: the select. */\n onGraphics?: () => void\n scenarios: () => TestRoomScenario[]\n onRun: (s: TestRoomScenario) => Promise<ScenarioReport | void>\n onRunAll: () => Promise<ScenarioReport | void>\n onTool: (index: number) => void\n onTap: () => void\n /** The combo button: its label (the combo's name) and what it toggles; absent when the room has no combo. */\n combo?: { label: string; onToggle: () => void }\n kick?: { label: string; onKick: () => 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 /** The room's test table: its panel goes between the inspector and the log. Absent: no panel. */\n testTable?: TestTable\n}\n\nexport interface RoomUi {\n /** Writes the log lines queued since the last frame (the room calls it every frame; a burst costs one DOM write). */\n flushLog(): void\n hud(state: HudState): void\n /** The hold timer around the crosshair, 0 to 1; null hides it. Called every frame while it runs. */\n holdRing(value: number | null): void\n toast(text: string): void\n /** A warning that stays on screen under the tool (the memory watch: memory keeps growing after each clear); null takes it away. */\n alert(text: string | null): 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-ring{position:absolute;left:50%;top:50%;width:64px;height:64px;margin:-32px 0 0 -32px;transform:rotate(-90deg);display:none;pointer-events:none;filter:drop-shadow(0 0 2px #000)}\n.tr-ring circle{fill:none;stroke-width:5}.tr-ring .tr-ring-bg{stroke:rgba(255,255,255,.25)}.tr-ring .tr-ring-fill{stroke:#ffd166;stroke-linecap:round}\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-alert{display:none;position:relative;z-index:20;margin-top:6px;background:rgba(183,28,28,.92);color:#fff;padding:6px 12px;border-radius:6px;font-size:13px;font-weight:600;box-shadow:0 2px 8px rgba(0,0,0,.4)}\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 + (o.testTable ? TEST_TABLE_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 ring = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n ring.setAttribute('class', 'tr-ring')\n ring.setAttribute('viewBox', '0 0 64 64')\n const ringCircle = (className: string): SVGCircleElement => {\n const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle')\n circle.setAttribute('class', className)\n circle.setAttribute('cx', '32')\n circle.setAttribute('cy', '32')\n circle.setAttribute('r', '27')\n ring.appendChild(circle)\n return circle\n }\n ringCircle('tr-ring-bg')\n const ringFill = ringCircle('tr-ring-fill')\n const RING_LENGTH = 2 * Math.PI * 27\n ringFill.style.strokeDasharray = String(RING_LENGTH)\n const top = mk('div', 'tr-top')\n const toolBox = mk('div', 'tr-tool')\n const status = mk('div', 'tr-status')\n const alertBox = mk('div', 'tr-alert')\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, alertBox, 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 // the test table sits between the inspector and the log (the log gives way), so the catalogue keeps its room on the right\n const tablePanel = o.testTable ? createTestTablePanel(o.testTable, t) : null\n left.append(insp, ...(tablePanel ? [tablePanel.element] : []), 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 rebuildLog()\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 // a blast storm logs hundreds of lines in one frame: they queue and the DOM is touched once per frame, for the last MAX_LINES only\n let pendingAdds: LogEntry[] = []\n const pendingUpdates = new Map<number, LogEntry>()\n let isLogStale = false\n const isLogVisible = (): boolean => !window.matchMedia?.('(max-width:980px)').matches || root.classList.contains('open')\n const buildNode = (e: LogEntry): HTMLElement => {\n const n = mk('div')\n fill(n, e)\n nodes.set(e.seq, n)\n return n\n }\n function rebuildLog(): void {\n pendingAdds = []\n pendingUpdates.clear()\n isLogStale = false\n logBody.textContent = ''\n nodes.clear()\n const fragment = document.createDocumentFragment()\n for (const e of o.log.entries().slice(-MAX_LINES * 3)) if (filters[e.channel]) fragment.appendChild(buildNode(e))\n logBody.appendChild(fragment)\n trimLog()\n }\n function trimLog(): void {\n while (logBody.childElementCount > MAX_LINES) {\n const oldest = nodes.keys().next()\n if (oldest.done) break\n nodes.delete(oldest.value)\n logBody.firstElementChild?.remove()\n }\n // scrolled at the next flush, before it touches the DOM: read now, scrollHeight would lay the page out in the middle of the frame\n // (perf.mjs, 2026-11-03: part of the 118 ms long task of the horde chain's first blast)\n if (autoscroll) isScrollDue = true\n }\n let isScrollDue = false\n const scrollToEnd = (): void => {\n if (!isScrollDue) return\n isScrollDue = false\n logBody.scrollTop = logBody.scrollHeight\n }\n const flushLog = (): void => {\n scrollToEnd()\n if (pendingAdds.length === 0 && pendingUpdates.size === 0) return\n if (!isLogVisible()) {\n isLogStale = true\n pendingAdds = []\n pendingUpdates.clear()\n return\n }\n if (isLogStale) return rebuildLog()\n const fragment = document.createDocumentFragment()\n for (const e of pendingAdds.slice(-MAX_LINES)) if (filters[e.channel]) fragment.appendChild(buildNode(e))\n pendingAdds = []\n logBody.appendChild(fragment)\n for (const [seq, e] of pendingUpdates) {\n const n = nodes.get(seq)\n if (n) fill(n, e)\n }\n pendingUpdates.clear()\n trimLog()\n }\n const offLog = o.log.on((e, updated) => {\n if (updated) pendingUpdates.set(e.seq, e)\n else pendingAdds.push(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 comboBtn = o.combo ? ctl(`${o.combo.label} (N)`, () => o.combo!.onToggle()) : null\n if (o.kick) ctl(o.kick.label, () => o.kick!.onKick())\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 if (o.onGraphics) {\n const g = ctl(t('ui.graphics'), () => o.onGraphics!())\n g.dataset.testid = 'graphics-button'\n } else {\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 }\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 if (isLogStale && isLogVisible()) rebuildLog()\n o.onResize()\n }\n toggle.onclick = togglePanels\n\n root.append(cross, ring, 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.ground) {\n const g = i.ground\n insp.appendChild(mk('div', 't', `${i.object} › ${g.surface}`))\n insp.appendChild(row(t('ins.material'), g.material))\n insp.appendChild(row(t('ins.dug'), `${num(g.dug * 100, 0)} cm`))\n insp.appendChild(row(t('ins.dig_limit'), `${num(g.remaining, 2)} m`))\n if (g.scorch > 0.01) insp.appendChild(row(t('ins.char'), `${num(g.scorch * 100, 0)} %`))\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 holdRing(value) {\n ring.style.display = value === null ? 'none' : 'block'\n if (value !== null) ringFill.style.strokeDashoffset = String(RING_LENGTH * (1 - value))\n },\n flushLog,\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 comboBtn?.classList.toggle('on', !!s.combo)\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 alert(text) {\n alertBox.textContent = text ?? ''\n alertBox.style.display = text ? 'block' : 'none'\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 tablePanel?.refresh()\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 tablePanel?.dispose()\n if (toastTimer) clearTimeout(toastTimer)\n root.remove()\n },\n }\n rebuildLog()\n return api\n}\n","/**\n * The extra views modules ask for (`ModuleHost.addView`: rear-view and side mirrors, a reversing camera) and the main-view takeover (`ModuleHost.setViewCamera`: a vehicle's chase or\n * cockpit camera). Each extra view is rendered into its own render target and laid on the screen as a quad, flipped for a mirror and with rounded corners when asked; everything it\n * creates is disposed when the view is taken away or the room is torn down.\n */\nimport type * as THREE_NS from 'three'\nimport type { ModuleView } from '@adatechnology/game-contracts'\n\ntype Entry = {\n readonly view: ModuleView\n readonly target: THREE_NS.WebGLRenderTarget\n readonly quad: THREE_NS.Mesh\n readonly frame: THREE_NS.Mesh\n readonly alpha: THREE_NS.Texture | null\n}\n\nexport type ModuleViews = {\n add(view: ModuleView): () => void\n setMain(camera: THREE_NS.Camera | null): void\n /** The camera the main view renders from: the module's when one took it over. */\n main(fallback: THREE_NS.Camera): THREE_NS.Camera\n /** Draws every extra view over what is already on the screen. */\n render(scene: THREE_NS.Scene): void\n readonly count: number\n dispose(): void\n}\n\nconst FRAME_PX = 3\n\nexport function createModuleViews(THREE: typeof THREE_NS, gl: THREE_NS.WebGLRenderer): ModuleViews {\n const entries: Entry[] = []\n let mainCamera: THREE_NS.Camera | null = null\n const overlay = new THREE.Scene()\n const ortho = new THREE.OrthographicCamera(-0.5, 0.5, 0.5, -0.5, 0, 2)\n ortho.position.z = 1\n const plane = new THREE.PlaneGeometry(1, 1)\n\n // a rounded rectangle as an alpha mask (white inside), drawn once per view on a small canvas\n const roundedMask = (rounded: number, aspect: number): THREE_NS.Texture | null => {\n if (!rounded || typeof document === 'undefined') return null\n const canvas = document.createElement('canvas')\n canvas.width = 256\n canvas.height = Math.max(16, Math.round(256 / aspect))\n const g = canvas.getContext('2d')\n if (!g) return null\n const r = Math.min(canvas.width, canvas.height) * Math.min(0.5, rounded)\n g.fillStyle = '#000'\n g.fillRect(0, 0, canvas.width, canvas.height)\n g.fillStyle = '#fff'\n g.beginPath()\n g.roundRect(0, 0, canvas.width, canvas.height, r)\n g.fill()\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.NoColorSpace\n return texture\n }\n\n const size = (): { w: number; h: number } => {\n // a stand-in renderer (tests, a headless host) may not measure itself\n if (typeof gl.getSize !== 'function') return { w: 960, h: 600 }\n const v = new THREE.Vector2()\n gl.getSize(v)\n return { w: v.x, h: v.y }\n }\n\n const take = (entry: Entry): void => {\n const i = entries.indexOf(entry)\n if (i < 0) return\n entries.splice(i, 1)\n overlay.remove(entry.quad, entry.frame)\n entry.target.dispose()\n ;(entry.quad.material as THREE_NS.Material).dispose()\n ;(entry.frame.material as THREE_NS.Material).dispose()\n entry.alpha?.dispose()\n }\n\n return {\n add(view) {\n const { w, h } = size()\n const scale = view.resolution ?? 0.5\n const pr = typeof gl.getPixelRatio === 'function' ? gl.getPixelRatio() : 1\n const target = new THREE.WebGLRenderTarget(Math.max(16, Math.round(w * view.rect.width * pr * scale)), Math.max(16, Math.round(h * view.rect.height * pr * scale)), { samples: 2 })\n target.texture.colorSpace = THREE.LinearSRGBColorSpace\n const alpha = roundedMask(view.rounded ?? 0, (w * view.rect.width) / Math.max(1, h * view.rect.height))\n const quad = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ map: target.texture, side: THREE.DoubleSide, depthTest: false, depthWrite: false, ...(alpha ? { alphaMap: alpha, transparent: true } : {}) }))\n const frame = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ color: 0x0b0c0e, side: THREE.DoubleSide, depthTest: false, depthWrite: false, ...(alpha ? { alphaMap: alpha, transparent: true } : {}) }))\n quad.renderOrder = 1\n frame.visible = quad.visible = false\n overlay.add(frame, quad)\n const entry: Entry = { view, target, quad, frame, alpha }\n entries.push(entry)\n return () => take(entry)\n },\n setMain(camera) {\n mainCamera = camera\n },\n main(fallback) {\n if (!mainCamera) return fallback\n const persp = mainCamera as THREE_NS.PerspectiveCamera\n const back = fallback as THREE_NS.PerspectiveCamera\n if (persp.isPerspectiveCamera && back.isPerspectiveCamera && persp.aspect !== back.aspect) {\n persp.aspect = back.aspect\n persp.updateProjectionMatrix()\n }\n return mainCamera\n },\n render(scene) {\n if (!entries.length) return\n const { w, h } = size()\n const autoClear = gl.autoClear\n const shadows = gl.shadowMap.autoUpdate\n // the shadow maps were drawn for the main view this frame: the extra views reuse them\n gl.shadowMap.autoUpdate = false\n for (const entry of entries) {\n const cam = entry.view.camera as THREE_NS.PerspectiveCamera\n const aspect = (w * entry.view.rect.width) / Math.max(1, h * entry.view.rect.height)\n if (cam.isPerspectiveCamera && Math.abs(cam.aspect - aspect) > 1e-3) {\n cam.aspect = aspect\n cam.updateProjectionMatrix()\n }\n gl.setRenderTarget(entry.target)\n gl.clear()\n gl.render(scene, cam)\n }\n gl.setRenderTarget(null)\n gl.autoClear = false\n gl.setScissorTest(true)\n for (const entry of entries) {\n const r = entry.view.rect\n const x = r.x * w\n const y = (1 - r.y - r.height) * h\n const vw = r.width * w\n const vh = r.height * h\n for (const mesh of [entry.frame, entry.quad]) mesh.visible = false\n // the dark frame a few pixels larger, then the picture\n entry.frame.visible = true\n gl.setViewport(x - FRAME_PX, y - FRAME_PX, vw + 2 * FRAME_PX, vh + 2 * FRAME_PX)\n gl.setScissor(x - FRAME_PX, y - FRAME_PX, vw + 2 * FRAME_PX, vh + 2 * FRAME_PX)\n gl.render(overlay, ortho)\n entry.frame.visible = false\n entry.quad.visible = true\n entry.quad.scale.x = entry.view.mirror ? -1 : 1\n gl.setViewport(x, y, vw, vh)\n gl.setScissor(x, y, vw, vh)\n gl.render(overlay, ortho)\n entry.quad.visible = false\n }\n gl.setScissorTest(false)\n gl.setViewport(0, 0, w, h)\n gl.autoClear = autoClear\n gl.shadowMap.autoUpdate = shadows\n },\n get count() {\n return entries.length\n },\n dispose() {\n for (const entry of [...entries]) take(entry)\n plane.dispose()\n mainCamera = null\n },\n }\n}\n"],"mappings":"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","names":["impactKey","slides","control","key","key","box","box","document","key","key","key","key","a","b","g","box","STANDING_EYE","LOOK_RANGE","STANDOFF","APPROACH_SPEED","box","key","releaseObject3D","box","key","mk","fold","box","mk","list","box","key","BODY_HEIGHT","key","t","host","slides","box","releaseObject3D","push","height","step","fire","px","py","pz","tool","grab","room","id","status"]}
|