lantern-engine 0.0.0-stage → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +101 -0
- package/LICENSE +21 -0
- package/README.md +113 -2
- package/dist/assets/takeCleanerWorker-DTcI_Jqr.js +31 -0
- package/dist/assets/takeCleanerWorker-DTcI_Jqr.js.map +1 -0
- package/dist/constants-CjYVdFid.js +252 -0
- package/dist/constants-CjYVdFid.js.map +1 -0
- package/dist/lantern-engine.js +3473 -0
- package/dist/lantern-engine.js.map +1 -0
- package/dist/pixel.js +1404 -0
- package/dist/pixel.js.map +1 -0
- package/dist/types/anim/Animator.d.ts +50 -0
- package/dist/types/anim/Animator.d.ts.map +1 -0
- package/dist/types/anim/animationSystem.d.ts +13 -0
- package/dist/types/anim/animationSystem.d.ts.map +1 -0
- package/dist/types/assets/AssetLoader.d.ts +85 -0
- package/dist/types/assets/AssetLoader.d.ts.map +1 -0
- package/dist/types/audio/MusicPlayer.d.ts +57 -0
- package/dist/types/audio/MusicPlayer.d.ts.map +1 -0
- package/dist/types/audio/SoundEngine.d.ts +42 -0
- package/dist/types/audio/SoundEngine.d.ts.map +1 -0
- package/dist/types/audio/cleanTake.d.ts +3 -0
- package/dist/types/audio/cleanTake.d.ts.map +1 -0
- package/dist/types/audio/sampleBank.d.ts +27 -0
- package/dist/types/audio/sampleBank.d.ts.map +1 -0
- package/dist/types/audio/soundTable.d.ts +14 -0
- package/dist/types/audio/soundTable.d.ts.map +1 -0
- package/dist/types/audio/synth.d.ts +34 -0
- package/dist/types/audio/synth.d.ts.map +1 -0
- package/dist/types/audio/takeCleanerWorker.d.ts +2 -0
- package/dist/types/audio/takeCleanerWorker.d.ts.map +1 -0
- package/dist/types/core/BitmapLabel.d.ts +26 -0
- package/dist/types/core/BitmapLabel.d.ts.map +1 -0
- package/dist/types/core/Camera.d.ts +90 -0
- package/dist/types/core/Camera.d.ts.map +1 -0
- package/dist/types/core/Clock.d.ts +11 -0
- package/dist/types/core/Clock.d.ts.map +1 -0
- package/dist/types/core/Graphics.d.ts +37 -0
- package/dist/types/core/Graphics.d.ts.map +1 -0
- package/dist/types/core/Group.d.ts +15 -0
- package/dist/types/core/Group.d.ts.map +1 -0
- package/dist/types/core/Image.d.ts +25 -0
- package/dist/types/core/Image.d.ts.map +1 -0
- package/dist/types/core/ObjectFactory.d.ts +34 -0
- package/dist/types/core/ObjectFactory.d.ts.map +1 -0
- package/dist/types/core/Pointer.d.ts +27 -0
- package/dist/types/core/Pointer.d.ts.map +1 -0
- package/dist/types/core/Rectangle.d.ts +26 -0
- package/dist/types/core/Rectangle.d.ts.map +1 -0
- package/dist/types/core/Stage.d.ts +58 -0
- package/dist/types/core/Stage.d.ts.map +1 -0
- package/dist/types/core/Text.d.ts +22 -0
- package/dist/types/core/Text.d.ts.map +1 -0
- package/dist/types/core/TextureRegistry.d.ts +51 -0
- package/dist/types/core/TextureRegistry.d.ts.map +1 -0
- package/dist/types/core/Tweener.d.ts +53 -0
- package/dist/types/core/Tweener.d.ts.map +1 -0
- package/dist/types/core/atlas.d.ts +16 -0
- package/dist/types/core/atlas.d.ts.map +1 -0
- package/dist/types/core/atlasPlan.d.ts +34 -0
- package/dist/types/core/atlasPlan.d.ts.map +1 -0
- package/dist/types/core/eases.d.ts +3 -0
- package/dist/types/core/eases.d.ts.map +1 -0
- package/dist/types/core/gameObject.d.ts +42 -0
- package/dist/types/core/gameObject.d.ts.map +1 -0
- package/dist/types/core/pixiPatches.d.ts +9 -0
- package/dist/types/core/pixiPatches.d.ts.map +1 -0
- package/dist/types/core/types.d.ts +4 -0
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/types/ecs/SparseSet.d.ts +25 -0
- package/dist/types/ecs/SparseSet.d.ts.map +1 -0
- package/dist/types/ecs/World.d.ts +133 -0
- package/dist/types/ecs/World.d.ts.map +1 -0
- package/dist/types/ecs/fields.d.ts +34 -0
- package/dist/types/ecs/fields.d.ts.map +1 -0
- package/dist/types/engine/Engine.d.ts +80 -0
- package/dist/types/engine/Engine.d.ts.map +1 -0
- package/dist/types/engine/FixedLoop.d.ts +32 -0
- package/dist/types/engine/FixedLoop.d.ts.map +1 -0
- package/dist/types/engine/Scene.d.ts +37 -0
- package/dist/types/engine/Scene.d.ts.map +1 -0
- package/dist/types/engine/SceneManager.d.ts +31 -0
- package/dist/types/engine/SceneManager.d.ts.map +1 -0
- package/dist/types/events/EventBus.d.ts +20 -0
- package/dist/types/events/EventBus.d.ts.map +1 -0
- package/dist/types/fx/hitStop.d.ts +20 -0
- package/dist/types/fx/hitStop.d.ts.map +1 -0
- package/dist/types/fx/viewCull.d.ts +14 -0
- package/dist/types/fx/viewCull.d.ts.map +1 -0
- package/dist/types/index.d.ts +68 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/input/Actions.d.ts +75 -0
- package/dist/types/input/Actions.d.ts.map +1 -0
- package/dist/types/input/Keyboard.d.ts +25 -0
- package/dist/types/input/Keyboard.d.ts.map +1 -0
- package/dist/types/input/aimAxis.d.ts +9 -0
- package/dist/types/input/aimAxis.d.ts.map +1 -0
- package/dist/types/input/longPress.d.ts +21 -0
- package/dist/types/input/longPress.d.ts.map +1 -0
- package/dist/types/input/stickAxis.d.ts +26 -0
- package/dist/types/input/stickAxis.d.ts.map +1 -0
- package/dist/types/input/touchDetect.d.ts +18 -0
- package/dist/types/input/touchDetect.d.ts.map +1 -0
- package/dist/types/light/LightLayer.d.ts +65 -0
- package/dist/types/light/LightLayer.d.ts.map +1 -0
- package/dist/types/net/Connection.d.ts +66 -0
- package/dist/types/net/Connection.d.ts.map +1 -0
- package/dist/types/net/InterpolationBuffer.d.ts +36 -0
- package/dist/types/net/InterpolationBuffer.d.ts.map +1 -0
- package/dist/types/net/PredictedMover.d.ts +43 -0
- package/dist/types/net/PredictedMover.d.ts.map +1 -0
- package/dist/types/net/Room.d.ts +69 -0
- package/dist/types/net/Room.d.ts.map +1 -0
- package/dist/types/net/RoomHost.d.ts +74 -0
- package/dist/types/net/RoomHost.d.ts.map +1 -0
- package/dist/types/net/cadence.d.ts +22 -0
- package/dist/types/net/cadence.d.ts.map +1 -0
- package/dist/types/net/constants.d.ts +24 -0
- package/dist/types/net/constants.d.ts.map +1 -0
- package/dist/types/net/movement.d.ts +50 -0
- package/dist/types/net/movement.d.ts.map +1 -0
- package/dist/types/net/protocol.d.ts +59 -0
- package/dist/types/net/protocol.d.ts.map +1 -0
- package/dist/types/net/serverClock.d.ts +14 -0
- package/dist/types/net/serverClock.d.ts.map +1 -0
- package/dist/types/net/snapshotCodec.d.ts +55 -0
- package/dist/types/net/snapshotCodec.d.ts.map +1 -0
- package/dist/types/pixel/Darkness.d.ts +78 -0
- package/dist/types/pixel/Darkness.d.ts.map +1 -0
- package/dist/types/pixel/Evaporation.d.ts +30 -0
- package/dist/types/pixel/Evaporation.d.ts.map +1 -0
- package/dist/types/pixel/PixelLayer.d.ts +85 -0
- package/dist/types/pixel/PixelLayer.d.ts.map +1 -0
- package/dist/types/pixel/index.d.ts +22 -0
- package/dist/types/pixel/index.d.ts.map +1 -0
- package/dist/types/pixel/lights.d.ts +34 -0
- package/dist/types/pixel/lights.d.ts.map +1 -0
- package/dist/types/pixel/palette.d.ts +54 -0
- package/dist/types/pixel/palette.d.ts.map +1 -0
- package/dist/types/pixel/pixel.d.ts +80 -0
- package/dist/types/pixel/pixel.d.ts.map +1 -0
- package/dist/types/pixel/pixelPaint.d.ts +43 -0
- package/dist/types/pixel/pixelPaint.d.ts.map +1 -0
- package/dist/types/pixel/pixelTone.d.ts +49 -0
- package/dist/types/pixel/pixelTone.d.ts.map +1 -0
- package/dist/types/pixel/propKit.d.ts +26 -0
- package/dist/types/pixel/propKit.d.ts.map +1 -0
- package/dist/types/pixel/ramp.d.ts +31 -0
- package/dist/types/pixel/ramp.d.ts.map +1 -0
- package/dist/types/pixel/selout.d.ts +3 -0
- package/dist/types/pixel/selout.d.ts.map +1 -0
- package/dist/types/pixel/spritePixels.d.ts +29 -0
- package/dist/types/pixel/spritePixels.d.ts.map +1 -0
- package/dist/types/platform/touch.d.ts +5 -0
- package/dist/types/platform/touch.d.ts.map +1 -0
- package/dist/types/rig/PosePlayer.d.ts +64 -0
- package/dist/types/rig/PosePlayer.d.ts.map +1 -0
- package/dist/types/rig/RigView.d.ts +68 -0
- package/dist/types/rig/RigView.d.ts.map +1 -0
- package/dist/types/rig/Skeleton.d.ts +14 -0
- package/dist/types/rig/Skeleton.d.ts.map +1 -0
- package/dist/types/rig/humanoid.d.ts +4 -0
- package/dist/types/rig/humanoid.d.ts.map +1 -0
- package/dist/types/rig/humanoidPoses.d.ts +117 -0
- package/dist/types/rig/humanoidPoses.d.ts.map +1 -0
- package/dist/types/rig/poseMath.d.ts +14 -0
- package/dist/types/rig/poseMath.d.ts.map +1 -0
- package/dist/types/rig/rigTypes.d.ts +82 -0
- package/dist/types/rig/rigTypes.d.ts.map +1 -0
- package/dist/types/settings.d.ts +25 -0
- package/dist/types/settings.d.ts.map +1 -0
- package/dist/types/tilemap/TilemapView.d.ts +42 -0
- package/dist/types/tilemap/TilemapView.d.ts.map +1 -0
- package/dist/types/tilemap/collision.d.ts +16 -0
- package/dist/types/tilemap/collision.d.ts.map +1 -0
- package/dist/types/tilemap/tiled.d.ts +104 -0
- package/dist/types/tilemap/tiled.d.ts.map +1 -0
- package/package.json +82 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lantern-engine.js","sources":["../src/core/Rectangle.ts","../src/core/Camera.ts","../src/core/Clock.ts","../src/core/BitmapLabel.ts","../src/core/Group.ts","../src/core/Image.ts","../src/core/Text.ts","../src/core/ObjectFactory.ts","../src/core/Pointer.ts","../src/core/eases.ts","../src/core/Tweener.ts","../src/core/Stage.ts","../src/core/TextureRegistry.ts","../src/events/EventBus.ts","../src/engine/FixedLoop.ts","../src/engine/SceneManager.ts","../src/engine/Engine.ts","../src/ecs/SparseSet.ts","../src/ecs/fields.ts","../src/ecs/World.ts","../src/engine/Scene.ts","../src/core/atlasPlan.ts","../src/core/atlas.ts","../src/tilemap/tiled.ts","../src/assets/AssetLoader.ts","../src/anim/Animator.ts","../src/anim/animationSystem.ts","../src/net/movement.ts","../src/tilemap/collision.ts","../src/tilemap/TilemapView.ts","../src/rig/Skeleton.ts","../src/rig/humanoid.ts","../src/rig/poseMath.ts","../src/rig/humanoidPoses.ts","../src/rig/PosePlayer.ts","../src/rig/RigView.ts","../src/light/LightLayer.ts","../src/fx/hitStop.ts","../src/fx/viewCull.ts","../src/audio/cleanTake.ts","../src/audio/sampleBank.ts","../src/audio/soundTable.ts","../src/audio/synth.ts","../src/audio/SoundEngine.ts","../src/audio/MusicPlayer.ts","../src/input/Keyboard.ts","../src/input/Actions.ts","../src/input/aimAxis.ts","../src/input/stickAxis.ts","../src/input/longPress.ts","../src/net/snapshotCodec.ts","../src/net/cadence.ts","../src/net/serverClock.ts","../src/net/protocol.ts","../src/net/PredictedMover.ts","../src/net/InterpolationBuffer.ts","../src/net/Room.ts","../src/net/RoomHost.ts","../src/net/Connection.ts"],"sourcesContent":["import { Container, Graphics as PixiGraphics } from 'pixi.js';\nimport { GameObject } from './gameObject';\n\n/** A filled rectangle placed by its origin (centred by default). */\nexport class Rectangle extends GameObject(Container) {\n private readonly g = new PixiGraphics();\n private ox = 0.5;\n private oy = 0.5;\n\n constructor(\n private w: number,\n private h: number,\n private color: number,\n private fillAlpha = 1,\n ) {\n super();\n this.addChild(this.g);\n this.redraw();\n }\n\n get originX(): number {\n return this.ox;\n }\n\n get originY(): number {\n return this.oy;\n }\n\n get rectWidth(): number {\n return this.w;\n }\n\n get rectHeight(): number {\n return this.h;\n }\n\n get fillColor(): number {\n return this.color;\n }\n\n get fillOpacity(): number {\n return this.fillAlpha;\n }\n\n setOrigin(x = 0.5, y = x): this {\n this.ox = x;\n this.oy = y;\n return this.redraw();\n }\n\n setFillStyle(color: number, alpha = 1): this {\n this.color = color;\n this.fillAlpha = alpha;\n return this.redraw();\n }\n\n setDisplaySize(w: number, h: number): this {\n return this.setScale(w / this.w, h / this.h);\n }\n\n resize(w: number, h: number): this {\n this.w = w;\n this.h = h;\n return this.redraw();\n }\n\n private redraw(): this {\n this.g.clear().rect(-this.w * this.ox, -this.h * this.oy, this.w, this.h).fill({ color: this.color, alpha: this.fillAlpha });\n return this;\n }\n}\n","import type { Container } from 'pixi.js';\nimport { Rectangle } from './Rectangle';\n\nexport interface TrackOptions {\n /**\n * How much of the way to the target the camera closes each 60th of a second (0–1, default 1: locked on). 0.1 is a\n * soft follow; the rate is the same at any frame rate.\n */\n lerp?: number;\n /** A box round the screen's centre (world px) the target may move in without the camera moving. */\n deadzoneWidth?: number;\n deadzoneHeight?: number;\n /** Where on the target to look (world px from its position), e.g. a little above a body's feet. */\n offsetX?: number;\n offsetY?: number;\n}\n\nexport interface ViewRect {\n x: number;\n y: number;\n width: number;\n height: number;\n right: number;\n bottom: number;\n}\n\n/**\n * Moves and zooms the world layer. `scrollX/scrollY` is the world point at the top-left of the screen, so\n * `round(scroll * zoom) / zoom` snaps the view to whole screen pixels.\n */\nexport class Camera {\n zoom = 1;\n /** Backing pixels per screen pixel (the renderer's resolution, `zoomResolution`): what `snap` rounds to. */\n resolution = 1;\n /** Lands the view on whole backing pixels (pixel art); off, the world moves smoothly between them. */\n roundPixels = false;\n scrollX = 0;\n scrollY = 0;\n width = 0;\n height = 0;\n private bounds: { x: number; y: number; width: number; height: number } | null = null;\n private shakeUntil = 0;\n private shakeMs = 1;\n private shakeAngle: number | undefined = undefined;\n private shakeIntensity = 0;\n private flashRect: Rectangle | null = null;\n private flashStart = 0;\n private flashMs = 1;\n private flashPeak = 1;\n /** Screen-layer containers laid over the world with its exact transform, shake included (see `follow`). */\n private readonly followers = new Set<Container>();\n private target: { readonly x: number; readonly y: number } | null = null;\n private trackOpts: Required<TrackOptions> = { lerp: 1, deadzoneWidth: 0, deadzoneHeight: 0, offsetX: 0, offsetY: 0 };\n private lastApply = -1;\n\n constructor(\n private readonly world: Container,\n private readonly screen: Container,\n ) {}\n\n get worldView(): ViewRect {\n const width = this.width / this.zoom;\n const height = this.height / this.zoom;\n return { x: this.scrollX, y: this.scrollY, width, height, right: this.scrollX + width, bottom: this.scrollY + height };\n }\n\n setZoom(z: number): this {\n this.zoom = z;\n return this;\n }\n\n /** A world coordinate snapped to the nearest backing pixel: one screen pixel, or a half at ×1.5. */\n snap(v: number): number {\n const k = this.zoom * this.resolution;\n return Math.round(v * k) / k;\n }\n\n setBounds(x: number, y: number, width: number, height: number): this {\n this.bounds = { x, y, width, height };\n return this;\n }\n\n centerOn(x: number, y: number): this {\n this.scrollX = x - this.width / this.zoom / 2;\n this.scrollY = y - this.height / this.zoom / 2;\n this.clamp();\n return this;\n }\n\n setScroll(x: number, y: number): this {\n this.scrollX = x;\n this.scrollY = y;\n this.clamp();\n return this;\n }\n\n /**\n * Screen shake: `intensity` is a fraction of the screen size, like before. With an `angle` (the way a blow travelled)\n * the shake runs back and forth along it instead of at random, so a hit is felt coming from somewhere.\n */\n shake(ms: number, intensity: number, angle?: number): void {\n const now = performance.now();\n if (now < this.shakeUntil && intensity < this.shakeIntensity) return;\n this.shakeUntil = now + ms;\n this.shakeMs = ms;\n this.shakeIntensity = intensity;\n this.shakeAngle = angle;\n }\n\n /**\n * Keeps a container on the screen layer placed exactly over the world layer — zoom, scroll and this frame's\n * shake — for things drawn in world units above the screen-layer night (fireflies). Written in `apply`, after\n * the scene updated, so it never lags the world by a frame or misses a shake the world takes.\n */\n follow(layer: Container): void {\n this.followers.add(layer);\n }\n\n unfollow(layer: Container): void {\n this.followers.delete(layer);\n }\n\n /** Full-screen colour flash starting at `peak` alpha and fading out over `ms`. */\n flash(ms: number, r: number, g: number, b: number, _force = false, peak = 1): void {\n if (!this.flashRect || this.flashRect.destroyed) {\n this.flashRect = new Rectangle(1, 1, 0xffffff).setOrigin(0, 0);\n this.screen.addChild(this.flashRect);\n }\n this.flashRect.resize(this.width, this.height).setFillStyle((r << 16) | (g << 8) | b).setAlpha(peak).setVisible(true);\n this.flashStart = performance.now();\n this.flashMs = ms;\n this.flashPeak = peak;\n }\n\n /**\n * Keeps `target` (anything with `x` and `y`, read every frame: an entity's position, a sprite) in view, inside the\n * bounds if there are any. Replaces any target before.\n */\n track(target: { readonly x: number; readonly y: number }, options: TrackOptions = {}): this {\n this.target = target;\n this.trackOpts = { lerp: 1, deadzoneWidth: 0, deadzoneHeight: 0, offsetX: 0, offsetY: 0, ...options };\n if ((options.lerp ?? 1) >= 1) this.centerOn(target.x + this.trackOpts.offsetX, target.y + this.trackOpts.offsetY);\n return this;\n }\n\n untrack(): this {\n this.target = null;\n return this;\n }\n\n /** Moves the view toward the tracked target for a frame `dtMs` long. */\n private follow1(dtMs: number): void {\n const t = this.target;\n if (!t) return;\n const o = this.trackOpts;\n const vw = this.width / this.zoom;\n const vh = this.height / this.zoom;\n const cx = this.scrollX + vw / 2;\n const cy = this.scrollY + vh / 2;\n const tx = t.x + o.offsetX;\n const ty = t.y + o.offsetY;\n // only the part of the target's offset outside the deadzone moves the camera\n const hx = o.deadzoneWidth / 2;\n const hy = o.deadzoneHeight / 2;\n const dx = tx - cx > hx ? tx - cx - hx : tx - cx < -hx ? tx - cx + hx : 0;\n const dy = ty - cy > hy ? ty - cy - hy : ty - cy < -hy ? ty - cy + hy : 0;\n const k = o.lerp >= 1 ? 1 : 1 - Math.pow(1 - Math.max(0, o.lerp), dtMs / (1000 / 60));\n this.scrollX += dx * k;\n this.scrollY += dy * k;\n this.clamp();\n }\n\n /** Writes the camera into the world layer; called once per frame after the scene updated. */\n apply(now: number): void {\n const dtMs = this.lastApply < 0 ? 1000 / 60 : Math.min(100, now - this.lastApply);\n this.lastApply = now;\n this.follow1(dtMs);\n let ox = 0;\n let oy = 0;\n if (now < this.shakeUntil) {\n const k = (this.shakeUntil - now) / this.shakeMs;\n if (this.shakeAngle !== undefined) {\n // along the blow: thrown the way it went, then rocking back, a little less each beat\n const swing = Math.cos(((now - (this.shakeUntil - this.shakeMs)) / 28) * Math.PI) * this.shakeIntensity * this.width * k;\n ox = Math.round(Math.cos(this.shakeAngle) * swing);\n oy = Math.round(Math.sin(this.shakeAngle) * swing);\n } else {\n ox = Math.round((Math.random() * 2 - 1) * this.shakeIntensity * this.width * k);\n oy = Math.round((Math.random() * 2 - 1) * this.shakeIntensity * this.height * k);\n }\n }\n this.world.scale.set(this.zoom);\n const k = this.zoom * this.resolution;\n const sx = this.roundPixels ? Math.round(this.scrollX * k) / this.resolution : this.scrollX * this.zoom;\n const sy = this.roundPixels ? Math.round(this.scrollY * k) / this.resolution : this.scrollY * this.zoom;\n this.world.position.set(-sx + ox, -sy + oy);\n for (const f of this.followers) {\n f.scale.set(this.zoom);\n f.position.copyFrom(this.world.position);\n }\n if (this.flashRect?.visible) {\n const t = (now - this.flashStart) / this.flashMs;\n if (t >= 1) this.flashRect.setVisible(false);\n else this.flashRect.alpha = this.flashPeak * (1 - t);\n }\n }\n\n private clamp(): void {\n const b = this.bounds;\n if (!b) return;\n const vw = this.width / this.zoom;\n const vh = this.height / this.zoom;\n this.scrollX = vw >= b.width ? b.x + (b.width - vw) / 2 : Math.min(Math.max(this.scrollX, b.x), b.x + b.width - vw);\n this.scrollY = vh >= b.height ? b.y + (b.height - vh) / 2 : Math.min(Math.max(this.scrollY, b.y), b.y + b.height - vh);\n }\n}\n","interface Timer {\n at: number;\n fn: () => void;\n removed: boolean;\n}\n\n/** Scene time and one-shot timers, advanced by the frame loop. */\nexport class Clock {\n now = performance.now();\n private timers: Timer[] = [];\n\n delayedCall(ms: number, fn: () => void): { remove: () => void } {\n const t: Timer = { at: this.now + ms, fn, removed: false };\n this.timers.push(t);\n return { remove: () => void (t.removed = true) };\n }\n\n update(now: number): void {\n this.now = now;\n const due = this.timers.filter((t) => !t.removed && t.at <= now);\n if (!due.length) return;\n this.timers = this.timers.filter((t) => !t.removed && t.at > now);\n for (const t of due) {\n // one timer that throws does not take the others due this frame with it\n try {\n t.fn();\n } catch (err) {\n console.error('[timer] failed', err);\n }\n }\n }\n\n clear(): void {\n this.timers = [];\n }\n}\n","import { BitmapFont, BitmapText, DynamicBitmapFont } from 'pixi.js';\nimport { GameObject } from './gameObject';\n\nconst INSTALLED = new Set<string>();\n\n/**\n * The glyphs baked into every label font: printable ASCII plus whatever a game adds (`addLabelGlyphs`) for the words\n * its labels print, so no glyph is baked mid-frame onto a fresh page (a new canvas a page, and iOS hands out none\n * once its canvas memory is spent).\n */\nconst CHARS: (string | [string, string])[] = [[' ', '~']];\n\n/** Adds letters every label font bakes ahead (accented letters of a language the labels print). Call before `installLabelFont`. */\nexport function addLabelGlyphs(letters: string): void {\n CHARS.push(letters);\n}\n/**\n * The side of one glyph page in CSS pixels; a page's canvas is this × the resolution. Pixi's default, 512, made every\n * label font a 2048² canvas at resolution 4 (16 MB each, ten of them at boot); the numbers' glyphs fill a few pages of\n * this size instead.\n */\nconst PAGE_SIZE = 128;\n\n/**\n * Rasterises one label font once and returns its name. Called ahead of time for the damage numbers\n * : baking a font on its first number froze the first frame that printed one by ~60 ms.\n */\nexport function installLabelFont(fontFamily: string, size: number, color: string, stroke: string, strokeWidth: number, resolution: number): string {\n const name = `label|${fontFamily}|${size}|${color}|${stroke}|${strokeWidth}|${resolution}`;\n if (!INSTALLED.has(name)) {\n // `install` takes no page size of its own: it reads the dynamic font's default, set for this call only\n const defaults = DynamicBitmapFont.defaultOptions;\n const was = defaults.textureSize;\n defaults.textureSize = PAGE_SIZE;\n try {\n BitmapFont.install({\n name,\n chars: CHARS,\n resolution,\n style: { fontFamily, fontSize: size, fill: color, stroke: { color: stroke, width: strokeWidth, join: 'round' } },\n });\n } finally {\n defaults.textureSize = was;\n }\n INSTALLED.add(name);\n }\n return name;\n}\n\n/**\n * Text drawn from a bitmap font: the glyphs are rasterised once per font, so changing the string costs no canvas\n * redraw and no texture upload, and every label of one font batches with the others. For the floating numbers, which\n * a crowded fight throws dozens of a second — a plain `Text` repaints its canvas at resolution 4 and uploads it on\n * every change.\n */\nexport class BitmapLabel extends GameObject(BitmapText) {\n /**\n * `fontFamily` must already be loaded (`document.fonts.load`), or the glyphs bake in the fallback.\n * Styled like `worldText`: the same font, size, colour and outline, rasterised at the same resolution.\n */\n constructor(x: number, y: number, text: string, fontFamily: string, size: number, color: string, stroke: string, strokeWidth: number, resolution: number) {\n const name = installLabelFont(fontFamily, size, color, stroke, strokeWidth, resolution);\n super({ text, style: { fontFamily: name, fontSize: size } });\n this.position.set(x, y);\n }\n\n setOrigin(x = 0.5, y = x): this {\n this.anchor.set(x, y);\n return this;\n }\n\n setText(text: string): this {\n this.text = text;\n return this;\n }\n}\n","import { Container, type Container as PixiContainer } from 'pixi.js';\nimport { GameObject } from './gameObject';\n\n/** A container of world objects, drawn in list order (children do not sort by depth). */\nexport class Group extends GameObject(Container) {\n get list(): PixiContainer[] {\n return this.children;\n }\n\n add(child: PixiContainer | PixiContainer[]): this {\n for (const c of Array.isArray(child) ? child : [child]) this.addChild(c);\n return this;\n }\n\n addAt(child: PixiContainer, index: number): this {\n this.addChildAt(child, Math.min(index, this.children.length));\n return this;\n }\n\n remove(child: PixiContainer, destroy = false): this {\n if (child.parent === this) this.removeChild(child);\n if (destroy) child.destroy({ children: true, context: true });\n return this;\n }\n\n /** Puts `child` directly below `other` in the draw order. */\n moveBelow(child: PixiContainer, other: PixiContainer): this {\n if (child.parent !== this || other.parent !== this || child === other) return this;\n this.removeChild(child);\n this.addChildAt(child, this.getChildIndex(other));\n return this;\n }\n\n /** Puts `child` directly above `other` in the draw order. */\n moveAbove(child: PixiContainer, other: PixiContainer): this {\n if (child.parent !== this || other.parent !== this || child === other) return this;\n this.removeChild(child);\n this.addChildAt(child, this.getChildIndex(other) + 1);\n return this;\n }\n}\n","import { Sprite } from 'pixi.js';\nimport { GameObject } from './gameObject';\nimport type { TextureRegistry } from './TextureRegistry';\n\n/** A textured sprite, centred by default; frames are looked up by name in the texture registry. */\nexport class Image extends GameObject(Sprite) {\n textureKey: string;\n frameName: string;\n\n constructor(\n private readonly registry: TextureRegistry,\n x: number,\n y: number,\n key: string,\n frame?: string | number,\n ) {\n super(registry.get(key, frame));\n this.textureKey = key;\n this.frameName = frame === undefined ? '' : String(frame);\n this.anchor.set(0.5);\n this.position.set(x, y);\n }\n\n get originX(): number {\n return this.anchor.x;\n }\n\n get originY(): number {\n return this.anchor.y;\n }\n\n /** Width of the frame itself, unscaled. */\n get frameWidth(): number {\n return this.texture.orig.width;\n }\n\n get frameHeight(): number {\n return this.texture.orig.height;\n }\n\n get displayWidth(): number {\n return Math.abs(this.frameWidth * this.scaleX);\n }\n\n set displayWidth(w: number) {\n this.scaleX = w / this.frameWidth;\n }\n\n get displayHeight(): number {\n return Math.abs(this.frameHeight * this.scaleY);\n }\n\n set displayHeight(h: number) {\n this.scaleY = h / this.frameHeight;\n }\n\n setOrigin(x = 0.5, y = x): this {\n this.anchor.set(x, y);\n return this;\n }\n\n setDisplaySize(w: number, h: number): this {\n return this.setScale(w / this.frameWidth, h / this.frameHeight);\n }\n\n setFrame(frame: string | number): this {\n this.frameName = String(frame);\n this.texture = this.registry.get(this.textureKey, frame);\n return this;\n }\n\n setTexture(key: string, frame?: string | number): this {\n this.textureKey = key;\n this.frameName = frame === undefined ? '' : String(frame);\n this.texture = this.registry.get(key, frame);\n return this;\n }\n}\n","import { Text as PixiText, type TextStyleOptions } from 'pixi.js';\nimport { GameObject } from './gameObject';\n\nexport interface TextStyle {\n fontFamily?: string;\n fontSize: string | number;\n color?: string;\n stroke?: string;\n strokeThickness?: number;\n /** Texture pixels per world pixel: world text is zoomed by the camera, so it is rasterised finer. */\n resolution?: number;\n align?: 'left' | 'center' | 'right';\n lineSpacing?: number;\n wordWrapWidth?: number;\n}\n\n/** Canvas text in world or screen space. */\nexport class Text extends GameObject(PixiText) {\n constructor(x: number, y: number, text: string, style: TextStyle) {\n // only keys that are set: an explicit undefined overrides Pixi's default (leading: undefined = NaN height)\n const pixiStyle: TextStyleOptions = {\n fontFamily: style.fontFamily ?? 'monospace',\n fontSize: typeof style.fontSize === 'string' ? parseFloat(style.fontSize) : style.fontSize,\n fill: style.color ?? '#ffffff',\n };\n if (style.stroke) pixiStyle.stroke = { color: style.stroke, width: style.strokeThickness ?? 1, join: 'round' };\n if (style.align) pixiStyle.align = style.align;\n if (style.lineSpacing !== undefined) pixiStyle.leading = style.lineSpacing;\n if (style.wordWrapWidth !== undefined) {\n pixiStyle.wordWrap = true;\n pixiStyle.wordWrapWidth = style.wordWrapWidth;\n }\n super({ text, resolution: style.resolution ?? 1, style: pixiStyle });\n this.position.set(x, y);\n }\n\n setOrigin(x = 0.5, y = x): this {\n this.anchor.set(x, y);\n return this;\n }\n\n setText(text: string): this {\n this.text = text;\n return this;\n }\n}\n","import type { Container } from 'pixi.js';\nimport { BitmapLabel } from './BitmapLabel';\nimport { Graphics } from './Graphics';\nimport { Group } from './Group';\nimport { Image } from './Image';\nimport { Rectangle } from './Rectangle';\nimport type { Stage } from './Stage';\nimport { Text, type TextStyle } from './Text';\n\n/** `scene.add.*`: creates an object and puts it on the world layer, where depth sorts it. */\nexport class ObjectFactory {\n constructor(private readonly stage: Stage) {}\n\n image(x: number, y: number, key: string, frame?: string | number): Image {\n return this.attach(new Image(this.stage.textures, x, y, key, frame));\n }\n\n /**\n * A copy of `src` as it is drawn right now (afterimages, clones). A live texture, repainted every frame, is\n * snapshotted first, and the snapshot is freed with the copy.\n */\n still(x: number, y: number, src: Image): Image {\n const textures = this.stage.textures;\n if (!textures.isLive(src.textureKey)) return this.image(x, y, src.textureKey, src.frameName);\n const key = textures.snapshot(src.textureKey, src.frameName);\n const img = this.image(x, y, key, '0');\n img.once('destroyed', () => textures.remove(key));\n return img;\n }\n\n graphics(opts?: { x?: number; y?: number }): Graphics {\n const g = this.attach(new Graphics());\n g.position.set(opts?.x ?? 0, opts?.y ?? 0);\n return g;\n }\n\n container(x = 0, y = 0, children: Container[] = []): Group {\n const c = this.attach(new Group());\n c.position.set(x, y);\n c.add(children);\n return c;\n }\n\n rectangle(x: number, y: number, w: number, h: number, color: number, alpha = 1): Rectangle {\n const r = this.attach(new Rectangle(w, h, color, alpha));\n r.position.set(x, y);\n return r;\n }\n\n text(x: number, y: number, text: string, style: TextStyle): Text {\n return this.attach(new Text(x, y, text, style));\n }\n\n /** A bitmap-font label (`BitmapLabel`): cheap to change, for text rewritten many times a second. */\n label(x: number, y: number, text: string, fontFamily: string, size: number, color: string, stroke: string, strokeWidth: number, resolution: number): BitmapLabel {\n return this.attach(new BitmapLabel(x, y, text, fontFamily, size, color, stroke, strokeWidth, resolution));\n }\n\n /** Puts an object made elsewhere on the world layer, as the factory's own are (a `PixelLayer`, a custom class). */\n existing<T extends Container & { scene: Stage }>(obj: T): T {\n return this.attach(obj);\n }\n\n private attach<T extends Container & { scene: Stage }>(obj: T): T {\n obj.scene = this.stage;\n this.stage.world.addChild(obj);\n return obj;\n }\n}\n","import type { Camera } from './Camera';\nimport { isTouchUi } from '../platform/touch';\n\n/** MouseEvent.button (0 left, 1 middle, 2 right) as a MouseEvent.buttons bit. */\nfunction buttonBit(button: number): number {\n return button === 1 ? 4 : button === 2 ? 2 : button === 0 ? 1 : 0;\n}\n\n/**\n * The mouse over the game canvas. Presses count only when they start on the canvas (not on the React UI above it);\n * moves are followed everywhere so aiming keeps working at the edge of a panel.\n */\nexport class Pointer {\n /**\n * A press this returns true for is not counted as a held button (e.g. Shift + right-click opening a context menu\n * instead of firing what the right button is bound to). Unset, every press counts.\n */\n static ignorePress: ((e: PointerEvent) => boolean) | null = null;\n\n /** Screen position relative to the canvas, in CSS pixels. */\n x = 0;\n y = 0;\n worldX = 0;\n worldY = 0;\n private buttons = 0;\n private readonly cleanup: (() => void)[] = [];\n\n constructor(private readonly canvas: HTMLCanvasElement) {\n // with the on-screen controls a finger on the world is not a mouse: it would swing at every tap and drag the\n // aim after the joystick thumb (touch controls aim on their own). A real mouse still works.\n const fingers = isTouchUi();\n const on = <K extends keyof WindowEventMap>(target: Window | HTMLElement, type: K, fn: (e: WindowEventMap[K]) => void) => {\n const handler = (e: WindowEventMap[K]) => {\n if (fingers && e instanceof PointerEvent && e.pointerType === 'touch') return;\n fn(e);\n };\n target.addEventListener(type, handler as EventListener);\n this.cleanup.push(() => target.removeEventListener(type, handler as EventListener));\n };\n // Pointer events, since Pixi's event system cancels the mouse events that follow them. Read `button` (the one\n // that changed), not `buttons`: synthetic input (CDP) leaves `buttons` at 0.\n on(canvas, 'pointerdown', (e) => {\n this.track(e);\n if (Pointer.ignorePress?.(e)) return;\n this.buttons |= buttonBit(e.button);\n });\n on(window, 'pointermove', (e) => {\n this.track(e);\n // a second button pressed or released while one is held arrives as a move\n if (e.button >= 0) this.buttons = (e.buttons & buttonBit(e.button)) !== 0 ? this.buttons | buttonBit(e.button) : this.buttons & ~buttonBit(e.button);\n });\n on(window, 'pointerup', (e) => {\n this.buttons &= ~buttonBit(e.button);\n });\n on(window, 'blur', () => {\n this.buttons = 0;\n });\n on(canvas, 'contextmenu', (e) => e.preventDefault());\n }\n\n leftButtonDown(): boolean {\n return (this.buttons & 1) !== 0;\n }\n\n rightButtonDown(): boolean {\n return (this.buttons & 2) !== 0;\n }\n\n updateWorldPoint(cam: Camera): void {\n this.worldX = cam.scrollX + this.x / cam.zoom;\n this.worldY = cam.scrollY + this.y / cam.zoom;\n }\n\n destroy(): void {\n for (const fn of this.cleanup) fn();\n this.cleanup.length = 0;\n }\n\n private track(e: MouseEvent): void {\n const r = this.canvas.getBoundingClientRect();\n this.x = e.clientX - r.left;\n this.y = e.clientY - r.top;\n }\n}\n","export type EaseFn = (t: number) => number;\n\nconst linear: EaseFn = (t) => t;\n\n/** Easing functions by the names tween configs use ('Cubic.Out', 'Back.Out', ...). */\nconst EASES: Record<string, EaseFn> = {\n Linear: linear,\n 'Quad.In': (t) => t * t,\n 'Quad.Out': (t) => t * (2 - t),\n 'Cubic.Out': (t) => 1 - Math.pow(1 - t, 3),\n 'Sine.In': (t) => 1 - Math.cos((t * Math.PI) / 2),\n 'Sine.InOut': (t) => -(Math.cos(Math.PI * t) - 1) / 2,\n 'Back.Out': (t) => {\n const s = 1.70158;\n const u = t - 1;\n return u * u * ((s + 1) * u + s) + 1;\n },\n};\n\nexport function easeByName(name: string | undefined): EaseFn {\n if (!name) return EASES['Quad.Out']!; // Phaser's default tween ease is Power1 = Quad.Out\n const fn = EASES[name];\n if (!fn) console.warn(`[tween] unknown ease ${name}`);\n return fn ?? linear;\n}\n","import { easeByName } from './eases';\n\nexport type TweenTarget = Record<string, unknown> & { destroyed?: boolean };\n\n/** Tween config in the shape the renderer has always used: numeric props at the top level or under `props`. */\nexport interface TweenConfig {\n targets: object | object[];\n duration?: number;\n delay?: number;\n /** Ms to stay at the end values before a yoyo plays back. */\n hold?: number;\n yoyo?: boolean;\n /** Extra plays after the first (-1 = forever). */\n repeat?: number;\n ease?: string;\n props?: Record<string, number>;\n onStart?: () => void;\n onUpdate?: () => void;\n onComplete?: () => void;\n [prop: string]: unknown;\n}\n\nconst RESERVED = new Set([\n 'targets', 'duration', 'delay', 'hold', 'yoyo', 'repeat', 'ease', 'props', 'onStart', 'onUpdate', 'onComplete',\n]);\n\ninterface Track {\n target: TweenTarget;\n prop: string;\n from: number;\n to: number;\n}\n\n/** One running tween; `remove()` stops it without calling onComplete. */\nexport class Tween {\n private tracks: Track[] | null = null;\n private elapsed = 0;\n private plays = 0;\n removed = false;\n readonly targets: TweenTarget[];\n\n constructor(\n private readonly cfg: TweenConfig,\n private readonly ends: Record<string, number>,\n ) {\n const t = cfg.targets;\n this.targets = (Array.isArray(t) ? t : [t]) as TweenTarget[];\n }\n\n /**\n * Every target is a destroyed display object: nothing is left to move. A forever tween (`repeat: -1`) on a sprite\n * its owner freed used to stay in the list for good, holding the sprite, and the list grew with every map loaded.\n * A plain object (a clock a callback reads) has no `destroyed` and is never taken for one. Only a forever tween is\n * dropped this way: a finite one still runs out and calls its `onComplete`, which may clean up more than the sprite.\n */\n private orphaned(): boolean {\n if (this.cfg.repeat !== -1) return false;\n const ts = this.targets;\n if (ts.length === 0) return false;\n for (const t of ts) if (t.destroyed !== true) return false;\n return true;\n }\n\n remove(): void {\n this.removed = true;\n }\n\n stop(): void {\n this.removed = true;\n }\n\n /** Advances by `dt` ms; returns false once the tween is finished. */\n step(dt: number): boolean {\n if (this.removed) return false;\n if (this.orphaned()) {\n this.removed = true;\n return false;\n }\n const cfg = this.cfg;\n const delay = cfg.delay ?? 0;\n this.elapsed += dt;\n if (this.elapsed < delay) return true;\n if (!this.tracks) {\n this.tracks = [];\n for (const target of this.targets) {\n for (const [prop, to] of Object.entries(this.ends)) this.tracks.push({ target, prop, from: read(target, prop), to });\n }\n cfg.onStart?.();\n }\n const duration = Math.max(1, cfg.duration ?? 1000);\n const hold = cfg.yoyo ? cfg.hold ?? 0 : 0;\n const cycle = cfg.yoyo ? duration * 2 + hold : duration;\n let local = this.elapsed - delay - this.plays * cycle;\n const repeat = cfg.repeat ?? 0;\n let finished = false;\n if (local >= cycle) {\n if (repeat === -1 || this.plays < repeat) {\n this.plays++;\n local -= cycle;\n } else {\n local = cycle;\n finished = true;\n }\n }\n let p: number;\n if (!cfg.yoyo) p = local / duration;\n else if (local <= duration) p = local / duration;\n else if (local <= duration + hold) p = 1;\n else p = 1 - (local - duration - hold) / duration;\n const k = easeByName(cfg.ease)(Math.min(1, Math.max(0, p)));\n for (const t of this.tracks) if (!t.target.destroyed) write(t.target, t.prop, t.from + (t.to - t.from) * k);\n cfg.onUpdate?.();\n if (finished) {\n this.removed = true;\n cfg.onComplete?.();\n return false;\n }\n return true;\n }\n}\n\nfunction read(target: TweenTarget, prop: string): number {\n const v = prop === 'scale' ? target['scaleX'] : target[prop];\n return typeof v === 'number' ? v : 0;\n}\n\nfunction write(target: TweenTarget, prop: string, value: number): void {\n if (prop === 'scale') {\n target['scaleX'] = value;\n target['scaleY'] = value;\n } else target[prop] = value;\n}\n\n/** Frame-driven tween manager (the renderer's replacement for Phaser's TweenManager). */\nexport class Tweener {\n /** Global speed factor; hit-stop slows every tween at once. */\n timeScale = 1;\n private tweens: Tween[] = [];\n\n add(cfg: TweenConfig): Tween {\n const ends: Record<string, number> = { ...(cfg.props ?? {}) };\n const starts: Record<string, number> = {};\n for (const [k, v] of Object.entries(cfg)) {\n if (RESERVED.has(k)) continue;\n if (typeof v === 'number') ends[k] = v;\n else if (v && typeof v === 'object' && 'to' in v) {\n const range = v as { from?: number; to: number };\n ends[k] = range.to;\n if (range.from !== undefined) starts[k] = range.from;\n }\n }\n // `{ from, to }` jumps to `from` right away, before any delay\n const targets = (Array.isArray(cfg.targets) ? cfg.targets : [cfg.targets]) as Record<string, unknown>[];\n for (const t of targets) for (const [k, v] of Object.entries(starts)) t[k] = v;\n const tween = new Tween(cfg, ends);\n this.tweens.push(tween);\n return tween;\n }\n\n killTweensOf(target: object | object[]): void {\n const set = new Set(Array.isArray(target) ? target : [target]);\n for (const t of this.tweens) if (t.targets.some((x) => set.has(x))) t.remove();\n }\n\n update(dt: number): void {\n const scaled = dt * this.timeScale;\n // tweens started from a callback run from the next frame on, like Phaser's\n // compacted in place: the ones added meanwhile sit past `n` and keep their order after the survivors\n const list = this.tweens;\n const n = list.length;\n let kept = 0;\n for (let i = 0; i < n; i++) {\n const t = list[i]!;\n if (stepSafely(t, scaled)) list[kept++] = t;\n }\n // a callback that cleared the manager dropped this list, and every tween on it was removed\n if (this.tweens !== list) return;\n for (let i = n; i < list.length; i++) list[kept++] = list[i]!;\n list.length = kept;\n }\n\n clear(): void {\n for (const t of this.tweens) t.remove();\n this.tweens = [];\n }\n}\n\n/** A tween whose step or callback throws is dropped, so it neither throws every frame nor leaves the list half compacted. */\nfunction stepSafely(t: { step(dt: number): boolean }, dt: number): boolean {\n try {\n return t.step(dt);\n } catch (err) {\n console.error('[tween] dropped after an error', err);\n return false;\n }\n}\n","import { Container, type Application } from 'pixi.js';\nimport { Camera } from './Camera';\nimport { Clock } from './Clock';\nimport { ObjectFactory } from './ObjectFactory';\nimport { Pointer } from './Pointer';\nimport type { TextureRegistry } from './TextureRegistry';\nimport { Tweener } from './Tweener';\n\n/**\n * What a world object is created in: a world layer the camera moves (children sorted by depth), a screen layer\n * above it, and the per-frame services (tweens, timers, camera, pointer). Subclasses implement `update`.\n */\nexport abstract class Stage {\n /** Told of every fault a guarded step caught (error telemetry, if the game sets one). */\n static onCaught: ((where: string, err: unknown) => void) | null = null;\n\n readonly world = new Container({ sortableChildren: true });\n readonly screen = new Container();\n readonly add = new ObjectFactory(this);\n readonly tweens = new Tweener();\n readonly time = new Clock();\n readonly cameras: { main: Camera };\n readonly input: { activePointer: Pointer };\n private readonly resizeListeners: (() => void)[] = [];\n private lastWidth = 0;\n private lastHeight = 0;\n\n constructor(\n readonly app: Application,\n readonly textures: TextureRegistry,\n ) {\n app.stage.addChild(this.world, this.screen);\n this.cameras = { main: new Camera(this.world, this.screen) };\n this.input = { activePointer: new Pointer(app.canvas) };\n this.syncSize();\n }\n\n get width(): number {\n return this.app.screen.width;\n }\n\n get height(): number {\n return this.app.screen.height;\n }\n\n get fps(): number {\n return this.app.ticker.FPS;\n }\n\n /** Calls `fn` whenever the window changes size; the returned function stops it (a per-map listener must). */\n onResize(fn: () => void): () => void {\n this.resizeListeners.push(fn);\n return () => {\n const i = this.resizeListeners.indexOf(fn);\n if (i >= 0) this.resizeListeners.splice(i, 1);\n };\n }\n\n abstract update(now: number, delta: number): void;\n\n /**\n * One frame: game logic, then tweens and timers, then the camera. Pixi renders after. Each step is guarded: a\n * ticker listener that throws never asks for the next animation frame, so one bad frame used to stop the world for\n * good — the canvas frozen and no input reaching the server (seen on Android).\n */\n frame(delta: number): void {\n const now = performance.now();\n this.guard('resize', () => this.syncSize());\n this.guard('update', () => this.update(now, delta));\n this.guard('tweens', () => this.tweens.update(delta));\n this.guard('timers', () => this.time.update(now));\n this.guard('camera', () => this.cameras.main.apply(now));\n }\n\n private readonly reported = new Set<string>();\n\n /**\n * Runs one step of a frame and swallows what it throws, so the steps after it still run. Subclasses guard the parts\n * of their own `update` too: a fault before the camera follows the player used to leave the view standing on one\n * spot while the world went on.\n */\n protected guard(step: string, fn: () => void): void {\n this.guarded(step, fn, undefined);\n }\n\n /** `guard` for a step that answers something: `fallback` when it threw. */\n protected guarded<T>(step: string, fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch (err) {\n this.caught(step, err);\n return fallback;\n }\n }\n\n /** What a guarded step threw: logged once per distinct error, or a fault repeating every frame floods the log at 60 a second. */\n protected caught(step: string, err: unknown): void {\n const key = `${step}|${err instanceof Error ? err.message : String(err)}`;\n if (this.reported.has(key)) return;\n this.reported.add(key);\n console.error(`[frame] ${step} failed`, err);\n // caught here, so the window's error listener never hears of it: tell the telemetry ourselves\n Stage.onCaught?.(`[frame] ${step}`, err);\n }\n\n destroy(): void {\n this.tweens.clear();\n this.time.clear();\n this.input.activePointer.destroy();\n this.world.destroy({ children: true, context: true });\n this.screen.destroy({ children: true, context: true });\n }\n\n private syncSize(): void {\n const { width, height } = this.app.screen;\n const cam = this.cameras.main;\n cam.width = width;\n cam.height = height;\n if (width === this.lastWidth && height === this.lastHeight) return;\n this.lastWidth = width;\n this.lastHeight = height;\n // a copy: a listener may unsubscribe itself (or another) while they run\n for (const fn of [...this.resizeListeners]) fn();\n }\n}\n","import { CanvasSource, Rectangle, Texture } from 'pixi.js';\n\n/** A canvas-backed texture with named frames; repaint the canvas, then `refresh()` to upload it. */\nexport class CanvasTexture {\n readonly frames = new Map<string, Texture>();\n readonly source: CanvasSource;\n readonly whole: Texture;\n\n constructor(\n readonly key: string,\n readonly canvas: HTMLCanvasElement,\n ) {\n this.source = new CanvasSource({ resource: canvas, scaleMode: 'nearest' });\n this.whole = new Texture({ source: this.source });\n }\n\n get width(): number {\n return this.canvas.width;\n }\n\n get height(): number {\n return this.canvas.height;\n }\n\n get context(): CanvasRenderingContext2D {\n return this.canvas.getContext('2d')!;\n }\n\n /** Adds a frame cut from the canvas (`_source` kept for the old call shape). */\n add(name: string, _source: number, x: number, y: number, w: number, h: number): void {\n this.frames.get(name)?.destroy();\n this.frames.set(name, new Texture({ source: this.source, frame: new Rectangle(x, y, w, h) }));\n }\n\n /**\n * Registers under this texture a frame that lives on another one (an atlas page after the first), so the frame is\n * found by this texture's key. A texture of its own over the other page's source: each side frees its own.\n */\n adopt(name: string, from: CanvasTexture): void {\n const src = from.frames.get(name);\n if (!src) return;\n this.frames.get(name)?.destroy();\n this.frames.set(name, new Texture({ source: from.source, frame: src.frame.clone() }));\n }\n\n refresh(): void {\n this.source.update();\n }\n\n destroy(): void {\n for (const t of this.frames.values()) t.destroy();\n this.frames.clear();\n this.whole.destroy();\n this.source.destroy();\n }\n}\n\n/** Every texture of the world by key: the sprite atlas and per-player repainted sheets. */\nexport class TextureRegistry {\n private readonly textures = new Map<string, CanvasTexture>();\n /** Textures repainted or freed while in use (a rig body, its hand): a copy of one must snapshot it first. */\n private readonly live = new Set<string>();\n private missing = new Set<string>();\n private snapshots = 0;\n\n markLive(key: string): void {\n this.live.add(key);\n }\n\n isLive(key: string): boolean {\n return this.live.has(key);\n }\n\n /** A new texture holding frame `frame` of `key` as it is painted right now; returns its key (one frame, '0'). */\n snapshot(key: string, frame?: string | number): string {\n const src = this.get(key, frame);\n const { x, y, width, height } = src.frame;\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const from = this.textures.get(key)?.canvas;\n if (from) canvas.getContext('2d')!.drawImage(from, x, y, width, height, 0, 0, width, height);\n const copy = `${key}#still${++this.snapshots}`;\n this.addCanvas(copy, canvas).add('0', 0, 0, 0, width, height);\n return copy;\n }\n\n /**\n * `snapshot` into a texture kept for reuse (`into`): its canvas is repainted in place and uploaded again, and only\n * made anew when the frame's size changes. Frame '0' is the copy.\n */\n snapshotInto(key: string, frame: string | number | undefined, into: string): void {\n const src = this.get(key, frame);\n const { x, y, width, height } = src.frame;\n let tex = this.textures.get(into);\n if (!tex || tex.width !== width || tex.height !== height) {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n tex = this.addCanvas(into, canvas);\n tex.add('0', 0, 0, 0, width, height);\n }\n const ctx = tex.context;\n ctx.clearRect(0, 0, width, height);\n const from = this.textures.get(key)?.canvas;\n if (from) ctx.drawImage(from, x, y, width, height, 0, 0, width, height);\n tex.refresh();\n }\n\n exists(key: string): boolean {\n return this.textures.has(key);\n }\n\n addCanvas(key: string, canvas: HTMLCanvasElement): CanvasTexture {\n this.remove(key);\n const tex = new CanvasTexture(key, canvas);\n this.textures.set(key, tex);\n return tex;\n }\n\n /** A canvas cut into equal frames named 0, 1, 2... left to right, then row by row. */\n addSpriteSheet(key: string, canvas: HTMLCanvasElement, size: { frameWidth: number; frameHeight: number }): CanvasTexture {\n const tex = this.addCanvas(key, canvas);\n const cols = Math.floor(canvas.width / size.frameWidth);\n const rows = Math.floor(canvas.height / size.frameHeight);\n for (let i = 0; i < cols * rows; i++) {\n tex.add(String(i), 0, (i % cols) * size.frameWidth, Math.floor(i / cols) * size.frameHeight, size.frameWidth, size.frameHeight);\n }\n return tex;\n }\n\n createCanvas(key: string, width: number, height: number): CanvasTexture {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return this.addCanvas(key, canvas);\n }\n\n remove(key: string): void {\n this.textures.get(key)?.destroy();\n this.textures.delete(key);\n this.live.delete(key);\n }\n\n get(key: string, frame?: string | number): Texture {\n const tex = this.textures.get(key);\n if (!tex) return this.warn(key);\n if (frame === undefined || frame === '') return tex.whole;\n return tex.frames.get(String(frame)) ?? this.warn(`${key}/${frame}`);\n }\n\n private warn(what: string): Texture {\n if (!this.missing.has(what)) {\n this.missing.add(what);\n console.warn(`[textures] missing ${what}`);\n }\n return Texture.EMPTY;\n }\n}\n","/**\n * Typed observer: listeners subscribe per event name and run in subscription order.\n * `Events` maps each event name to its payload, e.g. `EventBus<{ enemyKilled: { id: number } }>`.\n *\n * A listener that throws does not stop the ones after it; the error is handed to `onError` (the console by default).\n */\nexport class EventBus<Events extends object> {\n private readonly listeners = new Map<keyof Events, ((payload: never) => void)[]>();\n\n constructor(private readonly onError: (type: keyof Events, err: unknown) => void = (type, err) => console.error(`[events] ${String(type)} listener failed`, err)) {}\n\n /** Subscribes to `type`; returns the unsubscribe function. */\n on<K extends keyof Events>(type: K, fn: (payload: Events[K]) => void): () => void {\n this.listeners.set(type, [...(this.listeners.get(type) ?? []), fn]);\n return () => this.off(type, fn);\n }\n\n /** Subscribes for the next `type` only. */\n once<K extends keyof Events>(type: K, fn: (payload: Events[K]) => void): () => void {\n const off = this.on(type, (payload) => {\n off();\n fn(payload);\n });\n return off;\n }\n\n off<K extends keyof Events>(type: K, fn: (payload: Events[K]) => void): void {\n const list = this.listeners.get(type);\n if (!list) return;\n const left = list.filter((f) => f !== fn);\n if (left.length) this.listeners.set(type, left);\n else this.listeners.delete(type);\n }\n\n emit<K extends keyof Events>(type: K, payload: Events[K]): void {\n // the list is replaced, never mutated, on every (un)subscribe: walking this one is safe while listeners change it\n for (const fn of this.listeners.get(type) ?? []) {\n try {\n (fn as (payload: Events[K]) => void)(payload);\n } catch (err) {\n this.onError(type, err);\n }\n }\n }\n\n listenerCount(type: keyof Events): number {\n return this.listeners.get(type)?.length ?? 0;\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","/**\n * A fixed-timestep accumulator: frames arrive whenever the display wants them, the simulation advances in equal\n * steps. Movement and anything a server replays must run here, so every machine takes the same steps whatever its\n * frame rate.\n *\n * A frame that comes very late (a tab in the background, a debugger) would owe hundreds of steps; at most\n * `maxStepsPerFrame` are run and the rest of the debt is dropped, so the game slows down instead of freezing while it\n * catches up (the \"spiral of death\").\n */\nexport interface FixedLoopOptions {\n /** Steps per second (default 60). */\n hz?: number;\n /** The most steps one frame may run before the debt is dropped (default 8). */\n maxStepsPerFrame?: number;\n}\n\nexport class FixedLoop {\n readonly stepMs: number;\n readonly stepSeconds: number;\n private readonly maxSteps: number;\n private carry = 0;\n /** Steps taken since the loop started. */\n tick = 0;\n\n constructor(options: FixedLoopOptions = {}) {\n const hz = options.hz ?? 60;\n if (!(hz > 0)) throw new Error(`FixedLoop: hz must be positive, got ${hz}`);\n this.stepMs = 1000 / hz;\n this.stepSeconds = 1 / hz;\n this.maxSteps = Math.max(1, options.maxStepsPerFrame ?? 8);\n }\n\n /**\n * Feeds one frame of `deltaMs` and runs `step` as many times as it owes. Returns the share of a step left over\n * (0–1), for interpolating what is drawn between the last two steps.\n */\n advance(deltaMs: number, step: (tick: number) => void): number {\n if (deltaMs > 0 && Number.isFinite(deltaMs)) this.carry += deltaMs;\n let ran = 0;\n while (this.carry >= this.stepMs) {\n if (ran === this.maxSteps) {\n this.carry %= this.stepMs;\n break;\n }\n this.carry -= this.stepMs;\n ran++;\n step(this.tick++);\n }\n return this.carry / this.stepMs;\n }\n\n /** Forgets any debt, e.g. after a scene change or a long load. */\n reset(): void {\n this.carry = 0;\n }\n}\n","import type { Engine } from './Engine';\nimport type { Scene } from './Scene';\n\n/**\n * A stack of scenes. Only the top one updates; the ones under it are paused but still drawn (a pause menu over the\n * level). Changes are queued and applied one at a time, so a scene that replaces itself from inside its own update,\n * or an async `onEnter` still loading, never leaves two scenes half entered.\n */\nexport class SceneManager {\n private readonly stack: Scene[] = [];\n private queue: Promise<void> = Promise.resolve();\n /** True while an async `onEnter` is running: nothing updates until it is done. */\n private entering = false;\n\n constructor(private readonly engine: Engine) {}\n\n /** The scene that updates, if any. */\n get current(): Scene | undefined {\n return this.entering ? undefined : this.stack[this.stack.length - 1];\n }\n\n /** Every scene on the stack, bottom first. */\n get all(): readonly Scene[] {\n return this.stack;\n }\n\n /** Removes every scene and enters `scene`. */\n replace(scene: Scene): Promise<void> {\n return this.enqueue(async () => {\n while (this.stack.length) this.exitTop();\n await this.enter(scene);\n });\n }\n\n /** Pauses the current scene and enters `scene` over it. */\n push(scene: Scene): Promise<void> {\n return this.enqueue(async () => {\n this.stack[this.stack.length - 1]?.onPause();\n await this.enter(scene);\n });\n }\n\n /** Leaves the current scene and resumes the one under it. */\n pop(): Promise<void> {\n return this.enqueue(async () => {\n if (!this.stack.length) return;\n this.exitTop();\n this.stack[this.stack.length - 1]?.onResume();\n });\n }\n\n /** Leaves every scene (the engine is shutting down). */\n clear(): Promise<void> {\n return this.enqueue(async () => {\n while (this.stack.length) this.exitTop();\n });\n }\n\n private async enter(scene: Scene): Promise<void> {\n if (this.stack.includes(scene)) throw new Error(`${scene.constructor.name} is already on the scene stack`);\n scene.attach(this.engine);\n this.stack.push(scene);\n this.entering = true;\n try {\n await scene.onEnter();\n } finally {\n this.entering = false;\n }\n this.engine.loop.reset();\n }\n\n private exitTop(): void {\n const scene = this.stack.pop();\n if (!scene) return;\n try {\n scene.onExit();\n } finally {\n scene.detach();\n }\n }\n\n private enqueue(job: () => Promise<void>): Promise<void> {\n const run = this.queue.then(job);\n // a failed change must not wedge every change after it\n this.queue = run.catch((err) => this.engine.reportError('scene', err));\n return run;\n }\n}\n","import { Application, TextureSource } from 'pixi.js';\nimport { Stage } from '../core/Stage';\nimport { TextureRegistry } from '../core/TextureRegistry';\nimport { patchPixi } from '../core/pixiPatches';\nimport { EventBus } from '../events/EventBus';\nimport { FixedLoop } from './FixedLoop';\nimport { SceneManager } from './SceneManager';\nimport type { Scene } from './Scene';\n\nexport interface EngineOptions {\n /** Where the canvas goes. */\n parent: HTMLElement;\n /** A fixed canvas size in CSS pixels. Leave both out to fill `parent` and follow its size. */\n width?: number;\n height?: number;\n /** CSS colour behind the world (default black). */\n background?: string;\n /** World pixels are drawn this many screen pixels wide (default 1). Whole numbers keep pixel art crisp. */\n zoom?: number;\n /** Simulation steps per second (default 60). */\n hz?: number;\n /** Textures shared by the stage; a fresh registry by default. */\n textures?: TextureRegistry;\n /**\n * Pixel art: nearest-neighbour textures, no antialiasing, one backing pixel per CSS pixel, and a camera that lands\n * on whole pixels (default false: smooth textures drawn at the screen's own density, for any other art style).\n */\n pixelPerfect?: boolean;\n /** Backing pixels per CSS pixel when not `pixelPerfect` (default `devicePixelRatio`, at most 2). */\n resolution?: number;\n /**\n * Renderer preference (default 'webgl'). WebGL 2 runs everywhere the engine is tested. 'webgpu' is experimental:\n * Pixi falls back to WebGL where WebGPU is missing, but the engine's own paths (pooled `PixelLayer` buffers, the\n * `erase` blend `Darkness` cuts lights with, the fill filters) have only been profiled on WebGL.\n */\n preference?: 'webgl' | 'webgpu';\n}\n\nexport interface EngineEvents {\n /** Something a guarded step or a system threw; the frame carried on. */\n error: { where: string; error: unknown };\n /** After every rendered frame's update, before Pixi renders. */\n frame: { now: number; dt: number };\n}\n\n/** The stage the engine drives: its per-frame update is the engine's tick. */\nclass EngineStage extends Stage {\n constructor(\n app: Application,\n textures: TextureRegistry,\n private readonly tick: (now: number, delta: number) => void,\n ) {\n super(app, textures);\n }\n\n override update(now: number, delta: number): void {\n this.tick(now, delta);\n }\n}\n\n/**\n * The top of the engine: a Pixi application, the `Stage` (world and screen layers, camera, tweens, timers,\n * pointer), a fixed-step simulation loop and a stack of scenes.\n *\n * ```ts\n * const engine = await Engine.create({ parent: document.body, zoom: 3 });\n * await engine.scenes.replace(new MyLevel());\n * ```\n */\nexport class Engine {\n readonly stage: Stage;\n readonly loop: FixedLoop;\n readonly scenes: SceneManager;\n readonly events = new EventBus<EngineEvents>();\n private running = true;\n private destroyed = false;\n private readonly onTick = (t: { deltaMS: number }) => this.stage.frame(t.deltaMS);\n\n private constructor(\n readonly app: Application,\n textures: TextureRegistry,\n options: EngineOptions,\n ) {\n this.loop = new FixedLoop(options.hz === undefined ? {} : { hz: options.hz });\n this.stage = new EngineStage(app, textures, (now, delta) => this.tick(now, delta));\n const cam = this.stage.cameras.main;\n cam.setZoom(options.zoom ?? 1);\n cam.roundPixels = options.pixelPerfect === true;\n cam.resolution = app.renderer.resolution;\n this.scenes = new SceneManager(this);\n Stage.onCaught = (where, error) => this.events.emit('error', { where, error });\n app.ticker.add(this.onTick);\n }\n\n static async create(options: EngineOptions): Promise<Engine> {\n const pixel = options.pixelPerfect === true;\n TextureSource.defaultOptions.scaleMode = pixel ? 'nearest' : 'linear';\n const resolution = pixel ? 1 : (options.resolution ?? Math.min(2, typeof devicePixelRatio === 'number' ? devicePixelRatio : 1));\n patchPixi();\n const app = new Application();\n const fill = options.width === undefined && options.height === undefined;\n await app.init({\n ...(fill ? { resizeTo: options.parent } : { width: options.width ?? 800, height: options.height ?? 600 }),\n background: options.background ?? '#000000',\n antialias: !pixel,\n resolution,\n autoDensity: true,\n preference: options.preference ?? 'webgl',\n });\n options.parent.appendChild(app.canvas);\n return new Engine(app, options.textures ?? new TextureRegistry(), options);\n }\n\n /** The scene that updates now, if any. */\n get scene(): Scene | undefined {\n return this.scenes.current;\n }\n\n /** Stops simulating and drawing; the canvas keeps its last frame. */\n pause(): void {\n if (!this.running) return;\n this.running = false;\n this.app.ticker.stop();\n }\n\n resume(): void {\n if (this.running || this.destroyed) return;\n this.running = true;\n this.loop.reset();\n this.app.ticker.start();\n }\n\n get paused(): boolean {\n return !this.running;\n }\n\n /** Reports a fault to `events.error` (and the console when nobody listens). */\n reportError(where: string, error: unknown): void {\n if (this.events.listenerCount('error') === 0) console.error(`[engine] ${where}`, error);\n this.events.emit('error', { where, error });\n }\n\n /** Leaves every scene, removes the canvas and frees the renderer. */\n async destroy(): Promise<void> {\n if (this.destroyed) return;\n this.destroyed = true;\n await this.scenes.clear();\n this.app.ticker.remove(this.onTick);\n if (Stage.onCaught) Stage.onCaught = null;\n this.stage.destroy();\n this.events.clear();\n this.app.destroy({ removeView: true }, { children: true });\n }\n\n private tick(now: number, delta: number): void {\n const scene = this.scenes.current;\n if (scene) {\n const report = (s: { name: string }, err: unknown) => this.reportError(`system ${s.name}`, err);\n const step = this.loop.stepSeconds;\n const alpha = this.loop.advance(delta, () => {\n scene.world.run('fixed', { dt: step, now, alpha: 0 }, report);\n scene.fixedUpdate(step);\n });\n const dt = delta / 1000;\n scene.world.run('frame', { dt, now, alpha }, report);\n scene.update(dt, alpha);\n }\n this.events.emit('frame', { now, dt: delta / 1000 });\n }\n}\n","/**\n * One component type's storage: a sparse set. `sparse[index]` is where the entity's value sits in the dense arrays\n * (or -1), and `entities`/`values` are packed with no holes, so walking a component is a walk over two flat arrays\n * and finding one is two array reads. Removing swaps the last entry into the hole.\n *\n * Indexed by the entity's slot index (`entityIndex`), not the whole id: the generation is checked by the world.\n */\nexport class SparseSet<T> {\n private sparse: Int32Array = new Int32Array(64).fill(-1);\n /** Packed entity ids, in the same order as `values`. */\n readonly entities: number[] = [];\n readonly values: T[] = [];\n /** Bumped whenever an entity joins or leaves the set (not when a value changes): query caches key on it. */\n version = 0;\n\n get size(): number {\n return this.entities.length;\n }\n\n has(index: number): boolean {\n return index < this.sparse.length && this.sparse[index]! >= 0;\n }\n\n /** The value at slot `index`, or undefined. */\n get(index: number): T | undefined {\n if (index >= this.sparse.length) return undefined;\n const d = this.sparse[index]!;\n return d >= 0 ? this.values[d] : undefined;\n }\n\n set(index: number, entity: number, value: T): void {\n this.grow(index);\n const d = this.sparse[index]!;\n if (d >= 0) {\n this.values[d] = value;\n this.entities[d] = entity;\n return;\n }\n this.sparse[index] = this.entities.length;\n this.version++;\n this.entities.push(entity);\n this.values.push(value);\n }\n\n /** Removes slot `index`; true if it was there. */\n delete(index: number, indexOf: (entity: number) => number): boolean {\n if (index >= this.sparse.length) return false;\n const d = this.sparse[index]!;\n if (d < 0) return false;\n const last = this.entities.length - 1;\n if (d !== last) {\n const moved = this.entities[last]!;\n this.entities[d] = moved;\n this.values[d] = this.values[last]!;\n this.sparse[indexOf(moved)] = d;\n }\n this.entities.pop();\n this.values.pop();\n this.sparse[index] = -1;\n this.version++;\n return true;\n }\n\n clear(): void {\n this.version++;\n this.sparse.fill(-1);\n this.entities.length = 0;\n this.values.length = 0;\n }\n\n private grow(index: number): void {\n if (index < this.sparse.length) return;\n let n = this.sparse.length;\n while (n <= index) n *= 2;\n const next = new Int32Array(n).fill(-1);\n next.set(this.sparse);\n this.sparse = next;\n }\n}\n","import type { ComponentType } from './World';\n\n/**\n * Numeric components stored as columns of typed arrays instead of one object per entity: `Position.x` and\n * `Position.y` are two `Float32Array`s indexed by the entity's slot. A system walking thousands of bodies then reads\n * memory in order and makes no garbage, which is several times faster than objects at scale (see `bench/`).\n *\n * ```ts\n * const Position = defineFields('Position', { x: 'f32', y: 'f32' });\n * world.add(e, Position, { x: 10, y: 20 });\n * const p = world.columns(Position); // fetch per run: columns grow (and are replaced) as entities are added\n * world.each(Position, (e, i) => { p.x[i] += 1; });\n * ```\n *\n * In `each`/`query` a field component's value is the entity's slot index `i`, the index into every column.\n */\nexport type FieldKind = 'f32' | 'f64' | 'i8' | 'i16' | 'i32' | 'u8' | 'u16' | 'u32';\n\nexport type FieldSpec = Record<string, FieldKind>;\n\nexport type ArrayOf<K extends FieldKind> = K extends 'f32'\n ? Float32Array\n : K extends 'f64'\n ? Float64Array\n : K extends 'i8'\n ? Int8Array\n : K extends 'i16'\n ? Int16Array\n : K extends 'i32'\n ? Int32Array\n : K extends 'u8'\n ? Uint8Array\n : K extends 'u16'\n ? Uint16Array\n : Uint32Array;\n\n/** One typed array per field, indexed by slot. */\nexport type Columns<S extends FieldSpec> = { [K in keyof S]: ArrayOf<S[K]> };\n\n/** What `add` takes for a field component: any subset of its fields (the rest start at 0). */\nexport type FieldValues<S extends FieldSpec> = { [K in keyof S]?: number };\n\n/** A component of numeric fields. Its value in `each`/`query` is the slot index. */\nexport interface FieldsType<S extends FieldSpec> extends ComponentType<number> {\n readonly fields: S;\n}\n\nconst CTORS: Record<FieldKind, new (n: number) => ArrayLike<number> & { set(a: ArrayLike<number>): void }> = {\n f32: Float32Array,\n f64: Float64Array,\n i8: Int8Array,\n i16: Int16Array,\n i32: Int32Array,\n u8: Uint8Array,\n u16: Uint16Array,\n u32: Uint32Array,\n};\n\nexport function isFields(type: ComponentType<unknown>): type is FieldsType<FieldSpec> {\n return (type as { fields?: unknown }).fields !== undefined;\n}\n\n/** Fresh columns of at least `n` slots, keeping what `old` held. */\nexport function growColumns(spec: FieldSpec, n: number, old?: Record<string, ArrayLike<number>>): Record<string, ArrayLike<number>> {\n const out: Record<string, ArrayLike<number>> = {};\n for (const [name, kind] of Object.entries(spec)) {\n const col = new CTORS[kind](n);\n const prev = old?.[name];\n if (prev) col.set(prev);\n out[name] = col;\n }\n return out;\n}\n","import { SparseSet } from './SparseSet';\nimport { growColumns, isFields, type Columns, type FieldSpec, type FieldValues, type FieldsType } from './fields';\n\n/**\n * An entity–component–system store. Entities are numbers; components are data kept in one sparse set per component\n * type; systems are functions run in the order they were added, each in a phase:\n *\n * - `fixed` runs once per simulation step (`FixedLoop`), for movement and rules;\n * - `frame` runs once per rendered frame, for drawing and anything purely visual.\n *\n * Storage is a sparse set per component (packed arrays, O(1) lookups), the layout fast ECS libraries use. For hot\n * loops prefer `each` (a callback, no allocation per entity) over `query` (an iterator yielding a fresh row).\n *\n * Entity ids are recycled: an id carries its slot index and a generation, so an id kept after its entity was\n * destroyed never matches the entity that later reuses the slot.\n *\n * Changing structure while walking: adding components is always safe (new entries are not visited this walk).\n * Removing a component or destroying an entity while a `query`, an `each` or a system run is in progress is deferred\n * until it ends, so nothing is skipped or visited twice.\n */\n\nexport type Entity = number;\n\n/** A component type: a typed key. Make one per kind of data with `defineComponent`. */\nexport interface ComponentType<T> {\n readonly id: number;\n readonly name: string;\n /** Phantom field carrying `T`; never set. */\n readonly __type?: T;\n}\n\nlet nextComponentId = 0;\n\nexport function defineComponent<T>(name: string): ComponentType<T> {\n return { id: nextComponentId++, name };\n}\n\n/** A component of numeric fields kept in typed-array columns (`fields.ts`): the fast form for data every body has. */\nexport function defineFields<const S extends FieldSpec>(name: string, fields: S): FieldsType<S> {\n return { id: nextComponentId++, name, fields };\n}\n\nexport type SystemPhase = 'fixed' | 'frame';\n\nexport interface SystemContext {\n world: World;\n /** Seconds this run covers: one step in `fixed`, the frame's length in `frame`. */\n dt: number;\n /** `performance.now()` of the frame. */\n now: number;\n /** In `frame`: the share of a step since the last fixed step (0–1), for interpolation. 0 in `fixed`. */\n alpha: number;\n}\n\nexport interface System {\n readonly name: string;\n readonly phase: SystemPhase;\n run(ctx: SystemContext): void;\n /** Called when the system is taken out of its world (or the world is cleared). */\n dispose?(): void;\n}\n\n/** A system from a function. */\nexport function system(name: string, phase: SystemPhase, run: (ctx: SystemContext) => void): System {\n return { name, phase, run };\n}\n\nexport type ComponentValues<T extends readonly ComponentType<unknown>[]> = { [K in keyof T]: T[K] extends ComponentType<infer V> ? V : never };\n\n/** Slot index in the low 22 bits (4 million live entities), generation above. */\nconst INDEX_BITS = 22;\nconst INDEX_MASK = (1 << INDEX_BITS) - 1;\nconst MAX_GENERATION = 2 ** 31;\n\n/** The slot an entity id sits in. */\nexport const entityIndex = (e: Entity): number => e & INDEX_MASK;\n\ntype Pending = { kind: 'destroy'; e: Entity } | { kind: 'remove'; e: Entity; type: ComponentType<unknown> };\n\nexport class World {\n /** Current generation per slot; an id is alive when its generation matches and the slot is in use. */\n private generations: number[] = [];\n private readonly inUse: boolean[] = [];\n private readonly free: number[] = [];\n private live = 0;\n private readonly stores: (SparseSet<unknown> | undefined)[] = [];\n /** Typed-array columns of the field components, by component id. */\n private readonly cols: (Record<string, ArrayLike<number>> | undefined)[] = [];\n private readonly systems: System[] = [];\n private readonly pending: Pending[] = [];\n /** `slots` results by the component ids asked for, rebuilt only when one of those sets changed membership. */\n private readonly slotCache = new Map<string, { versions: number[]; slots: Int32Array; view: Int32Array }>();\n /** Walks (`query`, `each`, system runs) in progress: structure changes wait until it is 0. */\n private walking = 0;\n\n /** A new entity with no components. */\n create(): Entity {\n let index: number;\n if (this.free.length) {\n index = this.free.pop()!;\n } else {\n index = this.generations.length;\n if (index > INDEX_MASK) throw new Error('World: too many live entities');\n this.generations.push(0);\n this.inUse.push(false);\n }\n this.inUse[index] = true;\n this.live++;\n return this.generations[index]! * (INDEX_MASK + 1) + index;\n }\n\n /** A new entity with these components. */\n spawn(...components: [ComponentType<unknown>, unknown][]): Entity {\n const e = this.create();\n for (const [type, value] of components) this.add(e, type, value);\n return e;\n }\n\n isAlive(e: Entity): boolean {\n const index = entityIndex(e);\n return this.inUse[index] === true && this.generations[index] === Math.floor(e / (INDEX_MASK + 1));\n }\n\n /** Live entities. */\n get size(): number {\n return this.live;\n }\n\n /** Removes an entity and every component it had (deferred while a walk is in progress). */\n destroy(e: Entity): void {\n if (!this.isAlive(e)) return;\n if (this.walking > 0) {\n this.pending.push({ kind: 'destroy', e });\n return;\n }\n const index = entityIndex(e);\n for (const store of this.stores) store?.delete(index, entityIndex);\n this.inUse[index] = false;\n this.generations[index] = (this.generations[index]! + 1) % MAX_GENERATION;\n this.free.push(index);\n this.live--;\n }\n\n /** Gives an entity a field component; fields left out start at 0. Returns the slot index into its columns. */\n add<S extends FieldSpec>(e: Entity, type: FieldsType<S>, values?: FieldValues<S>): number;\n add<T>(e: Entity, type: ComponentType<T>, value: T): T;\n add(e: Entity, type: ComponentType<unknown>, value?: unknown): unknown {\n if (!this.isAlive(e)) throw new Error(`World.add: entity ${e} is not alive`);\n const index = entityIndex(e);\n if (isFields(type)) {\n const cols = this.columnsOf(type, index + 1) as Record<string, { [i: number]: number }>;\n const values = (value ?? {}) as Record<string, number>;\n for (const name of Object.keys(type.fields)) cols[name]![index] = values[name] ?? 0;\n this.store(type).set(index, e, index);\n return index;\n }\n this.store(type).set(index, e, value);\n return value;\n }\n\n /**\n * The typed-array columns of a field component, indexed by slot. Fetch them per system run: adding entities may\n * grow them into new arrays.\n */\n columns<S extends FieldSpec>(type: FieldsType<S>): Columns<S> {\n return this.columnsOf(type, this.generations.length) as unknown as Columns<S>;\n }\n\n get<T>(e: Entity, type: ComponentType<T>): T | undefined {\n if (!this.isAlive(e)) return undefined;\n return this.stores[type.id]?.get(entityIndex(e)) as T | undefined;\n }\n\n /** The component, or an error naming what is missing: for code that knows the entity has it. */\n require<T>(e: Entity, type: ComponentType<T>): T {\n const store = this.stores[type.id];\n if (!this.isAlive(e) || !store?.has(entityIndex(e))) throw new Error(`World.require: entity ${e} has no ${type.name}`);\n return store.get(entityIndex(e)) as T;\n }\n\n has(e: Entity, type: ComponentType<unknown>): boolean {\n return this.isAlive(e) && (this.stores[type.id]?.has(entityIndex(e)) ?? false);\n }\n\n /** Takes one component off an entity (deferred while a walk is in progress). */\n remove(e: Entity, type: ComponentType<unknown>): void {\n if (!this.isAlive(e)) return;\n if (this.walking > 0) {\n this.pending.push({ kind: 'remove', e, type });\n return;\n }\n this.stores[type.id]?.delete(entityIndex(e), entityIndex);\n }\n\n /** How many entities hold `type`. */\n count(type: ComponentType<unknown>): number {\n return this.stores[type.id]?.size ?? 0;\n }\n\n /**\n * Calls `fn(entity, ...components)` for every live entity holding all of `types`. Allocates nothing per entity:\n * the form for systems that walk thousands of bodies every step.\n */\n each<const T extends readonly ComponentType<unknown>[]>(...args: [...types: T, fn: (e: Entity, ...values: ComponentValues<T>) => void]): void {\n const fn = args[args.length - 1] as (e: Entity, ...values: unknown[]) => void;\n const types = args.slice(0, -1) as unknown as T;\n const sets = this.setsFor(types);\n if (!sets) return;\n const lead = smallest(sets);\n const n = lead.entities.length;\n this.walking++;\n try {\n if (sets.length === 1) {\n for (let i = n - 1; i >= 0; i--) fn(lead.entities[i]!, lead.values[i]);\n } else if (sets.length === 2) {\n const [a, b] = sets as [SparseSet<unknown>, SparseSet<unknown>];\n for (let i = n - 1; i >= 0; i--) {\n const e = lead.entities[i]!;\n const index = entityIndex(e);\n if (!a.has(index) || !b.has(index)) continue;\n fn(e, a.get(index), b.get(index));\n }\n } else {\n const row: unknown[] = new Array(sets.length);\n for (let i = n - 1; i >= 0; i--) {\n const e = lead.entities[i]!;\n const index = entityIndex(e);\n let all = true;\n for (let s = 0; s < sets.length; s++) {\n const set = sets[s]!;\n if (!set.has(index)) {\n all = false;\n break;\n }\n row[s] = set.get(index);\n }\n if (all) fn(e, ...row);\n }\n }\n } finally {\n this.endWalk();\n }\n }\n\n /**\n * The slot index of every entity holding all of `types`, as a typed array: the fastest walk there is, made for\n * field components (`defineFields`), whose columns are indexed by slot.\n *\n * ```ts\n * const p = world.columns(Position), v = world.columns(Velocity);\n * const slots = world.slots(Position, Velocity);\n * for (let k = 0; k < slots.length; k++) { const i = slots[k]!; p.x[i]! += v.x[i]! * dt; }\n * ```\n *\n * The result is cached and rebuilt only when an entity joins or leaves one of those components, so asking every\n * step is cheap. It is a view the world owns: read it, don't keep it past the step, and fetch it again after\n * adding or removing components.\n */\n slots(...types: ComponentType<unknown>[]): Int32Array {\n const key = types.map((t) => t.id).join(',');\n const sets = this.setsFor(types);\n if (!sets) return EMPTY_SLOTS;\n let cached = this.slotCache.get(key);\n if (cached && cached.versions.every((v, k) => v === sets[k]!.version)) return cached.view;\n const lead = smallest(sets);\n const out = cached && cached.slots.length >= lead.size ? cached.slots : new Int32Array(Math.max(16, lead.size));\n let n = 0;\n for (let d = 0; d < lead.entities.length; d++) {\n const index = entityIndex(lead.entities[d]!);\n let all = true;\n for (const set of sets) {\n if (set !== lead && !set.has(index)) {\n all = false;\n break;\n }\n }\n if (all) out[n++] = index;\n }\n cached = { versions: sets.map((x) => x.version), slots: out, view: out.subarray(0, n) };\n this.slotCache.set(key, cached);\n return cached.view;\n }\n\n /**\n * Every live entity holding all of `types`, with those components in the same order. Yields a fresh row per\n * entity: convenient, but `each` is the form for hot loops.\n */\n *query<const T extends readonly ComponentType<unknown>[]>(...types: T): IterableIterator<[Entity, ...ComponentValues<T>]> {\n const sets = this.setsFor(types);\n if (!sets) return;\n const lead = smallest(sets);\n this.walking++;\n try {\n for (let i = lead.entities.length - 1; i >= 0; i--) {\n const e = lead.entities[i]!;\n const index = entityIndex(e);\n const row: unknown[] = [e];\n let all = true;\n for (const set of sets) {\n if (!set.has(index)) {\n all = false;\n break;\n }\n row.push(set.get(index));\n }\n if (all) yield row as [Entity, ...ComponentValues<T>];\n }\n } finally {\n this.endWalk();\n }\n }\n\n /** The first entity matching the query, or undefined: for singletons (the player, the camera target). */\n first<const T extends readonly ComponentType<unknown>[]>(...types: T): [Entity, ...ComponentValues<T>] | undefined {\n for (const row of this.query(...types)) return row;\n return undefined;\n }\n\n addSystem(s: System): this {\n if (this.systems.some((x) => x.name === s.name)) throw new Error(`World.addSystem: a system named \"${s.name}\" is already added`);\n this.systems.push(s);\n return this;\n }\n\n removeSystem(name: string): void {\n const i = this.systems.findIndex((s) => s.name === name);\n if (i < 0) return;\n const [s] = this.systems.splice(i, 1);\n s!.dispose?.();\n }\n\n /** Runs every system of `phase` in the order added. A system that throws is reported and the rest still run. */\n run(phase: SystemPhase, ctx: Omit<SystemContext, 'world'>, onError?: (system: System, err: unknown) => void): void {\n const full: SystemContext = { dt: ctx.dt, now: ctx.now, alpha: ctx.alpha, world: this };\n this.walking++;\n try {\n for (const s of this.systems) {\n if (s.phase !== phase) continue;\n try {\n s.run(full);\n } catch (err) {\n if (onError) onError(s, err);\n else throw err;\n }\n }\n } finally {\n this.endWalk();\n }\n }\n\n /** Every entity, component and system gone. */\n clear(): void {\n for (const s of this.systems.splice(0)) s.dispose?.();\n for (const store of this.stores) store?.clear();\n this.generations = this.generations.map((g) => (g + 1) % MAX_GENERATION);\n this.inUse.fill(false);\n this.free.length = 0;\n for (let i = this.generations.length - 1; i >= 0; i--) this.free.push(i);\n this.live = 0;\n this.pending.length = 0;\n this.slotCache.clear();\n }\n\n private columnsOf(type: FieldsType<FieldSpec>, slots: number): Record<string, ArrayLike<number>> {\n let cols = this.cols[type.id];\n const have = cols ? (Object.values(cols)[0]?.length ?? 0) : 0;\n if (!cols || have < slots) {\n let n = Math.max(64, have);\n while (n < slots) n *= 2;\n cols = growColumns(type.fields, n, cols);\n this.cols[type.id] = cols;\n }\n return cols;\n }\n\n private store<T>(type: ComponentType<T>): SparseSet<unknown> {\n let s = this.stores[type.id];\n if (!s) {\n s = new SparseSet<unknown>();\n this.stores[type.id] = s;\n }\n return s;\n }\n\n /** The stores for `types`, or null when one has never been used (so nothing can match). */\n private setsFor(types: readonly ComponentType<unknown>[]): SparseSet<unknown>[] | null {\n if (types.length === 0) return null;\n const sets: SparseSet<unknown>[] = [];\n for (const t of types) {\n const s = this.stores[t.id];\n if (!s || s.size === 0) return null;\n sets.push(s);\n }\n return sets;\n }\n\n private endWalk(): void {\n this.walking--;\n if (this.walking > 0 || this.pending.length === 0) return;\n const pending = this.pending.splice(0);\n for (const p of pending) {\n if (p.kind === 'destroy') this.destroy(p.e);\n else this.remove(p.e, p.type);\n }\n }\n}\n\nconst EMPTY_SLOTS = new Int32Array(0);\n\nfunction smallest(sets: SparseSet<unknown>[]): SparseSet<unknown> {\n let lead = sets[0]!;\n for (const s of sets) if (s.size < lead.size) lead = s;\n return lead;\n}\n","import { Container } from 'pixi.js';\nimport { World } from '../ecs/World';\nimport type { Engine } from './Engine';\n\n/**\n * One screen of the game: a title, a level, a pause menu. A scene owns a `World` of entities and systems and a\n * `root` container in the engine's world layer; both are cleared when it leaves, so nothing it made outlives it.\n *\n * Override the hooks you need. `fixedUpdate` runs once per simulation step, `update` once per rendered frame, both\n * after the world's own systems of that phase.\n */\nexport abstract class Scene {\n readonly world = new World();\n /** Everything the scene draws in the world goes under this (the camera moves it). */\n readonly root = new Container({ sortableChildren: true });\n /** Everything the scene draws on the screen (HUD) goes under this. */\n readonly hud = new Container();\n private bound: Engine | null = null;\n\n /** The engine running this scene; only valid between `enter` and `exit`. */\n get engine(): Engine {\n if (!this.bound) throw new Error(`${this.constructor.name}: not running in an engine`);\n return this.bound;\n }\n\n /** Called once when the scene becomes active. May be async: the scene starts updating when it resolves. */\n onEnter(): void | Promise<void> {}\n /** Called when the scene is removed. The world and containers are cleared after it returns. */\n onExit(): void {}\n /** Called when another scene is pushed over this one. */\n onPause(): void {}\n /** Called when the scene over this one is popped. */\n onResume(): void {}\n /** Once per simulation step, `dt` in seconds. */\n fixedUpdate(_dt: number): void {}\n /** Once per rendered frame, `dt` in seconds; `alpha` is the share of a step since the last one (0–1). */\n update(_dt: number, _alpha: number): void {}\n\n /** @internal Engine-side wiring; games call `engine.scenes`. */\n attach(engine: Engine): void {\n this.bound = engine;\n engine.stage.world.addChild(this.root);\n engine.stage.screen.addChild(this.hud);\n }\n\n /** @internal Clears what the scene made but keeps its containers, so the same scene may be entered again. */\n detach(): void {\n this.world.clear();\n for (const c of [this.root, this.hud]) {\n for (const child of c.removeChildren()) child.destroy({ children: true });\n c.removeFromParent();\n }\n this.bound = null;\n }\n}\n","/*\n * Where every image goes in the world atlas, kept pure (no canvas) so the packing decision is unit-tested. The\n * builder (`atlas.ts`) paints what this plans.\n */\n\nexport const ATLAS_PAD = 2;\nconst MIN_ATLAS_WIDTH = 1024;\n/** The page side every desktop GPU takes, and the one the atlas was built to before pages existed. */\nexport const ATLAS_PAGE_FULL = 8192;\n/** The page side on a GPU that reports less than `ATLAS_PAGE_FULL` (older iPhones and iPads: 4096). */\nconst ATLAS_PAGE_SMALL = 4096;\n\n/**\n * How big an atlas page may be on this device: 8192 wherever the GPU takes it (every desktop — unchanged), else\n * split at 4096, or at the largest power of two the GPU does take if that is smaller still. Unknown: 8192, as before.\n */\nexport function atlasPageLimit(maxTextureSize: number | null): number {\n if (maxTextureSize === null || maxTextureSize >= ATLAS_PAGE_FULL) return ATLAS_PAGE_FULL;\n return Math.min(ATLAS_PAGE_SMALL, 2 ** Math.floor(Math.log2(Math.max(1, maxTextureSize))));\n}\n\nexport interface AtlasSize {\n w: number;\n h: number;\n}\n\nexport interface AtlasPage {\n width: number;\n height: number;\n}\n\nexport interface AtlasPlan {\n pages: AtlasPage[];\n /** One per input, in input order: the page and the top-left corner. */\n places: { page: number; x: number; y: number }[];\n}\n\n/**\n * Shelf-packs the images, tallest first, into pages no larger than `limit` on either side. The page width is the\n * power of two that fits the widest image and the square root of the total area (at least 1024), capped at `limit`;\n * a shelf that would run past `limit` starts a new page. With everything fitting under `limit` this is exactly the\n * single page the atlas always was. An image larger than `limit` itself is given a page of its own (the GPU will\n * refuse it, but nothing else is lost with it).\n */\nexport function planAtlas(sizes: readonly AtlasSize[], limit: number): AtlasPlan {\n const order = sizes.map((_, i) => i).sort((a, b) => sizes[b]!.h - sizes[a]!.h);\n const area = sizes.reduce((sum, s) => sum + (s.w + ATLAS_PAD) * (s.h + ATLAS_PAD), 0);\n const widest = Math.max(1, ...sizes.map((s) => s.w + ATLAS_PAD));\n const width = Math.min(limit, Math.max(MIN_ATLAS_WIDTH, 2 ** Math.ceil(Math.log2(Math.max(widest, Math.sqrt(area))))));\n const places: AtlasPlan['places'] = new Array(sizes.length);\n const pages: AtlasPage[] = [];\n let page = 0;\n let x = 0;\n let y = 0;\n let shelf = 0;\n let pageWidth = width;\n const close = () => pages.push({ width: pageWidth, height: y + shelf });\n for (const i of order) {\n const w = sizes[i]!.w + ATLAS_PAD;\n const h = sizes[i]!.h + ATLAS_PAD;\n if (x > 0 && x + w > pageWidth) {\n x = 0;\n y += shelf;\n shelf = 0;\n }\n if (y > 0 && y + h > limit) {\n close();\n page++;\n x = 0;\n y = 0;\n shelf = 0;\n pageWidth = width;\n }\n // an image wider than the page (only past `limit`) widens its own page rather than overlapping the edge\n if (w > pageWidth) pageWidth = w;\n places[i] = { page, x, y };\n x += w;\n shelf = Math.max(shelf, h);\n }\n if (sizes.length > 0) close();\n return { pages, places };\n}\n","import type { TextureRegistry } from './TextureRegistry';\nimport { ATLAS_PAGE_FULL, planAtlas } from './atlasPlan';\n\ninterface AtlasItem {\n name: string;\n canvas: HTMLCanvasElement;\n frameWidth?: number;\n frameHeight?: number;\n}\n\n/**\n * Packs many small procedurally painted canvases into as few textures as the GPU allows, so Pixi can batch every\n * sprite of the world into very few draw calls. One page on every desktop (up to 8192 square); a device whose GPU\n * takes less gets pages of `limit` (`atlasPageLimit`, `planAtlas`). Every frame is registered under the one `key`\n * whichever page holds it — the pages after the first are textures of their own (`key~1`, `key~2`…) whose frames\n * the first page's texture adopts — so the world keeps asking for `atlas` and a frame name, and never knows.\n * Frame names: `name` for single images, `name#i` for sheet frames.\n */\nexport class AtlasBuilder {\n private items: AtlasItem[] = [];\n\n add(name: string, canvas: HTMLCanvasElement): void {\n this.items.push({ name, canvas });\n }\n\n addSheet(name: string, canvas: HTMLCanvasElement, frameWidth: number, frameHeight: number): void {\n this.items.push({ name, canvas, frameWidth, frameHeight });\n }\n\n build(textures: TextureRegistry, key: string, limit = ATLAS_PAGE_FULL): void {\n const items = this.items;\n const plan = planAtlas(items.map((it) => ({ w: it.canvas.width, h: it.canvas.height })), limit);\n const pages = plan.pages.map((p, i) => {\n const canvas = document.createElement('canvas');\n canvas.width = p.width;\n canvas.height = p.height;\n // kept on the CPU (`willReadFrequently`): the atlas is drawn once, then read many times — the sway rigs' trunks,\n // a death's evaporating pixels, a hit's white silhouette — and on a GPU canvas the first read pulled the whole\n // page back, 300 ms on entering a new map (profiled)\n return { canvas, ctx: canvas.getContext('2d', { willReadFrequently: true })!, key: i === 0 ? key : `${key}~${i}` };\n });\n items.forEach((it, i) => {\n const at = plan.places[i]!;\n pages[at.page]!.ctx.drawImage(it.canvas, at.x, at.y);\n });\n const first = textures.addCanvas(key, pages[0]!.canvas);\n const texOf = pages.map((p, i) => (i === 0 ? first : textures.addCanvas(p.key, p.canvas)));\n items.forEach((it, i) => {\n const at = plan.places[i]!;\n const page = texOf[at.page]!;\n // a frame on a later page is also registered on the first, so `atlas` + its name finds it\n const add = (name: string, x: number, y: number, w: number, h: number) => {\n page.add(name, 0, x, y, w, h);\n if (at.page > 0) first.adopt(name, page);\n };\n if (it.frameWidth && it.frameHeight) {\n // a sheet may wrap into rows (`makeSheet`'s `maxWidth`, a very large creature's); frames are read row by row\n const cols = Math.floor(it.canvas.width / it.frameWidth);\n const rows = Math.max(1, Math.floor(it.canvas.height / it.frameHeight));\n for (let f = 0; f < cols * rows; f++)\n add(`${it.name}#${f}`, at.x + (f % cols) * it.frameWidth, at.y + Math.floor(f / cols) * it.frameHeight, it.frameWidth, it.frameHeight);\n } else {\n add(it.name, at.x, at.y, it.canvas.width, it.canvas.height);\n }\n });\n const sizes = plan.pages.map((p) => `${p.width}x${p.height}`).join(' + ');\n console.info(`[atlas] ${key}: ${items.length} images packed into ${sizes}${plan.pages.length > 1 ? ` (pages of ${limit})` : ''}`);\n }\n}\n","/**\n * Maps made in Tiled (https://www.mapeditor.org), read from its JSON format (`.tmj`, or `.json`). Supported:\n * orthogonal, finite maps; tile layers as CSV arrays or uncompressed base64; object layers; group layers (flattened);\n * custom properties; flipped tiles. Not supported (refused with a message saying so): infinite maps, compressed layer\n * data, isometric and hexagonal maps, external `.tsj` tilesets (embed them: Map → Embed Tilesets).\n *\n * Pure: no Pixi, no DOM, so a server can read the same map for collision.\n */\n\n/** The three flags Tiled keeps in a gid's high bits; the rest is the tile id. */\nexport const FLIP_H = 0x80000000;\nexport const FLIP_V = 0x40000000;\nexport const FLIP_D = 0x20000000;\nconst GID_MASK = 0x1fffffff;\n\nexport type TiledPropertyValue = string | number | boolean;\nexport type Properties = Record<string, TiledPropertyValue>;\n\nexport interface TileLayer {\n kind: 'tiles';\n name: string;\n /** Row-major gids (0 = empty), flip flags kept. Read the tile id with `gidOf`. */\n data: Uint32Array;\n visible: boolean;\n opacity: number;\n offsetX: number;\n offsetY: number;\n properties: Properties;\n}\n\nexport interface MapObject {\n id: number;\n name: string;\n type: string;\n x: number;\n y: number;\n width: number;\n height: number;\n rotation: number;\n /** A tile object's gid, if it is one. */\n gid?: number;\n point: boolean;\n ellipse: boolean;\n polygon?: { x: number; y: number }[];\n properties: Properties;\n}\n\nexport interface ObjectLayer {\n kind: 'objects';\n name: string;\n objects: MapObject[];\n visible: boolean;\n properties: Properties;\n}\n\nexport type MapLayer = TileLayer | ObjectLayer;\n\nexport interface Tileset {\n name: string;\n firstGid: number;\n /** The image's path as written in the map, relative to the map file. */\n image: string;\n imageWidth: number;\n imageHeight: number;\n tileWidth: number;\n tileHeight: number;\n columns: number;\n tileCount: number;\n margin: number;\n spacing: number;\n /** Per local tile id: its custom properties. */\n tileProperties: Map<number, Properties>;\n /** Per local tile id: an animation (local tile ids and how long each shows, ms). */\n animations: Map<number, { tileId: number; duration: number }[]>;\n properties: Properties;\n}\n\nexport interface TileMap {\n width: number;\n height: number;\n tileWidth: number;\n tileHeight: number;\n layers: MapLayer[];\n tilesets: Tileset[];\n properties: Properties;\n backgroundColor?: string;\n}\n\n/** The tile id of a gid, without its flip flags. */\nexport const gidOf = (raw: number): number => raw & GID_MASK;\n\n/** Which tileset a gid belongs to, and the tile's id inside it; null for an empty cell or an unknown gid. */\nexport function tileAt(map: TileMap, raw: number): { tileset: Tileset; local: number } | null {\n const gid = gidOf(raw);\n if (gid === 0) return null;\n let found: Tileset | null = null;\n for (const ts of map.tilesets) if (ts.firstGid <= gid && (!found || ts.firstGid > found.firstGid)) found = ts;\n if (!found || gid - found.firstGid >= found.tileCount) return null;\n return { tileset: found, local: gid - found.firstGid };\n}\n\n/** Where tile `local` sits in its tileset image. */\nexport function tileRect(ts: Tileset, local: number): { x: number; y: number; w: number; h: number } {\n const col = local % ts.columns;\n const row = Math.floor(local / ts.columns);\n return { x: ts.margin + col * (ts.tileWidth + ts.spacing), y: ts.margin + row * (ts.tileHeight + ts.spacing), w: ts.tileWidth, h: ts.tileHeight };\n}\n\nexport function layerByName(map: TileMap, name: string): MapLayer | undefined {\n return map.layers.find((l) => l.name === name);\n}\n\n/** Every object of every object layer (optionally only those of one `type`/class). */\nexport function objectsOf(map: TileMap, type?: string): MapObject[] {\n const out: MapObject[] = [];\n for (const l of map.layers) if (l.kind === 'objects') for (const o of l.objects) if (type === undefined || o.type === type) out.push(o);\n return out;\n}\n\n// ── Parsing ─────────────────────────────────────────────────────────────────────────────────────────────────────────\n\n/* eslint-disable @typescript-eslint/no-explicit-any -- the input is untrusted JSON, checked field by field below */\ntype Json = any;\n\nclass TiledError extends Error {\n constructor(message: string) {\n super(`Tiled map: ${message}`);\n }\n}\n\nfunction props(list: Json): Properties {\n const out: Properties = {};\n if (!Array.isArray(list)) return out;\n for (const p of list) if (p && typeof p.name === 'string' && ['string', 'number', 'boolean'].includes(typeof p.value)) out[p.name] = p.value;\n return out;\n}\n\nfunction num(v: Json, what: string): number {\n if (typeof v !== 'number' || !Number.isFinite(v)) throw new TiledError(`${what} must be a number`);\n return v;\n}\n\nfunction decodeBase64(text: string): Uint8Array {\n if (typeof atob === 'function') {\n const bin = atob(text.trim());\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n }\n return new Uint8Array((globalThis as Json).Buffer.from(text, 'base64'));\n}\n\nfunction layerData(l: Json, cells: number): Uint32Array {\n if (l.compression) throw new TiledError(`layer \"${l.name}\" is ${l.compression}-compressed; save it as CSV or uncompressed base64`);\n let data: Uint32Array;\n if (l.encoding === 'base64') {\n const bytes = decodeBase64(String(l.data));\n if (bytes.length !== cells * 4) throw new TiledError(`layer \"${l.name}\" holds ${bytes.length / 4} cells, not ${cells}`);\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n data = new Uint32Array(cells);\n for (let i = 0; i < cells; i++) data[i] = view.getUint32(i * 4, true);\n } else {\n if (!Array.isArray(l.data) || l.data.length !== cells) throw new TiledError(`layer \"${l.name}\" must hold ${cells} cells`);\n data = Uint32Array.from(l.data as number[]);\n }\n return data;\n}\n\nfunction parseObject(o: Json): MapObject {\n const obj: MapObject = {\n id: num(o.id, 'object id'),\n name: String(o.name ?? ''),\n type: String(o.type ?? o.class ?? ''),\n x: num(o.x, 'object x'),\n y: num(o.y, 'object y'),\n width: Number(o.width ?? 0),\n height: Number(o.height ?? 0),\n rotation: Number(o.rotation ?? 0),\n point: o.point === true,\n ellipse: o.ellipse === true,\n properties: props(o.properties),\n };\n if (typeof o.gid === 'number') obj.gid = o.gid;\n if (Array.isArray(o.polygon)) obj.polygon = o.polygon.map((p: Json) => ({ x: num(p.x, 'polygon x'), y: num(p.y, 'polygon y') }));\n return obj;\n}\n\nfunction parseLayers(list: Json, map: { width: number; height: number }, out: MapLayer[], parent = { visible: true, opacity: 1, x: 0, y: 0 }): void {\n if (!Array.isArray(list)) return;\n for (const l of list) {\n const visible = parent.visible && l.visible !== false;\n const opacity = parent.opacity * (typeof l.opacity === 'number' ? l.opacity : 1);\n const offsetX = parent.x + Number(l.offsetx ?? 0);\n const offsetY = parent.y + Number(l.offsety ?? 0);\n if (l.type === 'tilelayer') {\n out.push({ kind: 'tiles', name: String(l.name ?? ''), data: layerData(l, map.width * map.height), visible, opacity, offsetX, offsetY, properties: props(l.properties) });\n } else if (l.type === 'objectgroup') {\n out.push({ kind: 'objects', name: String(l.name ?? ''), objects: (l.objects ?? []).map(parseObject), visible, properties: props(l.properties) });\n } else if (l.type === 'group') {\n parseLayers(l.layers, map, out, { visible, opacity, x: offsetX, y: offsetY });\n }\n // image layers are ignored: draw backgrounds yourself\n }\n}\n\nfunction parseTileset(t: Json): Tileset {\n if (typeof t.source === 'string') throw new TiledError(`tileset \"${t.source}\" is external; embed it in the map (Map → Embed Tilesets)`);\n if (typeof t.image !== 'string') throw new TiledError(`tileset \"${t.name}\" is a collection of images; use a single-image tileset`);\n const tileProperties = new Map<number, Properties>();\n const animations = new Map<number, { tileId: number; duration: number }[]>();\n for (const tile of t.tiles ?? []) {\n const id = num(tile.id, 'tile id');\n if (tile.properties) tileProperties.set(id, props(tile.properties));\n if (Array.isArray(tile.animation)) animations.set(id, tile.animation.map((f: Json) => ({ tileId: num(f.tileid, 'animation tileid'), duration: num(f.duration, 'animation duration') })));\n }\n return {\n name: String(t.name ?? ''),\n firstGid: num(t.firstgid, 'tileset firstgid'),\n image: t.image,\n imageWidth: num(t.imagewidth, 'tileset imagewidth'),\n imageHeight: num(t.imageheight, 'tileset imageheight'),\n tileWidth: num(t.tilewidth, 'tileset tilewidth'),\n tileHeight: num(t.tileheight, 'tileset tileheight'),\n columns: num(t.columns, 'tileset columns'),\n tileCount: num(t.tilecount, 'tileset tilecount'),\n margin: Number(t.margin ?? 0),\n spacing: Number(t.spacing ?? 0),\n tileProperties,\n animations,\n properties: props(t.properties),\n };\n}\n\n/** Reads a Tiled JSON map (already parsed with `JSON.parse`). Throws a `Tiled map: …` error saying what is wrong. */\nexport function parseTiled(json: unknown): TileMap {\n const m = json as Json;\n if (!m || typeof m !== 'object') throw new TiledError('not a JSON object');\n if (m.infinite) throw new TiledError('infinite maps are not supported; uncheck Map → Map Properties → Infinite');\n if (m.orientation && m.orientation !== 'orthogonal') throw new TiledError(`${m.orientation} maps are not supported, only orthogonal`);\n const width = num(m.width, 'width');\n const height = num(m.height, 'height');\n const layers: MapLayer[] = [];\n parseLayers(m.layers, { width, height }, layers);\n const map: TileMap = {\n width,\n height,\n tileWidth: num(m.tilewidth, 'tilewidth'),\n tileHeight: num(m.tileheight, 'tileheight'),\n layers,\n tilesets: (m.tilesets ?? []).map(parseTileset),\n properties: props(m.properties),\n };\n if (typeof m.backgroundcolor === 'string') map.backgroundColor = m.backgroundcolor;\n return map;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n","import { parseTiled, type TileMap, type Tileset } from '../tilemap/tiled';\n\n/** Where loaded images go: the stage's `TextureRegistry` satisfies it. */\nexport interface TextureSink {\n addCanvas(key: string, canvas: HTMLCanvasElement): unknown;\n addSpriteSheet(key: string, canvas: HTMLCanvasElement, size: { frameWidth: number; frameHeight: number }): unknown;\n}\n\nexport interface AssetLoaderOptions {\n /** Prefix for relative URLs (default: none, so relative to the page). */\n baseUrl?: string;\n /** Requests running at once (default 6). */\n concurrency?: number;\n /** For tests and custom transports: defaults to the global `fetch`. */\n fetch?: (url: string) => Promise<{ ok: boolean; status: number; blob(): Promise<Blob>; json(): Promise<unknown>; text(): Promise<string> }>;\n /** Turns image bytes into a canvas; defaults to `createImageBitmap` drawn onto a new canvas. */\n toCanvas?: (blob: Blob) => Promise<HTMLCanvasElement>;\n}\n\nexport interface TilemapAssetOptions {\n /** The texture key a tileset's image is loaded under (default: the tileset's name). */\n textureKey?: (tileset: Tileset) => string;\n}\n\nexport interface LoadProgress {\n done: number;\n total: number;\n /** The asset that just finished. */\n key: string;\n}\n\ntype Job = { key: string; run: () => Promise<void> };\n\n/** `url` resolved against `base` the way a browser would (a bare file name sits beside its map). */\nexport function resolveUrl(url: string, base: string): string {\n if (/^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith('/')) return url;\n const dir = base.slice(0, base.lastIndexOf('/') + 1);\n const parts = (dir + url).split('/');\n const out: string[] = [];\n for (const p of parts) {\n if (p === '..' && out.length && out[out.length - 1] !== '..' && out[out.length - 1] !== '') out.pop();\n else if (p !== '.') out.push(p);\n }\n return out.join('/');\n}\n\nasync function defaultToCanvas(blob: Blob): Promise<HTMLCanvasElement> {\n const bitmap = await createImageBitmap(blob);\n const canvas = document.createElement('canvas');\n canvas.width = bitmap.width;\n canvas.height = bitmap.height;\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('AssetLoader: no 2D context (out of canvas memory?)');\n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n return canvas;\n}\n\n/**\n * Loads a scene's assets before it starts: queue them, then `await load()`. Images become textures in the stage's\n * registry (frames of a sprite sheet named 0, 1, 2…); JSON, text and Tiled maps are kept here by key. A failed asset\n * fails the whole load with its URL in the message.\n *\n * ```ts\n * override async onEnter() {\n * const assets = new AssetLoader(this.engine.stage.textures);\n * assets.spritesheet('hero', 'art/hero.png', { frameWidth: 20, frameHeight: 24 }).tilemap('level', 'maps/level.tmj');\n * await assets.load(({ done, total }) => bar.set(done / total));\n * const map = assets.map('level');\n * }\n * ```\n */\nexport class AssetLoader {\n private readonly queue: Job[] = [];\n private readonly data = new Map<string, unknown>();\n private readonly maps = new Map<string, TileMap>();\n private readonly fetcher: NonNullable<AssetLoaderOptions['fetch']>;\n private readonly toCanvas: (blob: Blob) => Promise<HTMLCanvasElement>;\n private total = 0;\n private done = 0;\n\n constructor(\n private readonly textures: TextureSink,\n private readonly options: AssetLoaderOptions = {},\n ) {\n this.fetcher = options.fetch ?? ((url) => fetch(url));\n this.toCanvas = options.toCanvas ?? defaultToCanvas;\n }\n\n image(key: string, url: string): this {\n return this.add(key, async () => {\n this.textures.addCanvas(key, await this.toCanvas(await this.blob(url)));\n });\n }\n\n /** An image cut into equal frames named 0, 1, 2…, left to right, then row by row. */\n spritesheet(key: string, url: string, size: { frameWidth: number; frameHeight: number }): this {\n return this.add(key, async () => {\n this.textures.addSpriteSheet(key, await this.toCanvas(await this.blob(url)), size);\n });\n }\n\n json(key: string, url: string): this {\n return this.add(key, async () => {\n this.data.set(key, await (await this.request(url)).json());\n });\n }\n\n text(key: string, url: string): this {\n return this.add(key, async () => {\n this.data.set(key, await (await this.request(url)).text());\n });\n }\n\n /** A Tiled JSON map, then every tileset image it names (resolved beside the map file). */\n tilemap(key: string, url: string, options: TilemapAssetOptions = {}): this {\n return this.add(key, async () => {\n const map = parseTiled(await (await this.request(url)).json());\n this.maps.set(key, map);\n const textureKey = options.textureKey ?? ((ts: Tileset) => ts.name);\n for (const ts of map.tilesets) this.image(textureKey(ts), resolveUrl(ts.image, url));\n });\n }\n\n /** Runs everything queued; `onProgress` after each asset. Safe to call again after queueing more. */\n async load(onProgress?: (p: LoadProgress) => void): Promise<void> {\n const limit = Math.max(1, this.options.concurrency ?? 6);\n const worker = async (): Promise<void> => {\n for (let job = this.queue.shift(); job; job = this.queue.shift()) {\n await job.run();\n this.done++;\n onProgress?.({ done: this.done, total: this.total, key: job.key });\n }\n };\n // a finished tilemap queues its tilesets: keep draining until nothing is left\n while (this.queue.length) await Promise.all(Array.from({ length: limit }, worker));\n }\n\n /** A loaded JSON value. */\n getJson<T = unknown>(key: string): T {\n if (!this.data.has(key)) throw new Error(`AssetLoader: no JSON or text loaded as \"${key}\"`);\n return this.data.get(key) as T;\n }\n\n /** A loaded text file. */\n getText(key: string): string {\n return this.getJson<string>(key);\n }\n\n /** A loaded Tiled map. */\n map(key: string): TileMap {\n const m = this.maps.get(key);\n if (!m) throw new Error(`AssetLoader: no tilemap loaded as \"${key}\"`);\n return m;\n }\n\n private add(key: string, run: () => Promise<void>): this {\n this.queue.push({ key, run });\n this.total++;\n return this;\n }\n\n private async request(url: string) {\n const full = resolveUrl(url, this.options.baseUrl ?? '');\n let res;\n try {\n res = await this.fetcher(full);\n } catch (err) {\n throw new Error(`AssetLoader: could not fetch ${full}: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!res.ok) throw new Error(`AssetLoader: ${full} answered ${res.status}`);\n return res;\n }\n\n private async blob(url: string): Promise<Blob> {\n return (await this.request(url)).blob();\n }\n}\n","/**\n * Frame animation of one sprite: which clip plays, which frame it is on. Pure state, advanced by time; a system copies\n * `frame` onto the sprite (`animationSystem`).\n *\n * ```ts\n * const clips = { idle: { frames: [0, 1], fps: 2 }, walk: { frames: [2, 3, 4, 5], fps: 10 }, die: { frames: [6, 7, 8], fps: 8, loop: false } };\n * const a = new Animator(clips, 'idle');\n * a.play('walk'); // switching to the clip already playing keeps its place\n * a.update(dt); // seconds\n * sprite.setFrame(a.frame);\n * ```\n */\nexport interface AnimationClip {\n /** Frame names or indices of the sprite sheet, in order. */\n frames: readonly (string | number)[];\n /** Frames per second (default 10). Pixel art usually wants 8–12. */\n fps?: number;\n /** Start over at the end (default true); otherwise hold the last frame and report it finished. */\n loop?: boolean;\n /** Per-frame lengths in ms, overriding `fps` (a held key pose, a quick smear). */\n durations?: readonly number[];\n}\n\nexport type AnimationClips = Record<string, AnimationClip>;\n\nexport class Animator<Name extends string = string> {\n private clip: AnimationClip;\n private index = 0;\n private elapsed = 0;\n private ended = false;\n private name: Name;\n /** Called when a clip that does not loop reaches its last frame. */\n onComplete: ((clip: Name) => void) | null = null;\n /** Playback speed multiplier (1 normal, 0 paused). */\n speed = 1;\n\n constructor(\n private readonly clips: Record<Name, AnimationClip>,\n initial: NoInfer<Name>,\n ) {\n const clip = clips[initial];\n if (!clip) throw new Error(`Animator: no clip \"${initial}\"`);\n if (clip.frames.length === 0) throw new Error(`Animator: clip \"${initial}\" has no frames`);\n this.clip = clip;\n this.name = initial;\n }\n\n /** The clip playing. */\n get current(): Name {\n return this.name;\n }\n\n /** The frame to show now. */\n get frame(): string | number {\n return this.clip.frames[this.index]!;\n }\n\n /** Which frame of the clip (0-based). */\n get frameIndex(): number {\n return this.index;\n }\n\n /** A non-looping clip has reached its last frame. */\n get finished(): boolean {\n return this.ended;\n }\n\n /** Plays `name`. The clip already playing keeps its place unless `restart`. */\n play(name: Name, restart = false): this {\n if (name === this.name && !restart) return this;\n const clip = this.clips[name];\n if (!clip) throw new Error(`Animator: no clip \"${name}\"`);\n if (clip.frames.length === 0) throw new Error(`Animator: clip \"${name}\" has no frames`);\n this.clip = clip;\n this.name = name;\n this.index = 0;\n this.elapsed = 0;\n this.ended = false;\n return this;\n }\n\n /** Advances by `dt` seconds; returns true when the frame changed. */\n update(dt: number): boolean {\n if (this.ended || !(dt > 0) || this.speed <= 0) return false;\n this.elapsed += dt * 1000 * this.speed;\n const before = this.index;\n const n = this.clip.frames.length;\n for (let len = this.lengthOf(this.index); this.elapsed >= len; len = this.lengthOf(this.index)) {\n this.elapsed -= len;\n if (this.index < n - 1) {\n this.index++;\n } else if (this.clip.loop !== false) {\n this.index = 0;\n } else {\n this.ended = true;\n this.elapsed = 0;\n this.onComplete?.(this.name);\n break;\n }\n }\n return this.index !== before;\n }\n\n private lengthOf(i: number): number {\n const ms = this.clip.durations?.[i] ?? 1000 / (this.clip.fps ?? 10);\n return Math.max(1, ms);\n }\n}\n","import type { Image } from '../core/Image';\nimport { defineComponent, system, type ComponentType, type System } from '../ecs/World';\nimport type { Animator } from './Animator';\n\n/** The engine's sprite component: the `Image` an entity is drawn as. */\nexport const SpriteComponent: ComponentType<Image> = defineComponent<Image>('Sprite');\n\n/** The engine's animation component: the `Animator` choosing the sprite's frame. */\nexport const AnimationComponent: ComponentType<Animator> = defineComponent<Animator>('Animation');\n\n/**\n * Advances every `Animator` each frame and shows its frame on the entity's sprite (only when it changed, so an idle\n * crowd costs no texture swaps).\n */\nexport function animationSystem(name = 'animation'): System {\n return system(name, 'frame', ({ world, dt }) => {\n world.each(SpriteComponent, AnimationComponent, (_e, sprite, anim) => {\n const changed = anim.update(dt);\n if (changed || sprite.frameName !== String(anim.frame)) sprite.setFrame(anim.frame);\n });\n });\n}\n","import {\n BODY_HALF_HEIGHT,\n BODY_HALF_WIDTH,\n COLLISION_EPSILON,\n INPUT_FLAG_DASH,\n INPUT_STEP_DT,\n type InputStep,\n type MovementParams,\n} from './constants';\n\n/*\n * Deterministic player movement simulation.\n *\n * The server runs this exact algorithm (or a port of it) as the authority;\n * the client runs it for prediction and replays unacknowledged steps after every snapshot.\n * Keep the operation order identical on both sides so floating point results match bit for bit.\n */\n\n/** 1/sqrt(2), written as a literal so every port uses the exact same double. */\nexport const DIAGONAL = 0.7071067811865476;\n\nexport interface CollisionGrid {\n readonly width: number;\n readonly height: number;\n readonly tileSize: number;\n /** 1 = solid, row-major. */\n readonly solid: Uint8Array;\n /** 1 = a solid tile a shot flies over (`shotOverTiles`), row-major; absent when the ground was not given. */\n readonly shotOver?: Uint8Array;\n /** Half the moving body's collision box, px. */\n readonly bodyHalfWidth: number;\n readonly bodyHalfHeight: number;\n}\n\nexport interface CollisionGridOptions {\n /** The tile id of every cell, row-major; needed only for `shotOverTiles`. */\n ground?: readonly number[];\n /** Tile ids nothing walks but a shot flies over (water, lava…): solid for bodies, open for shots. */\n shotOverTiles?: Iterable<number>;\n /** Half the moving body's collision box, px (default `BODY_HALF_WIDTH` × `BODY_HALF_HEIGHT`, a 10×6 foot box). */\n bodyHalfWidth?: number;\n bodyHalfHeight?: number;\n}\n\nexport interface MoverState {\n x: number;\n y: number;\n /** Last non-zero movement direction (normalized), used for dashing while idle. */\n lastDx: number;\n lastDy: number;\n dashLeft: number;\n dashCd: number;\n dashDx: number;\n dashDy: number;\n}\n\n/** A grid from a string of '0'/'1' per cell (row-major, '1' solid). */\nexport function createCollisionGrid(width: number, height: number, tileSize: number, solid: string, options: CollisionGridOptions = {}): CollisionGrid {\n if (solid.length !== width * height) {\n throw new Error(`collision string length ${solid.length} != ${width}x${height}`);\n }\n const bytes = new Uint8Array(width * height);\n for (let i = 0; i < bytes.length; i++) bytes[i] = solid.charCodeAt(i) === 49 ? 1 : 0;\n const { ground } = options;\n const over = new Set(options.shotOverTiles ?? []);\n let shotOver: Uint8Array | undefined;\n if (ground && ground.length === bytes.length && over.size) {\n shotOver = new Uint8Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) shotOver[i] = bytes[i] && over.has(ground[i]!) ? 1 : 0;\n }\n const bodyHalfWidth = options.bodyHalfWidth ?? BODY_HALF_WIDTH;\n const bodyHalfHeight = options.bodyHalfHeight ?? BODY_HALF_HEIGHT;\n return shotOver ? { width, height, tileSize, solid: bytes, shotOver, bodyHalfWidth, bodyHalfHeight } : { width, height, tileSize, solid: bytes, bodyHalfWidth, bodyHalfHeight };\n}\n\n/** Whether a shot in flight stops on this tile: solid, and not ground a shot flies over (`shotOverTiles`). */\nexport function blocksShot(grid: CollisionGrid, tx: number, ty: number): boolean {\n if (!isSolidTile(grid, tx, ty)) return false;\n return grid.shotOver?.[ty * grid.width + tx] !== 1;\n}\n\nexport function createMover(x: number, y: number): MoverState {\n return { x, y, lastDx: 1, lastDy: 0, dashLeft: 0, dashCd: 0, dashDx: 1, dashDy: 0 };\n}\n\nexport function isSolidTile(grid: CollisionGrid, tx: number, ty: number): boolean {\n if (tx < 0 || ty < 0 || tx >= grid.width || ty >= grid.height) return true;\n return grid.solid[ty * grid.width + tx] === 1;\n}\n\n/** True if the body box centered at (x, y) overlaps a solid tile. */\nexport function bodyCollides(grid: CollisionGrid, x: number, y: number): boolean {\n const ts = grid.tileSize;\n const x0 = Math.floor((x - grid.bodyHalfWidth) / ts);\n const x1 = Math.floor((x + grid.bodyHalfWidth) / ts);\n const y0 = Math.floor((y - grid.bodyHalfHeight) / ts);\n const y1 = Math.floor((y + grid.bodyHalfHeight) / ts);\n for (let ty = y0; ty <= y1; ty++) {\n for (let tx = x0; tx <= x1; tx++) {\n if (isSolidTile(grid, tx, ty)) return true;\n }\n }\n return false;\n}\n\n/** Moves along X by dx, stopping flush against the first solid tile column. */\nexport function moveX(grid: CollisionGrid, x: number, y: number, dx: number): number {\n if (dx === 0) return x;\n const ts = grid.tileSize;\n const nx = x + dx;\n const y0 = Math.floor((y - grid.bodyHalfHeight) / ts);\n const y1 = Math.floor((y + grid.bodyHalfHeight) / ts);\n if (dx > 0) {\n const tx = Math.floor((nx + grid.bodyHalfWidth) / ts);\n for (let ty = y0; ty <= y1; ty++) {\n if (isSolidTile(grid, tx, ty)) return tx * ts - grid.bodyHalfWidth - COLLISION_EPSILON;\n }\n } else {\n const tx = Math.floor((nx - grid.bodyHalfWidth) / ts);\n for (let ty = y0; ty <= y1; ty++) {\n if (isSolidTile(grid, tx, ty)) return (tx + 1) * ts + grid.bodyHalfWidth + COLLISION_EPSILON;\n }\n }\n return nx;\n}\n\n/** Moves along Y by dy, stopping flush against the first solid tile row. */\nexport function moveY(grid: CollisionGrid, x: number, y: number, dy: number): number {\n if (dy === 0) return y;\n const ts = grid.tileSize;\n const ny = y + dy;\n const x0 = Math.floor((x - grid.bodyHalfWidth) / ts);\n const x1 = Math.floor((x + grid.bodyHalfWidth) / ts);\n if (dy > 0) {\n const ty = Math.floor((ny + grid.bodyHalfHeight) / ts);\n for (let tx = x0; tx <= x1; tx++) {\n if (isSolidTile(grid, tx, ty)) return ty * ts - grid.bodyHalfHeight - COLLISION_EPSILON;\n }\n } else {\n const ty = Math.floor((ny - grid.bodyHalfHeight) / ts);\n for (let tx = x0; tx <= x1; tx++) {\n if (isSolidTile(grid, tx, ty)) return (ty + 1) * ts + grid.bodyHalfHeight + COLLISION_EPSILON;\n }\n }\n return ny;\n}\n\nfunction clampAxis(v: number): number {\n return v > 0 ? 1 : v < 0 ? -1 : 0;\n}\n\n/** Advances the mover by one fixed input step. Mutates `s`. */\nexport function stepMover(s: MoverState, step: InputStep, p: MovementParams, grid: CollisionGrid): void {\n if (s.dashCd > 0) s.dashCd--;\n\n // A dodge roll is committed: while it runs, input neither steers it nor aims the next one.\n const rolling = s.dashLeft > 0;\n let mx = p.canMove && !rolling ? clampAxis(step[0]) : 0;\n let my = p.canMove && !rolling ? clampAxis(step[1]) : 0;\n if (mx !== 0 && my !== 0) {\n mx = mx * DIAGONAL;\n my = my * DIAGONAL;\n }\n if (mx !== 0 || my !== 0) {\n s.lastDx = mx;\n s.lastDy = my;\n }\n\n if ((step[2] & INPUT_FLAG_DASH) !== 0 && p.canDash && p.canMove && s.dashLeft === 0 && s.dashCd === 0) {\n s.dashLeft = p.dashSteps;\n s.dashCd = p.dashCooldownSteps;\n s.dashDx = s.lastDx;\n s.dashDy = s.lastDy;\n }\n\n let vx: number;\n let vy: number;\n if (s.dashLeft > 0) {\n vx = s.dashDx * p.dashSpeed;\n vy = s.dashDy * p.dashSpeed;\n s.dashLeft--;\n } else {\n vx = mx * p.speed;\n vy = my * p.speed;\n }\n\n s.x = moveX(grid, s.x, s.y, vx * INPUT_STEP_DT);\n s.y = moveY(grid, s.x, s.y, vy * INPUT_STEP_DT);\n}\n","import { createCollisionGrid, type CollisionGrid, type CollisionGridOptions } from '../net/movement';\nimport { gidOf, tileAt, type TileMap } from './tiled';\n\nexport interface TiledCollisionOptions extends Omit<CollisionGridOptions, 'ground'> {\n /**\n * What makes a cell solid:\n * - a layer name: every non-empty cell of that tile layer is solid (a hidden \"collision\" layer is the usual way);\n * - `{ property }`: a cell is solid when its tile has that custom property set to true, on any tile layer.\n * Default: the layer named \"collision\" if there is one, else tiles with a `solid` property.\n */\n solid?: string | { property: string };\n}\n\n/** The `CollisionGrid` of a Tiled map, for `stepMover`; cells are the map's tiles. */\nexport function collisionFromTiled(map: TileMap, options: TiledCollisionOptions = {}): CollisionGrid {\n if (map.tileWidth !== map.tileHeight) throw new Error(`Tiled map: collision needs square tiles, not ${map.tileWidth}x${map.tileHeight}`);\n const rule = options.solid ?? (map.layers.some((l) => l.kind === 'tiles' && l.name === 'collision') ? 'collision' : { property: 'solid' });\n const cells = map.width * map.height;\n const solid = new Uint8Array(cells);\n if (typeof rule === 'string') {\n const layer = map.layers.find((l) => l.kind === 'tiles' && l.name === rule);\n if (!layer || layer.kind !== 'tiles') throw new Error(`Tiled map: no tile layer named \"${rule}\"`);\n for (let i = 0; i < cells; i++) if (gidOf(layer.data[i]!) !== 0) solid[i] = 1;\n } else {\n for (const layer of map.layers) {\n if (layer.kind !== 'tiles') continue;\n for (let i = 0; i < cells; i++) {\n const t = tileAt(map, layer.data[i]!);\n if (t && t.tileset.tileProperties.get(t.local)?.[rule.property] === true) solid[i] = 1;\n }\n }\n }\n let s = '';\n for (let i = 0; i < cells; i++) s += solid[i] ? '1' : '0';\n const { solid: _rule, ...gridOptions } = options;\n return createCollisionGrid(map.width, map.height, map.tileWidth, s, gridOptions);\n}\n","import { Container, Sprite } from 'pixi.js';\nimport type { Stage } from '../core/Stage';\nimport { FLIP_D, FLIP_H, FLIP_V, tileAt, tileRect, type TileLayer, type TileMap, type Tileset } from './tiled';\n\nexport interface TilemapViewOptions {\n /** The texture key holding a tileset's image (loaded with `AssetLoader.image`, or painted). Default: `tileset.name`. */\n textureFor?: (tileset: Tileset) => string;\n /** Tiles per chunk side (default 32): each chunk is painted once into a texture of its own. */\n chunkTiles?: number;\n /** Only these tile layers, by name; default every visible tile layer. */\n layers?: string[];\n /**\n * Depth of the first layer in the world layer; each layer after it one higher. Bodies are usually drawn at their y,\n * so the default keeps the map under every one of them. A layer with a numeric `depth` property is drawn there\n * instead (a roof layer over the bodies: `depth` = 1e6).\n */\n baseDepth?: number;\n /** Where the layers go (default the stage's world layer); a scene passes its `root` so they leave with it. */\n parent?: Container;\n}\n\nlet nextView = 0;\n\n/**\n * Draws a Tiled map's tile layers. Each layer is cut into chunks painted once into textures; a frame only toggles\n * which chunks are in view (`update`), so a map of any size costs a handful of sprites a frame.\n *\n * Animated tiles are drawn on their first frame.\n */\nexport class TilemapView {\n /** One container per drawn tile layer, by name, each at its own depth among the bodies. */\n readonly layers = new Map<string, Container>();\n private readonly chunks: { sprite: Sprite; x: number; y: number; w: number; h: number; key: string }[] = [];\n private readonly id = nextView++;\n\n constructor(\n private readonly stage: Stage,\n readonly map: TileMap,\n options: TilemapViewOptions = {},\n ) {\n const textureFor = options.textureFor ?? ((ts: Tileset) => ts.name);\n const chunk = Math.max(1, options.chunkTiles ?? 32);\n const base = options.baseDepth ?? -1_000_000;\n const wanted = options.layers ? new Set(options.layers) : null;\n const layers = map.layers.filter((l): l is TileLayer => l.kind === 'tiles' && (wanted ? wanted.has(l.name) : l.visible));\n const parent = options.parent ?? stage.world;\n layers.forEach((layer, n) => {\n const depth = typeof layer.properties.depth === 'number' ? layer.properties.depth : base + n;\n const holder = new Container();\n holder.zIndex = depth;\n holder.alpha = layer.opacity;\n holder.position.set(layer.offsetX, layer.offsetY);\n this.layers.set(layer.name, holder);\n parent.addChild(holder);\n for (let cy = 0; cy < map.height; cy += chunk) {\n for (let cx = 0; cx < map.width; cx += chunk) {\n const cw = Math.min(chunk, map.width - cx);\n const ch = Math.min(chunk, map.height - cy);\n this.paintChunk(layer, holder, cx, cy, cw, ch, textureFor);\n }\n }\n });\n }\n\n /** Shows only the chunks in the camera's view (plus a margin in world px). Call once a frame. */\n update(margin = 32): void {\n const v = this.stage.cameras.main.worldView;\n for (const c of this.chunks) {\n c.sprite.visible = c.x < v.right + margin && c.x + c.w > v.x - margin && c.y < v.bottom + margin && c.y + c.h > v.y - margin;\n }\n }\n\n /** World size of the map in px. */\n get widthPx(): number {\n return this.map.width * this.map.tileWidth;\n }\n\n get heightPx(): number {\n return this.map.height * this.map.tileHeight;\n }\n\n destroy(): void {\n for (const c of this.chunks) this.stage.textures.remove(c.key);\n this.chunks.length = 0;\n for (const c of this.layers.values()) c.destroy({ children: true });\n this.layers.clear();\n }\n\n private paintChunk(layer: TileLayer, holder: Container, cx: number, cy: number, cw: number, ch: number, textureFor: (ts: Tileset) => string): void {\n const { map } = this;\n const tw = map.tileWidth;\n const th = map.tileHeight;\n let any = false;\n const key = `tilemap:${this.id}:${layer.name}:${cx},${cy}`;\n // tiles taller than the grid (trees on a 16 px grid) overhang the cell above, so the chunk has room for them\n const tallest = Math.max(th, ...map.tilesets.map((t) => t.tileHeight));\n const pad = tallest - th;\n const tex = this.stage.textures.createCanvas(key, cw * tw, ch * th + pad);\n const ctx = tex.context;\n ctx.imageSmoothingEnabled = false;\n for (let y = 0; y < ch; y++) {\n for (let x = 0; x < cw; x++) {\n const raw = layer.data[(cy + y) * map.width + (cx + x)]!;\n const t = tileAt(map, raw);\n if (!t) continue;\n const src = this.stage.textures.exists(textureFor(t.tileset)) ? this.stage.textures.get(textureFor(t.tileset)).source.resource : null;\n if (!src) continue;\n const r = tileRect(t.tileset, t.local);\n // a tile is drawn on its cell's bottom-left corner, as Tiled does\n const dx = x * tw;\n const dy = pad + (y + 1) * th - r.h;\n ctx.save();\n ctx.translate(dx + r.w / 2, dy + r.h / 2);\n if (raw & FLIP_D) ctx.transform(0, 1, 1, 0, 0, 0);\n ctx.scale(raw & FLIP_H ? -1 : 1, raw & FLIP_V ? -1 : 1);\n ctx.drawImage(src as CanvasImageSource, r.x, r.y, r.w, r.h, -r.w / 2, -r.h / 2, r.w, r.h);\n ctx.restore();\n any = true;\n }\n }\n if (!any) {\n this.stage.textures.remove(key);\n return;\n }\n tex.refresh();\n const sprite = new Sprite(tex.whole);\n sprite.position.set(cx * tw, cy * th - pad);\n holder.addChild(sprite);\n this.chunks.push({ sprite, x: sprite.x + layer.offsetX, y: sprite.y + layer.offsetY, w: cw * tw, h: ch * th + pad, key });\n }\n}\n","import type { Joints, Limb, Point, RigDef, RigPose } from './rigTypes';\n\nconst RAD = Math.PI / 180;\nconst DOWN: Limb = [90, 2, 0, 2];\n\nfunction add(p: Point, dx: number, dy: number): Point {\n return { x: p.x + dx, y: p.y + dy };\n}\n\n/** Elbow and wrist (or knee and ankle) of a limb hung from `root`. */\nfunction chain(root: Point, limb: Limb): [Point, Point, number] {\n const [a1, l1, a2, l2] = limb;\n const upper = a1 * RAD;\n const lower = (a1 + a2) * RAD;\n const mid = add(root, Math.cos(upper) * l1, Math.sin(upper) * l1);\n return [mid, add(mid, Math.cos(lower) * l2, Math.sin(lower) * l2), lower];\n}\n\n/** Turns a pose (bone angles and lengths) into joint positions on the character's 20x24 grid. */\nexport class Skeleton {\n private readonly def: RigDef;\n\n constructor(def: RigDef) {\n this.def = def;\n }\n\n solve(pose: RigPose, bulky = false): Joints {\n const d = this.def;\n const wide = bulky ? d.bulkyShoulder : 0;\n const chest = { x: d.chest[0], y: d.chest[1] + (pose.by ?? 0) };\n const shoulderF = add(chest, d.shoulderF[0] + wide, d.shoulderF[1]);\n const shoulderB = add(chest, d.shoulderB[0] - wide, d.shoulderB[1]);\n const hx = pose.hipDx ?? 0;\n const hy = pose.hipDy ?? 0;\n const hipF = { x: d.hipF[0] + hx, y: d.hipF[1] + hy };\n const hipB = { x: d.hipB[0] + hx, y: d.hipB[1] + hy };\n const [elbowF, wristF, forearm] = this.frontArm(shoulderF, pose.armF ?? DOWN);\n const [elbowB, wristB] = chain(shoulderB, pose.armB ?? DOWN);\n const [kneeF, ankleF] = chain(hipF, pose.legF ?? DOWN);\n const [kneeB, ankleB] = chain(hipB, pose.legB ?? DOWN);\n const head = add(chest, pose.headDx ?? 0, pose.headDy ?? 0);\n return { chest, head, shoulderF, elbowF, wristF, shoulderB, elbowB, wristB, hipF, kneeF, ankleF, hipB, kneeB, ankleB, forearm };\n }\n\n /**\n * Elbow, wrist and forearm direction of the front arm (or of its motion smear) hung from `shoulder`. The fist keeps\n * the frame's last column for its outline: an arm reaching past that (a swing, a thrust, a draw on a bulky body) is\n * pulled back whole, so the forearm — and the weapon laid along it — keeps its angle.\n */\n frontArm(shoulder: Point, limb: Limb): [Point, Point, number] {\n const d = this.def;\n const [elbow, wrist, forearm] = chain(shoulder, limb);\n const over = Math.max(0, wrist.x - (d.width - d.limbWidth - 1));\n return [add(elbow, -over, 0), add(wrist, -over, 0), forearm];\n }\n}\n","import type { RigDef } from './rigTypes';\nimport def from './humanoid.json';\n\n/** The proportions of the built-in 20×24 humanoid: chest, shoulders, hips and limb width. */\nexport const HUMANOID_RIG: RigDef = def as RigDef;\n","import type { Limb, RigPose } from './rigTypes';\n\nfunction lerp(a: number, b: number, k: number): number {\n return a + (b - a) * k;\n}\n\n/** Shortest turn from angle a to b, in degrees. */\nfunction lerpDeg(a: number, b: number, k: number): number {\n let d = (b - a) % 360;\n if (d > 180) d -= 360;\n if (d < -180) d += 360;\n return a + d * k;\n}\n\nfunction lerpLimb(a: Limb | undefined, b: Limb | undefined, k: number): Limb | undefined {\n if (!a || !b) return k < 1 ? a ?? b : b ?? a;\n return [lerpDeg(a[0], b[0], k), lerp(a[1], b[1], k), lerpDeg(a[2], b[2], k), lerp(a[3], b[3], k)];\n}\n\nfunction lerpOpt(a: number | undefined, b: number | undefined, k: number): number | undefined {\n if (a === undefined && b === undefined) return undefined;\n return lerp(a ?? 0, b ?? 0, k);\n}\n\n/**\n * The in-between of two poses at `k` (0 = a, 1 = b): bones turn along the shortest way and stretch, offsets slide.\n * What cannot be in between (face, cape trail, the curled torso) stays `a`'s until `b` is reached.\n */\nexport function blendPose(a: RigPose, b: RigPose, k: number): RigPose {\n if (k <= 0) return a;\n if (k >= 1) return b;\n const discrete = a;\n return {\n ...discrete,\n by: lerpOpt(a.by, b.by, k),\n armF: lerpLimb(a.armF, b.armF, k),\n armB: lerpLimb(a.armB, b.armB, k),\n legF: lerpLimb(a.legF, b.legF, k),\n legB: lerpLimb(a.legB, b.legB, k),\n hipDx: lerpOpt(a.hipDx, b.hipDx, k),\n hipDy: lerpOpt(a.hipDy, b.hipDy, k),\n headDx: lerpOpt(a.headDx, b.headDx, k),\n headDy: lerpOpt(a.headDy, b.headDy, k),\n smearArm: a.smearArm,\n curl: a.curl && b.curl ? [lerp(a.curl[0], b.curl[0], k), lerp(a.curl[1], b.curl[1], k)] : a.curl,\n };\n}\n\n/** `top` laid over `base`: every field `top` sets wins. */\nexport function overlay(base: RigPose, top: RigPose): RigPose {\n const out: RigPose = { ...base };\n for (const [key, value] of Object.entries(top)) if (value !== undefined) (out as Record<string, unknown>)[key] = value;\n return out;\n}\n\n/**\n * An action's upper body over a moving (or seated) body: the arms, head and face act while the legs keep the gait.\n * The chest takes both bobs, but rises at most a pixel so a tall hat keeps its headroom.\n */\nexport function upperOver(action: RigPose, legs: RigPose): RigPose {\n return {\n ...action,\n by: Math.max(-1, (action.by ?? 0) + (legs.by ?? 0)),\n legF: legs.legF,\n legB: legs.legB,\n hipDx: legs.hipDx,\n hipDy: legs.hipDy,\n // the far arm swings with the run, unless it holds the bow the action draws\n armB: action.armBFront ? action.armB : legs.armB,\n trail: legs.trail ?? action.trail,\n };\n}\n","import type { RigPose } from './rigTypes';\nimport poses from './poses.json';\nimport type { PoseClip } from './PosePlayer';\n\n/**\n * The built-in humanoid's pose library: 72 poses for `HUMANOID_RIG`, made for a 20×24 character facing right, and\n * clips that string them into motion. Use them as they are, mix them (`overlay`, `upperOver`), or as the starting\n * point for your own.\n */\nexport const HUMANOID_POSES: Readonly<Record<string, RigPose>> = poses as unknown as Record<string, RigPose>;\n\nconst seq = (prefix: string, n: number) => Array.from({ length: n }, (_, i) => `${prefix}${i}`);\n\n/** Ready-made clips over `HUMANOID_POSES`. Looping clips blend from their last pose back into the first. */\nexport const HUMANOID_CLIPS = {\n idle: { poses: seq('BREATHE', 6), fps: 6 },\n walk: { poses: seq('STRIDE', 6), fps: 10 },\n run: { poses: seq('JOG', 8), fps: 14 },\n roll: { poses: seq('ROLL', 12), fps: 30, loop: false, blend: false },\n dash: { poses: ['DASH'], fps: 1, loop: false },\n hurt: { poses: ['HURT', 'BREATHE0'], fps: 5, loop: false },\n dizzy: { poses: ['DIZZY', 'BREATHE0'], fps: 2 },\n crouch: { poses: ['CROUCH'], fps: 1, loop: false },\n kneel: { poses: ['KNEEL'], fps: 1, loop: false },\n sit: { poses: ['SIT'], fps: 1, loop: false },\n sitGround: { poses: ['SIT_GROUND'], fps: 1, loop: false },\n pick: { poses: ['CROUCH', 'PICK', 'CROUCH'], fps: 6, loop: false },\n lookBack: { poses: ['LOOK_BACK'], fps: 1, loop: false },\n stretch: { poses: ['BREATHE0', 'STRETCH', 'STRETCH', 'BREATHE0'], fps: 3, loop: false },\n cheer: { poses: ['BREATHE0', 'CHEER', 'CHEER'], fps: 6, loop: false },\n wave: { poses: ['WAVE_A', 'WAVE_B'], fps: 4 },\n dance: { poses: ['DANCE_A', 'DANCE_B'], fps: 3 },\n slash: { poses: ['SLASH_READY', 'SLASH_WIND', 'SLASH_SWEEP', 'SLASH_FOLLOW', 'SLASH_END', 'SLASH_RECOVER'], durations: [60, 90, 40, 60, 90, 120], loop: false },\n thrust: { poses: ['THRUST_READY', 'THRUST_LUNGE', 'THRUST_MID', 'THRUST_END', 'THRUST_RECOVER'], durations: [80, 50, 60, 100, 120], loop: false },\n overhead: { poses: ['OVERHEAD_READY', 'OVERHEAD', 'OVERHEAD_MID', 'OVERHEAD_FALL'], durations: [90, 140, 50, 160], loop: false },\n cast: { poses: ['CAST_CHARGE', 'CAST', 'CAST_RELEASE'], durations: [220, 120, 200], loop: false },\n throw: { poses: ['THROW_READY', 'THROW_WIND', 'THROW_RELEASE', 'THROW_MID', 'THROW_RECOVER'], durations: [70, 110, 40, 70, 120], loop: false },\n} satisfies Record<string, PoseClip>;\n\nexport type HumanoidClip = keyof typeof HUMANOID_CLIPS;\n","import { blendPose } from './poseMath';\nimport type { RigPose } from './rigTypes';\n\n/**\n * A clip of key poses: by name (looked up in the player's library) or inline. The player blends between them, so a\n * few keys make a smooth motion; `blend: false` steps from key to key instead (pixel-art timing, a tumble).\n */\nexport interface PoseClip {\n poses: readonly (string | RigPose)[];\n /** Keys per second (default 8). */\n fps?: number;\n /** Per-key lengths in ms, overriding `fps`. */\n durations?: readonly number[];\n /** Start over at the end, blending the last key into the first (default true). */\n loop?: boolean;\n /** Blend between keys (default true). */\n blend?: boolean;\n}\n\n/**\n * Plays pose clips over time and answers the pose of this moment, blended between keys, with a crossfade when the\n * clip changes. Pure: give it a library of poses and clips, call `update(dt)`, read `pose`.\n *\n * ```ts\n * const player = new PosePlayer(HUMANOID_POSES, HUMANOID_CLIPS, 'idle');\n * player.play('walk', { fadeMs: 120 });\n * player.update(dt);\n * view.setPose(player.pose);\n * ```\n */\nexport class PosePlayer<Name extends string = string> {\n private clip: PoseClip;\n private name: Name;\n private elapsed = 0;\n private ended = false;\n /** The pose being faded out of, and how long the fade lasts and has run. */\n private from: RigPose | null = null;\n private fadeMs = 0;\n private fadeAt = 0;\n private cached: RigPose | null = null;\n speed = 1;\n /** Called when a clip that does not loop reaches its end. */\n onComplete: ((clip: Name) => void) | null = null;\n\n constructor(\n private readonly library: Readonly<Record<string, RigPose>>,\n private readonly clips: Record<Name, PoseClip>,\n initial: NoInfer<Name>,\n ) {\n this.clip = this.clipOf(initial);\n this.name = initial;\n }\n\n get current(): Name {\n return this.name;\n }\n\n get finished(): boolean {\n return this.ended;\n }\n\n /** Time into the current clip, ms. */\n get time(): number {\n return this.elapsed;\n }\n\n /** Plays `name`, fading from the pose shown now over `fadeMs`. The clip already playing keeps going unless `restart`. */\n play(name: Name, options: { fadeMs?: number; restart?: boolean } = {}): this {\n if (name === this.name && !options.restart) return this;\n const fadeMs = options.fadeMs ?? 0;\n this.from = fadeMs > 0 ? this.pose : null;\n this.fadeMs = fadeMs;\n this.fadeAt = 0;\n this.clip = this.clipOf(name);\n this.name = name;\n this.elapsed = 0;\n this.ended = false;\n this.cached = null;\n return this;\n }\n\n /** Advances by `dt` seconds. */\n update(dt: number): void {\n if (!(dt > 0) || this.speed <= 0) return;\n const ms = dt * 1000 * this.speed;\n this.cached = null;\n if (this.from) {\n this.fadeAt += ms;\n if (this.fadeAt >= this.fadeMs) this.from = null;\n }\n if (this.ended) return;\n this.elapsed += ms;\n const total = this.totalMs();\n if (this.elapsed >= total) {\n if (this.clip.loop !== false) {\n this.elapsed %= total;\n } else {\n this.elapsed = total;\n this.ended = true;\n this.onComplete?.(this.name);\n }\n }\n }\n\n /** The pose to show now. */\n get pose(): RigPose {\n if (this.cached) return this.cached;\n let pose = this.sample(this.elapsed);\n if (this.from) pose = blendPose(this.from, pose, Math.min(1, this.fadeAt / this.fadeMs));\n this.cached = pose;\n return pose;\n }\n\n /** The current clip's pose at `ms` into it. */\n sample(ms: number): RigPose {\n const keys = this.clip.poses;\n const n = keys.length;\n let t = Math.max(0, ms);\n for (let i = 0; i < n; i++) {\n const len = this.lengthOf(i);\n if (t < len || i === n - 1) {\n const a = this.resolve(keys[i]!);\n const last = i === n - 1;\n if (this.clip.blend === false || n === 1 || (last && this.clip.loop === false)) return a;\n const b = this.resolve(keys[last ? 0 : i + 1]!);\n return blendPose(a, b, Math.min(1, t / len));\n }\n t -= len;\n }\n return this.resolve(keys[n - 1]!);\n }\n\n private totalMs(): number {\n let sum = 0;\n for (let i = 0; i < this.clip.poses.length; i++) sum += this.lengthOf(i);\n return sum;\n }\n\n private lengthOf(i: number): number {\n return Math.max(1, this.clip.durations?.[i] ?? 1000 / (this.clip.fps ?? 8));\n }\n\n private resolve(key: string | RigPose): RigPose {\n if (typeof key !== 'string') return key;\n const pose = this.library[key];\n if (!pose) throw new Error(`PosePlayer: no pose \"${key}\" in the library`);\n return pose;\n }\n\n private clipOf(name: Name): PoseClip {\n const clip = this.clips[name];\n if (!clip) throw new Error(`PosePlayer: no clip \"${name}\"`);\n if (clip.poses.length === 0) throw new Error(`PosePlayer: clip \"${name}\" has no poses`);\n for (const k of clip.poses) this.resolve(k);\n return clip;\n }\n}\n","import { Container, Graphics, Sprite } from 'pixi.js';\nimport type { TextureRegistry } from '../core/TextureRegistry';\nimport { Skeleton } from './Skeleton';\nimport type { Joints, Point, RigDef, RigPose } from './rigTypes';\n\n/** The parts a humanoid rig is drawn with, back to front in this order. */\nexport const RIG_PARTS = ['upperArmB', 'forearmB', 'thighB', 'shinB', 'torso', 'thighF', 'shinF', 'head', 'upperArmF', 'forearmF'] as const;\nexport type RigPart = (typeof RIG_PARTS)[number];\n\n/**\n * How one part looks. A textured part is an image drawn with its top-centre on the bone's root joint and turned to\n * follow the bone (cut-out animation, any art style); a vector part is a capsule (limbs), a rounded box (torso) or a\n * circle (head) in `color`.\n */\nexport interface PartSkin {\n /** Texture key (and frame) in the stage's registry; leave out for a vector part. */\n texture?: string;\n frame?: string | number;\n /** Stretch the image along the bone to the next joint instead of drawing it at its own size. */\n stretch?: boolean;\n /** Where on the image the root joint sits, as a share of its size (default 0.5, 0). */\n anchorX?: number;\n anchorY?: number;\n /** Vector fill (default by part). */\n color?: number;\n /** Vector thickness in grid px (default the rig's `limbWidth`; the torso's width; the head's diameter). */\n width?: number;\n /** Vector outline colour, or null for none (default a dark outline). */\n outline?: number | null;\n}\n\nexport type RigSkin = Partial<Record<RigPart, PartSkin>>;\n\nexport interface RigViewOptions {\n /** World px per grid px (default 1). */\n scale?: number;\n /** Head radius in grid px (default 5) and how far above the chest point its centre sits (default 5.5). */\n headRadius?: number;\n headRise?: number;\n /** A broader build: shoulders set wider. */\n bulky?: boolean;\n}\n\nconst DEFAULT_COLORS: Record<RigPart, number> = {\n upperArmB: 0x6a90d0,\n forearmB: 0xf0c8a0,\n thighB: 0x3a3048,\n shinB: 0x3a3048,\n torso: 0x4a6fb0,\n thighF: 0x3a3048,\n shinF: 0x3a3048,\n head: 0xf0c8a0,\n upperArmF: 0x6a90d0,\n forearmF: 0xf0c8a0,\n};\n\nconst BACK = new Set<RigPart>(['upperArmB', 'forearmB', 'thighB', 'shinB']);\n\n/** Which joints each limb part runs between. */\nconst BONES: Record<Exclude<RigPart, 'torso' | 'head'>, [keyof Joints, keyof Joints]> = {\n upperArmB: ['shoulderB', 'elbowB'],\n forearmB: ['elbowB', 'wristB'],\n thighB: ['hipB', 'kneeB'],\n shinB: ['kneeB', 'ankleB'],\n thighF: ['hipF', 'kneeF'],\n shinF: ['kneeF', 'ankleF'],\n upperArmF: ['shoulderF', 'elbowF'],\n forearmF: ['elbowF', 'wristF'],\n};\n\nfunction shadeOf(color: number, k: number): number {\n const r = Math.round(((color >> 16) & 255) * k);\n const g = Math.round(((color >> 8) & 255) * k);\n const b = Math.round((color & 255) * k);\n return (r << 16) | (g << 8) | b;\n}\n\n/**\n * A character drawn from a rig pose: give it a pose each frame (`setPose`, from a `PosePlayer`) and it places every\n * part. The container's origin is the character's feet (bottom centre of the rig's frame); `facing` mirrors it.\n */\nexport class RigView extends Container {\n private readonly skeleton: Skeleton;\n private readonly sprites = new Map<RigPart, Sprite>();\n private readonly layers = new Map<RigPart, Container>();\n private joints: Joints | null = null;\n private curl: [number, number] | undefined;\n private readonly scaleGrid: number;\n private readonly headRadius: number;\n private readonly headRise: number;\n private readonly bulky: boolean;\n\n constructor(\n private readonly def: RigDef,\n private readonly skin: RigSkin = {},\n textures?: TextureRegistry,\n options: RigViewOptions = {},\n ) {\n super();\n this.skeleton = new Skeleton(def);\n this.scaleGrid = options.scale ?? 1;\n this.headRadius = options.headRadius ?? 5;\n this.headRise = options.headRise ?? 5.5;\n this.bulky = options.bulky === true;\n // one container per part keeps the back-to-front order whatever mixes sprites and vectors\n const body = new Container();\n body.position.set(-def.width / 2, -def.height);\n this.addChild(body);\n for (const part of RIG_PARTS) {\n const layer = new Container();\n this.layers.set(part, layer);\n body.addChild(layer);\n const s = skin[part];\n if (s?.texture && textures) {\n const sprite = new Sprite(textures.get(s.texture, s.frame));\n sprite.anchor.set(s.anchorX ?? 0.5, s.anchorY ?? 0);\n // images are drawn at the world's scale, while the rig works in grid px\n sprite.scale.set(1 / this.scaleGrid);\n this.sprites.set(part, sprite);\n layer.addChild(sprite);\n }\n }\n // vector parts are drawn into a graphics in their own layer on each pose\n this.scale.set(this.scaleGrid);\n }\n\n /** 1 faces right, -1 faces left. */\n set facing(dir: 1 | -1) {\n this.scale.x = this.scaleGrid * dir;\n }\n\n get facing(): 1 | -1 {\n return this.scale.x < 0 ? -1 : 1;\n }\n\n /** The joints of the last pose, in grid px of the rig's frame (for attaching a held item, an effect). */\n get lastJoints(): Joints | null {\n return this.joints;\n }\n\n /** Where a joint of the last pose is in this view's parent, in world px. */\n jointInParent(name: keyof Omit<Joints, 'forearm'>): Point | null {\n if (!this.joints) return null;\n const j = this.joints[name];\n return { x: this.x + (j.x - this.def.width / 2) * this.scale.x, y: this.y + (j.y - this.def.height) * this.scale.y };\n }\n\n setPose(pose: RigPose): this {\n const j = this.skeleton.solve(pose, this.bulky);\n this.joints = j;\n this.curl = pose.curl;\n for (const part of RIG_PARTS) this.place(part, j);\n return this;\n }\n\n override destroy(options?: Parameters<Container['destroy']>[0]): void {\n super.destroy(options ?? { children: true });\n }\n\n private place(part: RigPart, j: Joints): void {\n const layer = this.layers.get(part)!;\n const skin = this.skin[part] ?? {};\n const sprite = this.sprites.get(part);\n const [a, b] = this.ends(part, j);\n const angle = Math.atan2(b.y - a.y, b.x - a.x);\n if (sprite) {\n sprite.position.set(a.x, a.y);\n sprite.rotation = angle - Math.PI / 2;\n if (skin.stretch && sprite.texture.height > 0) sprite.scale.y = Math.hypot(b.x - a.x, b.y - a.y) / sprite.texture.height;\n return;\n }\n let g = layer.children[0] as Graphics | undefined;\n if (!g) {\n g = new Graphics();\n layer.addChild(g);\n }\n g.clear();\n const base = skin.color ?? DEFAULT_COLORS[part];\n const color = BACK.has(part) ? shadeOf(base, part.endsWith('ArmB') || part === 'forearmB' ? this.def.backArmShade : this.def.backShade) : base;\n const outline = skin.outline === undefined ? 0x1a1424 : skin.outline;\n const stroke = outline === null ? null : { color: outline, width: 0.6 };\n if (part === 'head') {\n const r = skin.width !== undefined ? skin.width / 2 : this.headRadius;\n g.circle(a.x, a.y, r).fill(color);\n if (stroke) g.stroke(stroke);\n return;\n }\n if (part === 'torso') {\n const w = skin.width ?? Math.abs(this.def.shoulderF[0] - this.def.shoulderB[0]) + 1;\n if (this.curl) {\n g.circle(this.curl[0], this.curl[1], w / 2 + 1).fill(color);\n } else {\n const len = Math.hypot(b.x - a.x, b.y - a.y);\n g.roundRect(-w / 2, -0.5, w, len + 1, Math.min(2, w / 3)).fill(color);\n g.position.set(a.x, a.y);\n g.rotation = angle - Math.PI / 2;\n if (stroke) g.stroke(stroke);\n return;\n }\n g.position.set(0, 0);\n g.rotation = 0;\n if (stroke) g.stroke(stroke);\n return;\n }\n const w = skin.width ?? this.def.limbWidth;\n g.position.set(0, 0);\n g.rotation = 0;\n // the outline is a wider line in its colour drawn first, the limb over it\n if (stroke) g.moveTo(a.x, a.y).lineTo(b.x, b.y).stroke({ color: stroke.color, width: w + stroke.width * 2, cap: 'round' });\n g.moveTo(a.x, a.y).lineTo(b.x, b.y).stroke({ color, width: w, cap: 'round' });\n }\n\n /** The two points a part spans: a limb's joints, the torso from chest to hips, the head's centre (twice). */\n private ends(part: RigPart, j: Joints): [Point, Point] {\n if (part === 'head') {\n const c = { x: j.head.x, y: j.head.y - this.headRise };\n return [c, { x: c.x, y: c.y + 1 }];\n }\n if (part === 'torso') return [j.chest, { x: (j.hipF.x + j.hipB.x) / 2, y: (j.hipF.y + j.hipB.y) / 2 }];\n const [from, to] = BONES[part];\n return [j[from] as Point, j[to] as Point];\n }\n}\n","import { Container, RenderTexture, Sprite, Texture } from 'pixi.js';\nimport type { Stage } from '../core/Stage';\n\n/** A light in the world. Change its fields any time (follow a body by writing `x`/`y` each frame). */\nexport interface Light {\n x: number;\n y: number;\n /** World px. */\n radius: number;\n /** The colour it casts on what it lights (default warm white). */\n color?: number;\n /** 0–1: how much of the dark it takes away, and how strong its colour (default 1). */\n intensity?: number;\n /** Radius wobble, 0–1 (a torch ≈ 0.08). */\n flicker?: number;\n /** A light off is kept but not drawn. */\n on?: boolean;\n}\n\nexport interface LightLayerOptions {\n /** Colour of the dark (default deep blue). */\n ambient?: number;\n /** 0 no dark at all, 1 black where nothing is lit (default 0.85). */\n darkness?: number;\n /** How strongly lights tint what they light, 0–1 (default 0.35). */\n tint?: number;\n /** A light's height over its width: the ground is seen at a slant (default 1, round; a 3/4 view ≈ 0.85). */\n squash?: number;\n}\n\nlet gradient: Texture | null = null;\n\n/** One soft radial falloff, white with alpha, shared by every light. */\nfunction falloff(): Texture {\n if (gradient) return gradient;\n const size = 256;\n const canvas = document.createElement('canvas');\n canvas.width = canvas.height = size;\n const ctx = canvas.getContext('2d');\n if (!ctx) return Texture.EMPTY;\n const g = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2);\n // a bright core and a long, eased tail: reads as light, not as a disc\n g.addColorStop(0, 'rgba(255,255,255,1)');\n g.addColorStop(0.35, 'rgba(255,255,255,0.75)');\n g.addColorStop(0.7, 'rgba(255,255,255,0.25)');\n g.addColorStop(1, 'rgba(255,255,255,0)');\n ctx.fillStyle = g;\n ctx.fillRect(0, 0, size, size);\n gradient = Texture.from(canvas);\n gradient.source.scaleMode = 'linear';\n return gradient;\n}\n\n/**\n * Smooth darkness with lights cut out of it, for art that is not pixel art (the pixel module has its own dithered\n * `Darkness`). The dark is a screen-sized texture: each light erases a soft hole in it, and lays its colour over what\n * shows through. It sits on the screen layer, over the world and under the HUD you add after it.\n *\n * ```ts\n * const night = new LightLayer(stage, { darkness: 0.9 });\n * const torch = night.add({ x: 100, y: 80, radius: 90, color: 0xffb060, flicker: 0.08 });\n * // each frame: torch.x = hero.x; night.update(now);\n * ```\n */\nexport class LightLayer {\n private readonly lights = new Set<Light>();\n private readonly scratch = new Container();\n private readonly sheet = new Sprite(Texture.WHITE);\n private readonly holes = new Container();\n private readonly washes = new Container();\n private readonly view: Sprite;\n private rt: RenderTexture;\n private readonly pool: { hole: Sprite; wash: Sprite }[] = [];\n private ambient: number;\n private darkness: number;\n private readonly tint: number;\n private readonly squash: number;\n private readonly unsubscribe: () => void;\n\n constructor(\n private readonly stage: Stage,\n options: LightLayerOptions = {},\n ) {\n this.ambient = options.ambient ?? 0x0a0c24;\n this.darkness = options.darkness ?? 0.85;\n this.tint = options.tint ?? 0.35;\n this.squash = options.squash ?? 1;\n this.scratch.addChild(this.sheet, this.holes);\n this.rt = RenderTexture.create({ width: 1, height: 1 });\n this.view = new Sprite(this.rt);\n // the colour washes sit over the dark, added to what they light\n this.washes.blendMode = 'add';\n stage.screen.addChild(this.view, this.washes);\n this.unsubscribe = stage.onResize(() => this.fit());\n this.fit();\n }\n\n add(light: Light): Light {\n this.lights.add(light);\n return light;\n }\n\n remove(light: Light): void {\n this.lights.delete(light);\n }\n\n clear(): void {\n this.lights.clear();\n }\n\n /** Changes the dark: its colour and how dark (a day/night cycle eases these). */\n setAmbient(color: number, darkness: number): void {\n this.ambient = color;\n this.darkness = Math.min(1, Math.max(0, darkness));\n }\n\n /** Redraws the dark with this frame's lights. Call once a frame, after the camera moved. */\n update(now = performance.now()): void {\n const on = this.darkness > 0.004;\n this.view.visible = on;\n this.washes.visible = on;\n if (!on) return;\n const cam = this.stage.cameras.main;\n const z = cam.zoom;\n this.sheet.tint = this.ambient;\n this.sheet.alpha = this.darkness;\n let used = 0;\n for (const l of this.lights) {\n if (l.on === false || l.radius <= 0) continue;\n const sx = (l.x - cam.scrollX) * z;\n const sy = (l.y - cam.scrollY) * z;\n const wobble = l.flicker ? 1 + Math.sin(now / 97 + l.x) * Math.sin(now / 53 + l.y) * l.flicker : 1;\n const r = l.radius * z * wobble;\n // off screen by more than its radius: nothing of it shows\n if (sx < -r || sy < -r || sx > cam.width + r || sy > cam.height + r) continue;\n const s = this.sprites(used++);\n const intensity = Math.min(1, Math.max(0, l.intensity ?? 1));\n for (const sprite of [s.hole, s.wash]) {\n sprite.visible = true;\n sprite.position.set(sx, sy);\n sprite.width = r * 2;\n sprite.height = r * 2 * this.squash;\n }\n s.hole.alpha = intensity;\n s.wash.tint = l.color ?? 0xfff0dc;\n s.wash.alpha = intensity * this.tint;\n }\n for (let i = used; i < this.pool.length; i++) {\n this.pool[i]!.hole.visible = false;\n this.pool[i]!.wash.visible = false;\n }\n this.stage.app.renderer.render({ container: this.scratch, target: this.rt, clear: true });\n }\n\n destroy(): void {\n this.unsubscribe();\n this.view.destroy();\n this.washes.destroy({ children: true });\n this.scratch.destroy({ children: true });\n this.rt.destroy(true);\n this.lights.clear();\n }\n\n private sprites(i: number): { hole: Sprite; wash: Sprite } {\n let s = this.pool[i];\n if (!s) {\n const hole = new Sprite(falloff());\n hole.anchor.set(0.5);\n hole.blendMode = 'erase';\n const wash = new Sprite(falloff());\n wash.anchor.set(0.5);\n this.holes.addChild(hole);\n this.washes.addChild(wash);\n s = { hole, wash };\n this.pool.push(s);\n }\n return s;\n }\n\n private fit(): void {\n const w = Math.max(1, Math.ceil(this.stage.width));\n const h = Math.max(1, Math.ceil(this.stage.height));\n this.rt.resize(w, h);\n this.sheet.width = w;\n this.sheet.height = h;\n }\n}\n","/*\n * How hard a landed blow feels. Pure, so the numbers\n * can be pinned: the freeze-frame grows with the share of the body's health the blow took, a crit holds longer, and the\n * body struck is knocked a pixel or three away from whoever struck it — less the bigger it is.\n */\n\n/** The freeze-frame of a blow (ms): 40 for a scratch, up to 140 for one that took a third of the body; a crit +40. */\nexport function hitStopMs(share: number, crit: boolean): number {\n const base = Math.min(140, 40 + Math.max(0, share) * 400);\n return Math.round(base + (crit ? 40 : 0));\n}\n\n/** How far the body struck recoils away from the blow (whole world px): a heavy body barely, a crit a pixel further. */\nexport function recoilPx(heavy: boolean, share: number, crit: boolean): number {\n if (heavy) return crit ? 2 : 1;\n return Math.min(3, 2 + (share > 0.2 ? 1 : 0) + (crit ? 1 : 0));\n}\n\n/** How long a recoil takes to settle back (ms). */\nexport const RECOIL_MS = 120;\n\n/** The recoil left at `t` (0 the blow, 1 settled): out at once, eased back, whole pixels only. */\nexport function recoilAt(px: number, t: number): number {\n if (t >= 1 || px <= 0) return 0;\n return Math.round(px * (1 - t) * (1 - t));\n}\n\n/** The least time between two white flashes on a heavy body (ms). */\nexport const HEAVY_FLASH_GAP_MS = 400;\n\n/**\n * How long the body struck flashes white (ms), 0 for none: 70, a crit of one's own 140 (the impact frame), nothing with\n * `reduce` (a \"reduce flashes\" setting). A heavy body (a boss, anything drawn large) flashes only for the local\n * player's own crit, 60 ms, `HEAVY_FLASH_GAP_MS` apart: a sheet covering most of the screen turning white on every\n * blow, beat and tick is a strobe. Sparks, numbers and the recoil still mark every blow.\n */\nexport function hurtFlashMs(heavy: boolean, impact: boolean, reduce: boolean): number {\n if (reduce) return 0;\n if (heavy) return impact ? 60 : 0;\n return impact ? 140 : 70;\n}\n\n/** The gap a body keeps between two flashes (ms). */\nexport function hurtFlashGapMs(heavy: boolean): number {\n return heavy ? HEAVY_FLASH_GAP_MS : 0;\n}\n","/** What `inView` reads off the main camera (Camera's own fields; a fake stage may lack them). */\nexport interface CameraLike {\n zoom: number;\n scrollX?: number;\n scrollY?: number;\n width?: number;\n height?: number;\n}\n\n/**\n * Whether the world point (x, y) lies within `margin` world pixels of the screen. Effects use it to skip painting what\n * nobody can see. A camera that has no size yet (a tool's fake stage, before the first resize) counts everything in.\n */\nexport function inView(cam: CameraLike, x: number, y: number, margin: number): boolean {\n const w = cam.width;\n const h = cam.height;\n if (!w || !h || !(cam.zoom > 0)) return true;\n const left = cam.scrollX ?? 0;\n const top = cam.scrollY ?? 0;\n return x >= left - margin && y >= top - margin && x <= left + w / cam.zoom + margin && y <= top + h / cam.zoom + margin;\n}\n","/*\n * Cleans one recorded take (`SampleBank`): folded to mono, the silence an encoder or the model leaves at the start cut\n * (a swing heard 30 ms late reads as lag) and at the end trimmed, and brought to one loudness (`LOUDNESS`, RMS of what\n * is left, never past `PEAK`), so takes from different prompts sit at one level. Pure: run in `takeCleanerWorker.ts`,\n * because on the main thread the first blows of a fight froze the game 70–170 ms a take on a Mac and several times\n * that on a phone (profiled).\n */\n\n/** Below this share of the take's own peak a sample counts as silence when trimming (-40 dB). */\nconst FLOOR = 0.01;\n/** A take whose peak is under this is treated as empty (about -46 dBFS): the model returned near-silence. */\nconst EMPTY = 0.005;\n/** Target RMS of a cleaned take (-16 dBFS) and the peak it may not pass. */\nconst LOUDNESS = 0.16;\nconst PEAK = 0.95;\n/** Kept before the first loud sample, so the attack is not clipped into a click (s). */\nconst LEAD = 0.002;\n/** A short fade over the cut end, so a trimmed tail does not click (s). */\nconst TAIL_FADE = 0.01;\n\n/** The cleaned mono samples, or null for a take that is silence. */\nexport function cleanSamples(channels: Float32Array[], sampleRate: number): Float32Array | null {\n const n = channels[0]?.length ?? 0;\n const k0 = 1 / Math.max(1, channels.length);\n const mono = new Float32Array(n);\n for (const ch of channels) for (let i = 0; i < n; i++) mono[i]! += ch[i]! * k0;\n let top = 0;\n for (let i = 0; i < n; i++) {\n const a = Math.abs(mono[i]!);\n if (a > top) top = a;\n }\n if (top < EMPTY) return null;\n const floor = top * FLOOR;\n let start = 0;\n while (start < n && Math.abs(mono[start]!) < floor) start++;\n let end = n;\n while (end > start && Math.abs(mono[end - 1]!) < floor) end--;\n if (end <= start) return null;\n start = Math.max(0, start - Math.round(LEAD * sampleRate));\n const data = mono.slice(start, end);\n let power = 0;\n for (let i = 0; i < data.length; i++) power += data[i]! * data[i]!;\n const rms = Math.sqrt(power / data.length);\n const k = Math.min(LOUDNESS / Math.max(rms, 1e-6), PEAK / top);\n const fade = Math.min(data.length, Math.round(TAIL_FADE * sampleRate));\n for (let i = 0; i < data.length; i++) {\n const left = data.length - i;\n data[i]! *= k * (left < fade ? left / fade : 1);\n }\n return data;\n}\n","/**\n * The recorded takes of the sounds, registered by the game (`registerTakes`): `<sound>.mp3`, and `<sound>_2.mp3`…\n * when a sound has more than one. A\n * sound with takes plays one of them at random, never the same one twice running when it has more; a sound without\n * any — or whose takes have not decoded yet — falls back to its synth recipe in `SoundEngine`.\n *\n * Every take is cleaned once on decode (`cleanTake.ts`: mono, silence trimmed, one loudness), off the main thread\n * in `takeCleanerWorker.ts`, so `sounds.json`'s `fileGain` is the only mix knob. Measured on the first batch, peaks\n * alone left their loudness 20 dB apart.\n */\n\nimport { cleanSamples } from './cleanTake';\n\nconst TAKES: Record<string, string[]> = {};\n\n/**\n * Registers recorded takes by file path → url, e.g. a Vite `import.meta.glob('./sfx/*.mp3', { query: '?url',\n * import: 'default', eager: true })`. `hit.mp3`, `hit_2.mp3`… are takes of `hit`; sound names carry no digits.\n */\nexport function registerTakes(urls: Record<string, string>): void {\n for (const [path, url] of Object.entries(urls)) {\n const m = /(?:^|\\/)([a-z_]+?)(?:_\\d+)?\\.mp3$/.exec(path);\n if (m) (TAKES[m[1]!] ??= []).push(url);\n }\n}\n\n/** The sound has recorded takes in the build (decoded or not). */\nexport const hasTakes = (name: string): boolean => !!TAKES[name];\n\nexport class SampleBank {\n private readonly decoded = new Map<string, AudioBuffer[]>();\n private readonly loading = new Set<string>();\n private readonly last = new Map<string, number>();\n\n names(): string[] {\n return Object.keys(TAKES);\n }\n\n /** A decoded take, or null while none is ready (the caller then synthesises); starts loading on first ask. */\n take(ctx: AudioContext, name: string): AudioBuffer | null {\n const list = this.decoded.get(name);\n if (!list?.length) {\n this.load(ctx, name);\n return null;\n }\n let i = Math.floor(Math.random() * list.length);\n if (list.length > 1 && i === this.last.get(name)) i = (i + 1) % list.length;\n this.last.set(name, i);\n return list[i]!;\n }\n\n load(ctx: AudioContext, name: string): void {\n const urlsOf = TAKES[name];\n if (!urlsOf || this.loading.has(name)) return;\n this.loading.add(name);\n const list: AudioBuffer[] = [];\n this.decoded.set(name, list);\n for (const url of urlsOf) {\n fetch(url)\n .then((r) => r.arrayBuffer())\n .then((data) => ctx.decodeAudioData(data))\n .then((buf) => clean(buf))\n .then((data) => {\n if (!data) return;\n const out = ctx.createBuffer(1, data.length, ctx.sampleRate);\n out.copyToChannel(data as Float32Array<ArrayBuffer>, 0);\n list.push(out);\n })\n .catch(() => {});\n }\n }\n}\n\nlet worker: Worker | null | undefined;\nlet nextId = 0;\nconst waiting = new Map<number, (data: Float32Array | null) => void>();\n\n/** The cleaner worker, started on first use; null where workers cannot start (then takes are cleaned here). */\nfunction cleaner(): Worker | null {\n if (worker !== undefined) return worker;\n try {\n worker = new Worker(new URL('./takeCleanerWorker.ts', import.meta.url), { type: 'module' });\n worker.onmessage = (e: MessageEvent<{ id: number; data: Float32Array | null }>) => {\n waiting.get(e.data.id)?.(e.data.data);\n waiting.delete(e.data.id);\n };\n worker.onerror = () => {\n worker?.terminate();\n worker = null;\n for (const done of waiting.values()) done(null);\n waiting.clear();\n };\n } catch {\n worker = null;\n }\n return worker;\n}\n\n/** Takes handed over one per task: a fight's first blows ask for a dozen at once, and copying them all out in one\n * task still froze a frame. */\nlet turn: Promise<void> = Promise.resolve();\n\n/** A decoded take cleaned at the context's own rate (decodeAudioData resamples to it). */\nfunction clean(buf: AudioBuffer): Promise<Float32Array | null> {\n return new Promise((resolve) => {\n turn = turn\n .then(() => new Promise<void>((r) => setTimeout(r, 0)))\n .then(() => {\n send(buf).then(resolve, () => resolve(null));\n });\n });\n}\n\nfunction send(buf: AudioBuffer): Promise<Float32Array | null> {\n const channels = Array.from({ length: buf.numberOfChannels }, (_, c) => buf.getChannelData(c).slice());\n const w = cleaner();\n if (!w) return Promise.resolve(cleanSamples(channels, buf.sampleRate));\n const id = nextId++;\n return new Promise((resolve) => {\n waiting.set(id, resolve);\n w.postMessage({ id, channels, sampleRate: buf.sampleRate }, { transfer: channels.map((c) => c.buffer as ArrayBuffer) });\n });\n}\n","import type { SynthRecipe } from './synth';\n\n/**\n * The sounds the engine can play: synthesised recipes by name, plus the master share every sound plays at. Empty\n * until the game registers its own (`registerSounds`); the mapping from game happenings to sound names stays in\n * the game.\n */\nexport interface SoundTable {\n /** Share of the effects volume everything plays at: keeps full volume modest next to the music. */\n master: number;\n recipes: Record<string, SynthRecipe>;\n}\n\nexport const SOUNDS: SoundTable = { master: 1, recipes: {} };\n\nexport function registerSounds(table: Partial<SoundTable>): void {\n if (table.master !== undefined) SOUNDS.master = table.master;\n if (table.recipes) Object.assign(SOUNDS.recipes, table.recipes);\n}\n","/**\n * The combat sounds are written, not recorded: a few oscillator or noise layers rendered straight into a buffer\n * (`sounds.json` → `recipes`). Lo-fi on purpose — 22 kHz mono, short and soft — so they sit with the pixel art\n * instead of pretending to be a recording.\n */\nexport const SYNTH_RATE = 22050;\n\nexport interface SynthLayer {\n /** Waveform; `noise` is white noise, or sample-and-hold noise at `f` Hz when `f` is given (crunchier). */\n w: 'sine' | 'square' | 'tri' | 'saw' | 'noise';\n /** Pitch at the start and at the end of the layer (Hz), swept exponentially. */\n f?: [number, number];\n /** Length (s). */\n t: number;\n /** Delay before the layer starts (s). */\n d?: number;\n /** Attack (s). */\n at?: number;\n g: number;\n /** Decay curve exponent: 1 is linear, higher falls away faster. */\n c?: number;\n duty?: number;\n /** Low- and high-pass cutoff at the start and the end (Hz). */\n lp?: [number, number];\n hp?: [number, number];\n}\n\nexport interface SynthRecipe {\n layers: SynthLayer[];\n /** Random pitch spread per play (share of 1); the engine's default when absent. */\n jitter?: number;\n /** Level of the sound's recorded takes (`registerTakes`), which are normalised on decode; default 1. */\n fileGain?: number;\n}\n\nconst WAVES: Record<Exclude<SynthLayer['w'], 'noise'>, (p: number, duty: number) => number> = {\n sine: (p) => Math.sin(p * Math.PI * 2),\n square: (p, duty) => (p < duty ? 1 : -1),\n tri: (p) => 1 - 4 * Math.abs(p - 0.5),\n saw: (p) => 2 * p - 1,\n};\n\nconst sweep = (a: number, b: number, k: number): number => (a > 0 && b > 0 ? a * Math.pow(b / a, k) : a + (b - a) * k);\n\n/** A one-pole filter is enough for a stand-in, and it cannot ring or blow up the way a swept biquad can. */\nfunction onePole(cut: number): number {\n return 1 - Math.exp((-2 * Math.PI * Math.min(cut, SYNTH_RATE * 0.45)) / SYNTH_RATE);\n}\n\nexport function renderRecipe(recipe: SynthRecipe): Float32Array {\n const total = Math.max(...recipe.layers.map((l) => (l.d ?? 0) + l.t));\n const out = new Float32Array(Math.ceil(total * SYNTH_RATE) + 1);\n let seed = 0x9e3779b9;\n const rand = () => {\n seed ^= seed << 13;\n seed ^= seed >>> 17;\n seed ^= seed << 5;\n return ((seed >>> 0) / 0xffffffff) * 2 - 1;\n };\n for (const l of recipe.layers) {\n const start = Math.round((l.d ?? 0) * SYNTH_RATE);\n const n = Math.round(l.t * SYNTH_RATE);\n const at = Math.max(1, Math.round((l.at ?? 0.004) * SYNTH_RATE));\n let phase = 0;\n let held = 0;\n let lpState = 0;\n let hpState = 0;\n for (let i = 0; i < n && start + i < out.length; i++) {\n const k = i / n;\n const freq = l.f ? sweep(l.f[0], l.f[1], k) : 0;\n phase += freq / SYNTH_RATE;\n const p = phase - Math.floor(phase);\n let s: number;\n if (l.w === 'noise') {\n // sample-and-hold: a new value each time the phase wraps, which is what makes it crunch\n if (!l.f || p < freq / SYNTH_RATE || i === 0) held = rand();\n s = l.f ? held : rand();\n } else s = WAVES[l.w](p, l.duty ?? 0.5);\n if (l.lp) {\n lpState += (s - lpState) * onePole(sweep(l.lp[0], l.lp[1], k));\n s = lpState;\n }\n if (l.hp) {\n hpState += (s - hpState) * onePole(sweep(l.hp[0], l.hp[1], k));\n s -= hpState;\n }\n const env = i < at ? i / at : Math.pow(1 - (i - at) / Math.max(1, n - at), l.c ?? 2);\n out[start + i]! += s * env * l.g;\n }\n }\n // a stand-in never clips: peaks are brought back under full scale\n let peak = 0;\n for (const v of out) peak = Math.max(peak, Math.abs(v));\n if (peak > 0.95) for (let i = 0; i < out.length; i++) out[i]! *= 0.95 / peak;\n return out;\n}\n","import { engineSettings } from '../settings';\nimport { hasTakes, SampleBank } from './sampleBank';\nimport { SOUNDS } from './soundTable';\nimport { renderRecipe, SYNTH_RATE } from './synth';\n\n/**\n * Plays sound effects through Web Audio, on a gain of their own (`engineSettings.sfxVolume`, beside the music's).\n * A sound is one of its recorded takes (`registerTakes`, `SampleBank`) when it has\n * any, else its `sounds.json` recipe rendered once into a buffer the first time it is asked for. A sound in the\n * world fades with its distance from the local player, pans with where it happened and loses its highs as it goes\n * (`MUFFLE`); the local player's own swings and blows play at full weight, everyone else's at `OTHERS`.\n *\n * Kept lean on purpose (an earlier, much larger set of effects was taken out for being too busy): one sound per\n * kind per `MIN_GAP_MS`, never more than `MAX_VOICES` at once, and nothing but combat.\n */\n\n/** Beyond this (px) a sound in the world is not heard at all. */\nconst HEARING = 480;\nconst MAX_VOICES = 10;\n/** Minor sounds (footsteps) start only while fewer than this are playing, so they never take a blow's voice. */\nconst MINOR_VOICES = 6;\n/** The same kind twice inside this (ms) is one sound: a cleave clipping six bodies lands once. */\nconst MIN_GAP_MS = 60;\n/** Weight of what other players, pets and monsters do, against the local player's own. */\nconst OTHERS = 0.45;\nconst DEFAULT_JITTER = 0.05;\n/** A sound cut short by `maxMs` fades out over this, so the cut does not click. */\nconst CUT_FADE_MS = 80;\n/** Low-pass cutoff (Hz) right beside the listener and at the edge of hearing: far blows sound dull, not just quiet. */\nconst MUFFLE: [number, number] = [18000, 1800];\n/**\n * The tone of the whole effects bus: the recorded takes came back bright (hiss, glassy ice, blade scrapes) and read\n * as shrill next to the music, so the highs are shelved down and the very top cut, for every sound at once.\n */\nconst TAME_SHELF = { freq: 3500, gainDb: -7 };\nconst TAME_TOP = 11000;\n\nexport interface SoundOptions {\n /** Where it happened in the world; absent for what happens to or is done by the local player. */\n x?: number;\n y?: number;\n /** Done by (or to) the local player: full weight. */\n local?: boolean;\n /** Extra weight (default 1). */\n gain?: number;\n /** How far away it can be heard (px), when nearer than `HEARING`. */\n range?: number;\n /** Skipped when the mix is busy (footsteps). */\n minor?: boolean;\n /** Cut off after this long (ms), faded over `CUT_FADE_MS`: a cast's sound ends with the cast. */\n maxMs?: number;\n}\n\nexport class SoundEngine {\n private ctx: AudioContext | null = null;\n private master: GainNode | null = null;\n private readonly buffers = new Map<string, AudioBuffer | null>();\n private readonly samples = new SampleBank();\n private readonly lastAt = new Map<string, number>();\n private voices = 0;\n /** Where the local player stands, set by the world scene; null off the world screens. */\n listener: () => { x: number; y: number } | null = () => null;\n private onRunning: (running: boolean) => void = () => {};\n\n constructor() {\n if (typeof window === 'undefined') return;\n // iOS lets a page start sound only inside a gesture, counts `touchend` (not `pointerdown`) as one, and leaves\n // the context 'interrupted' after the app comes back from the background: every touch retries until it runs\n const unlock = () => {\n const ctx = this.context();\n if (!ctx || ctx.state === 'running') return;\n void ctx.resume();\n // one silent sample started inside the gesture is what WebKit needs to open the output\n const blank = ctx.createBufferSource();\n blank.buffer = ctx.createBuffer(1, 1, 22050);\n blank.connect(ctx.destination);\n blank.start();\n };\n // listening only while the context is not running: once it runs a touch has nothing to do, and the listeners\n // come back the moment it stops (the interrupted iOS case)\n const types = ['pointerdown', 'pointerup', 'touchend', 'keydown'] as const;\n const listen = (on: boolean) => {\n for (const type of types) {\n if (on) window.addEventListener(type, unlock, { capture: true });\n else window.removeEventListener(type, unlock, { capture: true });\n }\n };\n this.onRunning = (running) => listen(!running);\n listen(true);\n // game sound, not media: it follows the ring/silent switch and mixes with the player's own music (iOS 17+)\n const session = (navigator as Navigator & { audioSession?: { type: string } }).audioSession;\n if (session) session.type = 'ambient';\n engineSettings.subscribe((s) => {\n if (this.ctx && this.master) this.master.gain.setTargetAtTime(this.level(s.sfxVolume), this.ctx.currentTime, 0.02);\n });\n }\n\n play(name: string | undefined, opts: SoundOptions = {}): void {\n if (!name || (!SOUNDS.recipes[name] && !hasTakes(name))) return;\n if (engineSettings.getState().sfxVolume <= 0) return;\n const ctx = this.ctx;\n if (!ctx || ctx.state !== 'running' || this.voices >= (opts.minor ? MINOR_VOICES : MAX_VOICES)) return;\n let gain = (opts.gain ?? 1) * (opts.local ? 1 : OTHERS);\n let pan = 0;\n let far = 0;\n if (opts.x !== undefined && opts.y !== undefined) {\n const me = this.listener();\n if (me) {\n const dx = opts.x - me.x;\n const d = Math.hypot(dx, opts.y - me.y);\n const hearing = Math.min(HEARING, opts.range ?? HEARING);\n if (d >= hearing) return;\n gain *= Math.pow(1 - d / hearing, 1.5);\n far = d / HEARING;\n pan = Math.max(-0.7, Math.min(0.7, dx / 320));\n }\n }\n if (gain < 0.03) return;\n const now = performance.now();\n if (now - (this.lastAt.get(name) ?? -1e9) < MIN_GAP_MS) return;\n const take = this.samples.take(ctx, name);\n const buffer = take ?? this.buffer(ctx, name);\n if (!buffer) return;\n if (take) gain *= SOUNDS.recipes[name]?.fileGain ?? 1;\n this.lastAt.set(name, now);\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n const jitter = SOUNDS.recipes[name]?.jitter ?? DEFAULT_JITTER;\n src.playbackRate.value = 1 + (Math.random() * 2 - 1) * jitter;\n const g = ctx.createGain();\n g.gain.value = Math.min(1, gain);\n const p = ctx.createStereoPanner();\n p.pan.value = pan;\n const lp = ctx.createBiquadFilter();\n lp.type = 'lowpass';\n lp.frequency.value = MUFFLE[0] * Math.pow(MUFFLE[1] / MUFFLE[0], far);\n src.connect(lp).connect(g).connect(p).connect(this.master!);\n this.voices++;\n src.onended = () => {\n this.voices--;\n src.disconnect();\n lp.disconnect();\n g.disconnect();\n p.disconnect();\n };\n src.start();\n const lasts = (buffer.duration / src.playbackRate.value) * 1000;\n if (opts.maxMs !== undefined && lasts > opts.maxMs) {\n const end = ctx.currentTime + Math.max(CUT_FADE_MS, opts.maxMs) / 1000;\n g.gain.setValueAtTime(g.gain.value, end - CUT_FADE_MS / 1000);\n g.gain.linearRampToValueAtTime(0, end);\n src.stop(end);\n }\n }\n\n private level(volume: number): number {\n return Math.max(0, Math.min(1, volume)) * SOUNDS.master;\n }\n\n private context(): AudioContext | null {\n if (this.ctx) return this.ctx;\n if (typeof AudioContext === 'undefined') return null;\n this.ctx = new AudioContext();\n this.master = this.ctx.createGain();\n this.master.gain.value = this.level(engineSettings.getState().sfxVolume);\n const shelf = this.ctx.createBiquadFilter();\n shelf.type = 'highshelf';\n shelf.frequency.value = TAME_SHELF.freq;\n shelf.gain.value = TAME_SHELF.gainDb;\n const top = this.ctx.createBiquadFilter();\n top.type = 'lowpass';\n top.frequency.value = TAME_TOP;\n this.master.connect(shelf).connect(top).connect(this.ctx.destination);\n const ctx = this.ctx;\n const changed = () => {\n const running = ctx.state === 'running';\n this.onRunning(running);\n if (running) this.prerender(ctx);\n };\n ctx.addEventListener('statechange', changed);\n // a context allowed to run from the start changes no state\n if (ctx.state === 'running') queueMicrotask(changed);\n return ctx;\n }\n\n /**\n * Starts decoding every recorded take and renders every recipe not rendered yet, one per task, once the context\n * first runs — so the first swing of a fight does not pay for its sound in that frame.\n */\n private prerender(ctx: AudioContext): void {\n for (const name of this.samples.names()) this.samples.load(ctx, name);\n // a sound with recorded takes plays them; its recipe is only the fallback while they decode, not worth a 40 ms task\n const todo = Object.keys(SOUNDS.recipes).filter((name) => !this.buffers.has(name) && !hasTakes(name));\n const next = () => {\n const name = todo.shift();\n if (name === undefined) return;\n this.buffer(ctx, name);\n setTimeout(next, 0);\n };\n next();\n }\n\n /** Rendered on first use or by `prerender` (a few ms each), then kept. */\n private buffer(ctx: AudioContext, name: string): AudioBuffer | null {\n const cached = this.buffers.get(name);\n if (cached !== undefined) return cached;\n const recipe = SOUNDS.recipes[name];\n let buf: AudioBuffer | null = null;\n if (recipe) {\n const data = renderRecipe(recipe);\n buf = ctx.createBuffer(1, data.length, SYNTH_RATE);\n buf.getChannelData(0).set(data);\n }\n this.buffers.set(name, buf);\n return buf;\n }\n}\n\nexport const sound = new SoundEngine();\n","import { engineSettings } from '../settings';\n\nexport interface PlayOptions {\n /** Crossfade from what is playing, ms (default 1200). */\n fadeMs?: number;\n /** Start over at the end (default true). */\n loop?: boolean;\n /** This track's own level, 0–1, under the music volume (default 1). */\n volume?: number;\n}\n\n/** One playing track: an `<audio>` element, routed through a gain when Web Audio is there. */\ninterface Track {\n url: string;\n el: HTMLAudioElement;\n gain: GainNode | null;\n level: number;\n /** Fade from `from` to `to` between `start` and `start + ms` (performance.now()). */\n fade: { from: number; to: number; start: number; ms: number };\n dying: boolean;\n}\n\n/**\n * Background music: one track at a time, crossfaded when it changes, looping, at `engineSettings.musicVolume`.\n * Tracks stream through `<audio>` elements (no decoding a whole song into memory). Where Web Audio exists their level\n * is a gain node, since iOS ignores an element's own `volume`.\n *\n * Browsers start sound only after a user gesture: `play` before one is remembered and starts on the first tap or key.\n *\n * ```ts\n * music.play('music/forest.ogg');\n * music.play('music/boss.ogg', { fadeMs: 600 }); // crossfades\n * music.stop(2000);\n * ```\n */\nexport class MusicPlayer {\n private ctx: AudioContext | null = null;\n private master: GainNode | null = null;\n private readonly tracks: Track[] = [];\n private raf = 0;\n private unlocked = false;\n private readonly cleanup: (() => void)[] = [];\n\n constructor() {\n if (typeof window === 'undefined') return;\n const unlock = () => {\n this.unlocked = true;\n void this.ctx?.resume();\n for (const t of this.tracks) if (!t.dying && t.el.paused) void t.el.play().catch(() => {});\n };\n for (const type of ['pointerdown', 'keydown', 'touchend'] as const) {\n window.addEventListener(type, unlock, { passive: true });\n this.cleanup.push(() => window.removeEventListener(type, unlock));\n }\n this.cleanup.push(engineSettings.subscribe(() => this.applyVolume()));\n }\n\n /** The url of the track playing (or fading in), if any. */\n get current(): string | null {\n for (let i = this.tracks.length - 1; i >= 0; i--) if (!this.tracks[i]!.dying) return this.tracks[i]!.url;\n return null;\n }\n\n /** Plays `url`, crossfading from what plays now. The track already playing is left alone. */\n play(url: string, options: PlayOptions = {}): void {\n if (typeof Audio === 'undefined') return;\n if (this.current === url) return;\n const fadeMs = Math.max(0, options.fadeMs ?? 1200);\n this.fadeOutAll(fadeMs);\n const el = new Audio(url);\n el.loop = options.loop !== false;\n el.preload = 'auto';\n el.crossOrigin = 'anonymous';\n const track: Track = { url, el, gain: null, level: Math.min(1, Math.max(0, options.volume ?? 1)), fade: { from: 0, to: 1, start: performance.now(), ms: fadeMs }, dying: false };\n const ctx = this.context();\n if (ctx && this.master) {\n const gain = ctx.createGain();\n gain.gain.value = 0;\n ctx.createMediaElementSource(el).connect(gain).connect(this.master);\n track.gain = gain;\n } else {\n el.volume = 0;\n }\n this.tracks.push(track);\n if (this.unlocked || !this.needsGesture()) void el.play().catch(() => {});\n this.tick();\n }\n\n /** Fades the music out and stops it. */\n stop(fadeMs = 1200): void {\n this.fadeOutAll(Math.max(0, fadeMs));\n this.tick();\n }\n\n pause(): void {\n for (const t of this.tracks) t.el.pause();\n }\n\n resume(): void {\n for (const t of this.tracks) if (!t.dying) void t.el.play().catch(() => {});\n }\n\n destroy(): void {\n cancelAnimationFrame(this.raf);\n for (const fn of this.cleanup.splice(0)) fn();\n for (const t of this.tracks.splice(0)) this.release(t);\n void this.ctx?.close();\n this.ctx = null;\n }\n\n private fadeOutAll(ms: number): void {\n const now = performance.now();\n for (const t of this.tracks) {\n if (t.dying) continue;\n t.fade = { from: fadeValue(t.fade, now), to: 0, start: now, ms };\n t.dying = true;\n }\n }\n\n /** Runs the fades a frame at a time until none is left. */\n private tick = (): void => {\n cancelAnimationFrame(this.raf);\n const now = performance.now();\n let busy = false;\n for (let i = this.tracks.length - 1; i >= 0; i--) {\n const t = this.tracks[i]!;\n const v = fadeValue(t.fade, now);\n if (t.dying && v <= 0) {\n this.release(t);\n this.tracks.splice(i, 1);\n continue;\n }\n this.setLevel(t, v);\n if (now < t.fade.start + t.fade.ms) busy = true;\n }\n if (busy) this.raf = requestAnimationFrame(this.tick);\n };\n\n private applyVolume(): void {\n const now = performance.now();\n for (const t of this.tracks) this.setLevel(t, fadeValue(t.fade, now));\n }\n\n private setLevel(t: Track, fade: number): void {\n const v = Math.min(1, Math.max(0, fade * t.level * engineSettings.getState().musicVolume));\n if (t.gain) t.gain.gain.value = v;\n else t.el.volume = v;\n }\n\n private release(t: Track): void {\n t.el.pause();\n t.el.removeAttribute('src');\n t.el.load();\n t.gain?.disconnect();\n }\n\n private needsGesture(): boolean {\n return this.ctx?.state === 'suspended';\n }\n\n private context(): AudioContext | null {\n if (this.ctx) return this.ctx;\n const Ctor = (globalThis as { AudioContext?: typeof AudioContext }).AudioContext;\n if (!Ctor) return null;\n this.ctx = new Ctor();\n this.master = this.ctx.createGain();\n this.master.connect(this.ctx.destination);\n return this.ctx;\n }\n}\n\n/** A fade's value at `now`: linear from `from` to `to` over `ms`. */\nexport function fadeValue(f: { from: number; to: number; start: number; ms: number }, now: number): number {\n if (f.ms <= 0 || now >= f.start + f.ms) return f.to;\n if (now <= f.start) return f.from;\n return f.from + ((f.to - f.from) * (now - f.start)) / f.ms;\n}\n\n/** The shared music player. */\nexport const music = new MusicPlayer();\n","/**\n * Which keys are held, by `KeyboardEvent.code` (the physical key, so WASD stays WASD on any layout). `pressed` and\n * `released` report edges since the last `endStep`; call that once per simulation step so a tap shorter than a frame\n * is still seen by exactly one step.\n */\nexport class Keyboard {\n private readonly held = new Set<string>();\n private readonly down = new Set<string>();\n private readonly up = new Set<string>();\n private readonly cleanup: (() => void)[] = [];\n\n constructor(target: Window | HTMLElement = window) {\n const keydown = (e: Event) => {\n const k = (e as KeyboardEvent).code;\n if ((e as KeyboardEvent).repeat || this.held.has(k)) return;\n this.held.add(k);\n this.down.add(k);\n };\n const keyup = (e: Event) => {\n const k = (e as KeyboardEvent).code;\n if (!this.held.delete(k)) return;\n this.up.add(k);\n };\n // a key held while the window loses focus never sends its keyup: let everything go\n const blur = () => {\n for (const k of this.held) this.up.add(k);\n this.held.clear();\n };\n target.addEventListener('keydown', keydown);\n target.addEventListener('keyup', keyup);\n window.addEventListener('blur', blur);\n this.cleanup.push(\n () => target.removeEventListener('keydown', keydown),\n () => target.removeEventListener('keyup', keyup),\n () => window.removeEventListener('blur', blur),\n );\n }\n\n isDown(code: string): boolean {\n return this.held.has(code);\n }\n\n /** Any of these keys is held. */\n anyDown(...codes: string[]): boolean {\n return codes.some((c) => this.held.has(c));\n }\n\n /** Went down since the last `endStep`. */\n pressed(code: string): boolean {\n return this.down.has(code);\n }\n\n /** Came up since the last `endStep`. */\n released(code: string): boolean {\n return this.up.has(code);\n }\n\n /** -1, 0 or 1 from two sets of keys: `axis(['KeyA', 'ArrowLeft'], ['KeyD', 'ArrowRight'])`. */\n axis(negative: string[], positive: string[]): number {\n return (this.anyDown(...positive) ? 1 : 0) - (this.anyDown(...negative) ? 1 : 0);\n }\n\n /** Forgets this step's edges; held keys stay held. */\n endStep(): void {\n this.down.clear();\n this.up.clear();\n }\n\n destroy(): void {\n for (const fn of this.cleanup.splice(0)) fn();\n this.held.clear();\n this.endStep();\n }\n}\n","import type { Keyboard } from './Keyboard';\n\n/**\n * Named actions bound to any input: keys, gamepad buttons and sticks, and virtual buttons a touch UI presses. Game\n * code asks for `'jump'`, never for `Space`, so players can rebind and every device works the same.\n *\n * ```ts\n * const input = new Actions(keyboard, {\n * left: ['KeyA', 'ArrowLeft', 'pad:left', 'pad:lx-'],\n * right: ['KeyD', 'ArrowRight', 'pad:right', 'pad:lx+'],\n * jump: ['Space', 'pad:a'],\n * });\n * // in a fixed system:\n * input.poll();\n * if (input.pressed('jump')) …\n * const [x, y] = input.vector('left', 'right', 'up', 'down');\n * input.endStep();\n * ```\n *\n * Bindings: a `KeyboardEvent.code` (`KeyW`, `Space`, `ArrowUp`), `pad:<button>` (standard mapping names below),\n * `pad:<axis>+` / `pad:<axis>-` for a stick half (`lx`, `ly`, `rx`, `ry`), or `touch:<name>` for a virtual button\n * (`press`/`release`).\n */\nexport type Bindings<A extends string> = Record<A, readonly string[]>;\n\n/** Button names of the browser's standard gamepad mapping, in index order. */\nexport const PAD_BUTTONS = ['a', 'b', 'x', 'y', 'lb', 'rb', 'lt', 'rt', 'select', 'start', 'ls', 'rs', 'up', 'down', 'left', 'right', 'home'] as const;\nconst PAD_AXES = ['lx', 'ly', 'rx', 'ry'] as const;\n\n/** What the actions read from a gamepad; `navigator.getGamepads()` entries satisfy it. */\nexport interface PadState {\n readonly buttons: readonly { readonly pressed: boolean; readonly value: number }[];\n readonly axes: readonly number[];\n}\n\nexport interface ActionsOptions {\n /** Stick values under this count as 0 (default 0.25). */\n deadZone?: number;\n /** Where gamepads come from (default `navigator.getGamepads`); tests pass their own. */\n gamepads?: () => readonly (PadState | null)[];\n}\n\nexport class Actions<A extends string> {\n private bindings: Map<A, readonly string[]>;\n private readonly virtual = new Set<string>();\n private readonly virtualDown = new Set<string>();\n /** Analog value of each action this step (0–1), and last step's, for edges. */\n private now = new Map<A, number>();\n private before = new Map<A, number>();\n private readonly deadZone: number;\n private readonly gamepads: () => readonly (PadState | null)[];\n\n constructor(\n private readonly keyboard: Keyboard | null,\n bindings: Bindings<A>,\n options: ActionsOptions = {},\n ) {\n this.bindings = new Map(Object.entries(bindings) as [A, readonly string[]][]);\n this.deadZone = options.deadZone ?? 0.25;\n this.gamepads =\n options.gamepads ?? (() => (typeof navigator !== 'undefined' && typeof navigator.getGamepads === 'function' ? navigator.getGamepads() : []));\n }\n\n /** Replaces one action's bindings (a player's rebinding). */\n bind(action: A, inputs: readonly string[]): void {\n this.bindings.set(action, [...inputs]);\n }\n\n bindingsOf(action: A): readonly string[] {\n return this.bindings.get(action) ?? [];\n }\n\n /** A touch UI's virtual button went down: `touch:<name>` bindings read it. */\n press(name: string): void {\n this.virtual.add(name);\n this.virtualDown.add(name);\n }\n\n release(name: string): void {\n this.virtual.delete(name);\n }\n\n /** Reads every device once; call at the start of each simulation step. */\n poll(): void {\n [this.before, this.now] = [this.now, this.before];\n this.now.clear();\n const pads = this.gamepads().filter((p): p is PadState => p !== null);\n for (const [action, inputs] of this.bindings) {\n let v = 0;\n for (const input of inputs) v = Math.max(v, this.read(input, pads));\n if (v > 0) this.now.set(action, v);\n }\n }\n\n /** Held this step. */\n down(action: A): boolean {\n return (this.now.get(action) ?? 0) > 0;\n }\n\n /** How far it is held (0–1): 1 for a key, the trigger or stick amount for analog input. */\n value(action: A): number {\n return this.now.get(action) ?? 0;\n }\n\n /** Went down this step. */\n pressed(action: A): boolean {\n return this.down(action) && !((this.before.get(action) ?? 0) > 0);\n }\n\n /** Came up this step. */\n released(action: A): boolean {\n return !this.down(action) && (this.before.get(action) ?? 0) > 0;\n }\n\n /** `value(positive) - value(negative)`, in −1…1. */\n axis(negative: A, positive: A): number {\n return this.value(positive) - this.value(negative);\n }\n\n /** A 2D direction from four actions, never longer than 1 (a diagonal is not faster). */\n vector(left: A, right: A, up: A, down: A): [number, number] {\n const x = this.axis(left, right);\n const y = this.axis(up, down);\n const len = Math.hypot(x, y);\n return len > 1 ? [x / len, y / len] : [x, y];\n }\n\n /** Ends the step: the keyboard forgets its edges; virtual taps shorter than a step have now been seen. */\n endStep(): void {\n this.keyboard?.endStep();\n this.virtualDown.clear();\n }\n\n private read(input: string, pads: readonly PadState[]): number {\n if (input.startsWith('touch:')) {\n const name = input.slice(6);\n return this.virtual.has(name) || this.virtualDown.has(name) ? 1 : 0;\n }\n if (input.startsWith('pad:')) {\n const what = input.slice(4);\n let v = 0;\n const sign = what.endsWith('+') ? 1 : what.endsWith('-') ? -1 : 0;\n if (sign !== 0) {\n const axis = PAD_AXES.indexOf(what.slice(0, -1) as (typeof PAD_AXES)[number]);\n if (axis < 0) return 0;\n for (const p of pads) {\n const raw = (p.axes[axis] ?? 0) * sign;\n if (raw > this.deadZone) v = Math.max(v, (raw - this.deadZone) / (1 - this.deadZone));\n }\n return Math.min(1, v);\n }\n const button = PAD_BUTTONS.indexOf(what as (typeof PAD_BUTTONS)[number]);\n if (button < 0) return 0;\n // a digital button reports value 1 when pressed; an analog trigger its depth (some pads report 0 for a press)\n for (const p of pads) {\n const b = p.buttons[button];\n if (b?.pressed) v = Math.max(v, b.value > 0 ? b.value : 1);\n }\n return Math.min(1, v);\n }\n return this.keyboard?.isDown(input) || this.keyboard?.pressed(input) ? 1 : 0;\n }\n}\n","/**\n * An aim turned into the eight-way axis the keyboard makes (each part -1, 0 or 1; `stepMover` scales a diagonal),\n * so a step sent along it is one a key could have sent. A part counts once the aim leans past 22.5° towards it.\n */\nexport function aimAxis(aim: number): { dx: number; dy: number } {\n const c = Math.cos(aim);\n const s = Math.sin(aim);\n const lean = Math.sin(Math.PI / 8);\n return { dx: Math.abs(c) > lean ? Math.sign(c) : 0, dy: Math.abs(s) > lean ? Math.sign(s) : 0 };\n}\n","/**\n * The virtual joystick's arithmetic, kept pure so it can be tested. The stick hands the game the **same** axis\n * the keyboard does — `stepMover` clamps every step to -1/0/1 on each axis (movement is eight-way, and the server\n * reads it the same way), so an analog stick would only be rounded there anyway. The rounding happens here instead,\n * by eight 45° sectors, so a thumb held a little off the horizontal walks straight rather than flickering between\n * east and north-east.\n */\n\n/** Below this share of the stick's radius the thumb is resting: no movement, and the aim falls back (touchAim.ts). */\nexport const STICK_DEAD_ZONE = 0.28;\n\nexport interface StickVector {\n x: number;\n y: number;\n}\n\n/** The thumb's offset from where the stick was planted, as a vector of length at most 1 (radius = full tilt). */\nexport function stickVector(dx: number, dy: number, radius: number): StickVector {\n if (radius <= 0) return { x: 0, y: 0 };\n const len = Math.hypot(dx, dy);\n if (len === 0) return { x: 0, y: 0 };\n const k = len > radius ? 1 / len : 1 / radius;\n return { x: dx * k, y: dy * k };\n}\n\n/** True when the stick is tilted past the dead zone. */\nexport function stickActive(v: StickVector, deadZone = STICK_DEAD_ZONE): boolean {\n return Math.hypot(v.x, v.y) >= deadZone;\n}\n\n/**\n * The keyboard-shaped axis for a stick vector: each of dx, dy is -1, 0 or 1 (screen y grows downward, as the\n * keyboard's \"down\" does), nothing inside the dead zone, and the nearest of the eight directions otherwise.\n */\nexport function stickToAxis(v: StickVector, deadZone = STICK_DEAD_ZONE): { dx: number; dy: number } {\n if (!stickActive(v, deadZone)) return { dx: 0, dy: 0 };\n const sector = Math.round(Math.atan2(v.y, v.x) / (Math.PI / 4));\n const angle = sector * (Math.PI / 4);\n const round = (n: number) => (Math.abs(n) < 1e-9 ? 0 : Math.sign(n));\n return { dx: round(Math.cos(angle)), dy: round(Math.sin(angle)) };\n}\n","/**\n * A long press, as pure timing so it can be tested: a finger that stays down `ms` without moving more than `slop`\n * CSS px fires once, where it went down. A second finger, a move past the slop or a lift before the time is up is\n * not a long press — a tap stays a tap. The caller owns the clock (`fire(now)` from a timer or a frame).\n */\nexport class LongPress {\n private finger: { id: number; x: number; y: number; at: number } | null = null;\n private done = false;\n\n constructor(\n readonly ms = 480,\n readonly slop = 10,\n ) {}\n\n down(id: number, x: number, y: number, now: number): void {\n // a second finger means a pinch or the other thumb, never a press on one body\n if (this.finger) {\n this.finger = null;\n this.done = true;\n return;\n }\n this.finger = { id, x, y, at: now };\n this.done = false;\n }\n\n move(id: number, x: number, y: number): void {\n const f = this.finger;\n if (f && f.id === id && Math.hypot(x - f.x, y - f.y) > this.slop) this.finger = null;\n }\n\n up(id: number): void {\n if (this.finger?.id === id) this.finger = null;\n if (!this.finger) this.done = false;\n }\n\n /** Where the press is, the first time this is asked at or after `ms`; null otherwise. */\n fire(now: number): { x: number; y: number } | null {\n const f = this.finger;\n if (!f || this.done || now - f.at < this.ms) return null;\n this.done = true;\n return { x: f.x, y: f.y };\n }\n}\n","import type { EntityUpdate } from './constants';\n\n/** Any snapshot whose `up` block travels as binary records; the rest is JSON. */\nexport interface SnapshotLike {\n up?: EntityUpdate[];\n}\n\n/**\n * Binary wire form of a snapshot's `up` block. A server in another language must write the same bytes.\n *\n * A snapshot that carries no updates is still one text frame of JSON. A snapshot that does is one **binary** WebSocket\n * frame, big-endian throughout:\n *\n * ```\n * u8 SNAP_FRAME_TAG\n * u32 L, the byte length of the JSON that follows\n * L UTF-8 JSON of the snapshot with `up` left out\n * n × UPDATE_RECORD_BYTES, one record per EntityUpdate, n = (frame length - 5 - L) / 16\n * ```\n *\n * One record (16 bytes), the `[id, x, y, aim, anim, hp, flags]` tuple:\n *\n * | off | type | field |\n * |-----|-------|------------------------------------------------------------------------------------|\n * | 0 | i32 | id |\n * | 4 | i16 | x in 1/UPDATE_POS_SCALE px, clamped to [-32768, 32767] (−4096 … 4095.875 px) |\n * | 6 | i16 | y, the same |\n * | 8 | u8 | aim in 1/UPDATE_AIM_STEPS of a turn, wrapped; read back in [-π, π) |\n * | 9 | u8 | anim (ANIM), clamped to 0..255 |\n * | 10 | i32 | hp (big bodies go past 65535) |\n * | 14 | u16 | flags (ENTITY_FLAG, nine bits used today), clamped to 0..65535 |\n *\n * Quantisation error: position ≤ 1/16 px, aim ≤ π/256 rad. The position range holds maps up to 4096 px a side.\n * Each record is written once per actor state version on the server and shared by every viewer.\n */\nexport const SNAP_FRAME_TAG = 1;\n/** Tag byte + the u32 JSON length. */\nexport const SNAP_FRAME_HEADER_BYTES = 5;\nexport const UPDATE_RECORD_BYTES = 16;\nexport const UPDATE_POS_SCALE = 8;\nexport const UPDATE_AIM_STEPS = 256;\n\nconst TURN = Math.PI * 2;\n\nfunction clampInt(v: number, lo: number, hi: number): number {\n if (!Number.isFinite(v)) return Number.isNaN(v) ? 0 : v > 0 ? hi : lo;\n const r = Math.round(v);\n return r < lo ? lo : r > hi ? hi : r;\n}\n\n/** World px → the i16 on the wire. */\nexport function quantizePos(v: number): number {\n return clampInt(v * UPDATE_POS_SCALE, -32768, 32767);\n}\n\n/** Radians → the u8 on the wire (wrapped, so any angle is accepted). */\nexport function quantizeAim(a: number): number {\n if (!Number.isFinite(a)) return 0;\n const s = Math.round((a * UPDATE_AIM_STEPS) / TURN);\n return ((s % UPDATE_AIM_STEPS) + UPDATE_AIM_STEPS) % UPDATE_AIM_STEPS;\n}\n\nexport function dequantizeAim(b: number): number {\n return ((b >= UPDATE_AIM_STEPS / 2 ? b - UPDATE_AIM_STEPS : b) * TURN) / UPDATE_AIM_STEPS;\n}\n\nexport function writeUpdate(view: DataView, off: number, u: EntityUpdate): void {\n view.setInt32(off, clampInt(u[0], -0x80000000, 0x7fffffff));\n view.setInt16(off + 4, quantizePos(u[1]));\n view.setInt16(off + 6, quantizePos(u[2]));\n view.setUint8(off + 8, quantizeAim(u[3]));\n view.setUint8(off + 9, clampInt(u[4], 0, 255));\n view.setInt32(off + 10, clampInt(u[5], -0x80000000, 0x7fffffff));\n view.setUint16(off + 14, clampInt(u[6], 0, 0xffff));\n}\n\nexport function readUpdate(view: DataView, off: number): EntityUpdate {\n return [\n view.getInt32(off),\n view.getInt16(off + 4) / UPDATE_POS_SCALE,\n view.getInt16(off + 6) / UPDATE_POS_SCALE,\n dequantizeAim(view.getUint8(off + 8)),\n view.getUint8(off + 9),\n view.getInt32(off + 10),\n view.getUint16(off + 14),\n ];\n}\n\nexport function encodeUpdates(ups: readonly EntityUpdate[]): Uint8Array {\n const out = new Uint8Array(ups.length * UPDATE_RECORD_BYTES);\n const view = new DataView(out.buffer);\n for (let i = 0; i < ups.length; i++) writeUpdate(view, i * UPDATE_RECORD_BYTES, ups[i]!);\n return out;\n}\n\nexport function decodeUpdates(bytes: Uint8Array): EntityUpdate[] {\n if (bytes.byteLength % UPDATE_RECORD_BYTES !== 0) throw new Error(`update block of ${bytes.byteLength} bytes`);\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const out: EntityUpdate[] = [];\n for (let off = 0; off < bytes.byteLength; off += UPDATE_RECORD_BYTES) out.push(readUpdate(view, off));\n return out;\n}\n\n/** The updates exactly as a client reads them off the wire: what a local simulation sends, so it quantises like the server. */\nexport function quantizeUpdates(ups: readonly EntityUpdate[]): EntityUpdate[] {\n // Same numbers as decodeUpdates(encodeUpdates(ups)) without the byte round trip (`+ 0` turns -0 into 0, as a read does).\n const out: EntityUpdate[] = new Array(ups.length);\n for (let i = 0; i < ups.length; i++) {\n const u = ups[i]!;\n out[i] = [\n clampInt(u[0], -0x80000000, 0x7fffffff) + 0,\n quantizePos(u[1]) / UPDATE_POS_SCALE + 0,\n quantizePos(u[2]) / UPDATE_POS_SCALE + 0,\n dequantizeAim(quantizeAim(u[3])),\n clampInt(u[4], 0, 255) + 0,\n clampInt(u[5], -0x80000000, 0x7fffffff) + 0,\n clampInt(u[6], 0, 0xffff) + 0,\n ];\n }\n return out;\n}\n\ninterface TextCodecs {\n TextEncoder: new () => { encode(s: string): Uint8Array };\n TextDecoder: new () => { decode(b: Uint8Array): string };\n}\n// the protocol builds without DOM types; browsers and Node both have these\nconst text = globalThis as unknown as TextCodecs;\nconst encoder = new text.TextEncoder();\nconst decoder = new text.TextDecoder();\n\n/** A snapshot as the server frames it: binary when it carries updates (see the layout above). */\nexport function encodeSnapshotFrame<S extends SnapshotLike>(snap: S): Uint8Array {\n const { up, ...rest } = snap;\n const json = encoder.encode(JSON.stringify(rest));\n const records = up?.length ? up.length : 0;\n const out = new Uint8Array(SNAP_FRAME_HEADER_BYTES + json.byteLength + records * UPDATE_RECORD_BYTES);\n const view = new DataView(out.buffer);\n view.setUint8(0, SNAP_FRAME_TAG);\n view.setUint32(1, json.byteLength);\n out.set(json, SNAP_FRAME_HEADER_BYTES);\n const base = SNAP_FRAME_HEADER_BYTES + json.byteLength;\n for (let i = 0; i < records; i++) writeUpdate(view, base + i * UPDATE_RECORD_BYTES, up![i]!);\n return out;\n}\n\n/** Reads a binary snapshot frame back into the same object a text frame parses to. */\nexport function decodeSnapshotFrame<S extends SnapshotLike>(frame: ArrayBuffer | Uint8Array): S {\n const bytes = frame instanceof Uint8Array ? frame : new Uint8Array(frame);\n if (bytes.byteLength < SNAP_FRAME_HEADER_BYTES) throw new Error('short snapshot frame');\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const tag = view.getUint8(0);\n if (tag !== SNAP_FRAME_TAG) throw new Error(`unknown binary frame tag ${tag}`);\n const len = view.getUint32(1);\n const base = SNAP_FRAME_HEADER_BYTES + len;\n if (base > bytes.byteLength) throw new Error('snapshot frame JSON overruns the frame');\n const snap = JSON.parse(decoder.decode(bytes.subarray(SNAP_FRAME_HEADER_BYTES, base))) as S;\n if (base < bytes.byteLength) snap.up = decodeUpdates(bytes.subarray(base));\n return snap;\n}\n","/**\n * Every repeated player action with a timer — the basic attack, a skill's cooldown, the cast and attack locks, a\n * potion — runs on a **schedule**, not on \"the last time plus some slack\". An action may arrive up to its slack\n * early (network jitter bunches packets), but the next one is then due a whole interval after the later of the\n * arrival and the time this one was due, so the slack never adds up: a client sending every 0.8 of an interval\n * lands at most one per interval (67 in 100), not 100. A server must run the same arithmetic.\n */\nexport const CADENCE = {\n /** A basic attack may arrive this share of its interval early. */\n attackEarlyShare: 0.2,\n /** The cast lock and the attack lock a cast leaves may be cut this short. */\n lockSlackMs: 60,\n /** A skill may be cast this long before its cooldown ends. */\n cooldownSlackMs: 40,\n /** A potion may be drunk this long before its kind's cooldown ends. */\n potionSlackMs: 150,\n} as const;\n\n/** Whether an action arriving at `now` is earlier than its slack allows; `due` undefined = never taken, due at once. */\nexport function cadenceEarly(now: number, due: number | undefined, slack: number): boolean {\n return due !== undefined && now < due - slack;\n}\n\n/** When the action after one accepted at `now` is due: a whole interval after the later of `now` and `due`. */\nexport function cadenceNext(now: number, due: number | undefined, interval: number): number {\n return Math.max(now, due ?? now) + interval;\n}\n","/*\n * The server's clock, as this client best knows it. Everything the game reckons from wall time — the time of day,\n * the weather, timetables, daily resets — reads `serverNow()` instead\n * of `Date.now()`, so a phone whose clock is a few minutes off still sees the sky and the resets everyone else sees.\n *\n * The offset comes from timed exchanges: every pong (the server's time when it answered, against the ping's own\n * round trip) and any request that returns the server's time. The sample with the shortest round trip wins, since its\n * midpoint is the tightest guess; a sample older than a minute gives way to the next one so a drifting clock is\n * followed. Until the first one lands this device's own clock stands in (a game clock counting from the server's start must never\n * seed this). An offline game is its own server, so there the offset is zero.\n */\n\n/** A timed sample this old gives way to a new one, even a slower one. */\nconst STALE_MS = 60_000;\n/** A sample whose round trip took longer than this says too little about when the server answered: it is passed over. */\nexport const MAX_SAMPLE_RTT_MS = 2000;\n\nlet offset = 0;\nlet bestRtt = Infinity;\nlet takenAt = 0;\nlet timed = false;\n\n/** Server wall time now, in ms since the epoch. */\nexport function serverNow(): number {\n return Date.now() + offset;\n}\n\n/** The current estimate of server time minus this device's time, in ms. */\nexport function serverOffset(): number {\n return offset;\n}\n\n/**\n * A server timestamp `serverMs` taken halfway through an exchange that took `rttMs` to come back: the server's clock\n * then stood at `serverMs + rttMs / 2` of this device's now.\n */\nexport function noteServerTime(serverMs: number, rttMs: number, now = Date.now()): void {\n if (!Number.isFinite(serverMs) || !Number.isFinite(rttMs) || rttMs < 0 || rttMs > MAX_SAMPLE_RTT_MS) return;\n if (timed && rttMs > bestRtt && now - takenAt < STALE_MS) return;\n offset = serverMs + rttMs / 2 - now;\n bestRtt = rttMs;\n takenAt = now;\n timed = true;\n}\n\n/** Back to this device's own clock (offline, or leaving a server). */\nexport function resetServerClock(): void {\n offset = 0;\n bestRtt = Infinity;\n takenAt = 0;\n timed = false;\n}\n","import type { EntityUpdate, InputStep } from './constants';\nimport type { MoverState } from './movement';\n\n/*\n * The engine's netcode messages. JSON, but for snapshots that carry body updates, which travel as one binary frame\n * (`encodeSnapshotFrame`). A game adds its own messages beside these: anything with a `t` the engine does not know\n * is handed to the game untouched.\n */\n\n/** Client → server. */\nexport type ClientMessage =\n /** Asks to join; `data` is the game's own (a name, a character). */\n | { t: 'hello'; data?: unknown }\n /** Input steps `seq`, `seq + 1`, … taken since the last send. */\n | { t: 'input'; seq: number; steps: InputStep[] }\n /** A ping carrying the client's own clock, answered by a pong. */\n | { t: 'ping'; c: number };\n\n/** Server → client. */\nexport type ServerMessage =\n | { t: 'welcome'; id: number; tick: number; stepRate: number; snapRate: number }\n | { t: 'pong'; c: number; st: number }\n | Snapshot;\n\n/** A body's whole mover, so a client can rewind to it exactly: x, y, lastDx, lastDy, dashLeft, dashCd, dashDx, dashDy. */\nexport type MoverWire = [number, number, number, number, number, number, number, number];\n\n/** A body coming into view: its id and the game's own description of it (what it looks like). */\nexport interface SpawnInfo {\n id: number;\n data?: unknown;\n}\n\nexport interface Snapshot {\n t: 'snap';\n /** The server's step count when it was taken. */\n tick: number;\n /** The server's wall time when it was taken (ms since the epoch), for interpolation. */\n time: number;\n /** The last input step of this client the server has applied (-1 before any). */\n ack: number;\n /** This client's own body, whole, as of `ack`. */\n me?: MoverWire;\n /** Bodies that came into view. */\n sp?: SpawnInfo[];\n /** Bodies that left view. */\n rm?: number[];\n /** Every body in view: [id, x, y, aim, anim, hp, flags]. */\n up?: EntityUpdate[];\n}\n\nexport function moverToWire(m: MoverState): MoverWire {\n return [m.x, m.y, m.lastDx, m.lastDy, m.dashLeft, m.dashCd, m.dashDx, m.dashDy];\n}\n\nexport function moverFromWire(w: MoverWire, into: MoverState): MoverState {\n [into.x, into.y, into.lastDx, into.lastDy, into.dashLeft, into.dashCd, into.dashDx, into.dashDy] = w;\n return into;\n}\n","import type { InputStep, MovementParams } from './constants';\nimport { createMover, stepMover, type CollisionGrid, type MoverState } from './movement';\nimport { moverFromWire, type MoverWire } from './protocol';\n\n/**\n * Client-side prediction for the local player's body. Every input step is applied at once (the player sees their\n * own move with no lag) and kept until the server acknowledges it. When a snapshot says where the server has the\n * body as of step `ack`, the body is put there and every step after `ack` is replayed on top.\n *\n * Movement is deterministic (`stepMover`), so with the same steps, params and grid the replay lands exactly where\n * the prediction was and nothing moves. When it does not (the server refused a step, a collision only it knew of),\n * the difference is `correction`: draw the body at `drawX/drawY`, which ease that jump out over a few frames instead\n * of snapping.\n */\nexport class PredictedMover {\n readonly mover: MoverState;\n private pending: { seq: number; step: InputStep }[] = [];\n private nextSeq = 0;\n /** The jump the last reconciliation made, still being eased out (world px). */\n private offsetX = 0;\n private offsetY = 0;\n /** How big the last correction was (0 when the prediction was right). */\n correction = 0;\n /** Share of a visual correction left after each 60th of a second (default 0.8). */\n smoothing = 0.8;\n\n constructor(\n x: number,\n y: number,\n private params: MovementParams,\n private grid: CollisionGrid,\n ) {\n this.mover = createMover(x, y);\n }\n\n /** Applies one input step now and keeps it for replay; returns its sequence number (send it with the step). */\n step(step: InputStep): number {\n const seq = this.nextSeq++;\n this.pending.push({ seq, step: [step[0], step[1], step[2]] });\n stepMover(this.mover, step, this.params, this.grid);\n return seq;\n }\n\n /** Steps sent but not yet acknowledged. */\n get unacknowledged(): number {\n return this.pending.length;\n }\n\n /** The server's word: the body as of step `ack`. Rewinds there and replays the rest. */\n reconcile(ack: number, server: MoverWire): void {\n const beforeX = this.mover.x;\n const beforeY = this.mover.y;\n let drop = 0;\n while (drop < this.pending.length && this.pending[drop]!.seq <= ack) drop++;\n if (drop) this.pending = this.pending.slice(drop);\n moverFromWire(server, this.mover);\n for (const p of this.pending) stepMover(this.mover, p.step, this.params, this.grid);\n const dx = beforeX - this.mover.x;\n const dy = beforeY - this.mover.y;\n this.correction = Math.hypot(dx, dy);\n // a correction this small is float noise; one this large is a teleport, shown at once\n if (this.correction > 0.01 && this.correction < 64) {\n this.offsetX += dx;\n this.offsetY += dy;\n } else if (this.correction >= 64) {\n this.offsetX = this.offsetY = 0;\n }\n }\n\n /** Eases the visual correction out; call once a frame with its length in seconds. */\n smooth(dt: number): void {\n const k = Math.pow(this.smoothing, dt * 60);\n this.offsetX *= k;\n this.offsetY *= k;\n if (Math.abs(this.offsetX) < 0.01) this.offsetX = 0;\n if (Math.abs(this.offsetY) < 0.01) this.offsetY = 0;\n }\n\n /** Where to draw the body: the predicted place plus the correction still being eased out. */\n get drawX(): number {\n return this.mover.x + this.offsetX;\n }\n\n get drawY(): number {\n return this.mover.y + this.offsetY;\n }\n\n /** New movement rules (a buff, a slow): applied to future steps and to replays. */\n setParams(params: MovementParams): void {\n this.params = params;\n }\n\n setGrid(grid: CollisionGrid): void {\n this.grid = grid;\n }\n}\n","import type { EntityUpdate } from './constants';\n\n/** One body's state at one server time. */\ninterface Sample {\n time: number;\n x: number;\n y: number;\n aim: number;\n anim: number;\n hp: number;\n flags: number;\n}\n\nexport interface InterpolatedState {\n x: number;\n y: number;\n aim: number;\n /** Discrete fields come from the older of the two samples until the newer one is reached. */\n anim: number;\n hp: number;\n flags: number;\n}\n\n/**\n * Smooth motion for bodies the server moves (other players, monsters): snapshots arrive 10–30 times a second and\n * jittered, so each body is drawn a little in the past (`delayMs`) between the two snapshots around that moment.\n * Past the newest snapshot it extrapolates for at most `maxExtrapolateMs`, then holds.\n *\n * Times are server times (`Snapshot.time`); render at `serverNow()`.\n */\nexport class InterpolationBuffer {\n private readonly samples = new Map<number, Sample[]>();\n\n constructor(\n /** How far in the past bodies are drawn (default 100 ms: two snapshots at 20 Hz, so one may be late). */\n readonly delayMs = 100,\n private readonly maxExtrapolateMs = 120,\n private readonly keep = 30,\n ) {}\n\n /** Records every body of a snapshot taken at `time`. */\n push(time: number, updates: readonly EntityUpdate[]): void {\n for (const [id, x, y, aim, anim, hp, flags] of updates) {\n let list = this.samples.get(id);\n if (!list) {\n list = [];\n this.samples.set(id, list);\n }\n const last = list[list.length - 1];\n // out of order or repeated: a newer sample is already here\n if (last && time <= last.time) continue;\n list.push({ time, x, y, aim, anim, hp, flags });\n if (list.length > this.keep) list.splice(0, list.length - this.keep);\n }\n }\n\n /** Forgets a body (it left view). */\n remove(id: number): void {\n this.samples.delete(id);\n }\n\n has(id: number): boolean {\n return this.samples.has(id);\n }\n\n ids(): IterableIterator<number> {\n return this.samples.keys();\n }\n\n /** Where body `id` should be drawn at server time `now`, or null if nothing is known of it. */\n sample(id: number, now: number): InterpolatedState | null {\n const list = this.samples.get(id);\n if (!list || list.length === 0) return null;\n const t = now - this.delayMs;\n const first = list[0]!;\n if (t <= first.time || list.length === 1) return pick(first);\n for (let i = list.length - 1; i > 0; i--) {\n const a = list[i - 1]!;\n const b = list[i]!;\n if (t >= a.time && t <= b.time) {\n const k = b.time === a.time ? 1 : (t - a.time) / (b.time - a.time);\n return blend(a, b, k);\n }\n }\n // newer than every sample: carry on along the last motion, for a short while only\n const a = list[list.length - 2]!;\n const b = list[list.length - 1]!;\n const over = Math.min(t - b.time, this.maxExtrapolateMs);\n const k = b.time === a.time ? 1 : 1 + over / (b.time - a.time);\n return blend(a, b, k);\n }\n}\n\nfunction pick(s: Sample): InterpolatedState {\n return { x: s.x, y: s.y, aim: s.aim, anim: s.anim, hp: s.hp, flags: s.flags };\n}\n\nfunction blend(a: Sample, b: Sample, k: number): InterpolatedState {\n let d = b.aim - a.aim;\n if (d > Math.PI) d -= Math.PI * 2;\n if (d < -Math.PI) d += Math.PI * 2;\n const older = k < 1 ? a : b;\n return { x: a.x + (b.x - a.x) * k, y: a.y + (b.y - a.y) * k, aim: a.aim + d * k, anim: older.anim, hp: older.hp, flags: older.flags };\n}\n","import type { EntityUpdate, InputStep, MovementParams } from './constants';\nimport { createMover, stepMover, type CollisionGrid, type MoverState } from './movement';\nimport { moverToWire, type Snapshot } from './protocol';\n\nexport interface RoomPlayer<D = unknown> {\n readonly id: number;\n readonly mover: MoverState;\n /** The game's own data for this player (sent to others in `sp` when they first see it). */\n data: D;\n params: MovementParams;\n /** The last input step applied (-1 before any): what snapshots acknowledge. */\n ack: number;\n /** Steps received and not yet applied. */\n readonly queue: InputStep[];\n /** What the snapshot's update record carries beside the position; the game sets them. */\n aim: number;\n anim: number;\n hp: number;\n flags: number;\n /** Refused inputs (nonsense numbers, a flood): a game may kick past some count. */\n strikes: number;\n}\n\nexport interface RoomOptions<D> {\n grid: CollisionGrid;\n /** Movement rules a new player starts with. */\n params: MovementParams;\n /** Where a player who joins stands. */\n spawn: (id: number, data: D) => { x: number; y: number };\n /** Steps a player may have waiting before more are refused (default 30: half a second at 60). */\n maxQueue?: number;\n /** A player with more than `backlog` waiting catches up by running up to `maxStepsPerTick` a tick (default 3, 4). */\n maxStepsPerTick?: number;\n backlog?: number;\n /** Called after each step a player takes (set aim, anim, flags from it). */\n onStep?: (player: RoomPlayer<D>, step: InputStep) => void;\n}\n\n/**\n * An authoritative room for a server: players send input steps, the room applies them with the same `stepMover` the\n * clients predict with, and builds each player a snapshot of everyone (with their own body whole, so their\n * prediction can rewind to it). Transport-free: wire `input`, `step` and `snapshotFor` to any socket library.\n *\n * Every step a player sends is applied once, in order; a client cannot move faster by sending more (the queue is\n * capped and drained at most `maxStepsPerTick` a tick), and nonsense input is refused and counted.\n */\nexport class Room<D = unknown> {\n readonly players = new Map<number, RoomPlayer<D>>();\n tick = 0;\n private readonly known = new Map<number, Set<number>>();\n private readonly maxQueue: number;\n private readonly maxSteps: number;\n private readonly backlog: number;\n\n constructor(private readonly options: RoomOptions<D>) {\n this.maxQueue = options.maxQueue ?? 30;\n this.maxSteps = options.maxStepsPerTick ?? 3;\n this.backlog = options.backlog ?? 4;\n }\n\n join(id: number, data: D): RoomPlayer<D> {\n if (this.players.has(id)) throw new Error(`Room: player ${id} has already joined`);\n const at = this.options.spawn(id, data);\n const player: RoomPlayer<D> = {\n id,\n mover: createMover(at.x, at.y),\n data,\n params: { ...this.options.params },\n ack: -1,\n queue: [],\n aim: 0,\n anim: 0,\n hp: 0,\n flags: 0,\n strikes: 0,\n };\n this.players.set(id, player);\n this.known.set(id, new Set());\n return player;\n }\n\n leave(id: number): void {\n this.players.delete(id);\n this.known.delete(id);\n }\n\n /**\n * Input steps `seq`, `seq + 1`, … from a player. Steps already received are skipped (a resend), any step with\n * numbers no client sends refuses the whole message, and steps past a full queue are dropped. Returns false when\n * something was refused.\n */\n input(id: number, seq: number, steps: readonly InputStep[]): boolean {\n const p = this.players.get(id);\n if (!p) return false;\n if (!Number.isInteger(seq) || seq < 0 || !Array.isArray(steps) || steps.length > this.maxQueue) {\n p.strikes++;\n return false;\n }\n for (const s of steps) {\n if (!Array.isArray(s) || s.length !== 3 || !s.every((v) => Number.isFinite(v)) || Math.abs(s[0]) > 1 || Math.abs(s[1]) > 1 || !Number.isInteger(s[2])) {\n p.strikes++;\n return false;\n }\n }\n const next = p.ack + 1 + p.queue.length;\n // a gap (steps this room refused earlier) is filled with standing still, so sequence numbers stay the client's\n const gap = seq - next;\n if (gap > this.maxQueue) {\n p.strikes++;\n return false;\n }\n for (let i = 0; i < gap; i++) p.queue.push([0, 0, 0]);\n let ok = true;\n for (let i = 0; i < steps.length; i++) {\n if (seq + i < next) continue; // already have it: a resend\n if (p.queue.length >= this.maxQueue) {\n ok = false;\n p.strikes++;\n break;\n }\n p.queue.push([steps[i]![0], steps[i]![1], steps[i]![2]]);\n }\n return ok;\n }\n\n /** One simulation step for everyone. */\n step(): void {\n this.tick++;\n for (const p of this.players.values()) {\n const waiting = p.queue.length;\n if (waiting === 0) continue;\n const n = waiting > this.backlog ? Math.min(this.maxSteps, waiting - this.backlog + 1) : 1;\n for (let i = 0; i < n; i++) {\n const s = p.queue.shift()!;\n stepMover(p.mover, s, p.params, this.options.grid);\n p.ack++;\n this.options.onStep?.(p, s);\n }\n }\n }\n\n /** The snapshot player `id` should get now. `time` is the server's wall clock (ms). */\n snapshotFor(id: number, time: number): Snapshot | null {\n const me = this.players.get(id);\n const known = this.known.get(id);\n if (!me || !known) return null;\n const up: EntityUpdate[] = [];\n const sp: { id: number; data?: unknown }[] = [];\n const seen = new Set<number>();\n for (const p of this.players.values()) {\n seen.add(p.id);\n up.push([p.id, p.mover.x, p.mover.y, p.aim, p.anim, p.hp, p.flags]);\n if (!known.has(p.id)) {\n known.add(p.id);\n sp.push({ id: p.id, data: p.data });\n }\n }\n const rm: number[] = [];\n for (const k of known) {\n if (!seen.has(k)) {\n known.delete(k);\n rm.push(k);\n }\n }\n const snap: Snapshot = { t: 'snap', tick: this.tick, time, ack: me.ack, me: moverToWire(me.mover), up };\n if (sp.length) snap.sp = sp;\n if (rm.length) snap.rm = rm;\n return snap;\n }\n}\n","import type { Room } from './Room';\nimport { encodeSnapshotFrame } from './snapshotCodec';\nimport type { ClientMessage, ServerMessage, Snapshot } from './protocol';\n\n/** The least a server socket must do; a `ws` WebSocket, a uWebSockets one or a test double all fit. */\nexport interface HostSocket {\n send(data: string | Uint8Array): void;\n close(code?: number, reason?: string): void;\n}\n\nexport interface RoomHostOptions<D> {\n /** Simulation steps a second (default 60) and snapshots a second (default 20). */\n stepRate?: number;\n snapRate?: number;\n /** Turns a hello's data into the player's data (validate it here); throw to refuse the player. */\n admit?: (data: unknown, id: number) => D;\n /** Refused inputs before the player is disconnected (default 20). */\n maxStrikes?: number;\n /** The game's own messages (anything the engine does not handle). */\n onMessage?: (id: number, msg: { t: string; [k: string]: unknown }) => void;\n /** Called when a player joins or leaves. */\n onJoin?: (id: number) => void;\n onLeave?: (id: number) => void;\n /** Wall clock, for tests (default Date.now). */\n now?: () => number;\n}\n\n/**\n * Runs a `Room` for connected sockets: a socket says hello and joins, its input goes to the room, the room steps at\n * `stepRate`, and every player gets its own snapshot at `snapRate` (binary when it carries bodies). Pings are\n * answered with the server's time. A player who keeps sending nonsense is disconnected.\n *\n * ```ts\n * const host = new RoomHost(room);\n * wss.on('connection', (ws) => {\n * const id = host.connect(ws);\n * ws.on('message', (data, binary) => host.message(id, binary ? data : data.toString()));\n * ws.on('close', () => host.disconnect(id));\n * });\n * host.start();\n * ```\n */\nexport class RoomHost<D = unknown> {\n private readonly sockets = new Map<number, HostSocket>();\n private readonly joined = new Set<number>();\n private nextId = 1;\n private stepTimer: ReturnType<typeof setInterval> | null = null;\n private lastStepAt = 0;\n private stepsDue = 0;\n private readonly stepMs: number;\n private readonly snapEvery: number;\n private readonly now: () => number;\n\n constructor(\n readonly room: Room<D>,\n private readonly options: RoomHostOptions<D> = {},\n ) {\n this.stepMs = 1000 / (options.stepRate ?? 60);\n this.snapEvery = Math.max(1, Math.round((options.stepRate ?? 60) / (options.snapRate ?? 20)));\n this.now = options.now ?? Date.now;\n }\n\n /** A socket connected; returns the id its messages and its close are reported under. */\n connect(socket: HostSocket): number {\n const id = this.nextId++;\n this.sockets.set(id, socket);\n return id;\n }\n\n /** A message arrived from socket `id` (text as a string, binary as bytes). */\n message(id: number, data: string | ArrayBuffer | Uint8Array): void {\n if (typeof data !== 'string') return; // clients send JSON only\n let msg: ClientMessage | { t: string; [k: string]: unknown };\n try {\n msg = JSON.parse(data);\n } catch {\n return this.strike(id);\n }\n if (!msg || typeof msg !== 'object' || typeof msg.t !== 'string') return this.strike(id);\n switch (msg.t) {\n case 'hello': {\n if (this.joined.has(id)) return;\n let data: D;\n try {\n data = this.options.admit ? this.options.admit((msg as { data?: unknown }).data, id) : ((msg as { data?: unknown }).data as D);\n } catch (err) {\n this.sockets.get(id)?.close(4003, err instanceof Error ? err.message : 'refused');\n return;\n }\n this.room.join(id, data);\n this.joined.add(id);\n this.sendTo(id, { t: 'welcome', id, tick: this.room.tick, stepRate: 1000 / this.stepMs, snapRate: (1000 / this.stepMs) / this.snapEvery });\n this.options.onJoin?.(id);\n return;\n }\n case 'input': {\n const m = msg as Extract<ClientMessage, { t: 'input' }>;\n if (!this.joined.has(id)) return;\n if (!this.room.input(id, m.seq, m.steps)) this.checkStrikes(id);\n return;\n }\n case 'ping': {\n const c = (msg as { c?: unknown }).c;\n if (typeof c === 'number' && Number.isFinite(c)) this.sendTo(id, { t: 'pong', c, st: this.now() });\n return;\n }\n default:\n if (this.joined.has(id)) this.options.onMessage?.(id, msg as { t: string; [k: string]: unknown });\n }\n }\n\n /** Socket `id` closed. */\n disconnect(id: number): void {\n this.sockets.delete(id);\n if (this.joined.delete(id)) {\n this.room.leave(id);\n this.options.onLeave?.(id);\n }\n }\n\n /** Sends one of the game's own messages to a player. */\n sendTo(id: number, msg: ServerMessage | { t: string; [k: string]: unknown }): void {\n const s = this.sockets.get(id);\n if (!s) return;\n if ((msg as Snapshot).t === 'snap' && (msg as Snapshot).up?.length) s.send(encodeSnapshotFrame(msg as Snapshot));\n else s.send(JSON.stringify(msg));\n }\n\n /** Starts stepping on a timer. Steps are counted by the clock, so a late timer runs the steps it owes. */\n start(): void {\n if (this.stepTimer) return;\n this.lastStepAt = this.now();\n this.stepTimer = setInterval(() => {\n const now = this.now();\n this.stepsDue += (now - this.lastStepAt) / this.stepMs;\n this.lastStepAt = now;\n // a stall longer than a second is not caught up: the room just carries on\n this.stepsDue = Math.min(this.stepsDue, 60);\n while (this.stepsDue >= 1) {\n this.stepsDue--;\n this.stepOnce();\n }\n }, this.stepMs / 2);\n }\n\n stop(): void {\n if (this.stepTimer) clearInterval(this.stepTimer);\n this.stepTimer = null;\n }\n\n /** One step, and the snapshots when they are due. Exposed for tests and for servers that drive their own loop. */\n stepOnce(): void {\n this.room.step();\n if (this.room.tick % this.snapEvery !== 0) return;\n const now = this.now();\n for (const id of this.joined) {\n const snap = this.room.snapshotFor(id, now);\n if (snap) this.sendTo(id, snap);\n }\n }\n\n private strike(id: number): void {\n const p = this.room.players.get(id);\n if (p) {\n p.strikes++;\n this.checkStrikes(id);\n }\n }\n\n private checkStrikes(id: number): void {\n const p = this.room.players.get(id);\n if (p && p.strikes >= (this.options.maxStrikes ?? 20)) {\n this.sockets.get(id)?.close(4008, 'too much invalid input');\n this.disconnect(id);\n }\n }\n}\n","import { EventBus } from '../events/EventBus';\nimport type { InputStep } from './constants';\nimport { noteServerTime } from './serverClock';\nimport { decodeSnapshotFrame } from './snapshotCodec';\nimport type { ClientMessage, ServerMessage, Snapshot } from './protocol';\n\nexport interface ConnectionEvents {\n open: undefined;\n /** The socket closed; `willRetry` when it will reconnect by itself. */\n close: { code: number; reason: string; willRetry: boolean };\n welcome: Extract<ServerMessage, { t: 'welcome' }>;\n snapshot: Snapshot;\n /** Any message the engine does not handle: the game's own. */\n message: { t: string; [k: string]: unknown };\n}\n\nexport interface ConnectionOptions {\n /** Reconnect after the socket drops (default true), waiting longer each time up to `maxBackoffMs`. */\n reconnect?: boolean;\n maxBackoffMs?: number;\n /** Ping interval for the server clock and the round-trip time (default 1000 ms). */\n pingMs?: number;\n /** Sent on every (re)connect as `hello.data`. */\n hello?: () => unknown;\n /** The WebSocket class (default the global one; Node 22+ and browsers have it). */\n WebSocket?: typeof WebSocket;\n}\n\n/**\n * The client side of the engine's netcode over a WebSocket: hello on open, input steps batched and sent once a frame\n * (`queueInput` then `flush`), snapshots decoded (binary or JSON) onto `events`, pings that keep the server clock\n * (`serverNow`) and `rtt` up to date, and reconnection with backoff.\n */\nexport class Connection {\n readonly events = new EventBus<ConnectionEvents>();\n /** The last measured round trip, ms. */\n rtt = 0;\n private socket: WebSocket | null = null;\n private batch: { seq: number; steps: InputStep[] } | null = null;\n private closedByUs = false;\n private attempt = 0;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private retryTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n readonly url: string,\n private readonly options: ConnectionOptions = {},\n ) {}\n\n get open(): boolean {\n return this.socket?.readyState === 1;\n }\n\n connect(): this {\n this.closedByUs = false;\n const Impl = this.options.WebSocket ?? globalThis.WebSocket;\n if (!Impl) throw new Error('Connection: no WebSocket in this environment');\n const ws = new Impl(this.url);\n ws.binaryType = 'arraybuffer';\n this.socket = ws;\n ws.onopen = () => {\n this.attempt = 0;\n this.send({ t: 'hello', data: this.options.hello?.() });\n this.ping();\n this.pingTimer = setInterval(() => this.ping(), this.options.pingMs ?? 1000);\n this.events.emit('open', undefined);\n };\n ws.onmessage = (e) => this.receive(e.data);\n ws.onclose = (e) => {\n if (this.pingTimer) clearInterval(this.pingTimer);\n this.pingTimer = null;\n this.socket = null;\n const willRetry = !this.closedByUs && this.options.reconnect !== false;\n this.events.emit('close', { code: e.code, reason: e.reason, willRetry });\n if (willRetry) {\n const wait = Math.min(this.options.maxBackoffMs ?? 10_000, 250 * 2 ** this.attempt++);\n this.retryTimer = setTimeout(() => this.connect(), wait);\n }\n };\n return this;\n }\n\n /** Sends a message now (dropped while closed: input is resent by the prediction's own state, not by the socket). */\n send(msg: ClientMessage | { t: string; [k: string]: unknown }): void {\n if (this.socket?.readyState === 1) this.socket.send(JSON.stringify(msg));\n }\n\n /** Adds one input step to this frame's batch; `flush` sends it. Steps must come in sequence order. */\n queueInput(seq: number, step: InputStep): void {\n if (!this.batch) this.batch = { seq, steps: [] };\n this.batch.steps.push([step[0], step[1], step[2]]);\n }\n\n /** Sends this frame's input steps as one message. Call once a frame. */\n flush(): void {\n if (!this.batch) return;\n this.send({ t: 'input', seq: this.batch.seq, steps: this.batch.steps });\n this.batch = null;\n }\n\n close(): void {\n this.closedByUs = true;\n if (this.retryTimer) clearTimeout(this.retryTimer);\n if (this.pingTimer) clearInterval(this.pingTimer);\n this.socket?.close();\n this.socket = null;\n }\n\n private ping(): void {\n this.send({ t: 'ping', c: Date.now() });\n }\n\n private receive(data: unknown): void {\n let msg: ServerMessage | { t: string; [k: string]: unknown };\n try {\n msg = typeof data === 'string' ? JSON.parse(data) : (decodeSnapshotFrame<Snapshot>(data as ArrayBuffer) as Snapshot);\n } catch (err) {\n console.error('[net] could not read a message', err);\n return;\n }\n switch (msg.t) {\n case 'pong': {\n const m = msg as Extract<ServerMessage, { t: 'pong' }>;\n this.rtt = Date.now() - m.c;\n noteServerTime(m.st, this.rtt);\n return;\n }\n case 'welcome':\n this.events.emit('welcome', msg as Extract<ServerMessage, { t: 'welcome' }>);\n return;\n case 'snap':\n this.events.emit('snapshot', msg as Snapshot);\n return;\n default:\n this.events.emit('message', msg as { t: string; [k: string]: unknown });\n }\n }\n}\n"],"names":["Rectangle","GameObject","Container","w","h","color","fillAlpha","PixiGraphics","x","y","alpha","Camera","world","screen","width","height","z","v","k","ms","intensity","angle","now","layer","r","g","b","_force","peak","target","options","dtMs","t","o","vw","vh","cx","cy","tx","ty","hx","hy","dx","dy","ox","oy","swing","sx","sy","f","Clock","fn","due","err","INSTALLED","CHARS","addLabelGlyphs","letters","PAGE_SIZE","installLabelFont","fontFamily","size","stroke","strokeWidth","resolution","name","defaults","DynamicBitmapFont","was","BitmapFont","BitmapLabel","BitmapText","text","Group","child","c","index","destroy","other","Image","Sprite","registry","key","frame","Text","PixiText","style","pixiStyle","ObjectFactory","stage","src","textures","img","opts","Graphics","children","obj","buttonBit","button","Pointer","canvas","fingers","isTouchUi","on","type","handler","e","cam","linear","EASES","u","easeByName","RESERVED","Tween","cfg","ends","ts","dt","delay","prop","to","read","duration","hold","cycle","local","repeat","finished","p","write","value","Tweener","starts","range","targets","tween","set","scaled","list","kept","i","stepSafely","Stage","app","delta","step","fallback","CanvasTexture","CanvasSource","Texture","_source","from","TextureRegistry","copy","into","tex","ctx","cols","rows","what","EventBus","onError","off","payload","left","FixedLoop","hz","deltaMs","ran","SceneManager","engine","scene","job","run","EngineStage","tick","Engine","where","error","pixel","TextureSource","patchPixi","Application","fill","report","s","SparseSet","d","entity","indexOf","last","moved","n","next","CTORS","isFields","growColumns","spec","old","out","kind","col","prev","nextComponentId","defineComponent","defineFields","fields","system","phase","INDEX_BITS","INDEX_MASK","MAX_GENERATION","entityIndex","World","components","store","values","args","types","sets","lead","smallest","row","all","EMPTY_SLOTS","cached","full","slots","have","pending","Scene","_dt","_alpha","ATLAS_PAD","MIN_ATLAS_WIDTH","ATLAS_PAGE_FULL","ATLAS_PAGE_SMALL","atlasPageLimit","maxTextureSize","planAtlas","sizes","limit","order","_","a","area","sum","widest","places","pages","page","shelf","pageWidth","close","AtlasBuilder","frameWidth","frameHeight","items","plan","it","at","first","texOf","add","FLIP_H","FLIP_V","FLIP_D","GID_MASK","gidOf","raw","tileAt","map","gid","found","tileRect","layerByName","l","objectsOf","TiledError","message","props","num","decodeBase64","bin","layerData","cells","data","bytes","view","parseObject","parseLayers","parent","visible","opacity","offsetX","offsetY","parseTileset","tileProperties","animations","tile","id","parseTiled","json","m","layers","resolveUrl","url","base","parts","defaultToCanvas","blob","bitmap","AssetLoader","textureKey","onProgress","worker","res","Animator","clips","initial","clip","restart","before","len","SpriteComponent","AnimationComponent","animationSystem","_e","sprite","anim","DIAGONAL","createCollisionGrid","tileSize","solid","ground","over","shotOver","bodyHalfWidth","BODY_HALF_WIDTH","bodyHalfHeight","BODY_HALF_HEIGHT","blocksShot","grid","isSolidTile","createMover","bodyCollides","x0","x1","y0","y1","moveX","nx","COLLISION_EPSILON","moveY","ny","clampAxis","stepMover","rolling","mx","my","INPUT_FLAG_DASH","vx","vy","INPUT_STEP_DT","collisionFromTiled","rule","_rule","gridOptions","nextView","TilemapView","textureFor","chunk","wanted","depth","holder","cw","ch","margin","tw","th","any","pad","RAD","DOWN","chain","root","limb","a1","l1","a2","l2","upper","lower","mid","Skeleton","def","pose","bulky","wide","chest","shoulderF","shoulderB","hipF","hipB","elbowF","wristF","forearm","elbowB","wristB","kneeF","ankleF","kneeB","ankleB","head","shoulder","elbow","wrist","HUMANOID_RIG","lerp","lerpDeg","lerpLimb","lerpOpt","blendPose","overlay","top","upperOver","action","legs","HUMANOID_POSES","poses","seq","prefix","HUMANOID_CLIPS","PosePlayer","library","fadeMs","total","keys","RIG_PARTS","DEFAULT_COLORS","BACK","BONES","shadeOf","RigView","skin","body","part","dir","j","outline","gradient","falloff","LightLayer","RenderTexture","light","darkness","used","wobble","hole","wash","hitStopMs","share","crit","recoilPx","heavy","RECOIL_MS","recoilAt","px","HEAVY_FLASH_GAP_MS","hurtFlashMs","impact","reduce","hurtFlashGapMs","inView","FLOOR","EMPTY","LOUDNESS","PEAK","LEAD","TAIL_FADE","cleanSamples","channels","sampleRate","k0","mono","floor","start","end","power","rms","fade","TAKES","registerTakes","urls","path","hasTakes","SampleBank","urlsOf","buf","clean","nextId","waiting","cleaner","done","turn","resolve","send","SOUNDS","registerSounds","table","SYNTH_RATE","WAVES","duty","sweep","onePole","cut","renderRecipe","recipe","seed","rand","held","lpState","hpState","freq","env","HEARING","MAX_VOICES","MINOR_VOICES","MIN_GAP_MS","OTHERS","DEFAULT_JITTER","CUT_FADE_MS","MUFFLE","TAME_SHELF","TAME_TOP","SoundEngine","unlock","blank","listen","running","session","engineSettings","gain","pan","far","me","hearing","take","buffer","jitter","lp","lasts","volume","changed","todo","sound","MusicPlayer","el","track","fadeValue","busy","Ctor","music","Keyboard","keydown","keyup","blur","code","codes","negative","positive","PAD_BUTTONS","PAD_AXES","Actions","keyboard","bindings","inputs","pads","input","right","up","down","sign","axis","aimAxis","aim","lean","STICK_DEAD_ZONE","stickVector","radius","stickActive","deadZone","stickToAxis","round","LongPress","slop","SNAP_FRAME_TAG","SNAP_FRAME_HEADER_BYTES","UPDATE_RECORD_BYTES","UPDATE_POS_SCALE","UPDATE_AIM_STEPS","TURN","clampInt","lo","hi","quantizePos","quantizeAim","dequantizeAim","writeUpdate","readUpdate","encodeUpdates","ups","decodeUpdates","quantizeUpdates","encoder","decoder","encodeSnapshotFrame","snap","rest","records","decodeSnapshotFrame","tag","CADENCE","cadenceEarly","slack","cadenceNext","interval","STALE_MS","MAX_SAMPLE_RTT_MS","offset","bestRtt","takenAt","timed","serverNow","serverOffset","noteServerTime","serverMs","rttMs","resetServerClock","moverToWire","moverFromWire","PredictedMover","params","ack","server","beforeX","beforeY","drop","InterpolationBuffer","delayMs","maxExtrapolateMs","keep","time","updates","hp","flags","pick","blend","older","Room","player","steps","gap","ok","known","sp","seen","rm","RoomHost","room","socket","msg","Connection","Impl","ws","willRetry","wait"],"mappings":"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"}
|