@adatechnology/game-vehicles-three 0.5.0 → 0.6.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.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/test-area/module.ts","../src/build.ts","../src/lite.ts","../src/vehicle-lod.ts","../src/cabin-smoke.ts","../src/test-area/scenarios.ts","../src/test-area/text.ts","../src/test-area/types.ts"],"sourcesContent":["import { DEFERRED_PRIORITY, DEFERRED_QUEUE_ID, footprintBlocker } from '@adatechnology/game-contracts'\nimport { discardObject3D } from '@adatechnology/game-shapes-three'\nimport type { AnimationClipSpec, Footprint, BenchChange, ModuleArea, ModuleControl, ModuleHost, ModuleLayer, ModuleMetric, ModuleScenario, TestableItem, TestableModule, Vec3 } from '@adatechnology/game-contracts'\nimport { buildVehicleItem, crackedGlassMaterial, createCreaseQueue, createVehicleDestructible, createVehicleKit } from '@adatechnology/game-vehicles'\nimport type { ParticleMaterials, VehicleContext, VehicleItem, VehicleKit } from '@adatechnology/game-vehicles'\nimport { isRenderPools } from '@adatechnology/game-render-three'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\n\nimport { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { createVehiclesThree, primaryPaint } from '../build'\nimport { createVehicleLod } from '../vehicle-lod'\nimport type { VehicleLod } from '../vehicle-lod'\nimport { createCabinSmoke } from '../cabin-smoke'\nimport { createScenarios } from './scenarios'\nimport { fill, TEXT } from './text'\nimport { LIBRARY_BANK } from '@adatechnology/game-audio'\nimport { DEFAULT_TEST_WRECKS, defaultEffectIds, defaultSoundIds } from './types'\nimport type { EffectsLike, VehiclesContext, VehiclesTestFleet, VehiclesTestOptions } from './types'\n\nexport const VEHICLES_AREA_ID = 'vehicles_area'\n\n/** The eight vehicles of the Frota test page, in its order, and the item id each one has in the area. */\nexport const DEFAULT_TEST_VEHICLES: readonly string[] = ['compact_hatch', 'midsize_sedan', 'midsize_pickup', 'sport_bike', 'box_truck', 'city_bus', 'battle_tank', 'attack_helicopter']\nconst ITEM_OF: Readonly<Record<string, string>> = { compact_hatch: 'hatch', midsize_sedan: 'sedan', midsize_pickup: 'pickup', sport_bike: 'sport_bike', box_truck: 'box_truck', city_bus: 'city_bus', battle_tank: 'battle_tank', attack_helicopter: 'attack_helicopter' }\nconst itemId = (key: string): string => ITEM_OF[key] ?? key\n\n/** One item of the area: the fleet vehicle it is built from, its item id and, for a wreck, the scenario built into it. */\ntype Entry = { readonly key: string; readonly id: string; readonly scenario?: string }\n\nconst LANE = { z: 11, from: -12, wall: 13 }\n/** Radians a door, hood or lid may be off its rest and still count as shut. */\nconst LEAF_REST_RADIANS = 0.02\nconst MATERIAL_COLOURS: Record<string, number> = { metal: 0xcccccc, glass: 0x44aaff, rubber: 0xff9900, fuel: 0xff3300 }\nconst ZONE_COLOURS: Record<string, number> = { door: 0x55dd55, hood: 0xdddd33, lid: 0xdd9933, bumper: 0xdd55dd, glass: 0x44aaff, light: 0xffffff, wheel: 0xff7733 }\n\ntype Three = any\n/** Parts whose bottom is above this (m, from the ground) are overhead: the player walks under them (the helicopter's rotor, the tank's gun). */\nconst BODY_HEIGHT = 1.7\ntype Placed = {\n readonly root: any\n readonly key: string\n /** The damage scenario built into a wreck (its size is not the design size, so it is left out of the size error). */\n readonly scenario?: string\n readonly item: VehicleItem\n readonly index: number\n paint?: any\n /** Near in full, far fused (`createVehicleLod`); none in the light quality, which is fused already. */\n lod?: VehicleLod\n /** Hit: its damage only exists on the full model. */\n touched?: boolean\n /** Leaves away from their rest (an open door): drawn in full while any is. */\n posedParts?: Set<string>\n size?: { length: number; width: number; height: number }\n /** What the walking player bumps into, in the root's own space: the box of the parts low enough to hit a body (a rotor overhead is walked under). */\n footprint?: Footprint\n helpers: any[]\n}\n\n/**\n * The vehicles test area as a `TestableModule`: the vehicles of the Frota test (hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter), each with its own\n * `DestructibleImpl` and its door, hood and trunk clips, the eleven scenarios of that page (literal) and two for the drivers. The bench sets the quality (full or light mode), the paint\n * by seed and palette, the driving mode and the surface, and shows the damageable boxes by material, the zones by type and the axes of the output frame. Effects (fire, glass, sparks,\n * exhaust) are requested by id through `host.effects` when the host has it; this module draws none.\n */\nexport function createVehiclesTestModule(options: VehiclesTestOptions = {}): TestableModule<VehiclesContext> & { readonly placed: ReadonlyMap<string, unknown> } {\n const fleet: VehiclesTestFleet = options.fleet ?? { colorFromSeed, fleetDims, installFleet, paintPalettes, paletteOf }\n const locale = options.locale ?? 'pt-BR'\n const text = TEXT[locale] ?? (TEXT['pt-BR'] as (typeof TEXT)[string])\n const keys = options.vehicles ?? DEFAULT_TEST_VEHICLES\n const wrecks = options.wrecks ?? DEFAULT_TEST_WRECKS\n const entries: Entry[] = [...keys.map((key): Entry => ({ key, id: itemId(key) })), ...wrecks.map((w): Entry => ({ key: w.vehicle, id: w.key, scenario: w.scenario }))]\n const effectIds = { ...defaultEffectIds, ...options.effects }\n const soundIds = { ...defaultSoundIds, ...options.sounds }\n const settings = { quality: 'high', paint: false, seed: 1, palette: 'auto', driving: 'arcade', surface: 'dry_asphalt' }\n const kits = new WeakMap<object, VehicleKit>()\n const placed = new Map<string, Placed>()\n // the cabins hold the room's smoke out: through a shut car it does not pass, it gets in only by an open door, a broken window or a bullet hole\n const cabins = createCabinSmoke()\n let host: ModuleHost | null = null\n let three: Three = null\n let counter = 0\n let helpersShown = ''\n let axes: any[] = []\n let lane: Lane | null = null\n\n type Lane = { car: any; group: any; wall: any; mode: 'arcade' | 'semi'; step(dt: number): void; speed(): number; distance(): number; done: boolean; stopped: number }\n\n const effects = (): EffectsLike | undefined => host?.effects\n // the sounds are asked of the host's shared engine by id (the sink may be absent, and then the module is silent)\n const audio = () => host?.audio\n let engineLoop: { set(state: { volume?: number; frequency?: number; position?: Vec3 }): void; stop(): void } | undefined\n const stopEngine = (): void => {\n engineLoop?.stop()\n engineLoop = undefined\n }\n\n /** The puffs' materials come from the host's pool when it lends one (read at each puff: the host attaches after the first build). */\n const particleMaterials: ParticleMaterials = {\n own: <TMaterial>(build: () => TMaterial): TMaterial => (isRenderPools(host?.pools) ? (host.pools.materials.own(build as never) as unknown as TMaterial) : build()),\n release: (material) => (isRenderPools(host?.pools) ? host.pools.materials.release(material as never) : (material as { dispose?(): void }).dispose?.()),\n }\n\n const kitFor = (THREE: Three): VehicleKit => {\n three = THREE\n let kit = kits.get(THREE)\n if (!kit) {\n if (options.createKit) kit = options.createKit(THREE)\n else {\n kit = createVehicleKit({ THREE, locale, particleMaterials, effects: () => host?.effects, ...(options.document ? { document: options.document as never } : {}) })\n fleet.installFleet(kit)\n }\n kits.set(THREE, kit)\n }\n return kit\n }\n\n const paletteFor = (key: string) => (settings.palette === 'civil' ? fleet.paintPalettes.civil : settings.palette === 'military' ? fleet.paintPalettes.military : fleet.paletteOf(key))\n const paintOf = (entry: Placed): void => {\n if (!settings.paint) return\n entry.lod?.dispose()\n delete entry.lod\n const color = fleet.colorFromSeed(settings.seed + entry.index, paletteFor(entry.key))\n if (!entry.paint) {\n const vehicle = entry.item.vehicle as unknown as { vehicle: any }\n const primary = primaryPaint(entry.item.vehicle)\n if (!primary) return\n entry.paint = primary.clone()\n vehicle.vehicle.traverse((mesh: any) => {\n if (!mesh.isMesh) return\n if (Array.isArray(mesh.material)) mesh.material = mesh.material.map((m: any) => (m === primary ? entry.paint : m))\n else if (mesh.material === primary) mesh.material = entry.paint\n })\n }\n entry.paint.color.set(color)\n }\n\n const item = ({ key, id: itemKey, scenario }: Entry): TestableItem => ({\n id: itemKey,\n name: text.items[itemKey] ?? key,\n movable: false,\n // the first build of a vehicle takes most of a second\n slow: true,\n build: (THREE: unknown) => {\n const kit = kitFor(THREE as Three)\n const built = buildVehicleItem(kit, key, { lod: settings.quality === 'lite', ...(scenario ? { scenario } : {}) })\n built.root.userData.kit = kit\n const entry: Placed = { root: built.root, key, ...(scenario ? { scenario } : {}), item: built, index: counter++, helpers: [] }\n placed.set(built.root.uuid, entry)\n // measured now, before the destructible adds its own plates and mirrors: this is the size the fleet records\n measure(entry)\n paintOf(entry)\n return built.root\n },\n impl: (root: unknown, id: string) => {\n const r = root as { userData: Record<string, unknown> }\n const kit = r.userData.kit as VehicleKit\n const d = createVehicleDestructible(kit, r.userData.vehicle as VehicleContext, { id, frame: root, name: text.items[itemKey] ?? key, creaseQueue })\n tapEffects(d)\n // a leaf the room swings (door, hood, lid) is posed through here: away from its rest the vehicle draws in full, or the fused one shows it shut\n const setPartPose = d.setPartPose?.bind(d)\n {\n const rests = new Map((d.describe().parts as Array<{ id: string; rotation?: Vec3 }>).map((part) => [part.id, part.rotation ?? [0, 0, 0]]))\n d.setPartPose = (partId: string, position: Vec3, rotation?: Vec3) => {\n const entry = [...placed.values()].find((candidate) => candidate.root === root)\n const rest = rests.get(partId) ?? [0, 0, 0]\n const isOpen = (rotation ?? [0, 0, 0]).some((angle, axis) => Math.abs(angle - (rest[axis] ?? 0)) > LEAF_REST_RADIANS)\n if (entry) {\n entry.posedParts ??= new Set()\n if (isOpen) entry.posedParts.add(partId)\n else entry.posedParts.delete(partId)\n }\n return setPartPose?.(partId, position, rotation)\n }\n }\n const hitBody = d.hit.bind(d)\n d.hit = (h: never) => {\n const entry = [...placed.values()].find((candidate) => candidate.root === root)\n if (entry) entry.touched = true\n return hitBody(h)\n }\n cabins.track(id, d, root as { parent: unknown | null })\n r.userData.destructible = d\n return d\n },\n ...(clipsOf(key) ? { animations: clipsOf(key) as AnimationClipSpec[] } : {}),\n })\n\n // the clips are numbers (rotations of the door, hood and lid parts), so any three.js namespace computes them: the one in the options, else the global one\n const clipCache = new Map<string, AnimationClipSpec[]>()\n const clipsOf = (key: string): AnimationClipSpec[] | undefined => {\n const THREE = options.three ?? (globalThis as { THREE?: unknown }).THREE\n if (!THREE) return undefined\n if (!clipCache.has(key)) {\n const kit = kitFor(THREE as Three)\n const built = buildVehicleItem(kit, key)\n const d = createVehicleDestructible(kit, built.vehicle, { id: `${itemId(key)}_clips`, frame: built.root, headless: true })\n clipCache.set(key, d.animations())\n kit.dispose(built.vehicle)\n }\n return clipCache.get(key)\n }\n\n // events of the vehicle become effect requests: the module owns no particle code\n const tapEffects = (d: { hit(h: never): unknown[]; update?(dt: number): unknown[] }): void => {\n const request = (events: unknown[]): void => {\n const fx = effects()\n if (!fx) return\n for (const e of events as { type: string; part?: string; point?: Vec3; worldPoint?: Vec3 }[]) {\n const position = e.point ?? e.worldPoint\n if (!position) continue\n // a pierced tank only leaks; when the leak catches fire the whole sequence plays (the fire runs to the tank, then the blast)\n if (e.type === 'ignite') fx.play({ effect: /fuel_tank|tank/.test(e.part ?? '') ? effectIds.leakIgnited : effectIds.ignite, point: position })\n else if (e.type === 'explode') fx.play({ effect: effectIds.explode, point: position })\n else if (e.type === 'leak') fx.play({ effect: effectIds.leak, point: position })\n else if (e.type === 'fracture' && /glass|window|windshield/.test(e.part ?? '')) fx.play({ effect: effectIds.glass, point: position })\n else if (e.type === 'hole') fx.play({ effect: /glass|window|windshield/.test(e.part ?? '') ? effectIds.glass : effectIds.sparks, point: position })\n }\n }\n const hit = d.hit.bind(d)\n d.hit = (h) => {\n const events = hit(h)\n request(events)\n return events\n }\n if (d.update) {\n const update = d.update.bind(d)\n d.update = (dt) => {\n const events = update(dt)\n request(events)\n return events\n }\n }\n }\n\n // ---- measuring and the layers ----------------------------------------------------------------------------------------------------------\n const rootMatrix = (entry: Placed): any => {\n const m = new three.Matrix4().copy(entry.root.matrixWorld).invert()\n return m.multiply((entry.item.vehicle as unknown as { vehicle: any }).vehicle.matrixWorld)\n }\n const measure = (entry: Placed): { length: number; width: number; height: number } => {\n if (entry.size) return entry.size\n entry.root.updateMatrixWorld(true)\n const inverse = new three.Matrix4().copy(entry.root.matrixWorld).invert()\n const bounds = new three.Box3()\n const low = new three.Box3()\n const piece = new three.Box3()\n const matrix = new three.Matrix4()\n entry.root.traverse((mesh: any) => {\n if (!mesh.isMesh || !mesh.geometry || mesh.userData.ghost) return\n for (let p = mesh; p; p = p.parent) if (p.visible === false) return\n if (mesh.userData.helper) return\n mesh.geometry.computeBoundingBox()\n piece.copy(mesh.geometry.boundingBox).applyMatrix4(matrix.multiplyMatrices(inverse, mesh.matrixWorld))\n bounds.union(piece)\n if (piece.min.y < BODY_HEIGHT) low.union(piece)\n })\n const size = bounds.getSize(new three.Vector3())\n entry.size = { length: size.z, width: size.x, height: size.y }\n if (!low.isEmpty()) entry.footprint = { minX: low.min.x, maxX: low.max.x, minZ: low.min.z, maxZ: low.max.z }\n return entry.size\n }\n const clearHelpers = (): void => {\n for (const entry of placed.values()) {\n discardObject3D(entry.helpers)\n entry.helpers = []\n }\n discardObject3D(axes)\n axes = []\n helpersShown = ''\n }\n const boxKey = (): string => `${host?.bench?.layer('damageables')}|${host?.bench?.layer('zones')}|${host?.bench?.layer('axes')}|${placed.size}`\n const refreshLayers = (): void => {\n if (!host?.bench || !three) return\n clearHelpers()\n const kit = [...placed.values()][0] && ((([...placed.values()][0] as Placed).root.userData.kit as VehicleKit | undefined) ?? undefined)\n const mark = (entry: Placed, box: any, color: number): void => {\n const helper = new three.Box3Helper(box, color)\n helper.userData.helper = true\n entry.root.add(helper)\n entry.helpers.push(helper)\n }\n if (kit) {\n for (const entry of placed.values()) {\n if (!entry.root.parent) continue\n entry.root.updateMatrixWorld(true)\n const matrix = rootMatrix(entry)\n if (host.bench.layer('damageables')) for (const d of kit.damageables(entry.item.vehicle, matrix) as { material: string; box: any }[]) mark(entry, d.box, MATERIAL_COLOURS[d.material] ?? 0xffffff)\n if (host.bench.layer('zones')) {\n for (const zone of (entry.item.vehicle as unknown as { zones: { type: string; box?: { x0: number; y0: number; z0: number; x1: number; y1: number; z1: number } }[] }).zones ?? []) {\n if (!zone.box || zone.type === 'internal') continue\n const box = new three.Box3(new three.Vector3(zone.box.x0, zone.box.y0, zone.box.z0), new three.Vector3(zone.box.x1, zone.box.y1, zone.box.z1)).applyMatrix4(matrix)\n mark(entry, box, ZONE_COLOURS[zone.type] ?? 0xffffff)\n }\n }\n }\n }\n if (host.bench.layer('axes')) {\n const front = new three.ArrowHelper(new three.Vector3(0, 0, 1), new three.Vector3(0, 0.05, 0), 3, 0x3366ff)\n const right = new three.ArrowHelper(new three.Vector3(-1, 0, 0), new three.Vector3(0, 0.05, 0), 3, 0xff3333)\n const up = new three.ArrowHelper(new three.Vector3(0, 1, 0), new three.Vector3(0, 0.05, 0), 3, 0x33cc33)\n for (const arrow of [front, right, up]) {\n ;(host.scene as any).add(arrow)\n axes.push(arrow)\n }\n }\n helpersShown = boxKey()\n }\n\n // ---- the walking player ------------------------------------------------------------------------------------------------------------------\n // every vehicle on the floor (and the car on the lane) is solid: the point is taken into the vehicle's own space, so a turned vehicle blocks by its turned footprint\n const laneBlocked = footprintBlocker(\n () => lane?.group,\n () => (lane ? { minX: -lane.car.width / 2, maxX: lane.car.width / 2, minZ: -lane.car.length / 2, maxZ: lane.car.length / 2 } : null),\n )\n const blocked = (x: number, z: number, radius: number): boolean => {\n for (const entry of placed.values()) if (entry.footprint && footprintBlocker(entry.root, entry.footprint)(x, z, radius)) return true\n return laneBlocked(x, z, radius)\n }\n\n // ---- the lane ---------------------------------------------------------------------------------------------------------------------------\n const clearLane = (): void => {\n stopEngine()\n if (!lane) return\n lane.group.parent?.remove(lane.group)\n lane.wall.parent?.remove(lane.wall)\n lane = null\n }\n const startLane = (): void => {\n if (!host || !three) return\n clearLane()\n const kit = kitFor(three)\n const vehicles = createVehiclesThree(three, { kit, fleet })\n const built = vehicles.build('compact_hatch', { quality: 'lite', seed: settings.seed })\n const wall = new three.Mesh(new three.BoxGeometry(0.6, 2, 6), new three.MeshStandardMaterial({ color: 0x777777 }))\n wall.position.set(LANE.wall + 0.3, 1, LANE.z)\n const scene = host.scene as any\n scene.add(built.group, wall)\n const mode = settings.driving === 'semi' ? 'semi' : 'arcade'\n const surfaces = createSurfaces()\n const idle = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const state = { time: 0, exhaust: 0, ended: false, wasBlocked: false }\n const arcade = createArcadeDriver({ length: built.length, width: built.width })\n const semi = createSemiSimDriver({}, { surfaces })\n const driver = mode === 'semi' ? semi : arcade\n driver.place(LANE.from, LANE.z, 0)\n const gap = (): number => LANE.wall - (driver.state.x + built.length / 2)\n // brakes when the stopping distance (at the rule's deceleration, the surface's grip in the semi mode) plus a margin reaches the wall\n const decel = (): number => (mode === 'semi' ? 9 * surfaces.get(settings.surface).grip : arcade.spec.brakeAgainstMotion)\n const brakeAt = (): number => (lane ? (lane.speed() * lane.speed()) / (2 * decel()) + 3 : 3)\n const pose = (): void => {\n built.group.position.set(driver.state.x, 0, driver.state.z)\n built.group.rotation.y = driver.state.yaw + Math.PI / 2\n }\n pose()\n engineLoop = audio()?.loop?.(soundIds.engine, { position: [driver.state.x, 0.5, driver.state.z] })\n const log = (key: 'crash' | 'end', value: number): void => host?.log(fill(text, locale, text.lane[key], value.toFixed(1)))\n lane = {\n car: built,\n group: built.group,\n wall,\n mode,\n done: false,\n stopped: 0,\n speed: () => ('u' in driver.state ? (driver.state as { u: number }).u : (driver.state as { v: number }).v),\n distance: () => driver.state.x - LANE.from,\n step(dt) {\n if (state.ended) return\n state.time += dt\n const braking = gap() < brakeAt() && state.time > 0.5\n const input = { ...idle, throttle: braking ? 0 : 1, brake: braking ? 1 : 0, steer: Math.sin(state.time * 1.4) * 0.15 }\n if (mode === 'arcade') {\n const { events } = arcade.step(input, dt, { blocked: (x, z, yaw) => vehicleCorners(arcade.spec, x, z, yaw).some(([px]) => px >= LANE.wall) })\n for (const e of events) {\n if (e.type !== 'crash') continue\n log('crash', e.speed)\n audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, e.speed / 15) })\n }\n } else {\n semi.step(input, dt, { ground: () => ({ surface: settings.surface }) })\n if (gap() <= 0) {\n state.ended = true\n log('crash', Math.abs((semi.state as { u: number }).u))\n audio()?.play({ sound: soundIds.crash, position: [driver.state.x, 0.5, driver.state.z], volume: Math.min(1, Math.abs((semi.state as { u: number }).u) / 15) })\n }\n }\n pose()\n {\n const speed = Math.abs(lane?.speed() ?? 0)\n // the game's engine (jogo L70421): level 0.035 + speed x 0.003, frequency 38 + speed x 7\n engineLoop?.set({ volume: state.ended ? 0 : 0.035 + speed * 0.003, frequency: 38 + speed * 7, position: [driver.state.x, 0.5, driver.state.z] })\n }\n state.exhaust -= dt\n const fx = effects()\n if (fx && state.exhaust <= 0 && Math.abs(lane?.speed() ?? 0) > 0.5) {\n state.exhaust = 0.4\n fx.play({ effect: effectIds.exhaust, point: [driver.state.x - Math.cos(driver.state.yaw) * (built.length / 2), 0.3, driver.state.z + Math.sin(driver.state.yaw) * (built.length / 2)], scale: Math.min(1, Math.abs(lane?.speed() ?? 0) / 17) })\n }\n if (!state.ended && state.time > 1 && Math.abs(lane?.speed() ?? 0) < 0.05) {\n state.ended = true\n log('end', Math.max(0, gap()))\n }\n },\n }\n }\n\n // ---- the bench ----------------------------------------------------------------------------------------------------------------------------\n const onChange = (change: BenchChange): void => {\n if (change.kind === 'layer') return refreshLayers()\n if (change.kind === 'action') {\n if (change.id === 'repaint') for (const entry of placed.values()) paintOf(entry)\n else if (change.id === 'drive_lane') startLane()\n else if (change.id === 'clear_lane') clearLane()\n else if (change.id === 'honk') audio()?.play({ sound: soundIds.horn, position: lane ? [lane.group.position.x, 1, lane.group.position.z] : undefined })\n return\n }\n switch (change.id) {\n case 'quality': settings.quality = String(change.value); break\n case 'paint_by_seed': settings.paint = Boolean(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'color_seed': settings.seed = Number(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'palette': settings.palette = String(change.value); for (const entry of placed.values()) paintOf(entry); break\n case 'driving': settings.driving = String(change.value); break\n case 'surface': settings.surface = String(change.value); break\n default: break\n }\n }\n\n // one crease queue for every vehicle of the area; a host with a frame budget runs it, any other leaves each vehicle smoothing in its own update\n const creaseQueue = createCreaseQueue()\n\n const updateLod = (entry: Placed): void => {\n if (!host || settings.quality === 'lite') return\n entry.lod ??= createVehicleLod(entry.root.userData.kit, entry.item.vehicle, entry.root, entry.root.children[0])\n const at = host.player().position\n const distance = Math.hypot(at[0] - entry.root.position.x, at[2] - entry.root.position.z)\n // rolling over and blowing up move the body without a part pose: the fused copy would stay upright where the car was\n const c = entry.item.vehicle as { rollState?: unknown; flipped?: boolean; blast?: unknown; exploded?: boolean } | undefined\n if (c && (c.rollState || c.flipped || c.blast || c.exploded)) entry.touched = true\n // a wreck is built damaged: it never draws fused, only in batches (as a posed one)\n entry.lod.update(distance, entry.touched === true, entry.scenario !== undefined || (entry.posedParts?.size ?? 0) > 0)\n }\n\n const frame = (dt: number): void => {\n for (const [id, entry] of placed) {\n if (!entry.root.parent) {\n placed.delete(id)\n continue\n }\n measure(entry)\n updateLod(entry)\n }\n if (host?.bench && boxKey() !== helpersShown && (host.bench.layer('damageables') || host.bench.layer('zones') || helpersShown !== '')) refreshLayers()\n lane?.step(dt)\n cabins.sync(effects())\n }\n\n const count = (): { drawCalls: number; triangles: number } => {\n let drawCalls = 0\n let triangles = 0\n for (const entry of placed.values()) {\n entry.root.traverse((mesh: any) => {\n if (!mesh.isMesh || mesh.userData.helper) return\n for (let p = mesh; p; p = p.parent) if (p.visible === false) return\n drawCalls += 1\n const g = mesh.geometry\n triangles += (g.index ? g.index.count : g.attributes.position.count) / 3\n })\n }\n return { drawCalls, triangles: Math.round(triangles) }\n }\n const boxesOf = (material: string): number => {\n let total = 0\n for (const entry of placed.values()) {\n const kit = entry.root.userData.kit as VehicleKit | undefined\n if (kit) total += (kit.damageables(entry.item.vehicle) as { material: string }[]).filter((d) => d.material === material).length\n }\n return total\n }\n const sizeError = (): number => {\n let worst = 0\n for (const entry of placed.values()) {\n const want = fleet.fleetDims(entry.key)\n const got = entry.size\n if (!want || !got || entry.scenario) continue\n worst = Math.max(worst, Math.abs(got.length - want.length), Math.abs(got.width - want.width), Math.abs(got.height - want.height))\n }\n return Math.round(worst * 1000)\n }\n\n return {\n id: VEHICLES_AREA_ID,\n name: text.name,\n ground: { surface: 'road' },\n group: text.group,\n get placed() {\n return placed\n },\n items: () => entries.map(item),\n area: (): ModuleArea => {\n // the front row, each vehicle given room by its width, the front to +z; what is wider than a street (a helicopter with its rotor) stands alone in a row behind\n const gap = 1.6\n const WIDE = 6\n const rowOf = (list: readonly Entry[], z: number) => {\n let cursor = 0\n const spots = list.map((entry) => {\n const width = fleet.fleetDims(entry.key)?.width ?? 2\n const x = cursor + width / 2\n cursor += width + gap\n return { id: entry.id, x }\n })\n return { spots, z, width: Math.max(0, cursor - gap) }\n }\n const front = rowOf(entries.filter((e) => (fleet.fleetDims(e.key)?.width ?? 2) <= WIDE), 0)\n const back = rowOf(entries.filter((e) => (fleet.fleetDims(e.key)?.width ?? 2) > WIDE), -16)\n const placements = [front, back].flatMap((row) => row.spots.map(({ id, x }) => ({ item: id, position: [x - row.width / 2, 0, row.z] as Vec3, rotationY: 0 })))\n return { placements, view: { eye: [0, 5, Math.max(14, front.width * 0.6)], target: [0, 1, -2] } }\n },\n controls: (): ModuleControl[] => {\n const surfaceIds = createSurfaces().surfaces.map((s) => s.id)\n return [\n { kind: 'choice', id: 'quality', name: text.controls.quality, hint: text.hints.quality, options: (['high', 'lite'] as const).map((id) => ({ id, name: text.options.quality[id] as string })), default: 'high' },\n { kind: 'boolean', id: 'paint_by_seed', name: text.controls.paint_by_seed, hint: text.hints.paint_by_seed, default: false },\n { kind: 'number', id: 'color_seed', name: text.controls.color_seed, min: 0, max: 999, step: 1, default: 1 },\n { kind: 'choice', id: 'palette', name: text.controls.palette, hint: text.hints.palette, options: (['auto', 'civil', 'military'] as const).map((id) => ({ id, name: text.options.palette[id] as string })), default: 'auto' },\n { kind: 'choice', id: 'driving', name: text.controls.driving, hint: text.hints.driving, options: (['arcade', 'semi'] as const).map((id) => ({ id, name: text.options.driving[id] as string })), default: 'arcade' },\n { kind: 'choice', id: 'surface', name: text.controls.surface, hint: text.hints.surface, options: surfaceIds.map((id) => ({ id, name: text.options.surface[id] ?? id })), default: 'dry_asphalt' },\n { kind: 'action', id: 'repaint', name: text.actions.repaint },\n { kind: 'action', id: 'drive_lane', name: text.actions.drive_lane },\n { kind: 'action', id: 'clear_lane', name: text.actions.clear_lane },\n { kind: 'action', id: 'honk', name: text.actions.honk },\n ]\n },\n layers: (): ModuleLayer[] => (['damageables', 'zones', 'axes'] as const).map((id) => ({ id, name: text.layers[id], default: false })),\n metrics: (): ModuleMetric[] => [\n { id: 'vehicles', name: text.metrics.vehicles, read: () => placed.size },\n { id: 'triangles', name: text.metrics.triangles, read: () => count().triangles },\n { id: 'draw_calls', name: text.metrics.draw_calls, read: () => count().drawCalls },\n { id: 'size_error_mm', name: text.metrics.size_error_mm, unit: 'mm', read: sizeError },\n { id: 'metal', name: text.metrics.metal, read: () => boxesOf('metal') },\n { id: 'glass', name: text.metrics.glass, read: () => boxesOf('glass') },\n { id: 'rubber', name: text.metrics.rubber, read: () => boxesOf('rubber') },\n { id: 'fuel', name: text.metrics.fuel, read: () => boxesOf('fuel') },\n { id: 'speed', name: text.metrics.speed, unit: 'km/h', digits: 0, read: () => Math.round(Math.abs(lane?.speed() ?? 0) * 3.6) },\n { id: 'lane', name: text.metrics.lane, unit: 'm', digits: 1, read: () => lane?.distance() ?? 0 },\n ],\n scenarios: (): ModuleScenario<VehiclesContext>[] => createScenarios({ text, locale }),\n attach(lent) {\n host = lent\n three = lent.THREE\n const stopChange = lent.bench?.onChange(onChange)\n const stopFrame = lent.onFrame(frame)\n const stopBlocker = lent.addBlocker?.(blocked)\n const stopCrease = lent.defer?.(creaseQueue.deferredQueue(), DEFERRED_PRIORITY[DEFERRED_QUEUE_ID.VEHICLE_CREASE])\n if (isRenderPools(lent.pools)) lent.pools.materials.register('vehicles.cracked-glass', () => crackedGlassMaterial(three, new three.DataTexture(new Uint8Array(4), 1, 1)))\n // the engine loop and the horn live in the library bank of game-audio, which the room's engine does not carry on its own\n lent.audio?.register?.(LIBRARY_BANK)\n return () => {\n stopChange?.()\n stopFrame()\n stopBlocker?.()\n stopCrease?.()\n cabins.clear(effects())\n clearHelpers()\n clearLane()\n host = null\n }\n },\n }\n}\n\n/** What `loadVehiclesTestModule` needs of a room: `TestRoom.loadModule` has it. */\nexport type ModuleRoomLike = { loadModule(module: never): unknown }\n\n/**\n * Loads the vehicles module into a room. The door, hood and trunk clips of the items are computed when the room reads the items, before the module is lent the room's three.js\n * (`attach`), so this first lends an empty module to learn the namespace and then loads the real one with it. Pass `three` to skip that.\n */\nexport function loadVehiclesTestModule<Room extends ModuleRoomLike>(room: Room, options: VehiclesTestOptions = {}): ReturnType<Room['loadModule']> {\n let three = options.three\n if (!three) {\n room.loadModule({ id: 'vehicles_probe', name: 'Vehicles probe', group: 'Vehicles', items: () => [], attach: (lent: ModuleHost) => { three = lent.THREE; return () => undefined } } as never)\n }\n return room.loadModule(createVehiclesTestModule({ ...options, three }) as never) as ReturnType<Room['loadModule']>\n}\n","import { markKitOrigin } from '@adatechnology/game-contracts'\nimport type { Damageable, VehicleContext, VehicleKit } from '@adatechnology/game-vehicles'\n\nimport { colorFromSeed as defaultColorFromSeed, fleetDims as defaultFleetDims, paintPalettes as defaultPaintPalettes, paletteOf as defaultPaletteOf } from '@adatechnology/game-vehicles-fleet'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\n\nexport type VehicleQuality = 'high' | 'lite'\n\n/** The measured size of a fleet vehicle in metres (the shape of `FleetDims` of `game-vehicles-fleet`). */\nexport interface FleetDims {\n length: number\n width: number\n height: number\n}\n\n/**\n * The fleet content the builder reads: the paint palettes, the size the team measured and the colour a seed picks. It is the shape of what\n * `game-vehicles-fleet` exports (`defaultVehicleFleet()` of `game-kit-defaults` hands it over), so this adapter imports no content.\n */\nexport interface VehicleFleetContent {\n readonly paintPalettes: { readonly civil: unknown; readonly military: unknown }\n paletteOf(group: string): unknown\n colorFromSeed(seed: number | string, palette: unknown): string\n fleetDims(id: string): FleetDims | undefined\n}\n\nexport interface BuildVehicleOptions {\n /** `high`: the kit's vehicle at full detail. `lite`: fused into six meshes. Default `high`. */\n quality?: VehicleQuality\n /** Body colour as a CSS colour. Wins over `seed`. */\n color?: string\n /** Picks the body colour from the palette of the vehicle's group. */\n seed?: number | string\n /** State of the vehicle. Default `intact`. */\n state?: 'intact' | 'damaged' | 'modified'\n}\n\nexport interface BuiltVehicle {\n key: string\n quality: VehicleQuality\n /** The colour the body ended up with, or null when the vehicle keeps its own paint. */\n color: string | null\n seed: number | string | null\n /** Group in the game frame: front on +z, right on -x, centred on x and z, wheels on y = 0. */\n group: any\n /** Damageable boxes in the game frame. */\n damageables: Damageable[]\n triangles: number\n drawCalls: number\n /** Measured size of the group in metres: length along z, width along x, height along y. */\n length: number\n width: number\n height: number\n /** Pieces dropped for being smaller than 3 cm (lite only). */\n pruned: number\n /** The measured size the team recorded for this vehicle, when the fleet knows it. */\n expected: FleetDims | undefined\n /** The kit's context, for damage and animation (full detail only). */\n context: VehicleContext | null\n dispose(): void\n}\n\nexport interface VehiclesThree {\n readonly THREE: any\n readonly kit: VehicleKit\n build(key: string, options?: BuildVehicleOptions): BuiltVehicle\n}\n\nexport interface VehiclesThreeOptions {\n kit: VehicleKit\n /**\n * The fleet's palettes and measured sizes (`defaultVehicleFleet()` of `game-kit-defaults`, or the game's own). Default the ones of `game-vehicles-fleet`.\n * @deprecated pass `fleet`; the default is removed in the next major.\n */\n fleet?: VehicleFleetContent\n /** Vehicle id to the group id whose palette paints it. Defaults to the fleet group of the vehicle (`military` for the military ones). */\n groupOf?: (key: string) => string\n}\n\n/** Triangles and draw calls of the visible meshes of an object (a multi-material mesh costs one call per group). */\nfunction count(root: any): { triangles: number; drawCalls: number } {\n let triangles = 0\n let drawCalls = 0\n root.traverse((o: any) => {\n if (!o.isMesh || !o.geometry) return\n for (let p = o; p; p = p.parent) if (p.visible === false) return\n const g = o.geometry\n const n = g.index ? g.index.count : g.attributes.position ? g.attributes.position.count : 0\n if (Array.isArray(o.material) && g.groups.length) drawCalls += g.groups.length\n else drawCalls++\n triangles += n / 3\n })\n return { triangles: Math.round(triangles), drawCalls }\n}\n\n/** The material most triangles are painted with: the body colour. */\nexport function primaryPaint(c: any): any {\n let best: any = null\n let bestCount = -1\n const counts = new Map<any, number>()\n c.vehicle.traverse((o: any) => {\n if (!o.isMesh || !o.geometry) return\n const mats = Array.isArray(o.material) ? o.material : [o.material]\n const g = o.geometry\n const n = (g.index ? g.index.count : g.attributes.position.count) / 3\n for (const m of mats) if (c.paints.has(m)) counts.set(m, (counts.get(m) || 0) + n)\n })\n counts.forEach((n, m) => {\n if (n > bestCount) {\n bestCount = n\n best = m\n }\n })\n return best\n}\n\n/**\n * Builds vehicles in a game frame. Port of `FrotaLeve.criar(...).construir` (frota-leve.js 14311-14442): the kit builds with +x to the front\n * and +z to the right; the game wants +z to the front and -x to the right, the vehicle centred on x and z and standing on y = 0.\n */\nexport function createVehiclesThree(THREE: any, options: VehiclesThreeOptions): VehiclesThree {\n const kit = options.kit\n const fleet: VehicleFleetContent = options.fleet ?? { colorFromSeed: defaultColorFromSeed, fleetDims: defaultFleetDims, paintPalettes: defaultPaintPalettes, paletteOf: defaultPaletteOf }\n const { colorFromSeed, fleetDims, paintPalettes, paletteOf } = fleet\n const groupOf = options.groupOf || ((key: string) => (kit.find(key)?.group === kit.config.defaultGroup ? 'cars' : String(kit.find(key)?.group)))\n const militaryKeys = new Set<string>()\n const isMilitary = (key: string): boolean => militaryKeys.has(key) || paletteOf(groupOf(key)) === paintPalettes.military\n\n const build = (key: string, o: BuildVehicleOptions = {}): BuiltVehicle => {\n const quality: VehicleQuality = o.quality === 'lite' ? 'lite' : 'high'\n const spec = kit.find(key)\n if (!spec) throw new Error(`createVehiclesThree: unknown vehicle \"${key}\"`)\n const seed = o.seed == null ? null : o.seed\n const color = o.color || (seed != null ? colorFromSeed(seed, isMilitary(key) ? paintPalettes.military : paintPalettes.civil) : null)\n const c: any = kit.build(key, o.state || 'intact', undefined, { lod: quality === 'lite' })\n c.root.updateMatrixWorld(true)\n const primary = primaryPaint(c)\n const rotation = new THREE.Matrix4().makeRotationY(-Math.PI / 2)\n const bounds = new THREE.Box3()\n const piece = new THREE.Box3()\n const turned = new THREE.Matrix4()\n c.vehicle.traverse((m: any) => {\n if (!m.isMesh || !m.geometry || m.userData.ghost) return\n for (let p = m; p; p = p.parent) if (p.visible === false) return\n m.geometry.computeBoundingBox()\n piece.copy(m.geometry.boundingBox).applyMatrix4(turned.multiplyMatrices(rotation, m.matrixWorld))\n bounds.union(piece)\n })\n const cx = (bounds.min.x + bounds.max.x) / 2\n const cz = (bounds.min.z + bounds.max.z) / 2\n const pivotMatrix = new THREE.Matrix4().makeTranslation(-cx, -bounds.min.y, -cz).multiply(rotation)\n const group = new THREE.Group()\n group.name = `vehicle:${key}`\n markKitOrigin(group, { owner: 'game-vehicles-three', kind: 'vehicle', id: key })\n const damageables = kit.damageables(c, pivotMatrix)\n let pruned = 0\n if (quality === 'high') {\n const pivot = new THREE.Group()\n pivot.name = 'vehicle'\n pivot.matrixAutoUpdate = false\n pivot.matrix.copy(pivotMatrix)\n pivot.matrixWorldNeedsUpdate = true\n c.vehicle.matrixAutoUpdate = true\n pivot.add(c.vehicle)\n group.add(pivot)\n if (color && primary) {\n const repainted = primary.clone()\n repainted.color.set(color)\n c.vehicle.traverse((m: any) => {\n if (!m.isMesh) return\n if (Array.isArray(m.material)) m.material = m.material.map((x: any) => (x === primary ? repainted : x))\n else if (m.material === primary) m.material = repainted\n })\n }\n markDamageables(c, damageables)\n group.updateMatrixWorld(true)\n } else {\n const fusion = fuse(THREE, c, pivotMatrix, color ? new THREE.Color(color) : null, primary, kit.lodHiddenMaterials())\n for (const mesh of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh)\n pruned = fusion.pruned\n }\n const size = new THREE.Box3().setFromObject(group).getSize(new THREE.Vector3())\n const counted = count(group)\n group.userData.damageables = damageables\n group.userData.key = key\n group.userData.quality = quality\n return {\n key,\n quality,\n color,\n seed,\n group,\n damageables,\n triangles: counted.triangles,\n drawCalls: counted.drawCalls,\n length: +size.z.toFixed(3),\n width: +size.x.toFixed(3),\n height: +size.y.toFixed(3),\n pruned,\n expected: fleetDims(key),\n context: quality === 'high' ? c : null,\n dispose() {\n group.traverse((m: any) => {\n if (m.geometry) m.geometry.dispose()\n })\n },\n }\n }\n\n return { THREE, kit, build }\n}\n\n/** Tags the meshes of each damageable zone (and the tyres) so a hit test can tell what it hit. */\nfunction markDamageables(c: any, damageables: Damageable[]): void {\n const byZone: Record<string, Damageable> = {}\n for (const d of damageables) byZone[d.zone] = d\n for (const z of c.zones || []) {\n const d = byZone[z.id]\n if (!d) continue\n for (const o of z.objs || z.meshes || []) if (o && o.userData) o.userData.damageable = { material: d.material, zone: d.zone }\n }\n for (const w of c.wheels || []) {\n const z = (c.zones || []).find((zz: any) => zz.type === 'wheel' && zz.objs && zz.objs.indexOf(w) >= 0)\n w.userData.damageable = { material: 'rubber', zone: z ? z.id : 'wheel' }\n }\n}\n","/**\n * The light mode of the team's Frota Leve (frota-leve.js 14202-14310): a built vehicle fused into six meshes, one per class of material,\n * with the meshes nobody sees from outside left out. A literal port: the classes, the thresholds (3 cm prune, 0.99 opacity, 0.5 metalness,\n * 0.25 and 0.45 emissive) and the colours are the team's.\n */\n\n/** The six classes of a fused vehicle, in the order they are added to the group. */\nexport const LITE_CLASSES = ['paint', 'trim', 'metal', 'glass', 'light', 'plate'] as const\nexport type LiteClass = (typeof LITE_CLASSES)[number]\n\n/** Smallest extent in metres a piece needs to survive the fusion (the plate is always kept). */\nexport const PRUNE_BELOW = 0.03\n\ninterface Accumulator {\n P: number[]\n N: number[]\n C: number[]\n U: number[]\n I: number[]\n nv: number\n alpha: boolean\n uv: boolean\n map: any\n}\n\nexport interface LiteFusion {\n acc: Record<LiteClass, Accumulator>\n pruned: number\n}\n\nconst createAccumulators = (): Record<LiteClass, Accumulator> => {\n const acc = {} as Record<LiteClass, Accumulator>\n for (const name of LITE_CLASSES) acc[name] = { P: [], N: [], C: [], U: [], I: [], nv: 0, alpha: name === 'glass', uv: name === 'plate', map: null }\n return acc\n}\n\n/** Which class a material belongs to, or `null` when it is left out. */\nexport function classify(mat: any, mesh: any, c: any): LiteClass | null {\n if (mat.map) {\n if (mesh.userData.plate) return 'plate'\n if ((mat.userData && mat.userData.grille) || mat.name === 'grille' || (mat.metalness != null && mat.roughness != null && !mat.transparent)) return 'trim'\n return null\n }\n if (mat.transparent && mat.opacity < 0.99) {\n const col = mat.color\n if (col.r > col.g + col.b * 0.9 && col.r > 0.35) return 'light'\n if (col.r > 0.8 && col.g > 0.8 && mat.opacity < 0.3) return null\n return 'glass'\n }\n if (mat.isMeshBasicMaterial) return null\n const e = mat.emissive\n const ei = mat.emissiveIntensity == null ? 1 : mat.emissiveIntensity\n if (e && ((e.r + e.g + e.b) / 3) * ei > 0.25 && !mat.metalness) return 'light'\n if (e && ((e.r + e.g + e.b) / 3) * ei > 0.45) return 'light'\n if (mat.metalness >= 0.5) return 'metal'\n if (c.paints && c.paints.has(mat)) return 'paint'\n if (mat.opacity < 1 && mat.transparent) return null\n return 'trim'\n}\n\n/** The vertex colour of a piece of a class. `paintColor` replaces the primary paint. */\nexport function classColor(mat: any, cls: LiteClass, primary: any, paintColor: any, out: any): any {\n if (cls === 'paint' && paintColor && mat === primary) return out.copy(paintColor)\n if (cls === 'light') {\n const e = mat.emissive\n const ei = mat.emissiveIntensity == null ? 1 : mat.emissiveIntensity\n if (e && e.r + e.g + e.b > 0.05) {\n out.copy(e).multiplyScalar(Math.max(1, ei) * 1.0)\n out.r = Math.min(out.r, 1)\n out.g = Math.min(out.g, 1)\n out.b = Math.min(out.b, 1)\n return out\n }\n return out.copy(mat.color)\n }\n if (mat.map) return out.setRGB(0.12, 0.13, 0.14)\n return out.copy(mat.color)\n}\n\n/** The material of each class (vertex colours; glass blends; light is unlit; the plate keeps its canvas texture). */\nexport function liteMaterials(THREE: any, environment: any): Record<LiteClass, any> {\n return {\n paint: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.42, metalness: 0.3, side: THREE.DoubleSide, envMap: environment, envMapIntensity: 0.35 }),\n trim: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.78, metalness: 0.08, side: THREE.DoubleSide }),\n metal: new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.32, metalness: 0.85, envMap: environment, envMapIntensity: 1.1, side: THREE.DoubleSide }),\n glass: new THREE.MeshStandardMaterial({ vertexColors: true, transparent: true, depthWrite: false, roughness: 0.06, metalness: 0.3, side: THREE.DoubleSide, envMap: environment, envMapIntensity: 0.9 }),\n light: new THREE.MeshBasicMaterial({ vertexColors: true, side: THREE.DoubleSide }),\n plate: new THREE.MeshStandardMaterial({ roughness: 0.5, metalness: 0.1, side: THREE.DoubleSide }),\n }\n}\n\n/**\n * Walks the built vehicle and collects every visible mesh, in the frame of `pivot`, into one set of arrays per class.\n * `hidden` is the set of materials nobody sees from outside (`kit.lodHiddenMaterials()`).\n */\nexport function fuse(THREE: any, c: any, pivot: any, paintColor: any, primary: any, hidden: ReadonlySet<any>): LiteFusion {\n const acc = createAccumulators()\n const mw = new THREE.Matrix4()\n const nm = new THREE.Matrix3()\n const v = new THREE.Vector3()\n const col = new THREE.Color()\n const tmp = new THREE.Box3()\n let pruned = 0\n c.vehicle.updateMatrixWorld(true)\n c.vehicle.traverse((o: any) => {\n if (!o.isMesh || o.isInstancedMesh || o.isSkinnedMesh || !o.geometry || !o.geometry.attributes.position) return\n for (let p = o; p; p = p.parent) if (p.visible === false) return\n if (o.userData && (o.userData.ghost || o.userData.skipLite)) return\n const mats = Array.isArray(o.material) ? o.material : [o.material]\n const geo = o.geometry\n mw.multiplyMatrices(pivot, o.matrixWorld)\n nm.getNormalMatrix(mw)\n const flip = mw.determinant() < 0\n geo.computeBoundingBox()\n tmp.copy(geo.boundingBox).applyMatrix4(mw)\n const ext = Math.max(tmp.max.x - tmp.min.x, tmp.max.y - tmp.min.y, tmp.max.z - tmp.min.z)\n const pa = geo.attributes.position\n const na = geo.attributes.normal\n const ua = geo.attributes.uv\n const ca = geo.attributes.color\n const ix = geo.index\n const tot = ix ? ix.count : pa.count\n const groups = Array.isArray(o.material) && geo.groups.length ? geo.groups : [{ start: 0, count: tot, materialIndex: 0 }]\n groups.forEach((gr: any) => {\n const mat = mats[gr.materialIndex] || mats[0]\n if (!mat || hidden.has(mat)) return\n const cls = classify(mat, o, c)\n if (!cls) return\n if (ext < PRUNE_BELOW && cls !== 'plate') {\n pruned++\n return\n }\n const A = acc[cls]\n const a0 = Math.min(gr.start, tot)\n let n0 = Math.min(gr.count, tot - a0)\n n0 -= n0 % 3\n if (n0 < 3) return\n const cc = classColor(mat, cls, primary, paintColor, col)\n const alpha = cls === 'glass' ? (mat.transparent ? mat.opacity : 1) : 1\n if (cls === 'plate' && A.map && mat.map !== A.map) return\n if (cls === 'plate') A.map = mat.map\n const remap = new Map<number, number>()\n for (let i = 0; i < n0; i++) {\n const vi = ix ? ix.getX(a0 + i) : a0 + i\n if (remap.has(vi)) continue\n remap.set(vi, A.nv++)\n v.fromBufferAttribute(pa, vi).applyMatrix4(mw)\n A.P.push(v.x, v.y, v.z)\n if (na) {\n v.fromBufferAttribute(na, vi).applyMatrix3(nm).normalize()\n A.N.push(v.x, v.y, v.z)\n } else A.N.push(0, 1, 0)\n let cr = cc.r\n let cg = cc.g\n let cb = cc.b\n if (ca && cls !== 'plate') {\n cr *= ca.getX(vi)\n cg *= ca.getY(vi)\n cb *= ca.getZ(vi)\n }\n if (A.alpha) A.C.push(cr, cg, cb, alpha)\n else A.C.push(cr, cg, cb)\n if (A.uv) A.U.push(ua ? ua.getX(vi) : 0, ua ? ua.getY(vi) : 0)\n }\n for (let t = 0; t < n0; t += 3) {\n const i0 = remap.get(ix ? ix.getX(a0 + t) : a0 + t) as number\n const i1 = remap.get(ix ? ix.getX(a0 + t + 1) : a0 + t + 1) as number\n const i2 = remap.get(ix ? ix.getX(a0 + t + 2) : a0 + t + 2) as number\n if (flip) A.I.push(i0, i2, i1)\n else A.I.push(i0, i1, i2)\n }\n })\n })\n return { acc, pruned }\n}\n\n/** One mesh per class that has triangles. */\nexport function liteMeshes(THREE: any, fusion: LiteFusion, materials: Record<LiteClass, any>): any[] {\n const meshes: any[] = []\n for (const name of LITE_CLASSES) {\n const A = fusion.acc[name]\n if (!A.I.length) continue\n const g = new THREE.BufferGeometry()\n g.setAttribute('position', new THREE.Float32BufferAttribute(A.P, 3))\n g.setAttribute('normal', new THREE.Float32BufferAttribute(A.N, 3))\n g.setAttribute('color', new THREE.Float32BufferAttribute(A.C, A.alpha ? 4 : 3))\n if (A.uv) g.setAttribute('uv', new THREE.Float32BufferAttribute(A.U, 2))\n g.setIndex(A.nv > 65535 ? new THREE.Uint32BufferAttribute(A.I, 1) : new THREE.Uint16BufferAttribute(A.I, 1))\n g.computeBoundingBox()\n g.computeBoundingSphere()\n let mt = materials[name]\n if (name === 'plate') {\n mt = mt.clone()\n mt.map = A.map\n if (mt.map) mt.map.needsUpdate = true\n }\n const mesh = new THREE.Mesh(g, mt)\n mesh.name = name\n mesh.castShadow = name !== 'glass' && name !== 'light'\n mesh.receiveShadow = name !== 'light'\n meshes.push(mesh)\n }\n return meshes\n}\n","import { markKitOrigin } from '@adatechnology/game-contracts'\nimport { createStaticBatcher } from '@adatechnology/game-render-three'\nimport type { StaticBatcher } from '@adatechnology/game-render-three'\n\nimport { fuse, liteMaterials, liteMeshes } from './lite'\nimport { primaryPaint } from './build'\n\n/** Past this distance (m) an untouched vehicle draws fused: nobody sees a door seam from here, and the full model costs hundreds of draw calls. */\nexport const VEHICLE_LOD_DISTANCE = 14\nconst BATCH_BUDGET_MS = 2\n\nexport type VehicleLod = {\n /** `touched`: hit or driven, from now on it always draws in full (its damage only exists there); `posed`: a door, hood or lid is open now (fused only while all are shut). */\n update(distance: number, touched: boolean, posed?: boolean): void\n readonly fused: boolean\n dispose(): void\n}\n\nconst isShown = (object: any, top: any): boolean => {\n for (let node = object; node && node !== top; node = node.parent) if (node.visible === false) return false\n return true\n}\n\n/** Shows `full` near and the kit's fused light mode (one mesh per class of material) far, in `root`'s own space. Hit tests read the full model, visible or not. */\nexport function createVehicleLod(kit: any, context: any, root: any, full: any): VehicleLod {\n const THREE = kit.THREE\n // the full model is drawn whole once, off-camera parts included, before it may hide: its buffers reach the GPU then, not in the frame of a\n // blast. A model rebuilt in place (the destructible's reset) is new geometry, so it is drawn whole again.\n let isUploaded = false\n let modelKey = ''\n const culled = new Map<any, boolean>()\n const keyOf = (): string => full.children.filter((child: any) => child.name !== 'static-batches').map((child: any) => child.uuid).join()\n const armUpload = (): void => {\n // a model rebuilt again before its first draw (frames skipped on a slow machine) lets go of the old one's meshes\n for (const [mesh, wasCulled] of culled) mesh.frustumCulled = wasCulled\n culled.clear()\n modelKey = keyOf()\n isUploaded = false\n full.traverse((object: any) => {\n if (!object.isMesh || culled.has(object)) return\n culled.set(object, object.frustumCulled)\n object.frustumCulled = false\n })\n const probe = [...culled.keys()][0]\n if (!probe) {\n isUploaded = true\n return\n }\n const before = probe.onAfterRender\n probe.onAfterRender = function (this: any, ...args: unknown[]) {\n isUploaded = true\n probe.onAfterRender = before\n before?.apply(this, args)\n }\n }\n armUpload()\n let lite: any = null\n let isFused = false\n let isLocked = false\n // near, the full model draws its still parts in batches by material; a part that moves, dents or falls draws on its own again\n let batcher: StaticBatcher | null = null\n let shadow: any = null\n const castsShadow = new Set<any>()\n /** One mesh with the shape of the fused body, drawn only into the shadow map. */\n const shadowProxyOf = (fused: any): any => {\n const positions: number[] = []\n const indices: number[] = []\n for (const mesh of fused.children) {\n if (!mesh.isMesh || !mesh.castShadow) continue\n const geometry = mesh.geometry.clone().applyMatrix4(mesh.matrix)\n const offset = positions.length / 3\n const position = geometry.attributes.position\n for (let at = 0; at < position.count; at++) positions.push(position.getX(at), position.getY(at), position.getZ(at))\n const index = geometry.index ? Array.from(geometry.index.array as ArrayLike<number>) : Array.from({ length: position.count }, (_, at) => at)\n for (const vertex of index) indices.push(vertex + offset)\n geometry.dispose()\n }\n const geometry = new THREE.BufferGeometry()\n geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3))\n geometry.setIndex(indices)\n geometry.computeBoundingSphere()\n const proxy = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ colorWrite: false, depthWrite: false }))\n proxy.name = 'vehicle-shadow'\n markKitOrigin(proxy, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n proxy.castShadow = true\n proxy.userData.skipLite = true\n proxy.raycast = () => undefined\n root.add(proxy)\n return proxy\n }\n const drawFull = (): void => {\n // a vehicle hit in play is changing part by part: its batches would be given back as fast as they are made\n if (!batcher && isLocked) return\n if (!batcher) {\n lite ??= build()\n lite.visible = isFused\n shadow ??= shadowProxyOf(lite)\n shadow.visible = !isFused\n // the shadow comes from the one proxy, not from each part: a part's own shadow would be one more pass per draw\n full.traverse((object: any) => {\n if (!object.isMesh || !object.castShadow) return\n castsShadow.add(object)\n object.castShadow = false\n })\n // merged a material at a time over the next frames (BATCH_BUDGET_MS each), never in one frame\n batcher = createStaticBatcher(THREE, full, { budgetMs: BATCH_BUDGET_MS })\n batcher.group.traverse((object: any) => (object.userData.skipLite = true))\n markKitOrigin(batcher.group, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n return\n }\n batcher.update()\n // every part changed (the model was rebuilt, or all of it dented): batch what stands now\n if (!isLocked && batcher.stats().batched === 0 && batcher.stats().released > 0) {\n batcher.dispose()\n batcher = null\n }\n }\n const build = (): any => {\n root.updateMatrixWorld(true)\n const inverse = new THREE.Matrix4().copy(root.matrixWorld).invert()\n // a painted texture (a livery, a lettering) does not survive the fusion into vertex colours: those meshes stay as they are, drawn from the same geometry\n const textured: any[] = []\n full.traverse((object: any) => {\n if (!object.isMesh || object.userData.skipLite || !isShown(object, full)) return\n const materials = Array.isArray(object.material) ? object.material : [object.material]\n if (materials.some((material: any) => material?.map && !/plate/i.test(material.name ?? '')) && !/plate/i.test(object.name ?? '')) textured.push(object)\n })\n for (const mesh of textured) mesh.userData.skipLite = true\n const fusion = fuse(THREE, { ...context, vehicle: full }, inverse, null, primaryPaint(context), kit.lodHiddenMaterials())\n for (const mesh of textured) delete mesh.userData.skipLite\n const group = new THREE.Group()\n group.name = 'vehicle-lite'\n markKitOrigin(group, { owner: 'game-vehicles-three', kind: 'vehicle', id: root.name })\n for (const mesh of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh)\n for (const mesh of textured) {\n const copy = new THREE.Mesh(mesh.geometry, mesh.material)\n copy.matrixAutoUpdate = false\n copy.matrix.multiplyMatrices(inverse, mesh.matrixWorld)\n copy.castShadow = mesh.castShadow\n copy.receiveShadow = mesh.receiveShadow\n group.add(copy)\n }\n root.add(group)\n return group\n }\n const show = (shouldFuse: boolean): void => {\n if (shouldFuse === isFused) return\n isFused = shouldFuse\n full.visible = !shouldFuse\n if (lite) lite.visible = shouldFuse\n if (shadow) shadow.visible = !shouldFuse\n }\n const api: VehicleLod = {\n update(distance, touched, posed = false) {\n isLocked ||= touched\n if (keyOf() !== modelKey) {\n // the fused copy and the batches were made from the old model\n api.dispose()\n armUpload()\n }\n if (!isUploaded) return show(false)\n if (culled.size > 0) {\n for (const [mesh, wasCulled] of culled) mesh.frustumCulled = wasCulled\n culled.clear()\n }\n const shouldFuse = !isLocked && !posed && distance > (isFused ? VEHICLE_LOD_DISTANCE * 0.9 : VEHICLE_LOD_DISTANCE)\n if (shouldFuse && !lite) lite = build()\n show(shouldFuse)\n if (!shouldFuse) drawFull()\n },\n get fused() {\n return isFused\n },\n dispose() {\n show(false)\n batcher?.dispose()\n batcher = null\n for (const mesh of castsShadow) mesh.castShadow = true\n castsShadow.clear()\n shadow?.removeFromParent()\n shadow?.geometry.dispose()\n shadow = null\n if (!lite) return\n lite.removeFromParent()\n lite.traverse((object: any) => object.geometry?.dispose())\n lite = null\n },\n }\n return api\n}\n","import type { EffectSink, Enclosure } from '@adatechnology/game-contracts'\nimport { cabinEnclosure } from '@adatechnology/game-vehicles'\nimport type { CabinSource } from '@adatechnology/game-vehicles'\n\n/** One vehicle whose cabin holds out the host's smoke: its destructible and the object the host placed it in. */\ninterface Tracked {\n readonly source: CabinSource\n readonly frame: { readonly parent: unknown | null }\n declared: boolean\n /** It has been in the scene: leaving it now means it was taken away. */\n placed: boolean\n}\n\n/**\n * Keeps the host's effects told where the cabins of the vehicles are and how open they are (`EffectSink.enclose`), so the smoke, dust and steam\n * do not pass through a shut car: they go round it and get in only through an open door, a broken window or a bullet hole. `sync` every frame;\n * a vehicle whose object left the scene is forgotten and its cabin ended.\n */\nexport interface CabinSmoke {\n /** Follows the cabin of a vehicle by its object id; `frame` is the object the host placed it in (the destructible's `frame`). */\n track(id: string, source: CabinSource, frame: { readonly parent: unknown | null }): void\n /** Ends the cabin of one vehicle now. */\n untrack(id: string, effects: EffectSink | undefined): void\n /** Tells `effects` where every cabin is now. A host without `enclose` lets the smoke through, as before. */\n sync(effects: EffectSink | undefined): void\n /** Ends every cabin (the module leaves). */\n clear(effects: EffectSink | undefined): void\n /** The ids followed now. */\n ids(): string[]\n}\n\nexport function createCabinSmoke(): CabinSmoke {\n const tracked = new Map<string, Tracked>()\n const end = (id: string, entry: Tracked, effects: EffectSink | undefined): void => {\n if (entry.declared) effects?.enclose?.(id, null)\n tracked.delete(id)\n }\n return {\n track(id, source, frame) {\n tracked.set(id, { source, frame, declared: false, placed: false })\n },\n untrack(id, effects) {\n const entry = tracked.get(id)\n if (entry) end(id, entry, effects)\n },\n sync(effects) {\n if (!effects?.enclose) return\n for (const [id, entry] of tracked) {\n if (!entry.frame.parent) {\n // not placed yet (built, not added): wait; taken out of the scene: forget it\n if (entry.placed) end(id, entry, effects)\n continue\n }\n entry.placed = true\n const enclosure: Enclosure | null = cabinEnclosure(entry.source, { frame: entry.frame })\n if (enclosure || entry.declared) effects.enclose(id, enclosure)\n entry.declared = enclosure !== null\n }\n },\n clear(effects) {\n for (const [id, entry] of [...tracked]) end(id, entry, effects)\n },\n ids: () => [...tracked.keys()],\n }\n}\n","import type { ModuleScenario, Vec3 } from '@adatechnology/game-contracts'\nimport { createArcadeDriver, createSemiSimDriver, createSurfaces, vehicleCorners } from '@adatechnology/game-vehicles-driving'\nimport type { SemiInput, SemiWorld } from '@adatechnology/game-vehicles-driving'\nimport type { VehicleContext } from '@adatechnology/game-vehicles'\n\nimport { fill } from './text'\nimport type { VehiclesText } from './text'\nimport type { PartView, VehiclesContext, VehiclesRoom } from './types'\n\ntype Destructible = {\n partWorldCenter(part: string): Vec3\n detachedParts(): string[]\n describe(): { parts: { id: string; hp: number; shape: { size: Vec3 } }[] }\n status(): { leaking: unknown[]; exploded: boolean; lightsOn: boolean; canStart: boolean; canDrive: boolean }\n state(): { groups: unknown[] }\n rollover(): void\n vehicle: { flipped?: boolean }\n}\n\ntype Spawned = { id: string; d: Destructible }\n\nexport type ScenarioDeps = {\n readonly text: VehiclesText\n readonly locale: string\n}\n\nconst add = (p: Vec3, dx: number, dy: number, dz: number): Vec3 => [p[0] + dx, p[1] + dy, p[2] + dz]\n\n/**\n * The scenarios of the vehicles area. The first eleven are the Frota test page's, literal (same shots, same hits, same checks and the same sentences); the vehicle faces +z,\n * its left is +x and its right -x. Then the burnt sedan built by the kit's `burnt` scenario, the arcade driver down a lane that ends in a wall, and the semi-simulation braking on three surfaces (new in the kit).\n */\nexport const createScenarios = (deps: ScenarioDeps): ModuleScenario<VehiclesContext>[] => {\n const { text, locale } = deps\n const say = (id: string, ...values: unknown[]): string => fill(text, locale, text.checks[id] as string, ...values)\n const scenario = (id: string, run: ModuleScenario<VehiclesContext>['run']): ModuleScenario<VehiclesContext> => ({ id, name: text.scenarios[id] ?? id, run })\n const put = (room: VehiclesRoom, item: string, z = -7): Spawned => {\n const spawned = room.spawn(item, [0, 0, z], 0)\n return { id: spawned.objectId, d: spawned.root.userData.destructible as Destructible }\n }\n const part = (room: VehiclesRoom, v: Spawned, id: string): PartView => room.world.part(v.id, id)\n const events = (room: VehiclesRoom, type: string, v: Spawned): number => room.log.entries({ type, objectId: v.id }).length\n\n return [\n scenario('vehicles_9mm_windshield', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('windshield')\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n room.look(add(c, 0, 0.5, 3), c)\n step(0.1)\n room.use()\n step(0.4)\n const w = part(room, v, 'windshield')\n expect(w.holes.length >= 1 && !!w.holes[0]?.through, say('windshield_holes', w.holes.length, w.holes[0]?.through))\n expect(w.cracks.length >= 1 && w.status === 'damaged', say('windshield_cracks', w.cracks.length, w.status))\n }),\n scenario('vehicles_shotgun_door', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const c = v.d.partWorldCenter('door_front_left')\n room.setTool('shotgun_pump_12')\n room.waitUntilReady()\n room.look(add(c, 2.5, 0, 0), c)\n step(0.1)\n room.use()\n step(0.4)\n const p = part(room, v, 'door_front_left')\n const marks = p.holes.length + p.dents.length\n expect(marks >= 2 && p.hp < p.maxHp, say('door_marks', p.holes.length, p.dents.length, Math.round(p.hp), p.maxHp))\n }),\n scenario('vehicles_ram_front', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('bumper_front')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [0, 0, -1], energy: 45000, radius: 0.6, source: 'teste' })\n step(2.5)\n const b = part(room, v, 'bumper_front')\n const h = part(room, v, 'hood')\n expect(b.dents.length >= 1 && h.dents.length >= 1, say('front_crush', b.dents.length, h.dents.length))\n const det = v.d.detachedParts()\n expect(det.indexOf('bumper_front') >= 0, say('bumper_off', det.join(', ')))\n }),\n scenario('vehicles_engine_fire', ({ room, step, expect }) => {\n const v = put(room, 'pickup')\n const c = v.d.partWorldCenter('engine')\n for (let i = 0; i < 80; i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.5, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n const e = part(room, v, 'engine')\n expect(e.burning && e.temperature > 250, say('engine_burning', e.burning, Math.round(e.temperature)))\n expect(events(room, 'ignite', v) >= 1, say('ignite_lines', events(room, 'ignite', v)))\n }),\n scenario('vehicles_fuel_tank', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const spec = v.d.describe().parts.filter((p) => p.id === 'fuel_tank')[0] as { shape: { size: Vec3 } }\n const c = v.d.partWorldCenter('fuel_tank')\n // the shot comes in from below, under the fuel level\n const low: Vec3 = [c[0], c[1] - spec.shape.size[1] / 2 + 0.06, c[2]]\n room.setTool('pistol_9mm')\n room.waitUntilReady()\n room.look(add(low, 0, 0, -2.5), low)\n step(0.1)\n room.use()\n step(1)\n const t = part(room, v, 'fuel_tank')\n const nl = v.d.status().leaking.length\n expect(nl >= 1 && t.liters < 55, say('tank_leaking', nl, t.liters.toFixed(1)))\n for (let i = 0; i < 160 && !events(room, 'explode', v); i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.6, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n expect(events(room, 'ignite', v) >= 1, say('ignited', events(room, 'ignite', v)))\n step(2)\n expect(events(room, 'explode', v) === 1 && v.d.status().exploded, say('exploded', events(room, 'explode', v)))\n const vc = v.d.partWorldCenter('engine')\n room.look(add(vc, 4, 0, -3), vc)\n }),\n scenario('vehicles_unbolt_wheel', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const joint = 'wheel_front_left~underbody'\n const c = v.d.partWorldCenter('wheel_front_left')\n room.setTool('wrench')\n // the wrench turns the hub bolts (the wheel~chassis joint), the same path as the first-person use\n for (let k = 0; k < 120 && room.world.disassemble(v.id, joint, 'wrench', 0.1) < 1; k++) step(0.1)\n step(1)\n const st = room.world.state(v.id)\n const open = !!st.joints.filter((j) => j.id === joint)[0]?.open\n expect(open && st.groups.length >= 2 && events(room, 'detach', v) >= 1, say('wheel_wrench', open, st.groups.length, events(room, 'detach', v)))\n step(2)\n room.look(add(c, 2.2, 0, 0.2), add(c, 0, -0.1, 0))\n }),\n scenario('vehicles_tear_bumper', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('bumper_front')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [0, 0, -1], energy: 30000, radius: 0.6, source: 'teste' })\n step(2.5)\n const det = v.d.detachedParts()\n expect(det.indexOf('bumper_front') >= 0, say('loose_parts', det.join(', ')))\n room.look(add(c, 2, 0, 3.5), add(c, 0, 0, -0.5))\n }),\n scenario('vehicles_break_mirror', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const c = v.d.partWorldCenter('mirror_left')\n room.world.hit(v.id, { type: 'blunt', point: c, direction: [-1, 0, 0], energy: 2500, radius: 0.1, source: 'teste' })\n step(2)\n const m = part(room, v, 'mirror_left')\n expect(m.status === 'broken' && v.d.state().groups.length >= 1, say('mirror_broken', m.status))\n }),\n scenario('vehicles_kill_battery', ({ room, step, expect }) => {\n const v = put(room, 'pickup')\n expect(v.d.status().lightsOn && v.d.status().canStart, say('battery_before'))\n room.playAnimation('open_hood', v.id)\n step(1.5)\n for (let i = 0; i < 80 && room.world.disassemble(v.id, 'battery~underbody', 'wrench', 0.1) < 1; i++) step(0.1)\n step(0.5)\n const s = v.d.status()\n expect(!s.lightsOn && !s.canStart && !s.canDrive, say('battery_after', s.lightsOn, s.canStart))\n }),\n scenario('vehicles_rollover', ({ room, step, expect }) => {\n const v = put(room, 'sedan')\n const maxRoof = (v.d.describe().parts.filter((p) => p.id === 'roof')[0] as { hp: number }).hp\n v.d.rollover()\n step(8)\n const roof = part(room, v, 'roof')\n expect(!!v.d.vehicle.flipped, say('rolled_over', !!v.d.vehicle.flipped))\n expect(roof.hp < maxRoof && roof.dents.length >= 1, say('roof', Math.round(roof.hp), maxRoof, roof.dents.length))\n }),\n scenario('vehicles_melt', ({ room, step, expect }) => {\n const v = put(room, 'hatch')\n const c = v.d.partWorldCenter('tyre_front_left')\n for (let i = 0; i < 60; i++) {\n room.world.hit(v.id, { type: 'fire', point: c, temperature: 900, radius: 0.7, duration: 0.1, source: 'teste' })\n step(0.1)\n }\n step(30)\n const t = part(room, v, 'tyre_front_left')\n expect(events(room, 'melt', v) >= 1 && (t.status === 'melted' || t.melt > 0.5), say('tyre_melt', t.status, Math.round(t.melt * 100), events(room, 'melt', v)))\n }),\n // new in the kit: the burnt wreck comes ready from the kit (the fleet's `burnt` scenario built into the vehicle), no damage applied by the area\n scenario('vehicles_burnt_wreck', ({ room, expect }) => {\n const c = room.spawn('sedan_burnt', [0, 0, -7], 0).root.userData.vehicle as VehicleContext\n expect(c.zoneState.flags.burnt === true, say('wreck_burnt', c.zoneState.flags.burnt === true))\n const glass = c.zones.filter((z) => z.type === 'glass')\n const up = glass.filter((z) => (c.zoneState.health[z.id] ?? 100) > 0)\n expect(glass.length >= 1 && up.length === 0, say('wreck_glass', glass.length, up.length))\n }),\n // new in the kit: the drivers, headless (no vehicle is spawned)\n scenario('vehicles_drive_arcade', ({ expect }) => {\n const driver = createArcadeDriver()\n const wallX = 60\n driver.place(0, 0, 0)\n const world = { blocked: (x: number, z: number, yaw: number) => vehicleCorners(driver.spec, x, z, yaw).some(([px]) => px >= wallX) }\n let crashSpeed = 0\n let engine = 0\n let crashNoise = 0\n let after = 0\n for (let t = 0; t < 12; t += 1 / 60) {\n const { events: out } = driver.step({ throttle: 1, brake: 0, steer: 0, handbrake: false }, 1 / 60, world)\n for (const e of out) {\n if (e.type === 'crash' && !crashSpeed) {\n crashSpeed = e.speed\n after = driver.state.v\n }\n if (e.type === 'noise' && e.source === 'engine') engine++\n if (e.type === 'noise' && e.source === 'crash') crashNoise++\n }\n }\n expect(crashSpeed > driver.spec.crash.damageSpeed && crashSpeed <= driver.spec.maxForward + 1e-6, say('arcade_crash', crashSpeed.toFixed(1), driver.spec.maxForward))\n expect(after < 0, say('arcade_bounce', after.toFixed(1)))\n expect(engine >= 1 && crashNoise >= 1, say('arcade_noise', engine, crashNoise))\n }),\n scenario('vehicles_drive_semi', ({ expect }) => {\n const surfaces = createSurfaces()\n const coast: SemiInput = { throttle: 0, brake: 0, steer: 0, handbrake: false }\n const dt = 1 / 60\n const world = (surface: string): SemiWorld => ({ ground: () => ({ surface }) })\n const braking = (surface: string): number => {\n const driver = createSemiSimDriver({}, { surfaces })\n driver.state.u = 80 / 3.6\n for (let t = 0; t < 1; t += dt) driver.step({ ...coast, throttle: 0.3 }, dt, world(surface))\n driver.state.u = 80 / 3.6\n const start = driver.state.x\n for (let t = 0; t < 30 && driver.state.u > 0.1; t += dt) driver.step({ ...coast, brake: 1 }, dt, world(surface))\n return driver.state.x - start\n }\n const dry = braking('dry_asphalt')\n const wet = braking('wet_asphalt')\n const mud = braking('mud')\n expect(dry < wet && wet < mud, say('semi_order', dry.toFixed(1), wet.toFixed(1), mud.toFixed(1)))\n const bog = createSemiSimDriver({}, { surfaces })\n let bogged = 0\n for (let t = 0; t < 8; t += dt) bogged += bog.step({ ...coast, throttle: 1 }, dt, world('mud')).events.filter((e) => e.type === 'bogged').length\n expect(bog.state.bogged && bogged >= 1, say('semi_mud', bog.state.bogged))\n }),\n ]\n}\n","/** Words and sentences of the vehicles area. The check lines keep the sentences of the Frota test page; `{0}`, `{1}`... are filled in order, `{0:b}` is yes / no (true / false in English), `{0:open}` open / tight, `{0:on}` on / off. */\nexport type VehiclesText = {\n group: string\n name: string\n items: Record<string, string>\n controls: Record<'quality' | 'paint_by_seed' | 'color_seed' | 'palette' | 'driving' | 'surface', string>\n hints: Record<'quality' | 'paint_by_seed' | 'palette' | 'driving' | 'surface', string>\n options: { quality: Record<string, string>; palette: Record<string, string>; driving: Record<string, string>; surface: Record<string, string> }\n actions: Record<'repaint' | 'drive_lane' | 'clear_lane' | 'honk', string>\n layers: Record<'damageables' | 'zones' | 'axes', string>\n metrics: Record<'vehicles' | 'triangles' | 'draw_calls' | 'size_error_mm' | 'metal' | 'glass' | 'rubber' | 'fuel' | 'speed' | 'lane', string>\n words: { yes: string; no: string; open: string; tight: string; on: string; off: string }\n lane: Record<'crash' | 'end', string>\n scenarios: Record<string, string>\n checks: Record<string, string>\n}\n\nconst scenarioIds = [\n 'vehicles_9mm_windshield',\n 'vehicles_shotgun_door',\n 'vehicles_ram_front',\n 'vehicles_engine_fire',\n 'vehicles_fuel_tank',\n 'vehicles_unbolt_wheel',\n 'vehicles_tear_bumper',\n 'vehicles_break_mirror',\n 'vehicles_kill_battery',\n 'vehicles_rollover',\n 'vehicles_melt',\n 'vehicles_burnt_wreck',\n 'vehicles_drive_arcade',\n 'vehicles_drive_semi',\n] as const\n\nexport const VEHICLE_SCENARIO_IDS: readonly string[] = scenarioIds\n\n/** The ids of the Frota test page, for whoever keeps a report or a link made against it. */\nexport const PAGE_SCENARIO_ALIASES: Readonly<Record<string, string>> = {\n veiculos_9mm_parabrisa: 'vehicles_9mm_windshield',\n veiculos_espingarda_porta: 'vehicles_shotgun_door',\n veiculos_bater_frente: 'vehicles_ram_front',\n veiculos_fogo_motor: 'vehicles_engine_fire',\n veiculos_tanque: 'vehicles_fuel_tank',\n veiculos_soltar_roda: 'vehicles_unbolt_wheel',\n veiculos_arrancar_parachoque: 'vehicles_tear_bumper',\n veiculos_quebrar_retrovisor: 'vehicles_break_mirror',\n veiculos_matar_bateria: 'vehicles_kill_battery',\n veiculos_capotar: 'vehicles_rollover',\n veiculos_derreter: 'vehicles_melt',\n}\n\nexport const PAGE_ITEM_ALIASES: Readonly<Record<string, string>> = {\n hatch: 'hatch',\n sedan: 'sedan',\n picape: 'pickup',\n moto: 'sport_bike',\n caminhao: 'box_truck',\n onibus: 'city_bus',\n tanque: 'battle_tank',\n helicoptero: 'attack_helicopter',\n}\n\nexport const TEXT: Record<string, VehiclesText> = {\n en: {\n group: 'Vehicles',\n name: 'Vehicles area',\n items: { hatch: 'Compact hatch', sedan: 'Midsize sedan', pickup: 'Midsize pickup', sport_bike: 'Sport bike', box_truck: 'Box truck', city_bus: 'City bus', battle_tank: 'Battle tank', attack_helicopter: 'Attack helicopter', sedan_burnt: 'Burnt sedan', hatch_burnt: 'Burnt hatch' },\n controls: { quality: 'Quality', paint_by_seed: 'Paint by seed', color_seed: 'Colour seed', palette: 'Palette', driving: 'Driving', surface: 'Surface' },\n hints: {\n quality: 'High: the kit at full detail. Light: fewer segments and no interior (the light mode of the fleet); applies to the vehicles placed from now on',\n paint_by_seed: 'Off: every vehicle keeps its own paint. On: the body colour comes from the seed and the palette',\n palette: 'Auto: the palette of the vehicle group (civil, or military for the army vehicles)',\n driving: 'Arcade: the game car, simple and forgiving. Semi: a rigid body with springs, tyre friction, gears and surfaces',\n surface: 'The ground under the wheels in the semi mode (grip and aquaplaning)',\n },\n options: {\n quality: { high: 'High', lite: 'Light' },\n palette: { auto: 'Auto', civil: 'Civil', military: 'Military' },\n driving: { arcade: 'Arcade', semi: 'Semi-simulation' },\n surface: { dry_asphalt: 'Dry asphalt', wet_asphalt: 'Wet asphalt', dirt: 'Dirt', grass: 'Grass', mud: 'Mud', blood: 'Blood' },\n },\n actions: { repaint: 'Repaint with the seed', drive_lane: 'Drive the lane', clear_lane: 'Remove the lane car', honk: 'Honk the horn' },\n layers: { damageables: 'Damageable boxes by material', zones: 'Zone boxes by type', axes: 'Output frame axes' },\n metrics: { vehicles: 'Vehicles', triangles: 'Triangles', draw_calls: 'Draw calls', size_error_mm: 'Size against DIMS', metal: 'Metal boxes', glass: 'Glass boxes', rubber: 'Rubber boxes', fuel: 'Fuel boxes', speed: 'Lane speed', lane: 'Lane distance' },\n words: { yes: 'true', no: 'false', open: 'open', tight: 'tight', on: 'on', off: 'off' },\n lane: { crash: 'Lane: the car hit the wall at {0} m/s', end: 'Lane: the car stopped {0} m from the wall' },\n scenarios: {\n vehicles_9mm_windshield: 'Vehicles: 9 mm through the windshield',\n vehicles_shotgun_door: 'Vehicles: shotgun on the door',\n vehicles_ram_front: 'Vehicles: ram the front',\n vehicles_engine_fire: 'Vehicles: fire on the engine',\n vehicles_fuel_tank: 'Vehicles: shoot the fuel tank (leaks, ignites, explodes)',\n vehicles_unbolt_wheel: 'Vehicles: unbolt the wheel with the wrench',\n vehicles_tear_bumper: 'Vehicles: tear off the bumper',\n vehicles_break_mirror: 'Vehicles: break the mirror',\n vehicles_kill_battery: 'Vehicles: kill the battery (lights go out)',\n vehicles_rollover: 'Vehicles: roll over',\n vehicles_melt: 'Vehicles: melt (long fire burns the tyres)',\n vehicles_drive_arcade: 'Vehicles: arcade driving down a lane that ends in a wall',\n vehicles_drive_semi: 'Vehicles: semi-simulation braking on dry, wet and mud',\n vehicles_burnt_wreck: 'Vehicles: the burnt sedan comes out of the kit burnt, with the glass gone',\n },\n checks: {\n windshield_holes: 'Windshield: {0} hole(s), went through {1:b} (expected: 1, true)',\n windshield_cracks: 'Windshield cracked: {0} crack(s), state {1} (expected: damaged)',\n door_marks: 'Front left door: {0} hole(s), {1} dent(s), hp {2}/{3} (expected: 2 marks or more)',\n front_crush: 'Front crushed: bumper {0} dent(s), hood {1} (expected: 1 or more each)',\n bumper_off: 'The bumper came off: {0} (expected: bumper_front)',\n engine_burning: 'Engine: burning {0:b}, {1} °C (expected: true, above 250)',\n ignite_lines: 'Ignite lines in the log: {0} (expected: 1 or more)',\n tank_leaking: 'Tank leaking: {0} leak(s), {1} L left (expected: 1 or more, below 55)',\n ignited: 'Ignited: {0} ignite line(s) (expected: 1 or more)',\n exploded: 'Exploded: {0} explosion(s) (expected: 1)',\n wheel_wrench: 'Wrench on the wheel: bolts {0:open}, {1} group(s), {2} detach line(s) (expected: open, 2 or more, 1)',\n loose_parts: 'Loose parts: {0} (expected: bumper_front)',\n mirror_broken: 'Left mirror: {0} (expected: broken)',\n battery_before: 'Before: lights on and it starts (expected: yes)',\n battery_after: 'No battery: lights {0:on}, start {1:b} (expected: off, false)',\n rolled_over: 'Rolled over: {0:b} (expected: true)',\n roof: 'Roof: hp {0}/{1}, {2} dent(s) (expected: below max, 1 or more)',\n tyre_melt: 'Tyre: {0}, melted {1}%, {2} melt line(s) (expected: melted or above 50%)',\n arcade_crash: 'Arcade: the wall is hit at {0} m/s (expected: the crash above 4 m/s, at most {1})',\n arcade_bounce: 'Arcade: the car bounces back at {0} m/s (expected: below 0)',\n arcade_noise: 'Arcade: {0} engine noise(s) and {1} crash noise(s) (expected: 1 or more each)',\n semi_order: 'Semi: braking from 80 km/h takes dry {0} m, wet {1} m, mud {2} m (expected: dry shorter than wet shorter than mud)',\n semi_mud: 'Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)',\n wreck_burnt: 'Burnt sedan: burnt flag {0:b} (expected: yes)',\n wreck_glass: 'Burnt sedan: {0} glass zone(s), {1} still above 0 (expected: 1 or more, none above 0)',\n },\n },\n 'pt-BR': {\n group: 'Veículos',\n name: 'Área de veículos',\n items: { hatch: 'Hatch compacto', sedan: 'Sedã médio', pickup: 'Picape média', sport_bike: 'Moto esportiva', box_truck: 'Caminhão baú', city_bus: 'Ônibus urbano', battle_tank: 'Tanque de guerra', attack_helicopter: 'Helicóptero de ataque', sedan_burnt: 'Sedã queimado', hatch_burnt: 'Hatch queimado' },\n controls: { quality: 'Qualidade', paint_by_seed: 'Pintar pela semente', color_seed: 'Semente da cor', palette: 'Paleta', driving: 'Direção', surface: 'Piso' },\n hints: {\n quality: 'Alta: o kit com todo o detalhe. Leve: menos segmentos e sem interior (o modo leve da frota); vale para os veículos postos daqui em diante',\n paint_by_seed: 'Desligado: cada veículo mantém a própria pintura. Ligado: a cor da carroceria vem da semente e da paleta',\n palette: 'Auto: a paleta do grupo do veículo (civil, ou militar para os do exército)',\n driving: 'Arcade: o carro do jogo, simples e tolerante. Semi: corpo rígido com molas, atrito do pneu, marchas e pisos',\n surface: 'O chão sob as rodas no modo semi (aderência e aquaplanagem)',\n },\n options: {\n quality: { high: 'Alta', lite: 'Leve' },\n palette: { auto: 'Auto', civil: 'Civil', military: 'Militar' },\n driving: { arcade: 'Arcade', semi: 'Semissimulação' },\n surface: { dry_asphalt: 'Asfalto seco', wet_asphalt: 'Asfalto molhado', dirt: 'Terra', grass: 'Grama', mud: 'Lama', blood: 'Sangue' },\n },\n actions: { repaint: 'Repintar com a semente', drive_lane: 'Percorrer a pista', clear_lane: 'Tirar o carro da pista', honk: 'Buzinar' },\n layers: { damageables: 'Caixas danificáveis por material', zones: 'Caixas das zonas por tipo', axes: 'Eixos do quadro de saída' },\n metrics: { vehicles: 'Veículos', triangles: 'Triângulos', draw_calls: 'Chamadas de desenho', size_error_mm: 'Medida contra DIMS', metal: 'Caixas de metal', glass: 'Caixas de vidro', rubber: 'Caixas de borracha', fuel: 'Caixas de combustível', speed: 'Velocidade na pista', lane: 'Distância na pista' },\n words: { yes: 'sim', no: 'não', open: 'soltos', tight: 'presos', on: 'acesos', off: 'apagados' },\n lane: { crash: 'Pista: o carro bateu no muro a {0} m/s', end: 'Pista: o carro parou a {0} m do muro' },\n scenarios: {\n vehicles_9mm_windshield: 'Veículos: 9 mm atravessa o para-brisa',\n vehicles_shotgun_door: 'Veículos: espingarda na porta',\n vehicles_ram_front: 'Veículos: bater de frente',\n vehicles_engine_fire: 'Veículos: fogo no motor',\n vehicles_fuel_tank: 'Veículos: atirar no tanque (vaza, pega fogo, explode)',\n vehicles_unbolt_wheel: 'Veículos: soltar a roda com a chave inglesa',\n vehicles_tear_bumper: 'Veículos: arrancar o para-choque',\n vehicles_break_mirror: 'Veículos: quebrar o retrovisor',\n vehicles_kill_battery: 'Veículos: matar a bateria (faróis apagam)',\n vehicles_rollover: 'Veículos: capotar',\n vehicles_melt: 'Veículos: derreter (fogo longo queima os pneus)',\n vehicles_drive_arcade: 'Veículos: direção arcade numa pista que acaba num muro',\n vehicles_drive_semi: 'Veículos: frenagem da semissimulação no seco, no molhado e na lama',\n vehicles_burnt_wreck: 'Veículos: o sedã queimado sai do kit queimado, sem os vidros',\n },\n checks: {\n windshield_holes: 'Para-brisa: {0} furo(s), atravessou {1:b} (esperado: 1, sim)',\n windshield_cracks: 'Para-brisa trincou: {0} trinca(s), estado {1} (esperado: damaged)',\n door_marks: 'Porta dianteira esquerda: {0} furo(s), {1} amassado(s), vida {2}/{3} (esperado: 2 marcas ou mais)',\n front_crush: 'Frente amassada: para-choque {0} amassado(s), capô {1} (esperado: 1 ou mais cada)',\n bumper_off: 'O para-choque soltou: {0} (esperado: bumper_front)',\n engine_burning: 'Motor: pegando fogo {0:b}, {1} °C (esperado: sim, acima de 250)',\n ignite_lines: 'Linhas de ignição no log: {0} (esperado: 1 ou mais)',\n tank_leaking: 'Tanque vazando: {0} vazamento(s), {1} L restantes (esperado: 1 ou mais, menos de 55)',\n ignited: 'Pegou fogo: {0} linha(s) de ignição (esperado: 1 ou mais)',\n exploded: 'Explodiu: {0} explosão (esperado: 1)',\n wheel_wrench: 'Chave na roda: parafusos {0:open}, {1} grupo(s), {2} linha(s) de soltura (esperado: soltos, 2 ou mais, 1)',\n loose_parts: 'Peças soltas: {0} (esperado: bumper_front)',\n mirror_broken: 'Retrovisor esquerdo: {0} (esperado: broken)',\n battery_before: 'Antes: faróis acesos e dá partida (esperado: sim)',\n battery_after: 'Sem bateria: faróis {0:on}, partida {1:b} (esperado: apagados, não)',\n rolled_over: 'Capotou: {0:b} (esperado: sim)',\n roof: 'Teto: vida {0}/{1}, {2} amassado(s) (esperado: menos que o máximo, 1 ou mais)',\n tyre_melt: 'Pneu: {0}, derretido {1}%, {2} linha(s) de derretimento (esperado: melted ou mais de 50%)',\n arcade_crash: 'Arcade: bate no muro a {0} m/s (esperado: a batida acima de 4 m/s, no máximo {1})',\n arcade_bounce: 'Arcade: o carro volta a {0} m/s (esperado: abaixo de 0)',\n arcade_noise: 'Arcade: {0} ruído(s) de motor e {1} de batida (esperado: 1 ou mais de cada)',\n semi_order: 'Semi: frear de 80 km/h leva no seco {0} m, no molhado {1} m, na lama {2} m (esperado: seco menor que molhado menor que lama)',\n semi_mud: 'Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)',\n wreck_burnt: 'Sedã queimado: marca de queimado {0:b} (esperado: sim)',\n wreck_glass: 'Sedã queimado: {0} zona(s) de vidro, {1} ainda acima de 0 (esperado: 1 ou mais, nenhuma acima de 0)',\n },\n },\n}\n\n/** Fills a check sentence: `{i}` plain, `{i:b}` yes / no, `{i:open}` open / tight, `{i:on}` on / off. In English the `:b` form prints the value itself (true, false, undefined), as the page does. */\nexport function fill(text: VehiclesText, locale: string, template: string, ...values: readonly unknown[]): string {\n return template.replace(/\\{(\\d+)(?::(b|open|on))?\\}/g, (_match, index: string, kind?: string) => {\n const value = values[Number(index)]\n if (kind === 'b') return locale === 'en' ? String(value) : value ? text.words.yes : text.words.no\n if (kind === 'open') return value ? text.words.open : text.words.tight\n if (kind === 'on') return value ? text.words.on : text.words.off\n return String(value)\n })\n}\n","import type { EffectSink, Vec3 } from '@adatechnology/game-contracts'\nimport type { VehicleKit } from '@adatechnology/game-vehicles'\n\nimport type { VehicleFleetContent } from '../build'\n\n/** The fleet the area runs on: its palettes and sizes, and how it is installed in a kit (`defaultVehicleFleet()` of `game-kit-defaults`). */\nexport type VehiclesTestFleet = VehicleFleetContent & { installFleet(kit: VehicleKit): void }\n\n/** What the module needs of a document (canvas textures of the kit): a real `document`, or a stub in Node. */\nexport type DocumentLike = { createElement(tag: string): unknown }\n\n/** The host's effects (`host.effects`, an `EffectSink` of the contracts: `game-vfx-three` is one): the module asks by id and writes no particle code. */\nexport type EffectsLike = EffectSink\n\n/** The events the module turns into effect requests, and the effect id each one asks for. A game maps its own ids over these. */\nexport type VehicleEffectIds = {\n readonly ignite: string\n readonly explode: string\n readonly glass: string\n readonly sparks: string\n readonly leak: string\n /** The leak of a pierced tank caught fire: the whole sequence (fire along the pool, then the blast). `leak` is only the pool and the drips. */\n readonly leakIgnited: string\n readonly exhaust: string\n}\n\nexport const defaultEffectIds: VehicleEffectIds = {\n ignite: 'vehicle_fire',\n explode: 'car_fuel_tank',\n glass: 'glass_burst',\n sparks: 'impact_metal',\n leak: 'vehicle_leak',\n leakIgnited: 'vehicle_leak_ignited',\n exhaust: 'vehicle_exhaust',\n}\n\n/** The sounds the module asks of `host.audio`, by id of the host's banks. `engine` is a loop (the game's saw through a 400 Hz low-pass), `horn` and `crash` one-shots. */\nexport type VehicleSoundIds = { readonly engine: string; readonly horn: string; readonly crash: string }\n\nexport const defaultSoundIds: VehicleSoundIds = { engine: 'engine_saw', horn: 'horn', crash: 'sfx_impact' }\n\n/** A damaged vehicle of the area: the item id, the fleet vehicle it is built from and the scenario of the kit applied while building. */\nexport type VehicleWreck = { readonly key: string; readonly vehicle: string; readonly scenario: string }\n\nexport const DEFAULT_TEST_WRECKS: readonly VehicleWreck[] = [\n { key: 'sedan_burnt', vehicle: 'midsize_sedan', scenario: 'burnt' },\n { key: 'hatch_burnt', vehicle: 'compact_hatch', scenario: 'burnt' },\n]\n\nexport type VehiclesTestOptions = {\n /**\n * The fleet content: paint palettes, measured sizes and the install into the default kit (`defaultVehicleFleet()` of `game-kit-defaults`). Default the ones of `game-vehicles-fleet`.\n * @deprecated pass `fleet`; the default is removed in the next major.\n */\n readonly fleet?: VehiclesTestFleet\n /** `en` or `pt-BR` (default). */\n readonly locale?: string\n /** The kit the vehicles are built with, per three.js namespace. Default: `createVehicleKit` with the fleet installed (`fleet.installFleet`). */\n readonly createKit?: (THREE: unknown) => VehicleKit\n readonly document?: DocumentLike\n /** The three.js namespace the door, hood and trunk clips are computed with (they are plain numbers, so any copy works). Default: the global `THREE`; without either the items bring no clips. */\n readonly three?: unknown\n /** The vehicles to lay out, as fleet ids (default the 8 of the Frota test: hatch, sedan, pickup, sport bike, box truck, city bus, battle tank, attack helicopter). */\n readonly vehicles?: readonly string[]\n /** Wrecks laid out after the vehicles: item `key` is the fleet vehicle `vehicle` built with the registered damage `scenario` (default `sedan_burnt` and `hatch_burnt`, the fleet's `burnt`; an empty list lays none). */\n readonly wrecks?: readonly VehicleWreck[]\n /** Effect ids requested through `host.effects` (the defaults are ids of `game-vfx`: the Garagem's `car_fuel_tank` blast, the `vehicle_fire`, `vehicle_leak` (pool and drips only), `vehicle_leak_ignited` (the whole sequence) and `vehicle_exhaust` recipes written around a car from `engine_smoke` and `fuel_leak`, and the point-based `glass_burst` and `impact_metal`). */\n readonly effects?: Partial<VehicleEffectIds>\n /** Sound ids requested through `host.audio` (the defaults are the `game-audio` ones: `engine_saw`, `horn`, `sfx_impact`). */\n readonly sounds?: Partial<VehicleSoundIds>\n}\n\n/** The part of the test room the scenarios use (the room's `ScenarioContext.room` has all of it). */\nexport type PartView = {\n holes: { through?: boolean }[]\n cracks: unknown[]\n dents: unknown[]\n status: string\n hp: number\n maxHp: number\n temperature: number\n burning: boolean\n liters: number\n melt: number\n}\n\nexport type SpawnedVehicle = { objectId: string; root: { userData: Record<string, unknown> } }\n\nexport type VehiclesRoom = {\n spawn(item: string, position?: Vec3, rotationY?: number): SpawnedVehicle\n setTool(weaponId: string): void\n /** Lets the tool in hand finish its draw time (the room's rule: a weapon cannot fire the moment it is taken). */\n waitUntilReady(): void\n look(position: Vec3, target: Vec3): void\n use(hold?: number): void\n playAnimation(clipId: string, objectId?: string): boolean\n world: {\n part(object: string, part: string): PartView\n hit(object: string, hit: Record<string, unknown>): unknown\n disassemble(object: string, joint: string, tool: string, dt: number): number\n state(object: string): { joints: { id: string; open: boolean }[]; groups: unknown[][] }\n }\n log: { entries(filter: { type?: string; objectId?: string }): readonly unknown[] }\n}\n\n/** What a scenario needs of the room: the pass/fail line, time, and the room for the ones that shoot and hit. */\nexport type VehiclesContext = {\n room: VehiclesRoom\n expect(condition: boolean, label: string, data?: Record<string, unknown>): void\n step(seconds: number): void\n}\n"],"mappings":"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","names":["createArcadeDriver","createSemiSimDriver","createSurfaces","vehicleCorners","colorFromSeed","fleetDims","paintPalettes","paletteOf","markKitOrigin","geometry","markKitOrigin","createSurfaces","createArcadeDriver","createSemiSimDriver","vehicleCorners","count"]}