// Headless harness: stubs Phaser just enough to load the real game modules // (Mining, AsteroidCluster, Ship, Config, Color) and exercise the ore logic. class GameObject { constructor(scene, x = 0, y = 0) { this.scene = scene; this.x = x; this.y = y; this.rotation = 0; this.alpha = 1; this.scale = 1; this.active = true; this.children = []; } add(obj) { this.children.push(obj); return this; } remove(obj) { this.children = this.children.filter((c) => c !== obj); return this; } setOrigin() { return this; } setScrollFactor() { return this; } setDepth() { return this; } setAlpha(a) { this.alpha = a; return this; } setScale(v) { this.scale = v; return this; } setTint(t) { this.tint = t; return this; } setBlendMode() { return this; } setPosition(x, y) { this.x = x; this.y = y; return this; } setStrokeStyle() { return this; } destroy() { this.active = false; this.destroyed = true; } } const Container = class extends GameObject {}; const Sprite = class extends GameObject { constructor(scene, x, y, key, frame) { super(scene, x, y); this.key = key; this.frame = frame; this.body = null; } }; function hexToRgbInt(v) { const m = String(v).trim().match(/^#?([0-9a-f]{6})$/i); return m ? parseInt(m[1], 16) : 0xffffff; } // --- Filter plumbing (js/visuals/SystemEffects.js) ----------------------- // The stub mirrors the two base classes the custom filter extends, with // just enough surface for the facade logic (apply/release/update) to run: // a controller that carries shader state, and a node that records the // uniforms setupUniforms() pushes. class Controller { constructor(camera, renderNode) { this.active = true; this.camera = camera; this.renderNode = renderNode; this.paddingOverride = null; this.ignoreDestroy = false; } setPaddingOverride(x, y, r, b) { this.paddingOverride = { x, y, width: r - x, height: b - y }; return this; } getPaddingCeil() { const p = this.paddingOverride ?? { x: 0, y: 0, width: 0, height: 0 }; return { x: Math.ceil(p.x), y: Math.ceil(p.y), width: Math.ceil(p.width), height: Math.ceil(p.height) }; } setActive(v) { this.active = v; return this; } destroy() { this.active = false; } } class BaseFilterShader { constructor(name, manager, _shaderKey, fragmentSource, _additions) { this.name = name; this.manager = manager; this.fragmentSource = Array.isArray(fragmentSource) ? fragmentSource.join('\n') : String(fragmentSource ?? ''); this.uniforms = {}; this.programManager = { setUniform: (nm, val) => { this.uniforms[nm] = val; }, }; } setupUniforms(_controller, _ctx) {} } export { Controller, BaseFilterShader }; export default { GameObjects: { Container, Sprite }, Physics: { Arcade: { Sprite } }, Display: { Color: { ValueToColor: (v) => ({ color: hexToRgbInt(v) }) } }, Filters: { Controller }, Renderer: { WebGL: { RenderNodes: { BaseFilterShader } } }, Math: { Clamp: (v, a, b) => Math.min(b, Math.max(a, v)), Linear: (a, b, t) => a + (b - a) * t, Angle: { Wrap: (a) => a, RotateTo: (c, w, s) => (Math.abs(w - c) <= s ? w : c + Math.sign(w - c) * s), }, }, BlendModes: { ADD: 'ADD' }, };