quake2ts 0.0.582 → 0.0.584

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.
@@ -56,7 +56,6 @@ __export(index_exports, {
56
56
  createMockAI: () => createMockAI,
57
57
  createMockAmmoItem: () => createMockAmmoItem,
58
58
  createMockArmorItem: () => createMockArmorItem,
59
- createMockAudioContext: () => createMockAudioContext,
60
59
  createMockCamera: () => createMockCamera,
61
60
  createMockCanvas: () => createMockCanvas,
62
61
  createMockCanvasContext2D: () => createMockCanvasContext2D,
@@ -142,7 +141,6 @@ __export(index_exports, {
142
141
  simulateBandwidthLimit: () => simulateBandwidthLimit,
143
142
  simulateCameraMovement: () => simulateCameraMovement,
144
143
  simulateFrames: () => simulateFrames,
145
- simulateFramesWithMock: () => simulateFramesWithMock,
146
144
  simulateHandshake: () => simulateHandshake,
147
145
  simulateNetworkCondition: () => simulateNetworkCondition,
148
146
  simulatePlayerInput: () => simulatePlayerInput,
@@ -155,6 +153,7 @@ __export(index_exports, {
155
153
  stairTrace: () => import_shared3.stairTrace,
156
154
  teardownBrowserEnvironment: () => teardownBrowserEnvironment,
157
155
  teardownMockAudioContext: () => teardownMockAudioContext,
156
+ teardownNodeEnvironment: () => teardownNodeEnvironment,
158
157
  throttleBandwidth: () => throttleBandwidth,
159
158
  verifySnapshotConsistency: () => verifySnapshotConsistency,
160
159
  waitForGameReady: () => waitForGameReady
@@ -2057,75 +2056,92 @@ function createMockCanvas(width = 300, height = 150) {
2057
2056
  canvas2.height = height;
2058
2057
  return canvas2;
2059
2058
  }
2060
- const canvas = new import_canvas2.Canvas(width, height);
2061
- const originalGetContext = canvas.getContext.bind(canvas);
2062
- canvas.getContext = function(contextId, options) {
2063
- if (contextId === "webgl2") {
2064
- return createMockWebGL2Context(canvas);
2065
- }
2066
- if (contextId === "2d") {
2067
- return originalGetContext("2d", options);
2068
- }
2069
- return originalGetContext(contextId, options);
2059
+ const napiCanvas = new import_canvas2.Canvas(width, height);
2060
+ const canvas = {
2061
+ width,
2062
+ height,
2063
+ getContext: (contextId, options) => {
2064
+ if (contextId === "2d") {
2065
+ return napiCanvas.getContext("2d", options);
2066
+ }
2067
+ if (contextId === "webgl2") {
2068
+ return createMockWebGL2Context(canvas);
2069
+ }
2070
+ return null;
2071
+ },
2072
+ toDataURL: () => napiCanvas.toDataURL(),
2073
+ toBuffer: (mime) => napiCanvas.toBuffer(mime)
2074
+ // Add other properties as needed
2070
2075
  };
2071
2076
  return canvas;
2072
2077
  }
2073
2078
  function createMockCanvasContext2D(canvas) {
2074
- if (!canvas) {
2075
- canvas = createMockCanvas();
2079
+ const c = canvas || createMockCanvas();
2080
+ const ctx = c.getContext("2d");
2081
+ if (!ctx) {
2082
+ throw new Error("Failed to create 2D context");
2076
2083
  }
2077
- return canvas.getContext("2d");
2084
+ return ctx;
2078
2085
  }
2079
2086
  function captureCanvasDrawCalls(context) {
2080
- const drawCalls = [];
2081
- const methodsToSpy = [
2082
- "fillRect",
2083
- "strokeRect",
2084
- "clearRect",
2085
- "fillText",
2086
- "strokeText",
2087
- "drawImage",
2088
- "beginPath",
2089
- "closePath",
2090
- "moveTo",
2091
- "lineTo",
2092
- "arc",
2093
- "arcTo",
2094
- "bezierCurveTo",
2095
- "quadraticCurveTo",
2096
- "stroke",
2097
- "fill",
2098
- "putImageData"
2099
- ];
2100
- methodsToSpy.forEach((method) => {
2101
- const original = context[method];
2102
- if (typeof original === "function") {
2103
- context[method] = function(...args) {
2104
- drawCalls.push({ method, args });
2105
- return original.apply(this, args);
2087
+ const calls = [];
2088
+ const proto = Object.getPrototypeOf(context);
2089
+ for (const key of Object.getOwnPropertyNames(proto)) {
2090
+ const value = context[key];
2091
+ if (typeof value === "function") {
2092
+ context[key] = function(...args) {
2093
+ calls.push({ method: key, args });
2094
+ return value.apply(context, args);
2106
2095
  };
2107
2096
  }
2108
- });
2109
- return drawCalls;
2097
+ }
2098
+ return calls;
2110
2099
  }
2111
2100
  function createMockImageData(width, height, fillColor) {
2112
- const imageData = new import_canvas2.ImageData(width, height);
2101
+ if (typeof global.ImageData !== "undefined") {
2102
+ const data2 = new Uint8ClampedArray(width * height * 4);
2103
+ if (fillColor) {
2104
+ for (let i = 0; i < data2.length; i += 4) {
2105
+ data2[i] = fillColor[0];
2106
+ data2[i + 1] = fillColor[1];
2107
+ data2[i + 2] = fillColor[2];
2108
+ data2[i + 3] = fillColor[3];
2109
+ }
2110
+ }
2111
+ return new global.ImageData(data2, width, height);
2112
+ }
2113
+ const data = new Uint8ClampedArray(width * height * 4);
2113
2114
  if (fillColor) {
2114
- const [r, g, b, a] = fillColor;
2115
- for (let i = 0; i < imageData.data.length; i += 4) {
2116
- imageData.data[i] = r;
2117
- imageData.data[i + 1] = g;
2118
- imageData.data[i + 2] = b;
2119
- imageData.data[i + 3] = a;
2115
+ for (let i = 0; i < data.length; i += 4) {
2116
+ data[i] = fillColor[0];
2117
+ data[i + 1] = fillColor[1];
2118
+ data[i + 2] = fillColor[2];
2119
+ data[i + 3] = fillColor[3];
2120
2120
  }
2121
2121
  }
2122
- return imageData;
2122
+ return new import_canvas2.ImageData(data, width, height);
2123
2123
  }
2124
- function createMockImage(width, height, src) {
2125
- const img = new import_canvas2.Image();
2126
- if (width) img.width = width;
2127
- if (height) img.height = height;
2128
- if (src) img.src = src;
2124
+ function createMockImage(width = 100, height = 100, src = "") {
2125
+ if (typeof document !== "undefined" && document.createElement) {
2126
+ const img2 = document.createElement("img");
2127
+ img2.width = width;
2128
+ img2.height = height;
2129
+ if (src) img2.src = src;
2130
+ return img2;
2131
+ }
2132
+ const img = {
2133
+ width,
2134
+ height,
2135
+ src,
2136
+ complete: true,
2137
+ onload: null,
2138
+ onerror: null
2139
+ };
2140
+ if (src) {
2141
+ setTimeout(() => {
2142
+ if (img.onload) img.onload();
2143
+ }, 0);
2144
+ }
2129
2145
  return img;
2130
2146
  }
2131
2147
 
@@ -2193,193 +2209,89 @@ function setupWebGPUMocks() {
2193
2209
  }
2194
2210
 
2195
2211
  // src/setup/timing.ts
2196
- var activeMockRAF;
2197
2212
  function createMockRAF() {
2198
2213
  let callbacks = [];
2199
- let nextId = 1;
2214
+ let lastId = 0;
2200
2215
  let currentTime = 0;
2201
2216
  const originalRAF = global.requestAnimationFrame;
2202
2217
  const originalCancelRAF = global.cancelAnimationFrame;
2203
- const raf = (callback) => {
2204
- const id = nextId++;
2205
- callbacks.push({ id, callback });
2206
- return id;
2218
+ global.requestAnimationFrame = (callback) => {
2219
+ lastId++;
2220
+ callbacks.push({ id: lastId, callback });
2221
+ return lastId;
2207
2222
  };
2208
- const cancel = (id) => {
2223
+ global.cancelAnimationFrame = (id) => {
2209
2224
  callbacks = callbacks.filter((cb) => cb.id !== id);
2210
2225
  };
2211
- const mock = {
2212
- tick(timestamp) {
2213
- if (typeof timestamp !== "number") {
2214
- currentTime += 16.6;
2215
- } else {
2216
- currentTime = timestamp;
2217
- }
2226
+ return {
2227
+ tick(time) {
2228
+ if (time) currentTime = time;
2229
+ else currentTime += 16.66;
2218
2230
  const currentCallbacks = [...callbacks];
2219
2231
  callbacks = [];
2220
- currentCallbacks.forEach(({ callback }) => {
2221
- callback(currentTime);
2222
- });
2232
+ currentCallbacks.forEach((cb) => cb.callback(currentTime));
2223
2233
  },
2224
- advance(deltaMs = 16.6) {
2225
- this.tick(currentTime + deltaMs);
2234
+ advance(ms) {
2235
+ currentTime += ms;
2236
+ this.tick(currentTime);
2226
2237
  },
2227
2238
  getCallbacks() {
2228
- return callbacks.map((c) => c.callback);
2229
- },
2230
- reset() {
2231
- callbacks = [];
2232
- nextId = 1;
2233
- currentTime = 0;
2234
- },
2235
- enable() {
2236
- activeMockRAF = this;
2237
- global.requestAnimationFrame = raf;
2238
- global.cancelAnimationFrame = cancel;
2239
- },
2240
- disable() {
2241
- if (activeMockRAF === this) {
2242
- activeMockRAF = void 0;
2243
- }
2244
- if (originalRAF) {
2245
- global.requestAnimationFrame = originalRAF;
2246
- } else {
2247
- delete global.requestAnimationFrame;
2248
- }
2249
- if (originalCancelRAF) {
2250
- global.cancelAnimationFrame = originalCancelRAF;
2251
- } else {
2252
- delete global.cancelAnimationFrame;
2253
- }
2239
+ return callbacks;
2254
2240
  }
2255
2241
  };
2256
- return mock;
2257
2242
  }
2258
2243
  function createMockPerformance(startTime = 0) {
2259
- let currentTime = startTime;
2260
- const mockPerf = {
2261
- now: () => currentTime,
2244
+ let now = startTime;
2245
+ const mockPerformance = {
2246
+ now: () => now,
2262
2247
  timeOrigin: startTime,
2263
2248
  timing: {
2264
2249
  navigationStart: startTime
2265
2250
  },
2266
- clearMarks: () => {
2267
- },
2268
- clearMeasures: () => {
2251
+ mark: (_name) => {
2269
2252
  },
2270
- clearResourceTimings: () => {
2253
+ measure: (_name, _start, _end) => {
2271
2254
  },
2272
2255
  getEntries: () => [],
2273
- getEntriesByName: () => [],
2274
- getEntriesByType: () => [],
2275
- mark: () => {
2276
- },
2277
- measure: () => {
2256
+ getEntriesByName: (_name) => [],
2257
+ getEntriesByType: (_type) => [],
2258
+ clearMarks: (_name) => {
2278
2259
  },
2279
- setResourceTimingBufferSize: () => {
2260
+ clearMeasures: (_name) => {
2280
2261
  },
2281
- toJSON: () => ({}),
2282
- addEventListener: () => {
2262
+ clearResourceTimings: () => {
2283
2263
  },
2284
- removeEventListener: () => {
2264
+ setResourceTimingBufferSize: (_maxSize) => {
2285
2265
  },
2286
- dispatchEvent: () => true
2287
- };
2288
- mockPerf.advance = (deltaMs) => {
2289
- currentTime += deltaMs;
2266
+ onresourcetimingbufferfull: null,
2267
+ toJSON: () => ({})
2290
2268
  };
2291
- mockPerf.setTime = (time) => {
2292
- currentTime = time;
2293
- };
2294
- return mockPerf;
2269
+ if (typeof global.performance === "undefined") {
2270
+ global.performance = mockPerformance;
2271
+ }
2272
+ return mockPerformance;
2295
2273
  }
2296
2274
  function createControlledTimer() {
2297
- let currentTime = 0;
2298
- let timers = [];
2299
- let nextId = 1;
2300
- const originalSetTimeout = global.setTimeout;
2301
- const originalClearTimeout = global.clearTimeout;
2302
- const originalSetInterval = global.setInterval;
2303
- const originalClearInterval = global.clearInterval;
2304
- const mockSetTimeout = (callback, delay = 0, ...args) => {
2305
- const id = nextId++;
2306
- timers.push({ id, callback, dueTime: currentTime + delay, args });
2307
- return id;
2308
- };
2309
- const mockClearTimeout = (id) => {
2310
- timers = timers.filter((t) => t.id !== id);
2311
- };
2312
- const mockSetInterval = (callback, delay = 0, ...args) => {
2313
- const id = nextId++;
2314
- timers.push({ id, callback, dueTime: currentTime + delay, interval: delay, args });
2315
- return id;
2316
- };
2317
- const mockClearInterval = (id) => {
2318
- timers = timers.filter((t) => t.id !== id);
2319
- };
2320
- global.setTimeout = mockSetTimeout;
2321
- global.clearTimeout = mockClearTimeout;
2322
- global.setInterval = mockSetInterval;
2323
- global.clearInterval = mockClearInterval;
2275
+ console.warn("createControlledTimer: Recommend using vi.useFakeTimers() instead.");
2324
2276
  return {
2325
- tick() {
2326
- this.advanceBy(0);
2277
+ advanceBy: (ms) => {
2327
2278
  },
2328
- advanceBy(ms) {
2329
- const targetTime = currentTime + ms;
2330
- while (true) {
2331
- let earliest = null;
2332
- for (const t of timers) {
2333
- if (!earliest || t.dueTime < earliest.dueTime) {
2334
- earliest = t;
2335
- }
2336
- }
2337
- if (!earliest || earliest.dueTime > targetTime) {
2338
- break;
2339
- }
2340
- currentTime = earliest.dueTime;
2341
- const { callback, args, interval, id } = earliest;
2342
- if (interval !== void 0) {
2343
- earliest.dueTime += interval;
2344
- if (interval === 0) earliest.dueTime += 1;
2345
- } else {
2346
- timers = timers.filter((t) => t.id !== id);
2347
- }
2348
- callback(...args);
2349
- }
2350
- currentTime = targetTime;
2279
+ runAll: () => {
2351
2280
  },
2352
- clear() {
2353
- timers = [];
2354
- },
2355
- restore() {
2356
- global.setTimeout = originalSetTimeout;
2357
- global.clearTimeout = originalClearTimeout;
2358
- global.setInterval = originalSetInterval;
2359
- global.clearInterval = originalClearInterval;
2281
+ clear: () => {
2360
2282
  }
2361
2283
  };
2362
2284
  }
2363
- function simulateFrames(count, frameTimeMs = 16.6, callback) {
2364
- if (!activeMockRAF) {
2365
- throw new Error("simulateFrames requires an active MockRAF. Ensure createMockRAF().enable() is called.");
2366
- }
2285
+ function simulateFrames(count, frameTime = 16, callback) {
2367
2286
  for (let i = 0; i < count; i++) {
2368
2287
  if (callback) callback(i);
2369
- activeMockRAF.advance(frameTimeMs);
2370
- }
2371
- }
2372
- function simulateFramesWithMock(mock, count, frameTimeMs = 16.6, callback) {
2373
- for (let i = 0; i < count; i++) {
2374
- if (callback) callback(i);
2375
- mock.advance(frameTimeMs);
2376
2288
  }
2377
2289
  }
2378
2290
 
2379
2291
  // src/setup/node.ts
2380
2292
  function setupNodeEnvironment(options = {}) {
2381
- if (options.polyfillFetch && typeof global.fetch === "undefined") {
2382
- }
2293
+ }
2294
+ function teardownNodeEnvironment() {
2383
2295
  }
2384
2296
 
2385
2297
  // src/engine/rendering.ts
@@ -2441,186 +2353,141 @@ function createMockRenderingContext() {
2441
2353
  }
2442
2354
 
2443
2355
  // src/setup/storage.ts
2444
- var import_auto2 = require("fake-indexeddb/auto");
2445
- function createMockLocalStorage(initialData = {}) {
2446
- const storage = new Map(Object.entries(initialData));
2356
+ function createStorageMock(initialData = {}) {
2357
+ const store = new Map(Object.entries(initialData));
2447
2358
  return {
2448
- getItem: (key) => storage.get(key) || null,
2449
- setItem: (key, value) => storage.set(key, value),
2450
- removeItem: (key) => storage.delete(key),
2451
- clear: () => storage.clear(),
2452
- key: (index) => Array.from(storage.keys())[index] || null,
2359
+ getItem: (key) => store.get(key) || null,
2360
+ setItem: (key, value) => store.set(key, value.toString()),
2361
+ removeItem: (key) => store.delete(key),
2362
+ clear: () => store.clear(),
2363
+ key: (index) => Array.from(store.keys())[index] || null,
2453
2364
  get length() {
2454
- return storage.size;
2365
+ return store.size;
2455
2366
  }
2456
2367
  };
2457
2368
  }
2369
+ function createMockLocalStorage(initialData = {}) {
2370
+ return createStorageMock(initialData);
2371
+ }
2458
2372
  function createMockSessionStorage(initialData = {}) {
2459
- return createMockLocalStorage(initialData);
2373
+ return createStorageMock(initialData);
2460
2374
  }
2461
- function createMockIndexedDB() {
2462
- if (typeof indexedDB === "undefined") {
2463
- throw new Error("IndexedDB mock not found. Ensure fake-indexeddb is loaded.");
2464
- }
2465
- return indexedDB;
2375
+ function createMockIndexedDB(databases) {
2376
+ return global.indexedDB;
2466
2377
  }
2467
2378
  function createStorageTestScenario(storageType = "local") {
2468
- if (storageType === "indexed") {
2469
- const dbName = `test-db-${Math.random().toString(36).substring(7)}`;
2470
- const storeName = "test-store";
2471
- const storage2 = createMockIndexedDB();
2472
- return {
2473
- storage: storage2,
2474
- populate: async (data) => {
2475
- return new Promise((resolve, reject) => {
2476
- const req = storage2.open(dbName, 1);
2477
- req.onupgradeneeded = (e) => {
2478
- const db = e.target.result;
2479
- db.createObjectStore(storeName);
2480
- };
2481
- req.onsuccess = (e) => {
2482
- const db = e.target.result;
2483
- const tx = db.transaction(storeName, "readwrite");
2484
- const store = tx.objectStore(storeName);
2485
- Object.entries(data).forEach(([k, v]) => store.put(v, k));
2486
- tx.oncomplete = () => {
2487
- db.close();
2488
- resolve();
2489
- };
2490
- tx.onerror = () => reject(tx.error);
2491
- };
2492
- req.onerror = () => reject(req.error);
2493
- });
2494
- },
2495
- verify: async (key, value) => {
2496
- return new Promise((resolve, reject) => {
2497
- const req = storage2.open(dbName, 1);
2498
- req.onsuccess = (e) => {
2499
- const db = e.target.result;
2500
- if (!db.objectStoreNames.contains(storeName)) {
2501
- db.close();
2502
- resolve(false);
2503
- return;
2504
- }
2505
- const tx = db.transaction(storeName, "readonly");
2506
- const store = tx.objectStore(storeName);
2507
- const getReq = store.get(key);
2508
- getReq.onsuccess = () => {
2509
- const result = getReq.result === value;
2510
- db.close();
2511
- resolve(result);
2512
- };
2513
- getReq.onerror = () => {
2514
- db.close();
2515
- resolve(false);
2516
- };
2517
- };
2518
- req.onerror = () => reject(req.error);
2519
- });
2520
- }
2521
- };
2522
- }
2523
- const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
2524
2379
  return {
2525
- storage,
2526
- populate(data) {
2527
- Object.entries(data).forEach(([k, v]) => storage.setItem(k, v));
2528
- },
2529
- verify(key, value) {
2530
- return storage.getItem(key) === value;
2531
- }
2380
+ localStorage: createMockLocalStorage(),
2381
+ sessionStorage: createMockSessionStorage(),
2382
+ indexedDB: createMockIndexedDB()
2532
2383
  };
2533
2384
  }
2534
2385
 
2535
2386
  // src/setup/audio.ts
2536
- function createMockAudioContext() {
2537
- const context = {
2538
- createGain: () => ({
2539
- connect: () => {
2540
- },
2541
- gain: { value: 1, setValueAtTime: () => {
2542
- } }
2543
- }),
2544
- createOscillator: () => ({
2545
- connect: () => {
2546
- },
2547
- start: () => {
2548
- },
2549
- stop: () => {
2550
- },
2551
- frequency: { value: 440 }
2552
- }),
2553
- createBufferSource: () => ({
2554
- connect: () => {
2555
- },
2556
- start: () => {
2557
- },
2558
- stop: () => {
2559
- },
2560
- buffer: null,
2561
- playbackRate: { value: 1 },
2562
- loop: false
2563
- }),
2564
- destination: {},
2565
- currentTime: 0,
2566
- state: "running",
2567
- resume: async () => {
2568
- },
2569
- suspend: async () => {
2570
- },
2571
- close: async () => {
2572
- },
2573
- decodeAudioData: async (buffer) => ({
2574
- duration: 1,
2575
- length: 44100,
2576
- sampleRate: 44100,
2577
- numberOfChannels: 2,
2578
- getChannelData: () => new Float32Array(44100)
2579
- }),
2580
- createBuffer: (channels, length2, sampleRate) => ({
2581
- duration: length2 / sampleRate,
2582
- length: length2,
2583
- sampleRate,
2584
- numberOfChannels: channels,
2585
- getChannelData: () => new Float32Array(length2)
2586
- }),
2587
- // Helper to track events if needed
2588
- _events: []
2589
- };
2590
- return new Proxy(context, {
2591
- get(target, prop, receiver) {
2592
- if (prop === "_events") return target._events;
2593
- const value = Reflect.get(target, prop, receiver);
2594
- if (typeof value === "function") {
2595
- return (...args) => {
2596
- target._events.push({ type: String(prop), args });
2597
- return Reflect.apply(value, target, args);
2598
- };
2599
- }
2600
- return value;
2601
- }
2602
- });
2603
- }
2604
2387
  function setupMockAudioContext() {
2605
- if (typeof global.AudioContext === "undefined" && typeof global.window !== "undefined") {
2606
- global.AudioContext = class {
2607
- constructor() {
2608
- return createMockAudioContext();
2609
- }
2610
- };
2611
- global.window.AudioContext = global.AudioContext;
2612
- global.window.webkitAudioContext = global.AudioContext;
2388
+ class MockAudioContext {
2389
+ constructor() {
2390
+ this.state = "suspended";
2391
+ this.destination = {};
2392
+ this.currentTime = 0;
2393
+ this.listener = {
2394
+ positionX: { value: 0 },
2395
+ positionY: { value: 0 },
2396
+ positionZ: { value: 0 },
2397
+ forwardX: { value: 0 },
2398
+ forwardY: { value: 0 },
2399
+ forwardZ: { value: 0 },
2400
+ upX: { value: 0 },
2401
+ upY: { value: 0 },
2402
+ upZ: { value: 0 },
2403
+ setOrientation: () => {
2404
+ },
2405
+ setPosition: () => {
2406
+ }
2407
+ };
2408
+ }
2409
+ createGain() {
2410
+ return {
2411
+ gain: { value: 1, linearRampToValueAtTime: () => {
2412
+ } },
2413
+ connect: () => {
2414
+ },
2415
+ disconnect: () => {
2416
+ }
2417
+ };
2418
+ }
2419
+ createBufferSource() {
2420
+ return {
2421
+ buffer: null,
2422
+ loop: false,
2423
+ playbackRate: { value: 1 },
2424
+ connect: () => {
2425
+ },
2426
+ start: () => {
2427
+ },
2428
+ stop: () => {
2429
+ },
2430
+ disconnect: () => {
2431
+ },
2432
+ onended: null
2433
+ };
2434
+ }
2435
+ createPanner() {
2436
+ return {
2437
+ panningModel: "equalpower",
2438
+ distanceModel: "inverse",
2439
+ positionX: { value: 0 },
2440
+ positionY: { value: 0 },
2441
+ positionZ: { value: 0 },
2442
+ orientationX: { value: 0 },
2443
+ orientationY: { value: 0 },
2444
+ orientationZ: { value: 0 },
2445
+ coneInnerAngle: 360,
2446
+ coneOuterAngle: 360,
2447
+ coneOuterGain: 0,
2448
+ connect: () => {
2449
+ },
2450
+ disconnect: () => {
2451
+ },
2452
+ setPosition: () => {
2453
+ },
2454
+ setOrientation: () => {
2455
+ }
2456
+ };
2457
+ }
2458
+ createBuffer(numOfChannels, length2, sampleRate) {
2459
+ return {
2460
+ duration: length2 / sampleRate,
2461
+ length: length2,
2462
+ sampleRate,
2463
+ numberOfChannels: numOfChannels,
2464
+ getChannelData: () => new Float32Array(length2)
2465
+ };
2466
+ }
2467
+ decodeAudioData(data, success) {
2468
+ const buffer = this.createBuffer(2, 100, 44100);
2469
+ if (success) success(buffer);
2470
+ return Promise.resolve(buffer);
2471
+ }
2472
+ resume() {
2473
+ return Promise.resolve();
2474
+ }
2475
+ suspend() {
2476
+ return Promise.resolve();
2477
+ }
2478
+ close() {
2479
+ return Promise.resolve();
2480
+ }
2613
2481
  }
2482
+ global.AudioContext = MockAudioContext;
2483
+ global.webkitAudioContext = MockAudioContext;
2614
2484
  }
2615
2485
  function teardownMockAudioContext() {
2616
- if (global.AudioContext && global.AudioContext.toString().includes("class")) {
2617
- delete global.AudioContext;
2618
- delete global.window.AudioContext;
2619
- delete global.window.webkitAudioContext;
2620
- }
2486
+ delete global.AudioContext;
2487
+ delete global.webkitAudioContext;
2621
2488
  }
2622
2489
  function captureAudioEvents(context) {
2623
- return context._events || [];
2490
+ return [];
2624
2491
  }
2625
2492
 
2626
2493
  // ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
@@ -3110,217 +2977,110 @@ function simulateCameraMovement(camera, input, deltaTime) {
3110
2977
  }
3111
2978
 
3112
2979
  // src/e2e/playwright.ts
3113
- var import_playwright = require("playwright");
3114
- var import_http = require("http");
3115
- var import_serve_handler = __toESM(require("serve-handler"), 1);
3116
2980
  async function createPlaywrightTestClient(options = {}) {
3117
- let staticServer;
3118
- let clientUrl = options.clientUrl;
3119
- const rootPath = options.rootPath || process.cwd();
3120
- if (!clientUrl) {
3121
- staticServer = (0, import_http.createServer)((request, response) => {
3122
- return (0, import_serve_handler.default)(request, response, {
3123
- public: rootPath,
3124
- cleanUrls: false,
3125
- headers: [
3126
- {
3127
- source: "**/*",
3128
- headers: [
3129
- { key: "Cache-Control", value: "no-cache" },
3130
- { key: "Access-Control-Allow-Origin", value: "*" },
3131
- { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
3132
- { key: "Cross-Origin-Embedder-Policy", value: "require-corp" }
3133
- ]
3134
- }
3135
- ]
3136
- });
3137
- });
3138
- await new Promise((resolve) => {
3139
- if (!staticServer) return;
3140
- staticServer.listen(0, () => {
3141
- const addr = staticServer?.address();
3142
- const port = typeof addr === "object" ? addr?.port : 0;
3143
- clientUrl = `http://localhost:${port}`;
3144
- console.log(`Test client serving from ${rootPath} at ${clientUrl}`);
3145
- resolve();
3146
- });
3147
- });
2981
+ let playwright;
2982
+ try {
2983
+ playwright = await import("playwright");
2984
+ } catch (e) {
2985
+ throw new Error("Playwright is not installed. Please install it to use this utility.");
3148
2986
  }
3149
- const browser = await import_playwright.chromium.launch({
3150
- headless: options.headless ?? true,
3151
- args: [
3152
- "--use-gl=egl",
3153
- "--ignore-gpu-blocklist",
3154
- ...options.launchOptions?.args || []
3155
- ],
3156
- ...options.launchOptions
2987
+ const browser = await playwright.chromium.launch({
2988
+ headless: options.headless ?? true
3157
2989
  });
3158
- const width = options.width || 1280;
3159
- const height = options.height || 720;
3160
2990
  const context = await browser.newContext({
3161
- viewport: { width, height },
3162
- deviceScaleFactor: 1,
3163
- ...options.contextOptions
2991
+ viewport: options.viewport || { width: 1280, height: 720 }
3164
2992
  });
3165
2993
  const page = await context.newPage();
3166
- const close = async () => {
3167
- await browser.close();
3168
- if (staticServer) {
3169
- staticServer.close();
3170
- }
3171
- };
3172
- const navigate = async (url) => {
3173
- const targetUrl = url || clientUrl;
3174
- if (!targetUrl) throw new Error("No URL to navigate to");
3175
- let finalUrl = targetUrl;
3176
- if (options.serverUrl && !targetUrl.includes("connect=")) {
3177
- const separator = targetUrl.includes("?") ? "&" : "?";
3178
- finalUrl = `${targetUrl}${separator}connect=${encodeURIComponent(options.serverUrl)}`;
3179
- }
3180
- console.log(`Navigating to: ${finalUrl}`);
3181
- await page.goto(finalUrl, { waitUntil: "domcontentloaded" });
3182
- };
3183
2994
  return {
3184
- browser,
3185
- context,
3186
2995
  page,
3187
- server: staticServer,
3188
- close,
3189
- navigate,
3190
- waitForGame: async (timeout = 1e4) => {
3191
- await waitForGameReady(page, timeout);
2996
+ browser,
2997
+ async navigate(url) {
2998
+ await page.goto(url);
2999
+ },
3000
+ async waitForGame() {
3001
+ await waitForGameReady(page);
3192
3002
  },
3193
- injectInput: async (type, data) => {
3003
+ async injectInput(type, data) {
3194
3004
  await page.evaluate(({ type: type2, data: data2 }) => {
3195
- if (window.injectGameInput) window.injectGameInput(type2, data2);
3005
+ console.log("Injecting input", type2, data2);
3196
3006
  }, { type, data });
3007
+ },
3008
+ async screenshot(name) {
3009
+ return await page.screenshot({ path: `${name}.png` });
3010
+ },
3011
+ async close() {
3012
+ await browser.close();
3197
3013
  }
3198
3014
  };
3199
3015
  }
3200
3016
  async function waitForGameReady(page, timeout = 1e4) {
3201
- try {
3202
- await page.waitForFunction(() => {
3203
- return window.gameInstance && window.gameInstance.isReady;
3204
- }, null, { timeout });
3205
- } catch (e) {
3206
- await page.waitForSelector("canvas", { timeout });
3207
- }
3017
+ await page.waitForFunction(() => {
3018
+ return window.game && window.game.isRunning;
3019
+ }, { timeout });
3208
3020
  }
3209
3021
  async function captureGameState(page) {
3210
3022
  return await page.evaluate(() => {
3211
- if (window.gameInstance && window.gameInstance.getState) {
3212
- return window.gameInstance.getState();
3213
- }
3214
- return {};
3023
+ const game = window.game;
3024
+ return {
3025
+ time: game ? game.time : 0,
3026
+ entities: game && game.entities ? game.entities.length : 0
3027
+ };
3215
3028
  });
3216
3029
  }
3217
3030
 
3218
3031
  // src/e2e/network.ts
3219
- var CONDITIONS = {
3220
- "good": {
3221
- offline: false,
3222
- downloadThroughput: 10 * 1024 * 1024,
3223
- // 10 Mbps
3224
- uploadThroughput: 5 * 1024 * 1024,
3225
- // 5 Mbps
3226
- latency: 20
3227
- },
3228
- "slow": {
3229
- offline: false,
3230
- downloadThroughput: 500 * 1024,
3231
- // 500 Kbps
3232
- uploadThroughput: 500 * 1024,
3233
- latency: 400
3234
- },
3235
- "unstable": {
3236
- offline: false,
3237
- downloadThroughput: 1 * 1024 * 1024,
3238
- uploadThroughput: 1 * 1024 * 1024,
3239
- latency: 100
3240
- },
3241
- "offline": {
3242
- offline: true,
3243
- downloadThroughput: 0,
3244
- uploadThroughput: 0,
3245
- latency: 0
3246
- }
3247
- };
3248
3032
  function simulateNetworkCondition(condition) {
3249
- const config = CONDITIONS[condition];
3250
- return createCustomNetworkCondition(config.latency, 0, 0, config);
3251
- }
3252
- function createCustomNetworkCondition(latency, jitter = 0, packetLoss = 0, baseConfig) {
3033
+ switch (condition) {
3034
+ case "good":
3035
+ return { latency: 20, jitter: 5, packetLoss: 0, bandwidth: 10 * 1024 * 1024 };
3036
+ case "slow":
3037
+ return { latency: 150, jitter: 20, packetLoss: 0.01, bandwidth: 1 * 1024 * 1024 };
3038
+ case "unstable":
3039
+ return { latency: 100, jitter: 100, packetLoss: 0.05, bandwidth: 512 * 1024 };
3040
+ case "offline":
3041
+ return { latency: 0, jitter: 0, packetLoss: 1, bandwidth: 0 };
3042
+ case "custom":
3043
+ default:
3044
+ return { latency: 0, jitter: 0, packetLoss: 0, bandwidth: Infinity };
3045
+ }
3046
+ }
3047
+ function createCustomNetworkCondition(latency, jitter, packetLoss) {
3253
3048
  return {
3254
- async apply(page) {
3255
- const client = await page.context().newCDPSession(page);
3256
- await client.send("Network.enable");
3257
- await client.send("Network.emulateNetworkConditions", {
3258
- offline: baseConfig?.offline || false,
3259
- latency: latency + Math.random() * jitter,
3260
- downloadThroughput: baseConfig?.downloadThroughput || -1,
3261
- uploadThroughput: baseConfig?.uploadThroughput || -1
3262
- });
3263
- },
3264
- async clear(page) {
3265
- const client = await page.context().newCDPSession(page);
3266
- await client.send("Network.emulateNetworkConditions", {
3267
- offline: false,
3268
- latency: 0,
3269
- downloadThroughput: -1,
3270
- uploadThroughput: -1
3271
- });
3272
- }
3049
+ latency,
3050
+ jitter,
3051
+ packetLoss,
3052
+ bandwidth: Infinity
3053
+ // Default to unlimited unless specified
3273
3054
  };
3274
3055
  }
3275
- async function throttleBandwidth(page, bytesPerSecond) {
3276
- const simulator = createCustomNetworkCondition(0, 0, 0, {
3277
- offline: false,
3278
- latency: 0,
3279
- downloadThroughput: bytesPerSecond,
3280
- uploadThroughput: bytesPerSecond
3281
- });
3282
- await simulator.apply(page);
3056
+ function throttleBandwidth(bytesPerSecond) {
3283
3057
  }
3284
3058
 
3285
3059
  // src/e2e/visual.ts
3286
- var import_path = __toESM(require("path"), 1);
3287
- var import_promises = __toESM(require("fs/promises"), 1);
3288
- async function captureGameScreenshot(page, name, options = {}) {
3289
- const dir = options.dir || "__screenshots__";
3290
- const screenshotPath = import_path.default.join(dir, `${name}.png`);
3291
- await import_promises.default.mkdir(dir, { recursive: true });
3292
- return await page.screenshot({
3293
- path: screenshotPath,
3294
- fullPage: options.fullPage ?? false,
3295
- animations: "disabled",
3296
- caret: "hide"
3297
- });
3298
- }
3299
- async function compareScreenshots(baseline, current, threshold = 0.1) {
3300
- if (baseline.equals(current)) {
3301
- return { pixelDiff: 0, matched: true };
3060
+ async function captureGameScreenshot(page, name) {
3061
+ return await page.screenshot({ path: `${name}.png` });
3062
+ }
3063
+ function compareScreenshots(baseline, current, threshold = 0.01) {
3064
+ if (baseline.length !== current.length) {
3065
+ return { diffPercentage: 1 };
3066
+ }
3067
+ let diffPixels = 0;
3068
+ const totalPixels = baseline.length;
3069
+ for (let i = 0; i < baseline.length; i++) {
3070
+ if (baseline[i] !== current[i]) {
3071
+ diffPixels++;
3072
+ }
3302
3073
  }
3074
+ const diffPercentage = diffPixels / totalPixels;
3303
3075
  return {
3304
- pixelDiff: -1,
3305
- // Unknown magnitude
3306
- matched: false
3076
+ diffPercentage
3077
+ // Generating a diff image buffer would require a library like pixelmatch
3307
3078
  };
3308
3079
  }
3309
- function createVisualTestScenario(page, sceneName) {
3080
+ function createVisualTestScenario(sceneName) {
3310
3081
  return {
3311
- async capture(snapshotName) {
3312
- return await captureGameScreenshot(page, `${sceneName}-${snapshotName}`);
3313
- },
3314
- async compare(snapshotName, baselineDir) {
3315
- const name = `${sceneName}-${snapshotName}`;
3316
- const current = await captureGameScreenshot(page, name, { dir: "__screenshots__/current" });
3317
- try {
3318
- const baselinePath = import_path.default.join(baselineDir, `${name}.png`);
3319
- const baseline = await import_promises.default.readFile(baselinePath);
3320
- return await compareScreenshots(baseline, current);
3321
- } catch (e) {
3322
- return { pixelDiff: -1, matched: false };
3323
- }
3082
+ sceneName,
3083
+ setup: async () => {
3324
3084
  }
3325
3085
  };
3326
3086
  }
@@ -3352,7 +3112,6 @@ function createVisualTestScenario(page, sceneName) {
3352
3112
  createMockAI,
3353
3113
  createMockAmmoItem,
3354
3114
  createMockArmorItem,
3355
- createMockAudioContext,
3356
3115
  createMockCamera,
3357
3116
  createMockCanvas,
3358
3117
  createMockCanvasContext2D,
@@ -3438,7 +3197,6 @@ function createVisualTestScenario(page, sceneName) {
3438
3197
  simulateBandwidthLimit,
3439
3198
  simulateCameraMovement,
3440
3199
  simulateFrames,
3441
- simulateFramesWithMock,
3442
3200
  simulateHandshake,
3443
3201
  simulateNetworkCondition,
3444
3202
  simulatePlayerInput,
@@ -3451,6 +3209,7 @@ function createVisualTestScenario(page, sceneName) {
3451
3209
  stairTrace,
3452
3210
  teardownBrowserEnvironment,
3453
3211
  teardownMockAudioContext,
3212
+ teardownNodeEnvironment,
3454
3213
  throttleBandwidth,
3455
3214
  verifySnapshotConsistency,
3456
3215
  waitForGameReady