quake2ts 0.0.582 → 0.0.585

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.
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  createBandwidthTestScenario: () => createBandwidthTestScenario,
44
44
  createBinaryStreamMock: () => createBinaryStreamMock,
45
45
  createBinaryWriterMock: () => createBinaryWriterMock,
46
+ createBounds: () => createBounds,
46
47
  createCombatTestContext: () => createCombatTestContext,
47
48
  createControlledTimer: () => createControlledTimer,
48
49
  createCustomNetworkCondition: () => createCustomNetworkCondition,
@@ -53,10 +54,11 @@ __export(index_exports, {
53
54
  createGameStateSnapshotFactory: () => createGameStateSnapshotFactory,
54
55
  createInputInjector: () => createInputInjector,
55
56
  createItemEntityFactory: () => createItemEntityFactory,
57
+ createMessageReaderMock: () => createMessageReaderMock,
58
+ createMessageWriterMock: () => createMessageWriterMock,
56
59
  createMockAI: () => createMockAI,
57
60
  createMockAmmoItem: () => createMockAmmoItem,
58
61
  createMockArmorItem: () => createMockArmorItem,
59
- createMockAudioContext: () => createMockAudioContext,
60
62
  createMockCamera: () => createMockCamera,
61
63
  createMockCanvas: () => createMockCanvas,
62
64
  createMockCanvasContext2D: () => createMockCanvasContext2D,
@@ -111,6 +113,7 @@ __export(index_exports, {
111
113
  createMonsterEntityFactory: () => createMonsterEntityFactory,
112
114
  createMultiplayerTestScenario: () => createMultiplayerTestScenario,
113
115
  createNetChanMock: () => createNetChanMock,
116
+ createPacketMock: () => createPacketMock,
114
117
  createPhysicsTestContext: () => createPhysicsTestContext,
115
118
  createPlayerEntityFactory: () => createPlayerEntityFactory,
116
119
  createPlayerStateFactory: () => createPlayerStateFactory,
@@ -119,12 +122,16 @@ __export(index_exports, {
119
122
  createServerSnapshot: () => createServerSnapshot,
120
123
  createSpawnTestContext: () => createSpawnTestContext,
121
124
  createStorageTestScenario: () => createStorageTestScenario,
125
+ createSurfaceMock: () => createSurfaceMock,
122
126
  createTestContext: () => createTestContext,
127
+ createTraceMock: () => createTraceMock,
128
+ createTransform: () => createTransform,
123
129
  createTriggerEntityFactory: () => createTriggerEntityFactory,
130
+ createVector3: () => createVector3,
124
131
  createViewTestScenario: () => createViewTestScenario,
125
132
  createVisualTestScenario: () => createVisualTestScenario,
126
- intersects: () => import_shared3.intersects,
127
- ladderTrace: () => import_shared3.ladderTrace,
133
+ intersects: () => import_shared2.intersects,
134
+ ladderTrace: () => import_shared2.ladderTrace,
128
135
  makeAxisBrush: () => makeAxisBrush,
129
136
  makeBrushFromMinsMaxs: () => makeBrushFromMinsMaxs,
130
137
  makeBspModel: () => makeBspModel,
@@ -134,6 +141,7 @@ __export(index_exports, {
134
141
  makePlane: () => makePlane,
135
142
  measureSnapshotSize: () => measureSnapshotSize,
136
143
  mockMonsterAttacks: () => mockMonsterAttacks,
144
+ randomVector3: () => randomVector3,
137
145
  serializeUserInfo: () => serializeUserInfo,
138
146
  setupBrowserEnvironment: () => setupBrowserEnvironment,
139
147
  setupMockAudioContext: () => setupMockAudioContext,
@@ -142,7 +150,6 @@ __export(index_exports, {
142
150
  simulateBandwidthLimit: () => simulateBandwidthLimit,
143
151
  simulateCameraMovement: () => simulateCameraMovement,
144
152
  simulateFrames: () => simulateFrames,
145
- simulateFramesWithMock: () => simulateFramesWithMock,
146
153
  simulateHandshake: () => simulateHandshake,
147
154
  simulateNetworkCondition: () => simulateNetworkCondition,
148
155
  simulatePlayerInput: () => simulatePlayerInput,
@@ -152,9 +159,10 @@ __export(index_exports, {
152
159
  simulateServerRegistration: () => simulateServerRegistration,
153
160
  simulateServerTick: () => simulateServerTick,
154
161
  simulateSnapshotDelivery: () => simulateSnapshotDelivery,
155
- stairTrace: () => import_shared3.stairTrace,
162
+ stairTrace: () => import_shared2.stairTrace,
156
163
  teardownBrowserEnvironment: () => teardownBrowserEnvironment,
157
164
  teardownMockAudioContext: () => teardownMockAudioContext,
165
+ teardownNodeEnvironment: () => teardownNodeEnvironment,
158
166
  throttleBandwidth: () => throttleBandwidth,
159
167
  verifySnapshotConsistency: () => verifySnapshotConsistency,
160
168
  waitForGameReady: () => waitForGameReady
@@ -179,7 +187,9 @@ var createBinaryWriterMock = () => ({
179
187
  writeInt32: import_vitest.vi.fn(),
180
188
  writeUint32: import_vitest.vi.fn(),
181
189
  writeFloat: import_vitest.vi.fn(),
182
- getData: import_vitest.vi.fn(() => new Uint8Array(0))
190
+ getData: import_vitest.vi.fn(() => new Uint8Array(0)),
191
+ writePos: import_vitest.vi.fn(),
192
+ writeDir: import_vitest.vi.fn()
183
193
  });
184
194
  var createNetChanMock = () => ({
185
195
  qport: 1234,
@@ -241,6 +251,37 @@ var createBinaryStreamMock = () => ({
241
251
  readPos: import_vitest.vi.fn(),
242
252
  readDir: import_vitest.vi.fn()
243
253
  });
254
+ var createMessageWriterMock = (overrides) => {
255
+ const mock = createBinaryWriterMock();
256
+ const writer = {
257
+ ...mock,
258
+ writeInt: mock.writeInt32,
259
+ // Alias writeInt to writeInt32
260
+ writeVector: mock.writePos,
261
+ // Alias writeVector to writePos
262
+ ...overrides
263
+ };
264
+ return writer;
265
+ };
266
+ var createMessageReaderMock = (data) => {
267
+ const mock = createBinaryStreamMock();
268
+ const reader = {
269
+ ...mock,
270
+ readInt: mock.readLong,
271
+ // Alias readInt to readLong (int32)
272
+ readVector: mock.readPos
273
+ // Alias readVector to readPos
274
+ };
275
+ return reader;
276
+ };
277
+ var createPacketMock = (overrides) => ({
278
+ type: "data",
279
+ sequence: 0,
280
+ ack: 0,
281
+ qport: 0,
282
+ data: new Uint8Array(0),
283
+ ...overrides
284
+ });
244
285
 
245
286
  // src/shared/bsp.ts
246
287
  var import_shared = require("@quake2ts/shared");
@@ -309,6 +350,28 @@ function makeBrushFromMinsMaxs(mins, maxs, contents = import_shared.CONTENTS_SOL
309
350
  };
310
351
  }
311
352
 
353
+ // src/shared/math.ts
354
+ var createVector3 = (x = 0, y = 0, z = 0) => ({
355
+ x,
356
+ y,
357
+ z
358
+ });
359
+ var createBounds = (mins = createVector3(0, 0, 0), maxs = createVector3(1, 1, 1)) => ({
360
+ mins,
361
+ maxs
362
+ });
363
+ var createTransform = (overrides) => ({
364
+ position: createVector3(),
365
+ rotation: createVector3(),
366
+ scale: createVector3(1, 1, 1),
367
+ ...overrides
368
+ });
369
+ var randomVector3 = (min2 = -100, max2 = 100) => ({
370
+ x: Math.random() * (max2 - min2) + min2,
371
+ y: Math.random() * (max2 - min2) + min2,
372
+ z: Math.random() * (max2 - min2) + min2
373
+ });
374
+
312
375
  // src/game/factories.ts
313
376
  var import_game = require("@quake2ts/game");
314
377
  var createPlayerStateFactory = (overrides) => ({
@@ -464,8 +527,29 @@ function createTriggerEntityFactory(classname, overrides = {}) {
464
527
  // src/game/helpers.ts
465
528
  var import_vitest2 = require("vitest");
466
529
  var import_game2 = require("@quake2ts/game");
467
- var import_shared2 = require("@quake2ts/shared");
468
530
  var import_shared3 = require("@quake2ts/shared");
531
+
532
+ // src/shared/collision.ts
533
+ var import_shared2 = require("@quake2ts/shared");
534
+ var createTraceMock = (overrides) => ({
535
+ fraction: 1,
536
+ endpos: { x: 0, y: 0, z: 0 },
537
+ plane: { normal: { x: 0, y: 0, z: 0 }, dist: 0, type: 0, signbits: 0 },
538
+ surface: { flags: 0 },
539
+ contents: 0,
540
+ ent: null,
541
+ allsolid: false,
542
+ startsolid: false,
543
+ ...overrides
544
+ });
545
+ var createSurfaceMock = (overrides) => ({
546
+ flags: 0,
547
+ name: "default",
548
+ value: 0,
549
+ ...overrides
550
+ });
551
+
552
+ // src/game/helpers.ts
469
553
  var createMockEngine = () => ({
470
554
  sound: import_vitest2.vi.fn(),
471
555
  soundIndex: import_vitest2.vi.fn((sound) => 0),
@@ -476,7 +560,7 @@ var createMockGame = (seed = 12345) => {
476
560
  const spawnRegistry = new import_game2.SpawnRegistry();
477
561
  const hooks = new import_game2.ScriptHookRegistry();
478
562
  const game = {
479
- random: (0, import_shared2.createRandomGenerator)({ seed }),
563
+ random: (0, import_shared3.createRandomGenerator)({ seed }),
480
564
  registerEntitySpawn: import_vitest2.vi.fn((classname, spawnFunc) => {
481
565
  spawnRegistry.register(classname, (entity) => spawnFunc(entity));
482
566
  }),
@@ -502,16 +586,12 @@ function createTestContext(options) {
502
586
  const engine = createMockEngine();
503
587
  const seed = options?.seed ?? 12345;
504
588
  const { game, spawnRegistry } = createMockGame(seed);
505
- const traceFn = import_vitest2.vi.fn((start, end, mins, maxs) => ({
506
- fraction: 1,
507
- ent: null,
508
- allsolid: false,
509
- startsolid: false,
510
- endpos: end,
511
- plane: { normal: { x: 0, y: 0, z: 1 }, dist: 0 },
512
- surfaceFlags: 0,
513
- contents: 0
514
- }));
589
+ const traceFn = import_vitest2.vi.fn(
590
+ (start, end, mins, maxs) => createTraceMock({
591
+ endpos: end,
592
+ plane: { normal: { x: 0, y: 0, z: 1 }, dist: 0, type: 0, signbits: 0 }
593
+ })
594
+ );
515
595
  const entityList = options?.initialEntities ? [...options.initialEntities] : [];
516
596
  const hooks = game.hooks;
517
597
  const entities = {
@@ -558,7 +638,7 @@ function createTestContext(options) {
558
638
  findByTargetName: import_vitest2.vi.fn(() => []),
559
639
  pickTarget: import_vitest2.vi.fn(() => null),
560
640
  killBox: import_vitest2.vi.fn(),
561
- rng: (0, import_shared2.createRandomGenerator)({ seed }),
641
+ rng: (0, import_shared3.createRandomGenerator)({ seed }),
562
642
  imports: {
563
643
  configstring: import_vitest2.vi.fn(),
564
644
  trace: traceFn,
@@ -2057,75 +2137,92 @@ function createMockCanvas(width = 300, height = 150) {
2057
2137
  canvas2.height = height;
2058
2138
  return canvas2;
2059
2139
  }
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);
2140
+ const napiCanvas = new import_canvas2.Canvas(width, height);
2141
+ const canvas = {
2142
+ width,
2143
+ height,
2144
+ getContext: (contextId, options) => {
2145
+ if (contextId === "2d") {
2146
+ return napiCanvas.getContext("2d", options);
2147
+ }
2148
+ if (contextId === "webgl2") {
2149
+ return createMockWebGL2Context(canvas);
2150
+ }
2151
+ return null;
2152
+ },
2153
+ toDataURL: () => napiCanvas.toDataURL(),
2154
+ toBuffer: (mime) => napiCanvas.toBuffer(mime)
2155
+ // Add other properties as needed
2070
2156
  };
2071
2157
  return canvas;
2072
2158
  }
2073
2159
  function createMockCanvasContext2D(canvas) {
2074
- if (!canvas) {
2075
- canvas = createMockCanvas();
2160
+ const c = canvas || createMockCanvas();
2161
+ const ctx = c.getContext("2d");
2162
+ if (!ctx) {
2163
+ throw new Error("Failed to create 2D context");
2076
2164
  }
2077
- return canvas.getContext("2d");
2165
+ return ctx;
2078
2166
  }
2079
2167
  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);
2168
+ const calls = [];
2169
+ const proto = Object.getPrototypeOf(context);
2170
+ for (const key of Object.getOwnPropertyNames(proto)) {
2171
+ const value = context[key];
2172
+ if (typeof value === "function") {
2173
+ context[key] = function(...args) {
2174
+ calls.push({ method: key, args });
2175
+ return value.apply(context, args);
2106
2176
  };
2107
2177
  }
2108
- });
2109
- return drawCalls;
2178
+ }
2179
+ return calls;
2110
2180
  }
2111
2181
  function createMockImageData(width, height, fillColor) {
2112
- const imageData = new import_canvas2.ImageData(width, height);
2182
+ if (typeof global.ImageData !== "undefined") {
2183
+ const data2 = new Uint8ClampedArray(width * height * 4);
2184
+ if (fillColor) {
2185
+ for (let i = 0; i < data2.length; i += 4) {
2186
+ data2[i] = fillColor[0];
2187
+ data2[i + 1] = fillColor[1];
2188
+ data2[i + 2] = fillColor[2];
2189
+ data2[i + 3] = fillColor[3];
2190
+ }
2191
+ }
2192
+ return new global.ImageData(data2, width, height);
2193
+ }
2194
+ const data = new Uint8ClampedArray(width * height * 4);
2113
2195
  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;
2196
+ for (let i = 0; i < data.length; i += 4) {
2197
+ data[i] = fillColor[0];
2198
+ data[i + 1] = fillColor[1];
2199
+ data[i + 2] = fillColor[2];
2200
+ data[i + 3] = fillColor[3];
2120
2201
  }
2121
2202
  }
2122
- return imageData;
2203
+ return new import_canvas2.ImageData(data, width, height);
2123
2204
  }
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;
2205
+ function createMockImage(width = 100, height = 100, src = "") {
2206
+ if (typeof document !== "undefined" && document.createElement) {
2207
+ const img2 = document.createElement("img");
2208
+ img2.width = width;
2209
+ img2.height = height;
2210
+ if (src) img2.src = src;
2211
+ return img2;
2212
+ }
2213
+ const img = {
2214
+ width,
2215
+ height,
2216
+ src,
2217
+ complete: true,
2218
+ onload: null,
2219
+ onerror: null
2220
+ };
2221
+ if (src) {
2222
+ setTimeout(() => {
2223
+ if (img.onload) img.onload();
2224
+ }, 0);
2225
+ }
2129
2226
  return img;
2130
2227
  }
2131
2228
 
@@ -2193,193 +2290,89 @@ function setupWebGPUMocks() {
2193
2290
  }
2194
2291
 
2195
2292
  // src/setup/timing.ts
2196
- var activeMockRAF;
2197
2293
  function createMockRAF() {
2198
2294
  let callbacks = [];
2199
- let nextId = 1;
2295
+ let lastId = 0;
2200
2296
  let currentTime = 0;
2201
2297
  const originalRAF = global.requestAnimationFrame;
2202
2298
  const originalCancelRAF = global.cancelAnimationFrame;
2203
- const raf = (callback) => {
2204
- const id = nextId++;
2205
- callbacks.push({ id, callback });
2206
- return id;
2299
+ global.requestAnimationFrame = (callback) => {
2300
+ lastId++;
2301
+ callbacks.push({ id: lastId, callback });
2302
+ return lastId;
2207
2303
  };
2208
- const cancel = (id) => {
2304
+ global.cancelAnimationFrame = (id) => {
2209
2305
  callbacks = callbacks.filter((cb) => cb.id !== id);
2210
2306
  };
2211
- const mock = {
2212
- tick(timestamp) {
2213
- if (typeof timestamp !== "number") {
2214
- currentTime += 16.6;
2215
- } else {
2216
- currentTime = timestamp;
2217
- }
2307
+ return {
2308
+ tick(time) {
2309
+ if (time) currentTime = time;
2310
+ else currentTime += 16.66;
2218
2311
  const currentCallbacks = [...callbacks];
2219
2312
  callbacks = [];
2220
- currentCallbacks.forEach(({ callback }) => {
2221
- callback(currentTime);
2222
- });
2313
+ currentCallbacks.forEach((cb) => cb.callback(currentTime));
2223
2314
  },
2224
- advance(deltaMs = 16.6) {
2225
- this.tick(currentTime + deltaMs);
2315
+ advance(ms) {
2316
+ currentTime += ms;
2317
+ this.tick(currentTime);
2226
2318
  },
2227
2319
  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
- }
2320
+ return callbacks;
2254
2321
  }
2255
2322
  };
2256
- return mock;
2257
2323
  }
2258
2324
  function createMockPerformance(startTime = 0) {
2259
- let currentTime = startTime;
2260
- const mockPerf = {
2261
- now: () => currentTime,
2325
+ let now = startTime;
2326
+ const mockPerformance = {
2327
+ now: () => now,
2262
2328
  timeOrigin: startTime,
2263
2329
  timing: {
2264
2330
  navigationStart: startTime
2265
2331
  },
2266
- clearMarks: () => {
2267
- },
2268
- clearMeasures: () => {
2332
+ mark: (_name) => {
2269
2333
  },
2270
- clearResourceTimings: () => {
2334
+ measure: (_name, _start, _end) => {
2271
2335
  },
2272
2336
  getEntries: () => [],
2273
- getEntriesByName: () => [],
2274
- getEntriesByType: () => [],
2275
- mark: () => {
2276
- },
2277
- measure: () => {
2337
+ getEntriesByName: (_name) => [],
2338
+ getEntriesByType: (_type) => [],
2339
+ clearMarks: (_name) => {
2278
2340
  },
2279
- setResourceTimingBufferSize: () => {
2341
+ clearMeasures: (_name) => {
2280
2342
  },
2281
- toJSON: () => ({}),
2282
- addEventListener: () => {
2343
+ clearResourceTimings: () => {
2283
2344
  },
2284
- removeEventListener: () => {
2345
+ setResourceTimingBufferSize: (_maxSize) => {
2285
2346
  },
2286
- dispatchEvent: () => true
2287
- };
2288
- mockPerf.advance = (deltaMs) => {
2289
- currentTime += deltaMs;
2290
- };
2291
- mockPerf.setTime = (time) => {
2292
- currentTime = time;
2347
+ onresourcetimingbufferfull: null,
2348
+ toJSON: () => ({})
2293
2349
  };
2294
- return mockPerf;
2350
+ if (typeof global.performance === "undefined") {
2351
+ global.performance = mockPerformance;
2352
+ }
2353
+ return mockPerformance;
2295
2354
  }
2296
2355
  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;
2356
+ console.warn("createControlledTimer: Recommend using vi.useFakeTimers() instead.");
2324
2357
  return {
2325
- tick() {
2326
- this.advanceBy(0);
2358
+ advanceBy: (ms) => {
2327
2359
  },
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;
2351
- },
2352
- clear() {
2353
- timers = [];
2360
+ runAll: () => {
2354
2361
  },
2355
- restore() {
2356
- global.setTimeout = originalSetTimeout;
2357
- global.clearTimeout = originalClearTimeout;
2358
- global.setInterval = originalSetInterval;
2359
- global.clearInterval = originalClearInterval;
2362
+ clear: () => {
2360
2363
  }
2361
2364
  };
2362
2365
  }
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
- }
2367
- for (let i = 0; i < count; i++) {
2368
- if (callback) callback(i);
2369
- activeMockRAF.advance(frameTimeMs);
2370
- }
2371
- }
2372
- function simulateFramesWithMock(mock, count, frameTimeMs = 16.6, callback) {
2366
+ function simulateFrames(count, frameTime = 16, callback) {
2373
2367
  for (let i = 0; i < count; i++) {
2374
2368
  if (callback) callback(i);
2375
- mock.advance(frameTimeMs);
2376
2369
  }
2377
2370
  }
2378
2371
 
2379
2372
  // src/setup/node.ts
2380
2373
  function setupNodeEnvironment(options = {}) {
2381
- if (options.polyfillFetch && typeof global.fetch === "undefined") {
2382
- }
2374
+ }
2375
+ function teardownNodeEnvironment() {
2383
2376
  }
2384
2377
 
2385
2378
  // src/engine/rendering.ts
@@ -2441,186 +2434,141 @@ function createMockRenderingContext() {
2441
2434
  }
2442
2435
 
2443
2436
  // src/setup/storage.ts
2444
- var import_auto2 = require("fake-indexeddb/auto");
2445
- function createMockLocalStorage(initialData = {}) {
2446
- const storage = new Map(Object.entries(initialData));
2437
+ function createStorageMock(initialData = {}) {
2438
+ const store = new Map(Object.entries(initialData));
2447
2439
  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,
2440
+ getItem: (key) => store.get(key) || null,
2441
+ setItem: (key, value) => store.set(key, value.toString()),
2442
+ removeItem: (key) => store.delete(key),
2443
+ clear: () => store.clear(),
2444
+ key: (index) => Array.from(store.keys())[index] || null,
2453
2445
  get length() {
2454
- return storage.size;
2446
+ return store.size;
2455
2447
  }
2456
2448
  };
2457
2449
  }
2450
+ function createMockLocalStorage(initialData = {}) {
2451
+ return createStorageMock(initialData);
2452
+ }
2458
2453
  function createMockSessionStorage(initialData = {}) {
2459
- return createMockLocalStorage(initialData);
2454
+ return createStorageMock(initialData);
2460
2455
  }
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;
2456
+ function createMockIndexedDB(databases) {
2457
+ return global.indexedDB;
2466
2458
  }
2467
2459
  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
2460
  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
- }
2461
+ localStorage: createMockLocalStorage(),
2462
+ sessionStorage: createMockSessionStorage(),
2463
+ indexedDB: createMockIndexedDB()
2532
2464
  };
2533
2465
  }
2534
2466
 
2535
2467
  // 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
2468
  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;
2469
+ class MockAudioContext {
2470
+ constructor() {
2471
+ this.state = "suspended";
2472
+ this.destination = {};
2473
+ this.currentTime = 0;
2474
+ this.listener = {
2475
+ positionX: { value: 0 },
2476
+ positionY: { value: 0 },
2477
+ positionZ: { value: 0 },
2478
+ forwardX: { value: 0 },
2479
+ forwardY: { value: 0 },
2480
+ forwardZ: { value: 0 },
2481
+ upX: { value: 0 },
2482
+ upY: { value: 0 },
2483
+ upZ: { value: 0 },
2484
+ setOrientation: () => {
2485
+ },
2486
+ setPosition: () => {
2487
+ }
2488
+ };
2489
+ }
2490
+ createGain() {
2491
+ return {
2492
+ gain: { value: 1, linearRampToValueAtTime: () => {
2493
+ } },
2494
+ connect: () => {
2495
+ },
2496
+ disconnect: () => {
2497
+ }
2498
+ };
2499
+ }
2500
+ createBufferSource() {
2501
+ return {
2502
+ buffer: null,
2503
+ loop: false,
2504
+ playbackRate: { value: 1 },
2505
+ connect: () => {
2506
+ },
2507
+ start: () => {
2508
+ },
2509
+ stop: () => {
2510
+ },
2511
+ disconnect: () => {
2512
+ },
2513
+ onended: null
2514
+ };
2515
+ }
2516
+ createPanner() {
2517
+ return {
2518
+ panningModel: "equalpower",
2519
+ distanceModel: "inverse",
2520
+ positionX: { value: 0 },
2521
+ positionY: { value: 0 },
2522
+ positionZ: { value: 0 },
2523
+ orientationX: { value: 0 },
2524
+ orientationY: { value: 0 },
2525
+ orientationZ: { value: 0 },
2526
+ coneInnerAngle: 360,
2527
+ coneOuterAngle: 360,
2528
+ coneOuterGain: 0,
2529
+ connect: () => {
2530
+ },
2531
+ disconnect: () => {
2532
+ },
2533
+ setPosition: () => {
2534
+ },
2535
+ setOrientation: () => {
2536
+ }
2537
+ };
2538
+ }
2539
+ createBuffer(numOfChannels, length2, sampleRate) {
2540
+ return {
2541
+ duration: length2 / sampleRate,
2542
+ length: length2,
2543
+ sampleRate,
2544
+ numberOfChannels: numOfChannels,
2545
+ getChannelData: () => new Float32Array(length2)
2546
+ };
2547
+ }
2548
+ decodeAudioData(data, success) {
2549
+ const buffer = this.createBuffer(2, 100, 44100);
2550
+ if (success) success(buffer);
2551
+ return Promise.resolve(buffer);
2552
+ }
2553
+ resume() {
2554
+ return Promise.resolve();
2555
+ }
2556
+ suspend() {
2557
+ return Promise.resolve();
2558
+ }
2559
+ close() {
2560
+ return Promise.resolve();
2561
+ }
2613
2562
  }
2563
+ global.AudioContext = MockAudioContext;
2564
+ global.webkitAudioContext = MockAudioContext;
2614
2565
  }
2615
2566
  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
- }
2567
+ delete global.AudioContext;
2568
+ delete global.webkitAudioContext;
2621
2569
  }
2622
2570
  function captureAudioEvents(context) {
2623
- return context._events || [];
2571
+ return [];
2624
2572
  }
2625
2573
 
2626
2574
  // ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
@@ -3110,217 +3058,110 @@ function simulateCameraMovement(camera, input, deltaTime) {
3110
3058
  }
3111
3059
 
3112
3060
  // 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
3061
  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
- });
3062
+ let playwright;
3063
+ try {
3064
+ playwright = await import("playwright");
3065
+ } catch (e) {
3066
+ throw new Error("Playwright is not installed. Please install it to use this utility.");
3148
3067
  }
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
3068
+ const browser = await playwright.chromium.launch({
3069
+ headless: options.headless ?? true
3157
3070
  });
3158
- const width = options.width || 1280;
3159
- const height = options.height || 720;
3160
3071
  const context = await browser.newContext({
3161
- viewport: { width, height },
3162
- deviceScaleFactor: 1,
3163
- ...options.contextOptions
3072
+ viewport: options.viewport || { width: 1280, height: 720 }
3164
3073
  });
3165
3074
  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
3075
  return {
3184
- browser,
3185
- context,
3186
3076
  page,
3187
- server: staticServer,
3188
- close,
3189
- navigate,
3190
- waitForGame: async (timeout = 1e4) => {
3191
- await waitForGameReady(page, timeout);
3077
+ browser,
3078
+ async navigate(url) {
3079
+ await page.goto(url);
3080
+ },
3081
+ async waitForGame() {
3082
+ await waitForGameReady(page);
3192
3083
  },
3193
- injectInput: async (type, data) => {
3084
+ async injectInput(type, data) {
3194
3085
  await page.evaluate(({ type: type2, data: data2 }) => {
3195
- if (window.injectGameInput) window.injectGameInput(type2, data2);
3086
+ console.log("Injecting input", type2, data2);
3196
3087
  }, { type, data });
3088
+ },
3089
+ async screenshot(name) {
3090
+ return await page.screenshot({ path: `${name}.png` });
3091
+ },
3092
+ async close() {
3093
+ await browser.close();
3197
3094
  }
3198
3095
  };
3199
3096
  }
3200
3097
  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
- }
3098
+ await page.waitForFunction(() => {
3099
+ return window.game && window.game.isRunning;
3100
+ }, { timeout });
3208
3101
  }
3209
3102
  async function captureGameState(page) {
3210
3103
  return await page.evaluate(() => {
3211
- if (window.gameInstance && window.gameInstance.getState) {
3212
- return window.gameInstance.getState();
3213
- }
3214
- return {};
3104
+ const game = window.game;
3105
+ return {
3106
+ time: game ? game.time : 0,
3107
+ entities: game && game.entities ? game.entities.length : 0
3108
+ };
3215
3109
  });
3216
3110
  }
3217
3111
 
3218
3112
  // 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
3113
  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) {
3114
+ switch (condition) {
3115
+ case "good":
3116
+ return { latency: 20, jitter: 5, packetLoss: 0, bandwidth: 10 * 1024 * 1024 };
3117
+ case "slow":
3118
+ return { latency: 150, jitter: 20, packetLoss: 0.01, bandwidth: 1 * 1024 * 1024 };
3119
+ case "unstable":
3120
+ return { latency: 100, jitter: 100, packetLoss: 0.05, bandwidth: 512 * 1024 };
3121
+ case "offline":
3122
+ return { latency: 0, jitter: 0, packetLoss: 1, bandwidth: 0 };
3123
+ case "custom":
3124
+ default:
3125
+ return { latency: 0, jitter: 0, packetLoss: 0, bandwidth: Infinity };
3126
+ }
3127
+ }
3128
+ function createCustomNetworkCondition(latency, jitter, packetLoss) {
3253
3129
  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
- }
3130
+ latency,
3131
+ jitter,
3132
+ packetLoss,
3133
+ bandwidth: Infinity
3134
+ // Default to unlimited unless specified
3273
3135
  };
3274
3136
  }
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);
3137
+ function throttleBandwidth(bytesPerSecond) {
3283
3138
  }
3284
3139
 
3285
3140
  // 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 };
3141
+ async function captureGameScreenshot(page, name) {
3142
+ return await page.screenshot({ path: `${name}.png` });
3143
+ }
3144
+ function compareScreenshots(baseline, current, threshold = 0.01) {
3145
+ if (baseline.length !== current.length) {
3146
+ return { diffPercentage: 1 };
3147
+ }
3148
+ let diffPixels = 0;
3149
+ const totalPixels = baseline.length;
3150
+ for (let i = 0; i < baseline.length; i++) {
3151
+ if (baseline[i] !== current[i]) {
3152
+ diffPixels++;
3153
+ }
3302
3154
  }
3155
+ const diffPercentage = diffPixels / totalPixels;
3303
3156
  return {
3304
- pixelDiff: -1,
3305
- // Unknown magnitude
3306
- matched: false
3157
+ diffPercentage
3158
+ // Generating a diff image buffer would require a library like pixelmatch
3307
3159
  };
3308
3160
  }
3309
- function createVisualTestScenario(page, sceneName) {
3161
+ function createVisualTestScenario(sceneName) {
3310
3162
  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
- }
3163
+ sceneName,
3164
+ setup: async () => {
3324
3165
  }
3325
3166
  };
3326
3167
  }
@@ -3339,6 +3180,7 @@ function createVisualTestScenario(page, sceneName) {
3339
3180
  createBandwidthTestScenario,
3340
3181
  createBinaryStreamMock,
3341
3182
  createBinaryWriterMock,
3183
+ createBounds,
3342
3184
  createCombatTestContext,
3343
3185
  createControlledTimer,
3344
3186
  createCustomNetworkCondition,
@@ -3349,10 +3191,11 @@ function createVisualTestScenario(page, sceneName) {
3349
3191
  createGameStateSnapshotFactory,
3350
3192
  createInputInjector,
3351
3193
  createItemEntityFactory,
3194
+ createMessageReaderMock,
3195
+ createMessageWriterMock,
3352
3196
  createMockAI,
3353
3197
  createMockAmmoItem,
3354
3198
  createMockArmorItem,
3355
- createMockAudioContext,
3356
3199
  createMockCamera,
3357
3200
  createMockCanvas,
3358
3201
  createMockCanvasContext2D,
@@ -3407,6 +3250,7 @@ function createVisualTestScenario(page, sceneName) {
3407
3250
  createMonsterEntityFactory,
3408
3251
  createMultiplayerTestScenario,
3409
3252
  createNetChanMock,
3253
+ createPacketMock,
3410
3254
  createPhysicsTestContext,
3411
3255
  createPlayerEntityFactory,
3412
3256
  createPlayerStateFactory,
@@ -3415,8 +3259,12 @@ function createVisualTestScenario(page, sceneName) {
3415
3259
  createServerSnapshot,
3416
3260
  createSpawnTestContext,
3417
3261
  createStorageTestScenario,
3262
+ createSurfaceMock,
3418
3263
  createTestContext,
3264
+ createTraceMock,
3265
+ createTransform,
3419
3266
  createTriggerEntityFactory,
3267
+ createVector3,
3420
3268
  createViewTestScenario,
3421
3269
  createVisualTestScenario,
3422
3270
  intersects,
@@ -3430,6 +3278,7 @@ function createVisualTestScenario(page, sceneName) {
3430
3278
  makePlane,
3431
3279
  measureSnapshotSize,
3432
3280
  mockMonsterAttacks,
3281
+ randomVector3,
3433
3282
  serializeUserInfo,
3434
3283
  setupBrowserEnvironment,
3435
3284
  setupMockAudioContext,
@@ -3438,7 +3287,6 @@ function createVisualTestScenario(page, sceneName) {
3438
3287
  simulateBandwidthLimit,
3439
3288
  simulateCameraMovement,
3440
3289
  simulateFrames,
3441
- simulateFramesWithMock,
3442
3290
  simulateHandshake,
3443
3291
  simulateNetworkCondition,
3444
3292
  simulatePlayerInput,
@@ -3451,6 +3299,7 @@ function createVisualTestScenario(page, sceneName) {
3451
3299
  stairTrace,
3452
3300
  teardownBrowserEnvironment,
3453
3301
  teardownMockAudioContext,
3302
+ teardownNodeEnvironment,
3454
3303
  throttleBandwidth,
3455
3304
  verifySnapshotConsistency,
3456
3305
  waitForGameReady