quake2ts 0.0.565 → 0.0.567
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/package.json +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/engine/dist/types/render/webgpu/context.d.ts +27 -0
- package/packages/engine/dist/types/render/webgpu/context.d.ts.map +1 -0
- package/packages/test-utils/dist/index.cjs +301 -178
- package/packages/test-utils/dist/index.cjs.map +1 -1
- package/packages/test-utils/dist/index.d.cts +87 -41
- package/packages/test-utils/dist/index.d.ts +87 -41
- package/packages/test-utils/dist/index.js +294 -178
- package/packages/test-utils/dist/index.js.map +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface WebGPUContextOptions {
|
|
2
|
+
powerPreference?: GPUPowerPreference;
|
|
3
|
+
requiredFeatures?: GPUFeatureName[];
|
|
4
|
+
requiredLimits?: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export interface WebGPUContextState {
|
|
7
|
+
adapter: GPUAdapter;
|
|
8
|
+
device: GPUDevice;
|
|
9
|
+
context?: GPUCanvasContext;
|
|
10
|
+
format: GPUTextureFormat;
|
|
11
|
+
features: Set<GPUFeatureName>;
|
|
12
|
+
limits: GPUSupportedLimits;
|
|
13
|
+
isHeadless: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates and initializes a WebGPU context.
|
|
17
|
+
*
|
|
18
|
+
* Handles adapter selection, device creation, and context configuration.
|
|
19
|
+
* Supports both browser (canvas) and headless environments.
|
|
20
|
+
*
|
|
21
|
+
* @param canvas - Optional canvas element for rendering. If omitted, assumes headless mode.
|
|
22
|
+
* @param options - Configuration options for device creation.
|
|
23
|
+
* @returns Initialized WebGPU context state.
|
|
24
|
+
* @throws Error if WebGPU is not supported or device creation fails.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createWebGPUContext(canvas?: HTMLCanvasElement, options?: WebGPUContextOptions): Promise<WebGPUContextState>;
|
|
27
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/render/webgpu/context.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,EAAE,kBAAkB,CAAC;IACrC,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAGD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,CAAC,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAsE7B"}
|
|
@@ -52,6 +52,9 @@ __export(index_exports, {
|
|
|
52
52
|
createMockCanvasContext2D: () => createMockCanvasContext2D,
|
|
53
53
|
createMockConnection: () => createMockConnection,
|
|
54
54
|
createMockEngine: () => createMockEngine,
|
|
55
|
+
createMockGPUAdapter: () => createMockGPUAdapter,
|
|
56
|
+
createMockGPUCanvasContext: () => createMockGPUCanvasContext,
|
|
57
|
+
createMockGPUDevice: () => createMockGPUDevice,
|
|
55
58
|
createMockGame: () => createMockGame,
|
|
56
59
|
createMockGameState: () => createMockGameState,
|
|
57
60
|
createMockHandshake: () => createMockHandshake,
|
|
@@ -62,8 +65,10 @@ __export(index_exports, {
|
|
|
62
65
|
createMockNetworkAddress: () => createMockNetworkAddress,
|
|
63
66
|
createMockPerformance: () => createMockPerformance,
|
|
64
67
|
createMockRAF: () => createMockRAF,
|
|
68
|
+
createMockRConClient: () => createMockRConClient,
|
|
65
69
|
createMockServer: () => createMockServer,
|
|
66
70
|
createMockServerClient: () => createMockServerClient,
|
|
71
|
+
createMockServerConsole: () => createMockServerConsole,
|
|
67
72
|
createMockServerState: () => createMockServerState,
|
|
68
73
|
createMockServerStatic: () => createMockServerStatic,
|
|
69
74
|
createMockSessionStorage: () => createMockSessionStorage,
|
|
@@ -93,6 +98,7 @@ __export(index_exports, {
|
|
|
93
98
|
setupBrowserEnvironment: () => setupBrowserEnvironment,
|
|
94
99
|
setupMockAudioContext: () => setupMockAudioContext,
|
|
95
100
|
setupNodeEnvironment: () => setupNodeEnvironment,
|
|
101
|
+
setupWebGPUMocks: () => setupWebGPUMocks,
|
|
96
102
|
simulateFrames: () => simulateFrames,
|
|
97
103
|
simulateFramesWithMock: () => simulateFramesWithMock,
|
|
98
104
|
simulateHandshake: () => simulateHandshake,
|
|
@@ -100,6 +106,7 @@ __export(index_exports, {
|
|
|
100
106
|
simulatePlayerInput: () => simulatePlayerInput,
|
|
101
107
|
simulatePlayerJoin: () => simulatePlayerJoin,
|
|
102
108
|
simulatePlayerLeave: () => simulatePlayerLeave,
|
|
109
|
+
simulateServerCommand: () => simulateServerCommand,
|
|
103
110
|
simulateServerTick: () => simulateServerTick,
|
|
104
111
|
simulateSnapshotDelivery: () => simulateSnapshotDelivery,
|
|
105
112
|
stairTrace: () => import_shared3.stairTrace,
|
|
@@ -769,6 +776,52 @@ async function simulateHandshake(client, server) {
|
|
|
769
776
|
return true;
|
|
770
777
|
}
|
|
771
778
|
|
|
779
|
+
// src/server/mocks/commands.ts
|
|
780
|
+
var import_vitest5 = require("vitest");
|
|
781
|
+
function createMockServerConsole(overrides) {
|
|
782
|
+
const outputBuffer = [];
|
|
783
|
+
const commandBuffer = [];
|
|
784
|
+
return {
|
|
785
|
+
exec: import_vitest5.vi.fn((cmd) => {
|
|
786
|
+
commandBuffer.push(cmd);
|
|
787
|
+
return `Executed: ${cmd}`;
|
|
788
|
+
}),
|
|
789
|
+
print: import_vitest5.vi.fn((text) => {
|
|
790
|
+
outputBuffer.push(text);
|
|
791
|
+
}),
|
|
792
|
+
broadcast: import_vitest5.vi.fn((text) => {
|
|
793
|
+
outputBuffer.push(`Broadcast: ${text}`);
|
|
794
|
+
}),
|
|
795
|
+
commandBuffer,
|
|
796
|
+
outputBuffer,
|
|
797
|
+
...overrides
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function createMockRConClient(password = "") {
|
|
801
|
+
return {
|
|
802
|
+
connected: false,
|
|
803
|
+
lastCommand: "",
|
|
804
|
+
lastResponse: "",
|
|
805
|
+
connect: import_vitest5.vi.fn(async (address, port, pwd) => {
|
|
806
|
+
return pwd === password;
|
|
807
|
+
}),
|
|
808
|
+
sendCommand: import_vitest5.vi.fn(async (cmd) => {
|
|
809
|
+
return `RCON Response for: ${cmd}`;
|
|
810
|
+
}),
|
|
811
|
+
disconnect: import_vitest5.vi.fn()
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
function simulateServerCommand(server, command) {
|
|
815
|
+
if (server.executeBuffer) {
|
|
816
|
+
server.executeBuffer(command);
|
|
817
|
+
return "Executed";
|
|
818
|
+
}
|
|
819
|
+
if (server.exec) {
|
|
820
|
+
return server.exec(command);
|
|
821
|
+
}
|
|
822
|
+
return "Unknown command handler";
|
|
823
|
+
}
|
|
824
|
+
|
|
772
825
|
// src/server/helpers/multiplayer.ts
|
|
773
826
|
var import_server3 = require("@quake2ts/server");
|
|
774
827
|
function createMultiplayerTestScenario(numPlayers = 2) {
|
|
@@ -1397,193 +1450,67 @@ function createMockImage(width, height, src) {
|
|
|
1397
1450
|
return img;
|
|
1398
1451
|
}
|
|
1399
1452
|
|
|
1400
|
-
// src/
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
// src/setup/storage.ts
|
|
1407
|
-
var import_auto2 = require("fake-indexeddb/auto");
|
|
1408
|
-
function createMockLocalStorage(initialData = {}) {
|
|
1409
|
-
const storage = new Map(Object.entries(initialData));
|
|
1453
|
+
// src/engine/mocks/webgpu.ts
|
|
1454
|
+
var import_vitest6 = require("vitest");
|
|
1455
|
+
function createMockGPUAdapter() {
|
|
1410
1456
|
return {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
clear: () => storage.clear(),
|
|
1415
|
-
key: (index) => Array.from(storage.keys())[index] || null,
|
|
1416
|
-
get length() {
|
|
1417
|
-
return storage.size;
|
|
1418
|
-
}
|
|
1457
|
+
requestDevice: import_vitest6.vi.fn().mockResolvedValue(createMockGPUDevice()),
|
|
1458
|
+
features: /* @__PURE__ */ new Set(),
|
|
1459
|
+
limits: {}
|
|
1419
1460
|
};
|
|
1420
1461
|
}
|
|
1421
|
-
function
|
|
1422
|
-
return
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1462
|
+
function createMockGPUDevice() {
|
|
1463
|
+
return {
|
|
1464
|
+
features: /* @__PURE__ */ new Set(),
|
|
1465
|
+
limits: {},
|
|
1466
|
+
queue: {
|
|
1467
|
+
submit: import_vitest6.vi.fn(),
|
|
1468
|
+
writeBuffer: import_vitest6.vi.fn(),
|
|
1469
|
+
writeTexture: import_vitest6.vi.fn(),
|
|
1470
|
+
copyExternalImageToTexture: import_vitest6.vi.fn()
|
|
1471
|
+
},
|
|
1472
|
+
createCommandEncoder: import_vitest6.vi.fn().mockReturnValue({
|
|
1473
|
+
beginRenderPass: import_vitest6.vi.fn().mockReturnValue({
|
|
1474
|
+
setPipeline: import_vitest6.vi.fn(),
|
|
1475
|
+
draw: import_vitest6.vi.fn(),
|
|
1476
|
+
end: import_vitest6.vi.fn()
|
|
1477
|
+
}),
|
|
1478
|
+
finish: import_vitest6.vi.fn()
|
|
1479
|
+
}),
|
|
1480
|
+
createRenderPipeline: import_vitest6.vi.fn(),
|
|
1481
|
+
createShaderModule: import_vitest6.vi.fn(),
|
|
1482
|
+
createBindGroup: import_vitest6.vi.fn(),
|
|
1483
|
+
createBindGroupLayout: import_vitest6.vi.fn(),
|
|
1484
|
+
createBuffer: import_vitest6.vi.fn(),
|
|
1485
|
+
createTexture: import_vitest6.vi.fn(),
|
|
1486
|
+
createSampler: import_vitest6.vi.fn()
|
|
1487
|
+
};
|
|
1429
1488
|
}
|
|
1430
|
-
function
|
|
1431
|
-
if (storageType === "indexed") {
|
|
1432
|
-
const dbName = `test-db-${Math.random().toString(36).substring(7)}`;
|
|
1433
|
-
const storeName = "test-store";
|
|
1434
|
-
const storage2 = createMockIndexedDB();
|
|
1435
|
-
return {
|
|
1436
|
-
storage: storage2,
|
|
1437
|
-
populate: async (data) => {
|
|
1438
|
-
return new Promise((resolve, reject) => {
|
|
1439
|
-
const req = storage2.open(dbName, 1);
|
|
1440
|
-
req.onupgradeneeded = (e) => {
|
|
1441
|
-
const db = e.target.result;
|
|
1442
|
-
db.createObjectStore(storeName);
|
|
1443
|
-
};
|
|
1444
|
-
req.onsuccess = (e) => {
|
|
1445
|
-
const db = e.target.result;
|
|
1446
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
1447
|
-
const store = tx.objectStore(storeName);
|
|
1448
|
-
Object.entries(data).forEach(([k, v]) => store.put(v, k));
|
|
1449
|
-
tx.oncomplete = () => {
|
|
1450
|
-
db.close();
|
|
1451
|
-
resolve();
|
|
1452
|
-
};
|
|
1453
|
-
tx.onerror = () => reject(tx.error);
|
|
1454
|
-
};
|
|
1455
|
-
req.onerror = () => reject(req.error);
|
|
1456
|
-
});
|
|
1457
|
-
},
|
|
1458
|
-
verify: async (key, value) => {
|
|
1459
|
-
return new Promise((resolve, reject) => {
|
|
1460
|
-
const req = storage2.open(dbName, 1);
|
|
1461
|
-
req.onsuccess = (e) => {
|
|
1462
|
-
const db = e.target.result;
|
|
1463
|
-
if (!db.objectStoreNames.contains(storeName)) {
|
|
1464
|
-
db.close();
|
|
1465
|
-
resolve(false);
|
|
1466
|
-
return;
|
|
1467
|
-
}
|
|
1468
|
-
const tx = db.transaction(storeName, "readonly");
|
|
1469
|
-
const store = tx.objectStore(storeName);
|
|
1470
|
-
const getReq = store.get(key);
|
|
1471
|
-
getReq.onsuccess = () => {
|
|
1472
|
-
const result = getReq.result === value;
|
|
1473
|
-
db.close();
|
|
1474
|
-
resolve(result);
|
|
1475
|
-
};
|
|
1476
|
-
getReq.onerror = () => {
|
|
1477
|
-
db.close();
|
|
1478
|
-
resolve(false);
|
|
1479
|
-
};
|
|
1480
|
-
};
|
|
1481
|
-
req.onerror = () => reject(req.error);
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
};
|
|
1485
|
-
}
|
|
1486
|
-
const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
|
|
1489
|
+
function createMockGPUCanvasContext() {
|
|
1487
1490
|
return {
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
},
|
|
1492
|
-
verify(key, value) {
|
|
1493
|
-
return storage.getItem(key) === value;
|
|
1494
|
-
}
|
|
1491
|
+
configure: import_vitest6.vi.fn(),
|
|
1492
|
+
unconfigure: import_vitest6.vi.fn(),
|
|
1493
|
+
getCurrentTexture: import_vitest6.vi.fn()
|
|
1495
1494
|
};
|
|
1496
1495
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
connect: () => {
|
|
1503
|
-
},
|
|
1504
|
-
gain: { value: 1, setValueAtTime: () => {
|
|
1505
|
-
} }
|
|
1506
|
-
}),
|
|
1507
|
-
createOscillator: () => ({
|
|
1508
|
-
connect: () => {
|
|
1509
|
-
},
|
|
1510
|
-
start: () => {
|
|
1511
|
-
},
|
|
1512
|
-
stop: () => {
|
|
1513
|
-
},
|
|
1514
|
-
frequency: { value: 440 }
|
|
1515
|
-
}),
|
|
1516
|
-
createBufferSource: () => ({
|
|
1517
|
-
connect: () => {
|
|
1518
|
-
},
|
|
1519
|
-
start: () => {
|
|
1520
|
-
},
|
|
1521
|
-
stop: () => {
|
|
1522
|
-
},
|
|
1523
|
-
buffer: null,
|
|
1524
|
-
playbackRate: { value: 1 },
|
|
1525
|
-
loop: false
|
|
1526
|
-
}),
|
|
1527
|
-
destination: {},
|
|
1528
|
-
currentTime: 0,
|
|
1529
|
-
state: "running",
|
|
1530
|
-
resume: async () => {
|
|
1531
|
-
},
|
|
1532
|
-
suspend: async () => {
|
|
1533
|
-
},
|
|
1534
|
-
close: async () => {
|
|
1535
|
-
},
|
|
1536
|
-
decodeAudioData: async (buffer) => ({
|
|
1537
|
-
duration: 1,
|
|
1538
|
-
length: 44100,
|
|
1539
|
-
sampleRate: 44100,
|
|
1540
|
-
numberOfChannels: 2,
|
|
1541
|
-
getChannelData: () => new Float32Array(44100)
|
|
1542
|
-
}),
|
|
1543
|
-
createBuffer: (channels, length, sampleRate) => ({
|
|
1544
|
-
duration: length / sampleRate,
|
|
1545
|
-
length,
|
|
1546
|
-
sampleRate,
|
|
1547
|
-
numberOfChannels: channels,
|
|
1548
|
-
getChannelData: () => new Float32Array(length)
|
|
1549
|
-
}),
|
|
1550
|
-
// Helper to track events if needed
|
|
1551
|
-
_events: []
|
|
1496
|
+
function setupWebGPUMocks() {
|
|
1497
|
+
const mockAdapter = createMockGPUAdapter();
|
|
1498
|
+
const mockGpu = {
|
|
1499
|
+
requestAdapter: import_vitest6.vi.fn().mockResolvedValue(mockAdapter),
|
|
1500
|
+
getPreferredCanvasFormat: import_vitest6.vi.fn().mockReturnValue("bgra8unorm")
|
|
1552
1501
|
};
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
if (typeof value === "function") {
|
|
1558
|
-
return (...args) => {
|
|
1559
|
-
target._events.push({ type: String(prop), args });
|
|
1560
|
-
return Reflect.apply(value, target, args);
|
|
1561
|
-
};
|
|
1562
|
-
}
|
|
1563
|
-
return value;
|
|
1564
|
-
}
|
|
1502
|
+
Object.defineProperty(global.navigator, "gpu", {
|
|
1503
|
+
value: mockGpu,
|
|
1504
|
+
writable: true,
|
|
1505
|
+
configurable: true
|
|
1565
1506
|
});
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
};
|
|
1574
|
-
global.window.AudioContext = global.AudioContext;
|
|
1575
|
-
global.window.webkitAudioContext = global.AudioContext;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
function teardownMockAudioContext() {
|
|
1579
|
-
if (global.AudioContext && global.AudioContext.toString().includes("class")) {
|
|
1580
|
-
delete global.AudioContext;
|
|
1581
|
-
delete global.window.AudioContext;
|
|
1582
|
-
delete global.window.webkitAudioContext;
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
function captureAudioEvents(context) {
|
|
1586
|
-
return context._events || [];
|
|
1507
|
+
global.GPUTextureUsage = {
|
|
1508
|
+
COPY_SRC: 1,
|
|
1509
|
+
COPY_DST: 2,
|
|
1510
|
+
TEXTURE_BINDING: 4,
|
|
1511
|
+
STORAGE_BINDING: 8,
|
|
1512
|
+
RENDER_ATTACHMENT: 16
|
|
1513
|
+
};
|
|
1587
1514
|
}
|
|
1588
1515
|
|
|
1589
1516
|
// src/setup/timing.ts
|
|
@@ -1770,6 +1697,195 @@ function simulateFramesWithMock(mock, count, frameTimeMs = 16.6, callback) {
|
|
|
1770
1697
|
}
|
|
1771
1698
|
}
|
|
1772
1699
|
|
|
1700
|
+
// src/setup/node.ts
|
|
1701
|
+
function setupNodeEnvironment(options = {}) {
|
|
1702
|
+
if (options.polyfillFetch && typeof global.fetch === "undefined") {
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
// src/setup/storage.ts
|
|
1707
|
+
var import_auto2 = require("fake-indexeddb/auto");
|
|
1708
|
+
function createMockLocalStorage(initialData = {}) {
|
|
1709
|
+
const storage = new Map(Object.entries(initialData));
|
|
1710
|
+
return {
|
|
1711
|
+
getItem: (key) => storage.get(key) || null,
|
|
1712
|
+
setItem: (key, value) => storage.set(key, value),
|
|
1713
|
+
removeItem: (key) => storage.delete(key),
|
|
1714
|
+
clear: () => storage.clear(),
|
|
1715
|
+
key: (index) => Array.from(storage.keys())[index] || null,
|
|
1716
|
+
get length() {
|
|
1717
|
+
return storage.size;
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
function createMockSessionStorage(initialData = {}) {
|
|
1722
|
+
return createMockLocalStorage(initialData);
|
|
1723
|
+
}
|
|
1724
|
+
function createMockIndexedDB() {
|
|
1725
|
+
if (typeof indexedDB === "undefined") {
|
|
1726
|
+
throw new Error("IndexedDB mock not found. Ensure fake-indexeddb is loaded.");
|
|
1727
|
+
}
|
|
1728
|
+
return indexedDB;
|
|
1729
|
+
}
|
|
1730
|
+
function createStorageTestScenario(storageType = "local") {
|
|
1731
|
+
if (storageType === "indexed") {
|
|
1732
|
+
const dbName = `test-db-${Math.random().toString(36).substring(7)}`;
|
|
1733
|
+
const storeName = "test-store";
|
|
1734
|
+
const storage2 = createMockIndexedDB();
|
|
1735
|
+
return {
|
|
1736
|
+
storage: storage2,
|
|
1737
|
+
populate: async (data) => {
|
|
1738
|
+
return new Promise((resolve, reject) => {
|
|
1739
|
+
const req = storage2.open(dbName, 1);
|
|
1740
|
+
req.onupgradeneeded = (e) => {
|
|
1741
|
+
const db = e.target.result;
|
|
1742
|
+
db.createObjectStore(storeName);
|
|
1743
|
+
};
|
|
1744
|
+
req.onsuccess = (e) => {
|
|
1745
|
+
const db = e.target.result;
|
|
1746
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1747
|
+
const store = tx.objectStore(storeName);
|
|
1748
|
+
Object.entries(data).forEach(([k, v]) => store.put(v, k));
|
|
1749
|
+
tx.oncomplete = () => {
|
|
1750
|
+
db.close();
|
|
1751
|
+
resolve();
|
|
1752
|
+
};
|
|
1753
|
+
tx.onerror = () => reject(tx.error);
|
|
1754
|
+
};
|
|
1755
|
+
req.onerror = () => reject(req.error);
|
|
1756
|
+
});
|
|
1757
|
+
},
|
|
1758
|
+
verify: async (key, value) => {
|
|
1759
|
+
return new Promise((resolve, reject) => {
|
|
1760
|
+
const req = storage2.open(dbName, 1);
|
|
1761
|
+
req.onsuccess = (e) => {
|
|
1762
|
+
const db = e.target.result;
|
|
1763
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
1764
|
+
db.close();
|
|
1765
|
+
resolve(false);
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1769
|
+
const store = tx.objectStore(storeName);
|
|
1770
|
+
const getReq = store.get(key);
|
|
1771
|
+
getReq.onsuccess = () => {
|
|
1772
|
+
const result = getReq.result === value;
|
|
1773
|
+
db.close();
|
|
1774
|
+
resolve(result);
|
|
1775
|
+
};
|
|
1776
|
+
getReq.onerror = () => {
|
|
1777
|
+
db.close();
|
|
1778
|
+
resolve(false);
|
|
1779
|
+
};
|
|
1780
|
+
};
|
|
1781
|
+
req.onerror = () => reject(req.error);
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
|
|
1787
|
+
return {
|
|
1788
|
+
storage,
|
|
1789
|
+
populate(data) {
|
|
1790
|
+
Object.entries(data).forEach(([k, v]) => storage.setItem(k, v));
|
|
1791
|
+
},
|
|
1792
|
+
verify(key, value) {
|
|
1793
|
+
return storage.getItem(key) === value;
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// src/setup/audio.ts
|
|
1799
|
+
function createMockAudioContext() {
|
|
1800
|
+
const context = {
|
|
1801
|
+
createGain: () => ({
|
|
1802
|
+
connect: () => {
|
|
1803
|
+
},
|
|
1804
|
+
gain: { value: 1, setValueAtTime: () => {
|
|
1805
|
+
} }
|
|
1806
|
+
}),
|
|
1807
|
+
createOscillator: () => ({
|
|
1808
|
+
connect: () => {
|
|
1809
|
+
},
|
|
1810
|
+
start: () => {
|
|
1811
|
+
},
|
|
1812
|
+
stop: () => {
|
|
1813
|
+
},
|
|
1814
|
+
frequency: { value: 440 }
|
|
1815
|
+
}),
|
|
1816
|
+
createBufferSource: () => ({
|
|
1817
|
+
connect: () => {
|
|
1818
|
+
},
|
|
1819
|
+
start: () => {
|
|
1820
|
+
},
|
|
1821
|
+
stop: () => {
|
|
1822
|
+
},
|
|
1823
|
+
buffer: null,
|
|
1824
|
+
playbackRate: { value: 1 },
|
|
1825
|
+
loop: false
|
|
1826
|
+
}),
|
|
1827
|
+
destination: {},
|
|
1828
|
+
currentTime: 0,
|
|
1829
|
+
state: "running",
|
|
1830
|
+
resume: async () => {
|
|
1831
|
+
},
|
|
1832
|
+
suspend: async () => {
|
|
1833
|
+
},
|
|
1834
|
+
close: async () => {
|
|
1835
|
+
},
|
|
1836
|
+
decodeAudioData: async (buffer) => ({
|
|
1837
|
+
duration: 1,
|
|
1838
|
+
length: 44100,
|
|
1839
|
+
sampleRate: 44100,
|
|
1840
|
+
numberOfChannels: 2,
|
|
1841
|
+
getChannelData: () => new Float32Array(44100)
|
|
1842
|
+
}),
|
|
1843
|
+
createBuffer: (channels, length, sampleRate) => ({
|
|
1844
|
+
duration: length / sampleRate,
|
|
1845
|
+
length,
|
|
1846
|
+
sampleRate,
|
|
1847
|
+
numberOfChannels: channels,
|
|
1848
|
+
getChannelData: () => new Float32Array(length)
|
|
1849
|
+
}),
|
|
1850
|
+
// Helper to track events if needed
|
|
1851
|
+
_events: []
|
|
1852
|
+
};
|
|
1853
|
+
return new Proxy(context, {
|
|
1854
|
+
get(target, prop, receiver) {
|
|
1855
|
+
if (prop === "_events") return target._events;
|
|
1856
|
+
const value = Reflect.get(target, prop, receiver);
|
|
1857
|
+
if (typeof value === "function") {
|
|
1858
|
+
return (...args) => {
|
|
1859
|
+
target._events.push({ type: String(prop), args });
|
|
1860
|
+
return Reflect.apply(value, target, args);
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
return value;
|
|
1864
|
+
}
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
function setupMockAudioContext() {
|
|
1868
|
+
if (typeof global.AudioContext === "undefined" && typeof global.window !== "undefined") {
|
|
1869
|
+
global.AudioContext = class {
|
|
1870
|
+
constructor() {
|
|
1871
|
+
return createMockAudioContext();
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
global.window.AudioContext = global.AudioContext;
|
|
1875
|
+
global.window.webkitAudioContext = global.AudioContext;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
function teardownMockAudioContext() {
|
|
1879
|
+
if (global.AudioContext && global.AudioContext.toString().includes("class")) {
|
|
1880
|
+
delete global.AudioContext;
|
|
1881
|
+
delete global.window.AudioContext;
|
|
1882
|
+
delete global.window.webkitAudioContext;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
function captureAudioEvents(context) {
|
|
1886
|
+
return context._events || [];
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1773
1889
|
// src/e2e/playwright.ts
|
|
1774
1890
|
var import_playwright = require("playwright");
|
|
1775
1891
|
var import_http = require("http");
|
|
@@ -2009,6 +2125,9 @@ function createVisualTestScenario(page, sceneName) {
|
|
|
2009
2125
|
createMockCanvasContext2D,
|
|
2010
2126
|
createMockConnection,
|
|
2011
2127
|
createMockEngine,
|
|
2128
|
+
createMockGPUAdapter,
|
|
2129
|
+
createMockGPUCanvasContext,
|
|
2130
|
+
createMockGPUDevice,
|
|
2012
2131
|
createMockGame,
|
|
2013
2132
|
createMockGameState,
|
|
2014
2133
|
createMockHandshake,
|
|
@@ -2019,8 +2138,10 @@ function createVisualTestScenario(page, sceneName) {
|
|
|
2019
2138
|
createMockNetworkAddress,
|
|
2020
2139
|
createMockPerformance,
|
|
2021
2140
|
createMockRAF,
|
|
2141
|
+
createMockRConClient,
|
|
2022
2142
|
createMockServer,
|
|
2023
2143
|
createMockServerClient,
|
|
2144
|
+
createMockServerConsole,
|
|
2024
2145
|
createMockServerState,
|
|
2025
2146
|
createMockServerStatic,
|
|
2026
2147
|
createMockSessionStorage,
|
|
@@ -2050,6 +2171,7 @@ function createVisualTestScenario(page, sceneName) {
|
|
|
2050
2171
|
setupBrowserEnvironment,
|
|
2051
2172
|
setupMockAudioContext,
|
|
2052
2173
|
setupNodeEnvironment,
|
|
2174
|
+
setupWebGPUMocks,
|
|
2053
2175
|
simulateFrames,
|
|
2054
2176
|
simulateFramesWithMock,
|
|
2055
2177
|
simulateHandshake,
|
|
@@ -2057,6 +2179,7 @@ function createVisualTestScenario(page, sceneName) {
|
|
|
2057
2179
|
simulatePlayerInput,
|
|
2058
2180
|
simulatePlayerJoin,
|
|
2059
2181
|
simulatePlayerLeave,
|
|
2182
|
+
simulateServerCommand,
|
|
2060
2183
|
simulateServerTick,
|
|
2061
2184
|
simulateSnapshotDelivery,
|
|
2062
2185
|
stairTrace,
|