quake2ts 0.0.621 → 0.0.630
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/resources.d.ts +107 -60
- package/packages/engine/dist/types/render/webgpu/resources.d.ts.map +1 -1
- package/packages/test-utils/dist/index.cjs +947 -115
- package/packages/test-utils/dist/index.cjs.map +1 -1
- package/packages/test-utils/dist/index.d.cts +214 -8
- package/packages/test-utils/dist/index.d.ts +214 -8
- package/packages/test-utils/dist/index.js +906 -114
- package/packages/test-utils/dist/index.js.map +1 -1
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
HandshakeStage: () => HandshakeStage,
|
|
43
43
|
InputInjector: () => InputInjector,
|
|
44
44
|
MockAudioBufferSourceNode: () => FakeBufferSource,
|
|
45
|
+
MockClientConfigStrings: () => MockClientConfigStrings,
|
|
45
46
|
MockNetDriver: () => MockNetDriver,
|
|
46
47
|
MockNetworkTransport: () => MockNetworkTransport,
|
|
47
48
|
MockPointerLock: () => MockPointerLock,
|
|
@@ -58,6 +59,7 @@ __export(index_exports, {
|
|
|
58
59
|
createBinaryWriterMock: () => createBinaryWriterMock,
|
|
59
60
|
createBounds: () => createBounds,
|
|
60
61
|
createCombatTestContext: () => createCombatTestContext,
|
|
62
|
+
createComputeTestSetup: () => createComputeTestSetup,
|
|
61
63
|
createConfigStringArrayMock: () => createConfigStringArrayMock,
|
|
62
64
|
createConfigStringMock: () => createConfigStringMock,
|
|
63
65
|
createControlledTimer: () => createControlledTimer,
|
|
@@ -68,33 +70,49 @@ __export(index_exports, {
|
|
|
68
70
|
createEntityFactory: () => createEntityFactory,
|
|
69
71
|
createEntityStateFactory: () => createEntityStateFactory,
|
|
70
72
|
createGameStateSnapshotFactory: () => createGameStateSnapshotFactory,
|
|
73
|
+
createHeadlessTestContext: () => createHeadlessTestContext,
|
|
71
74
|
createInputInjector: () => createInputInjector,
|
|
75
|
+
createInterpolationTestData: () => createInterpolationTestData,
|
|
72
76
|
createItemEntityFactory: () => createItemEntityFactory,
|
|
73
77
|
createMessageReaderMock: () => createMessageReaderMock,
|
|
74
78
|
createMessageWriterMock: () => createMessageWriterMock,
|
|
75
79
|
createMockAI: () => createMockAI,
|
|
76
80
|
createMockAmmoItem: () => createMockAmmoItem,
|
|
77
81
|
createMockArmorItem: () => createMockArmorItem,
|
|
82
|
+
createMockAssetManager: () => createMockAssetManager,
|
|
78
83
|
createMockAudioBuffer: () => createMockAudioBuffer,
|
|
79
84
|
createMockAudioContext: () => createMockAudioContext,
|
|
85
|
+
createMockBspMap: () => createMockBspMap,
|
|
80
86
|
createMockBspPipeline: () => createMockBspPipeline,
|
|
81
87
|
createMockBufferSource: () => createMockBufferSource,
|
|
82
88
|
createMockCamera: () => createMockCamera,
|
|
83
89
|
createMockCanvas: () => createMockCanvas,
|
|
84
90
|
createMockCanvasContext2D: () => createMockCanvasContext2D,
|
|
85
91
|
createMockChatMessage: () => createMockChatMessage,
|
|
92
|
+
createMockClientInfo: () => createMockClientInfo,
|
|
93
|
+
createMockClientState: () => createMockClientState,
|
|
86
94
|
createMockCollisionEntityIndex: () => createMockCollisionEntityIndex,
|
|
95
|
+
createMockCommand: () => createMockCommand,
|
|
96
|
+
createMockCommandEncoder: () => createMockCommandEncoder,
|
|
97
|
+
createMockComputePassEncoder: () => createMockComputePassEncoder,
|
|
98
|
+
createMockComputePipeline: () => createMockComputePipeline,
|
|
87
99
|
createMockConnection: () => createMockConnection,
|
|
100
|
+
createMockConnectionState: () => createMockConnectionState,
|
|
101
|
+
createMockConsole: () => createMockConsole,
|
|
102
|
+
createMockCvarRegistry: () => createMockCvarRegistry,
|
|
88
103
|
createMockDamageIndicator: () => createMockDamageIndicator,
|
|
89
104
|
createMockDamageInfo: () => createMockDamageInfo,
|
|
90
105
|
createMockDeltaFrame: () => createMockDeltaFrame,
|
|
106
|
+
createMockDownloadManager: () => createMockDownloadManager,
|
|
91
107
|
createMockEngine: () => createMockEngine,
|
|
92
108
|
createMockEntityState: () => createMockEntityState,
|
|
93
109
|
createMockFogData: () => createMockFogData,
|
|
110
|
+
createMockFrame: () => createMockFrame,
|
|
94
111
|
createMockFrameRenderer: () => createMockFrameRenderer,
|
|
95
112
|
createMockGPUAdapter: () => createMockGPUAdapter,
|
|
96
|
-
|
|
113
|
+
createMockGPUBuffer: () => createMockGPUBuffer,
|
|
97
114
|
createMockGPUDevice: () => createMockGPUDevice,
|
|
115
|
+
createMockGPUTexture: () => createMockGPUTexture,
|
|
98
116
|
createMockGame: () => createMockGame,
|
|
99
117
|
createMockGameExports: () => createMockGameExports,
|
|
100
118
|
createMockGameState: () => createMockGameState,
|
|
@@ -109,7 +127,9 @@ __export(index_exports, {
|
|
|
109
127
|
createMockKeyboardEvent: () => createMockKeyboardEvent,
|
|
110
128
|
createMockLocalStorage: () => createMockLocalStorage,
|
|
111
129
|
createMockMasterServer: () => createMockMasterServer,
|
|
130
|
+
createMockMd2Model: () => createMockMd2Model,
|
|
112
131
|
createMockMd2Pipeline: () => createMockMd2Pipeline,
|
|
132
|
+
createMockMd3Model: () => createMockMd3Model,
|
|
113
133
|
createMockMd3Pipeline: () => createMockMd3Pipeline,
|
|
114
134
|
createMockMonsterAI: () => createMockMonsterAI,
|
|
115
135
|
createMockMonsterMove: () => createMockMonsterMove,
|
|
@@ -121,12 +141,17 @@ __export(index_exports, {
|
|
|
121
141
|
createMockPerformance: () => createMockPerformance,
|
|
122
142
|
createMockPointerLock: () => createMockPointerLock,
|
|
123
143
|
createMockPowerupItem: () => createMockPowerupItem,
|
|
144
|
+
createMockPrecacheList: () => createMockPrecacheList,
|
|
145
|
+
createMockQueue: () => createMockQueue,
|
|
124
146
|
createMockRAF: () => createMockRAF,
|
|
125
147
|
createMockRConClient: () => createMockRConClient,
|
|
126
148
|
createMockRateLimiter: () => createMockRateLimiter,
|
|
127
149
|
createMockRefDef: () => createMockRefDef,
|
|
150
|
+
createMockRenderPassEncoder: () => createMockRenderPassEncoder,
|
|
151
|
+
createMockRenderPipeline: () => createMockRenderPipeline,
|
|
128
152
|
createMockRenderer: () => createMockRenderer,
|
|
129
153
|
createMockRenderingContext: () => createMockRenderingContext,
|
|
154
|
+
createMockSampler: () => createMockSampler,
|
|
130
155
|
createMockScoreboard: () => createMockScoreboard,
|
|
131
156
|
createMockServer: () => createMockServer,
|
|
132
157
|
createMockServerClient: () => createMockServerClient,
|
|
@@ -136,9 +161,12 @@ __export(index_exports, {
|
|
|
136
161
|
createMockServerState: () => createMockServerState,
|
|
137
162
|
createMockServerStatic: () => createMockServerStatic,
|
|
138
163
|
createMockSessionStorage: () => createMockSessionStorage,
|
|
164
|
+
createMockShaderModule: () => createMockShaderModule,
|
|
139
165
|
createMockSkyboxPipeline: () => createMockSkyboxPipeline,
|
|
140
166
|
createMockSnapshot: () => createMockSnapshot,
|
|
141
167
|
createMockSpritePipeline: () => createMockSpritePipeline,
|
|
168
|
+
createMockTexture: () => createMockTexture,
|
|
169
|
+
createMockTextureView: () => createMockTextureView,
|
|
142
170
|
createMockTransport: () => createMockTransport,
|
|
143
171
|
createMockUDPSocket: () => createMockUDPSocket,
|
|
144
172
|
createMockUserInfo: () => createMockUserInfo,
|
|
@@ -146,6 +174,7 @@ __export(index_exports, {
|
|
|
146
174
|
createMockWeapon: () => createMockWeapon,
|
|
147
175
|
createMockWeaponItem: () => createMockWeaponItem,
|
|
148
176
|
createMockWebGL2Context: () => createMockWebGL2Context,
|
|
177
|
+
createMockWebGPUContext: () => createMockWebGPUContext,
|
|
149
178
|
createMockWheelEvent: () => createMockWheelEvent,
|
|
150
179
|
createMonsterEntityFactory: () => createMonsterEntityFactory,
|
|
151
180
|
createMultiplayerTestScenario: () => createMultiplayerTestScenario,
|
|
@@ -156,7 +185,9 @@ __export(index_exports, {
|
|
|
156
185
|
createPlayerEntityFactory: () => createPlayerEntityFactory,
|
|
157
186
|
createPlayerStateFactory: () => createPlayerStateFactory,
|
|
158
187
|
createPlaywrightTestClient: () => createPlaywrightTestClient,
|
|
188
|
+
createPredictionTestScenario: () => createPredictionTestScenario,
|
|
159
189
|
createProjectileEntityFactory: () => createProjectileEntityFactory,
|
|
190
|
+
createRenderTestSetup: () => createRenderTestSetup,
|
|
160
191
|
createServerSnapshot: () => createServerSnapshot,
|
|
161
192
|
createSpawnTestContext: () => createSpawnTestContext,
|
|
162
193
|
createStorageTestScenario: () => createStorageTestScenario,
|
|
@@ -168,6 +199,7 @@ __export(index_exports, {
|
|
|
168
199
|
createVector3: () => createVector3,
|
|
169
200
|
createViewTestScenario: () => createViewTestScenario,
|
|
170
201
|
createVisualTestScenario: () => createVisualTestScenario,
|
|
202
|
+
initHeadlessWebGPU: () => initHeadlessWebGPU,
|
|
171
203
|
intersects: () => import_shared2.intersects,
|
|
172
204
|
ladderTrace: () => import_shared2.ladderTrace,
|
|
173
205
|
makeAxisBrush: () => makeAxisBrush,
|
|
@@ -180,6 +212,8 @@ __export(index_exports, {
|
|
|
180
212
|
measureSnapshotSize: () => measureSnapshotSize,
|
|
181
213
|
mockMonsterAttacks: () => mockMonsterAttacks,
|
|
182
214
|
randomVector3: () => randomVector3,
|
|
215
|
+
renderAndCapture: () => renderAndCapture,
|
|
216
|
+
runComputeAndReadback: () => runComputeAndReadback,
|
|
183
217
|
serializeUserInfo: () => serializeUserInfo,
|
|
184
218
|
setupBrowserEnvironment: () => setupBrowserEnvironment,
|
|
185
219
|
setupMockAudioContext: () => setupMockAudioContext,
|
|
@@ -187,6 +221,8 @@ __export(index_exports, {
|
|
|
187
221
|
setupWebGPUMocks: () => setupWebGPUMocks,
|
|
188
222
|
simulateBandwidthLimit: () => simulateBandwidthLimit,
|
|
189
223
|
simulateCameraMovement: () => simulateCameraMovement,
|
|
224
|
+
simulateClientPrediction: () => simulateClientPrediction,
|
|
225
|
+
simulateDownload: () => simulateDownload,
|
|
190
226
|
simulateFrames: () => simulateFrames,
|
|
191
227
|
simulateGravity: () => simulateGravity,
|
|
192
228
|
simulateHandshake: () => simulateHandshake,
|
|
@@ -207,7 +243,10 @@ __export(index_exports, {
|
|
|
207
243
|
teardownBrowserEnvironment: () => teardownBrowserEnvironment,
|
|
208
244
|
teardownMockAudioContext: () => teardownMockAudioContext,
|
|
209
245
|
teardownNodeEnvironment: () => teardownNodeEnvironment,
|
|
246
|
+
testComputeShader: () => testComputeShader,
|
|
247
|
+
testPipelineRendering: () => testPipelineRendering,
|
|
210
248
|
throttleBandwidth: () => throttleBandwidth,
|
|
249
|
+
verifySmoothing: () => verifySmoothing,
|
|
211
250
|
verifySnapshotConsistency: () => verifySnapshotConsistency,
|
|
212
251
|
waitForGameReady: () => waitForGameReady
|
|
213
252
|
});
|
|
@@ -663,6 +702,7 @@ function createTestContext(options) {
|
|
|
663
702
|
const entities = {
|
|
664
703
|
spawn: import_vitest2.vi.fn(() => {
|
|
665
704
|
const ent = new import_game2.Entity(entityList.length + 1);
|
|
705
|
+
ent.inUse = true;
|
|
666
706
|
entityList.push(ent);
|
|
667
707
|
hooks.onEntitySpawn(ent);
|
|
668
708
|
return ent;
|
|
@@ -672,6 +712,7 @@ function createTestContext(options) {
|
|
|
672
712
|
if (idx !== -1) {
|
|
673
713
|
entityList.splice(idx, 1);
|
|
674
714
|
}
|
|
715
|
+
ent.inUse = false;
|
|
675
716
|
hooks.onEntityRemove(ent);
|
|
676
717
|
}),
|
|
677
718
|
finalizeSpawn: import_vitest2.vi.fn(),
|
|
@@ -680,6 +721,7 @@ function createTestContext(options) {
|
|
|
680
721
|
if (idx !== -1) {
|
|
681
722
|
entityList.splice(idx, 1);
|
|
682
723
|
}
|
|
724
|
+
ent.inUse = false;
|
|
683
725
|
}),
|
|
684
726
|
setSpawnRegistry: import_vitest2.vi.fn(),
|
|
685
727
|
timeSeconds: 10,
|
|
@@ -2506,99 +2548,281 @@ function createMockImage(width = 100, height = 100, src = "") {
|
|
|
2506
2548
|
return img;
|
|
2507
2549
|
}
|
|
2508
2550
|
|
|
2509
|
-
//
|
|
2510
|
-
var
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2551
|
+
// ../../node_modules/.pnpm/webgpu@0.3.8/node_modules/webgpu/index.js
|
|
2552
|
+
var import_node_path = require("path");
|
|
2553
|
+
var import_node_url = require("url");
|
|
2554
|
+
var import_module = require("module");
|
|
2555
|
+
var import_meta = {};
|
|
2556
|
+
var require2 = (0, import_module.createRequire)(import_meta.url);
|
|
2557
|
+
var isMac = process.platform === "darwin";
|
|
2558
|
+
var __dirname = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
2559
|
+
var arch = isMac ? "universal" : process.arch;
|
|
2560
|
+
var dawnNodePath = (0, import_node_path.join)(__dirname, "dist", `${process.platform}-${arch}.dawn.node`);
|
|
2561
|
+
var { create, globals } = require2(dawnNodePath);
|
|
2562
|
+
|
|
2563
|
+
// src/setup/webgpu.ts
|
|
2564
|
+
async function initHeadlessWebGPU(options) {
|
|
2565
|
+
if (typeof process === "undefined" || process.release?.name !== "node") {
|
|
2566
|
+
throw new Error("initHeadlessWebGPU should only be called in a Node.js environment");
|
|
2567
|
+
}
|
|
2568
|
+
if (!globalThis.navigator) {
|
|
2569
|
+
globalThis.navigator = {};
|
|
2570
|
+
}
|
|
2571
|
+
if (!globalThis.navigator.gpu) {
|
|
2572
|
+
const gpu = create([]);
|
|
2573
|
+
try {
|
|
2574
|
+
Object.defineProperty(globalThis.navigator, "gpu", {
|
|
2575
|
+
value: gpu,
|
|
2576
|
+
writable: true,
|
|
2577
|
+
configurable: true
|
|
2578
|
+
});
|
|
2579
|
+
} catch (e) {
|
|
2580
|
+
console.warn("Could not define navigator.gpu, trying direct assignment");
|
|
2581
|
+
globalThis.navigator.gpu = gpu;
|
|
2582
|
+
}
|
|
2583
|
+
Object.assign(globalThis, globals);
|
|
2584
|
+
}
|
|
2585
|
+
const adapter = await navigator.gpu.requestAdapter({
|
|
2586
|
+
powerPreference: options?.powerPreference || "high-performance"
|
|
2587
|
+
});
|
|
2588
|
+
if (!adapter) {
|
|
2589
|
+
throw new Error("Failed to create WebGPU adapter");
|
|
2590
|
+
}
|
|
2591
|
+
const device = await adapter.requestDevice({
|
|
2592
|
+
requiredFeatures: options?.requiredFeatures || []
|
|
2593
|
+
});
|
|
2594
|
+
if (!device) {
|
|
2595
|
+
throw new Error("Failed to create WebGPU device");
|
|
2596
|
+
}
|
|
2524
2597
|
return {
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
lost: new Promise(() => {
|
|
2530
|
-
}),
|
|
2531
|
-
// Pending promise
|
|
2532
|
-
createShaderModule: import_vitest12.vi.fn(),
|
|
2533
|
-
createBindGroupLayout: import_vitest12.vi.fn(),
|
|
2534
|
-
createPipelineLayout: import_vitest12.vi.fn(),
|
|
2535
|
-
createRenderPipeline: import_vitest12.vi.fn(),
|
|
2536
|
-
createCommandEncoder: import_vitest12.vi.fn().mockReturnValue({
|
|
2537
|
-
copyTextureToBuffer: import_vitest12.vi.fn(),
|
|
2538
|
-
finish: import_vitest12.vi.fn()
|
|
2539
|
-
}),
|
|
2540
|
-
createBuffer: import_vitest12.vi.fn(),
|
|
2541
|
-
createTexture: import_vitest12.vi.fn().mockReturnValue({
|
|
2542
|
-
createView: import_vitest12.vi.fn()
|
|
2543
|
-
}),
|
|
2544
|
-
queue: {
|
|
2545
|
-
submit: import_vitest12.vi.fn(),
|
|
2546
|
-
writeBuffer: import_vitest12.vi.fn(),
|
|
2547
|
-
writeTexture: import_vitest12.vi.fn()
|
|
2598
|
+
adapter,
|
|
2599
|
+
device,
|
|
2600
|
+
cleanup: async () => {
|
|
2601
|
+
device.destroy();
|
|
2548
2602
|
}
|
|
2549
2603
|
};
|
|
2550
2604
|
}
|
|
2551
|
-
function
|
|
2605
|
+
async function createHeadlessTestContext() {
|
|
2606
|
+
const { adapter, device } = await initHeadlessWebGPU();
|
|
2552
2607
|
return {
|
|
2553
|
-
|
|
2554
|
-
|
|
2608
|
+
adapter,
|
|
2609
|
+
device,
|
|
2610
|
+
queue: device.queue
|
|
2555
2611
|
};
|
|
2556
2612
|
}
|
|
2613
|
+
|
|
2614
|
+
// src/engine/mocks/webgpu.ts
|
|
2615
|
+
var import_vitest12 = require("vitest");
|
|
2557
2616
|
function setupWebGPUMocks() {
|
|
2558
|
-
|
|
2617
|
+
Object.assign(globalThis, globals);
|
|
2559
2618
|
const mockGpu = {
|
|
2560
|
-
requestAdapter: import_vitest12.vi.fn()
|
|
2619
|
+
requestAdapter: import_vitest12.vi.fn(),
|
|
2561
2620
|
getPreferredCanvasFormat: import_vitest12.vi.fn().mockReturnValue("bgra8unorm")
|
|
2562
2621
|
};
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
});
|
|
2570
|
-
if (typeof GPUTextureUsage === "undefined") {
|
|
2571
|
-
global.GPUTextureUsage = {
|
|
2572
|
-
COPY_SRC: 1,
|
|
2573
|
-
COPY_DST: 2,
|
|
2574
|
-
TEXTURE_BINDING: 4,
|
|
2575
|
-
STORAGE_BINDING: 8,
|
|
2576
|
-
RENDER_ATTACHMENT: 16
|
|
2577
|
-
};
|
|
2578
|
-
}
|
|
2579
|
-
if (typeof GPUBufferUsage === "undefined") {
|
|
2580
|
-
global.GPUBufferUsage = {
|
|
2581
|
-
MAP_READ: 1,
|
|
2582
|
-
MAP_WRITE: 2,
|
|
2583
|
-
COPY_SRC: 4,
|
|
2584
|
-
COPY_DST: 8,
|
|
2585
|
-
INDEX: 16,
|
|
2586
|
-
VERTEX: 32,
|
|
2587
|
-
UNIFORM: 64,
|
|
2588
|
-
STORAGE: 128,
|
|
2589
|
-
INDIRECT: 256,
|
|
2590
|
-
QUERY_RESOLVE: 512
|
|
2591
|
-
};
|
|
2622
|
+
const mockAdapter = createMockGPUAdapter();
|
|
2623
|
+
const mockDevice = createMockGPUDevice();
|
|
2624
|
+
mockGpu.requestAdapter.mockResolvedValue(mockAdapter);
|
|
2625
|
+
mockAdapter.requestDevice.mockResolvedValue(mockDevice);
|
|
2626
|
+
if (!globalThis.navigator) {
|
|
2627
|
+
globalThis.navigator = {};
|
|
2592
2628
|
}
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2629
|
+
try {
|
|
2630
|
+
Object.defineProperty(globalThis.navigator, "gpu", {
|
|
2631
|
+
value: mockGpu,
|
|
2632
|
+
writable: true,
|
|
2633
|
+
configurable: true
|
|
2634
|
+
});
|
|
2635
|
+
} catch (e) {
|
|
2636
|
+
globalThis.navigator.gpu = mockGpu;
|
|
2598
2637
|
}
|
|
2599
2638
|
return {
|
|
2600
2639
|
mockGpu,
|
|
2601
|
-
mockAdapter
|
|
2640
|
+
mockAdapter,
|
|
2641
|
+
mockDevice
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
function createMockGPUAdapter(options = {}) {
|
|
2645
|
+
return {
|
|
2646
|
+
features: /* @__PURE__ */ new Set(),
|
|
2647
|
+
limits: {},
|
|
2648
|
+
isFallbackAdapter: false,
|
|
2649
|
+
requestDevice: import_vitest12.vi.fn().mockResolvedValue(createMockGPUDevice()),
|
|
2650
|
+
requestAdapterInfo: import_vitest12.vi.fn().mockResolvedValue({}),
|
|
2651
|
+
...options
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2654
|
+
function createMockGPUDevice(features = /* @__PURE__ */ new Set()) {
|
|
2655
|
+
const queue = createMockQueue();
|
|
2656
|
+
return {
|
|
2657
|
+
features,
|
|
2658
|
+
limits: {},
|
|
2659
|
+
queue,
|
|
2660
|
+
destroy: import_vitest12.vi.fn(),
|
|
2661
|
+
createBuffer: import_vitest12.vi.fn((descriptor) => createMockGPUBuffer(descriptor)),
|
|
2662
|
+
createTexture: import_vitest12.vi.fn((descriptor) => createMockGPUTexture(descriptor)),
|
|
2663
|
+
createSampler: import_vitest12.vi.fn(() => createMockSampler()),
|
|
2664
|
+
createBindGroupLayout: import_vitest12.vi.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2665
|
+
createPipelineLayout: import_vitest12.vi.fn(() => ({ label: "mock-pipeline-layout" })),
|
|
2666
|
+
createBindGroup: import_vitest12.vi.fn(() => ({ label: "mock-bind-group" })),
|
|
2667
|
+
createShaderModule: import_vitest12.vi.fn((descriptor) => createMockShaderModule(descriptor)),
|
|
2668
|
+
createComputePipeline: import_vitest12.vi.fn(() => createMockComputePipeline()),
|
|
2669
|
+
createRenderPipeline: import_vitest12.vi.fn(() => createMockRenderPipeline()),
|
|
2670
|
+
createComputePipelineAsync: import_vitest12.vi.fn().mockResolvedValue(createMockComputePipeline()),
|
|
2671
|
+
createRenderPipelineAsync: import_vitest12.vi.fn().mockResolvedValue(createMockRenderPipeline()),
|
|
2672
|
+
createCommandEncoder: import_vitest12.vi.fn(() => createMockCommandEncoder()),
|
|
2673
|
+
createQuerySet: import_vitest12.vi.fn(() => ({ label: "mock-query-set" })),
|
|
2674
|
+
pushErrorScope: import_vitest12.vi.fn(),
|
|
2675
|
+
popErrorScope: import_vitest12.vi.fn().mockResolvedValue(null),
|
|
2676
|
+
addEventListener: import_vitest12.vi.fn(),
|
|
2677
|
+
removeEventListener: import_vitest12.vi.fn(),
|
|
2678
|
+
dispatchEvent: import_vitest12.vi.fn(),
|
|
2679
|
+
onuncapturederror: null,
|
|
2680
|
+
label: "",
|
|
2681
|
+
lost: Promise.resolve({ reason: "destroyed", message: "Device lost" })
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2684
|
+
function createMockQueue() {
|
|
2685
|
+
return {
|
|
2686
|
+
submit: import_vitest12.vi.fn(),
|
|
2687
|
+
onSubmittedWorkDone: import_vitest12.vi.fn().mockResolvedValue(void 0),
|
|
2688
|
+
writeBuffer: import_vitest12.vi.fn(),
|
|
2689
|
+
writeTexture: import_vitest12.vi.fn(),
|
|
2690
|
+
copyExternalImageToTexture: import_vitest12.vi.fn(),
|
|
2691
|
+
label: ""
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
function createMockGPUBuffer(descriptor) {
|
|
2695
|
+
return {
|
|
2696
|
+
size: descriptor.size,
|
|
2697
|
+
usage: descriptor.usage,
|
|
2698
|
+
mapState: "unmapped",
|
|
2699
|
+
mapAsync: import_vitest12.vi.fn().mockResolvedValue(void 0),
|
|
2700
|
+
getMappedRange: import_vitest12.vi.fn(() => new ArrayBuffer(descriptor.size)),
|
|
2701
|
+
unmap: import_vitest12.vi.fn(),
|
|
2702
|
+
destroy: import_vitest12.vi.fn(),
|
|
2703
|
+
label: descriptor.label || ""
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
function createMockGPUTexture(descriptor) {
|
|
2707
|
+
const size = descriptor.size;
|
|
2708
|
+
let width = 0;
|
|
2709
|
+
let height = 0;
|
|
2710
|
+
let depthOrArrayLayers = 1;
|
|
2711
|
+
if (Array.isArray(size) || size instanceof Float32Array || size instanceof Uint32Array) {
|
|
2712
|
+
const arr = Array.from(size);
|
|
2713
|
+
width = arr[0] || 0;
|
|
2714
|
+
height = arr[1] || 1;
|
|
2715
|
+
depthOrArrayLayers = arr[2] || 1;
|
|
2716
|
+
} else if (typeof size === "object") {
|
|
2717
|
+
const dict = size;
|
|
2718
|
+
width = dict.width;
|
|
2719
|
+
height = dict.height || 1;
|
|
2720
|
+
depthOrArrayLayers = dict.depthOrArrayLayers || 1;
|
|
2721
|
+
}
|
|
2722
|
+
return {
|
|
2723
|
+
width,
|
|
2724
|
+
height,
|
|
2725
|
+
depthOrArrayLayers,
|
|
2726
|
+
mipLevelCount: descriptor.mipLevelCount || 1,
|
|
2727
|
+
sampleCount: descriptor.sampleCount || 1,
|
|
2728
|
+
dimension: descriptor.dimension || "2d",
|
|
2729
|
+
format: descriptor.format,
|
|
2730
|
+
usage: descriptor.usage,
|
|
2731
|
+
createView: import_vitest12.vi.fn(() => createMockTextureView()),
|
|
2732
|
+
destroy: import_vitest12.vi.fn(),
|
|
2733
|
+
label: descriptor.label || ""
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
function createMockTextureView() {
|
|
2737
|
+
return {
|
|
2738
|
+
label: ""
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
function createMockSampler() {
|
|
2742
|
+
return {
|
|
2743
|
+
label: ""
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
function createMockShaderModule(descriptor) {
|
|
2747
|
+
return {
|
|
2748
|
+
getCompilationInfo: import_vitest12.vi.fn().mockResolvedValue({ messages: [] }),
|
|
2749
|
+
label: descriptor.label || ""
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
function createMockComputePipeline() {
|
|
2753
|
+
return {
|
|
2754
|
+
getBindGroupLayout: import_vitest12.vi.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2755
|
+
label: ""
|
|
2756
|
+
};
|
|
2757
|
+
}
|
|
2758
|
+
function createMockRenderPipeline() {
|
|
2759
|
+
return {
|
|
2760
|
+
getBindGroupLayout: import_vitest12.vi.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2761
|
+
label: ""
|
|
2762
|
+
};
|
|
2763
|
+
}
|
|
2764
|
+
function createMockCommandEncoder() {
|
|
2765
|
+
return {
|
|
2766
|
+
beginRenderPass: import_vitest12.vi.fn(() => createMockRenderPassEncoder()),
|
|
2767
|
+
beginComputePass: import_vitest12.vi.fn(() => createMockComputePassEncoder()),
|
|
2768
|
+
copyBufferToBuffer: import_vitest12.vi.fn(),
|
|
2769
|
+
copyBufferToTexture: import_vitest12.vi.fn(),
|
|
2770
|
+
copyTextureToBuffer: import_vitest12.vi.fn(),
|
|
2771
|
+
copyTextureToTexture: import_vitest12.vi.fn(),
|
|
2772
|
+
clearBuffer: import_vitest12.vi.fn(),
|
|
2773
|
+
writeTimestamp: import_vitest12.vi.fn(),
|
|
2774
|
+
resolveQuerySet: import_vitest12.vi.fn(),
|
|
2775
|
+
finish: import_vitest12.vi.fn(() => ({ label: "mock-command-buffer" })),
|
|
2776
|
+
pushDebugGroup: import_vitest12.vi.fn(),
|
|
2777
|
+
popDebugGroup: import_vitest12.vi.fn(),
|
|
2778
|
+
insertDebugMarker: import_vitest12.vi.fn(),
|
|
2779
|
+
label: ""
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
function createMockRenderPassEncoder() {
|
|
2783
|
+
return {
|
|
2784
|
+
setPipeline: import_vitest12.vi.fn(),
|
|
2785
|
+
setIndexBuffer: import_vitest12.vi.fn(),
|
|
2786
|
+
setVertexBuffer: import_vitest12.vi.fn(),
|
|
2787
|
+
setBindGroup: import_vitest12.vi.fn(),
|
|
2788
|
+
setViewport: import_vitest12.vi.fn(),
|
|
2789
|
+
setScissorRect: import_vitest12.vi.fn(),
|
|
2790
|
+
setBlendConstant: import_vitest12.vi.fn(),
|
|
2791
|
+
setStencilReference: import_vitest12.vi.fn(),
|
|
2792
|
+
beginOcclusionQuery: import_vitest12.vi.fn(),
|
|
2793
|
+
endOcclusionQuery: import_vitest12.vi.fn(),
|
|
2794
|
+
executeBundles: import_vitest12.vi.fn(),
|
|
2795
|
+
draw: import_vitest12.vi.fn(),
|
|
2796
|
+
drawIndexed: import_vitest12.vi.fn(),
|
|
2797
|
+
drawIndirect: import_vitest12.vi.fn(),
|
|
2798
|
+
drawIndexedIndirect: import_vitest12.vi.fn(),
|
|
2799
|
+
end: import_vitest12.vi.fn(),
|
|
2800
|
+
pushDebugGroup: import_vitest12.vi.fn(),
|
|
2801
|
+
popDebugGroup: import_vitest12.vi.fn(),
|
|
2802
|
+
insertDebugMarker: import_vitest12.vi.fn(),
|
|
2803
|
+
label: ""
|
|
2804
|
+
};
|
|
2805
|
+
}
|
|
2806
|
+
function createMockComputePassEncoder() {
|
|
2807
|
+
return {
|
|
2808
|
+
setPipeline: import_vitest12.vi.fn(),
|
|
2809
|
+
setBindGroup: import_vitest12.vi.fn(),
|
|
2810
|
+
dispatchWorkgroups: import_vitest12.vi.fn(),
|
|
2811
|
+
dispatchWorkgroupsIndirect: import_vitest12.vi.fn(),
|
|
2812
|
+
end: import_vitest12.vi.fn(),
|
|
2813
|
+
pushDebugGroup: import_vitest12.vi.fn(),
|
|
2814
|
+
popDebugGroup: import_vitest12.vi.fn(),
|
|
2815
|
+
insertDebugMarker: import_vitest12.vi.fn(),
|
|
2816
|
+
label: ""
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
function createMockWebGPUContext() {
|
|
2820
|
+
const adapter = createMockGPUAdapter();
|
|
2821
|
+
const device = createMockGPUDevice();
|
|
2822
|
+
return {
|
|
2823
|
+
adapter,
|
|
2824
|
+
device,
|
|
2825
|
+
queue: device.queue
|
|
2602
2826
|
};
|
|
2603
2827
|
}
|
|
2604
2828
|
|
|
@@ -3002,20 +3226,140 @@ function createMockSkyboxPipeline(overrides) {
|
|
|
3002
3226
|
};
|
|
3003
3227
|
}
|
|
3004
3228
|
|
|
3005
|
-
// src/engine/
|
|
3229
|
+
// src/engine/mocks/assets.ts
|
|
3006
3230
|
var import_vitest14 = require("vitest");
|
|
3231
|
+
function createMockAssetManager(overrides) {
|
|
3232
|
+
return {
|
|
3233
|
+
textures: {
|
|
3234
|
+
get: import_vitest14.vi.fn(),
|
|
3235
|
+
set: import_vitest14.vi.fn(),
|
|
3236
|
+
has: import_vitest14.vi.fn(),
|
|
3237
|
+
clear: import_vitest14.vi.fn(),
|
|
3238
|
+
memoryUsage: 0
|
|
3239
|
+
},
|
|
3240
|
+
audio: {
|
|
3241
|
+
load: import_vitest14.vi.fn(),
|
|
3242
|
+
get: import_vitest14.vi.fn(),
|
|
3243
|
+
clearAll: import_vitest14.vi.fn()
|
|
3244
|
+
},
|
|
3245
|
+
loadTexture: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3246
|
+
registerTexture: import_vitest14.vi.fn(),
|
|
3247
|
+
loadSound: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3248
|
+
loadMd2Model: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3249
|
+
getMd2Model: import_vitest14.vi.fn(),
|
|
3250
|
+
loadMd3Model: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3251
|
+
getMd3Model: import_vitest14.vi.fn(),
|
|
3252
|
+
loadSprite: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3253
|
+
loadMap: import_vitest14.vi.fn().mockResolvedValue({}),
|
|
3254
|
+
getMap: import_vitest14.vi.fn(),
|
|
3255
|
+
loadPalette: import_vitest14.vi.fn().mockResolvedValue(void 0),
|
|
3256
|
+
isAssetLoaded: import_vitest14.vi.fn().mockReturnValue(true),
|
|
3257
|
+
listFiles: import_vitest14.vi.fn().mockReturnValue([]),
|
|
3258
|
+
resetForLevelChange: import_vitest14.vi.fn(),
|
|
3259
|
+
getMemoryUsage: import_vitest14.vi.fn().mockReturnValue({ textures: 0, audio: 0 }),
|
|
3260
|
+
clearCache: import_vitest14.vi.fn(),
|
|
3261
|
+
preloadAssets: import_vitest14.vi.fn().mockResolvedValue(void 0),
|
|
3262
|
+
queueLoad: import_vitest14.vi.fn().mockImplementation((path2) => Promise.resolve({})),
|
|
3263
|
+
...overrides
|
|
3264
|
+
};
|
|
3265
|
+
}
|
|
3266
|
+
function createMockTexture(width = 1, height = 1, data) {
|
|
3267
|
+
return {
|
|
3268
|
+
width,
|
|
3269
|
+
height,
|
|
3270
|
+
data: data || new Uint8Array(width * height * 4).fill(255),
|
|
3271
|
+
format: 0,
|
|
3272
|
+
// RGBA
|
|
3273
|
+
name: "mock_texture",
|
|
3274
|
+
uploaded: false
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
function createMockMd2Model(overrides) {
|
|
3278
|
+
return {
|
|
3279
|
+
header: {
|
|
3280
|
+
skinWidth: 0,
|
|
3281
|
+
skinHeight: 0,
|
|
3282
|
+
frameSize: 0,
|
|
3283
|
+
numSkins: 0,
|
|
3284
|
+
numVertices: 0,
|
|
3285
|
+
numSt: 0,
|
|
3286
|
+
numTriangles: 0,
|
|
3287
|
+
numGlCmds: 0,
|
|
3288
|
+
numFrames: 0,
|
|
3289
|
+
offsetSkins: 0,
|
|
3290
|
+
offsetSt: 0,
|
|
3291
|
+
offsetTriangles: 0,
|
|
3292
|
+
offsetFrames: 0,
|
|
3293
|
+
offsetGlCmds: 0,
|
|
3294
|
+
offsetEnd: 0
|
|
3295
|
+
},
|
|
3296
|
+
skins: [],
|
|
3297
|
+
texCoords: [],
|
|
3298
|
+
triangles: [],
|
|
3299
|
+
frames: [],
|
|
3300
|
+
glCommands: new Int32Array(0),
|
|
3301
|
+
...overrides
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
function createMockMd3Model(overrides) {
|
|
3305
|
+
return {
|
|
3306
|
+
header: {
|
|
3307
|
+
ident: 0,
|
|
3308
|
+
version: 0,
|
|
3309
|
+
name: "",
|
|
3310
|
+
flags: 0,
|
|
3311
|
+
numFrames: 0,
|
|
3312
|
+
numTags: 0,
|
|
3313
|
+
numSurfaces: 0,
|
|
3314
|
+
numSkins: 0,
|
|
3315
|
+
offsetFrames: 0,
|
|
3316
|
+
offsetTags: 0,
|
|
3317
|
+
offsetSurfaces: 0,
|
|
3318
|
+
offsetEnd: 0
|
|
3319
|
+
},
|
|
3320
|
+
frames: [],
|
|
3321
|
+
tags: [],
|
|
3322
|
+
surfaces: [],
|
|
3323
|
+
...overrides
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3326
|
+
function createMockBspMap(overrides) {
|
|
3327
|
+
return {
|
|
3328
|
+
version: 38,
|
|
3329
|
+
entities: [],
|
|
3330
|
+
planes: [],
|
|
3331
|
+
vertices: [],
|
|
3332
|
+
visibility: new Uint8Array(0),
|
|
3333
|
+
nodes: [],
|
|
3334
|
+
texInfo: [],
|
|
3335
|
+
faces: [],
|
|
3336
|
+
lightmaps: [],
|
|
3337
|
+
leafs: [],
|
|
3338
|
+
leafFaces: [],
|
|
3339
|
+
leafBrushes: [],
|
|
3340
|
+
edges: [],
|
|
3341
|
+
faceEdges: [],
|
|
3342
|
+
models: [],
|
|
3343
|
+
brushes: [],
|
|
3344
|
+
brushSides: [],
|
|
3345
|
+
...overrides
|
|
3346
|
+
};
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
// src/engine/rendering.ts
|
|
3350
|
+
var import_vitest15 = require("vitest");
|
|
3007
3351
|
function createMockRenderingContext() {
|
|
3008
3352
|
const gl = createMockWebGL2Context();
|
|
3009
3353
|
const camera = {
|
|
3010
|
-
update:
|
|
3011
|
-
getViewMatrix:
|
|
3012
|
-
getProjectionMatrix:
|
|
3013
|
-
getViewProjectionMatrix:
|
|
3014
|
-
getPosition:
|
|
3015
|
-
getForward:
|
|
3016
|
-
getRight:
|
|
3017
|
-
getUp:
|
|
3018
|
-
extractFrustumPlanes:
|
|
3354
|
+
update: import_vitest15.vi.fn(),
|
|
3355
|
+
getViewMatrix: import_vitest15.vi.fn().mockReturnValue(new Float32Array(16)),
|
|
3356
|
+
getProjectionMatrix: import_vitest15.vi.fn().mockReturnValue(new Float32Array(16)),
|
|
3357
|
+
getViewProjectionMatrix: import_vitest15.vi.fn().mockReturnValue(new Float32Array(16)),
|
|
3358
|
+
getPosition: import_vitest15.vi.fn().mockReturnValue([0, 0, 0]),
|
|
3359
|
+
getForward: import_vitest15.vi.fn().mockReturnValue([0, 0, -1]),
|
|
3360
|
+
getRight: import_vitest15.vi.fn().mockReturnValue([1, 0, 0]),
|
|
3361
|
+
getUp: import_vitest15.vi.fn().mockReturnValue([0, 1, 0]),
|
|
3362
|
+
extractFrustumPlanes: import_vitest15.vi.fn(),
|
|
3019
3363
|
transform: {
|
|
3020
3364
|
origin: [0, 0, 0],
|
|
3021
3365
|
angles: [0, 0, 0],
|
|
@@ -3023,29 +3367,29 @@ function createMockRenderingContext() {
|
|
|
3023
3367
|
}
|
|
3024
3368
|
};
|
|
3025
3369
|
const md2 = {
|
|
3026
|
-
render:
|
|
3027
|
-
init:
|
|
3028
|
-
resize:
|
|
3370
|
+
render: import_vitest15.vi.fn(),
|
|
3371
|
+
init: import_vitest15.vi.fn(),
|
|
3372
|
+
resize: import_vitest15.vi.fn()
|
|
3029
3373
|
};
|
|
3030
3374
|
const bsp = {
|
|
3031
|
-
render:
|
|
3032
|
-
init:
|
|
3033
|
-
resize:
|
|
3375
|
+
render: import_vitest15.vi.fn(),
|
|
3376
|
+
init: import_vitest15.vi.fn(),
|
|
3377
|
+
resize: import_vitest15.vi.fn()
|
|
3034
3378
|
};
|
|
3035
3379
|
const sprite = {
|
|
3036
|
-
render:
|
|
3037
|
-
init:
|
|
3038
|
-
resize:
|
|
3380
|
+
render: import_vitest15.vi.fn(),
|
|
3381
|
+
init: import_vitest15.vi.fn(),
|
|
3382
|
+
resize: import_vitest15.vi.fn()
|
|
3039
3383
|
};
|
|
3040
3384
|
const poly = {
|
|
3041
|
-
render:
|
|
3042
|
-
init:
|
|
3043
|
-
resize:
|
|
3385
|
+
render: import_vitest15.vi.fn(),
|
|
3386
|
+
init: import_vitest15.vi.fn(),
|
|
3387
|
+
resize: import_vitest15.vi.fn()
|
|
3044
3388
|
};
|
|
3045
3389
|
const particle = {
|
|
3046
|
-
render:
|
|
3047
|
-
init:
|
|
3048
|
-
resize:
|
|
3390
|
+
render: import_vitest15.vi.fn(),
|
|
3391
|
+
init: import_vitest15.vi.fn(),
|
|
3392
|
+
resize: import_vitest15.vi.fn()
|
|
3049
3393
|
};
|
|
3050
3394
|
return {
|
|
3051
3395
|
gl,
|
|
@@ -3198,6 +3542,207 @@ function captureAudioEvents(context) {
|
|
|
3198
3542
|
return [];
|
|
3199
3543
|
}
|
|
3200
3544
|
|
|
3545
|
+
// src/engine/helpers/webgpu-rendering.ts
|
|
3546
|
+
async function createRenderTestSetup(width = 256, height = 256) {
|
|
3547
|
+
const setup = await initHeadlessWebGPU();
|
|
3548
|
+
const { device } = setup;
|
|
3549
|
+
const renderTarget = device.createTexture({
|
|
3550
|
+
size: { width, height, depthOrArrayLayers: 1 },
|
|
3551
|
+
format: "rgba8unorm",
|
|
3552
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
|
|
3553
|
+
});
|
|
3554
|
+
const renderTargetView = renderTarget.createView();
|
|
3555
|
+
const commandEncoder = device.createCommandEncoder();
|
|
3556
|
+
const context = {
|
|
3557
|
+
adapter: setup.adapter,
|
|
3558
|
+
device: setup.device,
|
|
3559
|
+
queue: setup.device.queue
|
|
3560
|
+
};
|
|
3561
|
+
return {
|
|
3562
|
+
context,
|
|
3563
|
+
renderTarget,
|
|
3564
|
+
renderTargetView,
|
|
3565
|
+
commandEncoder,
|
|
3566
|
+
width,
|
|
3567
|
+
height,
|
|
3568
|
+
cleanup: async () => {
|
|
3569
|
+
renderTarget.destroy();
|
|
3570
|
+
await setup.cleanup();
|
|
3571
|
+
}
|
|
3572
|
+
};
|
|
3573
|
+
}
|
|
3574
|
+
async function renderAndCapture(setup, renderFn) {
|
|
3575
|
+
const { device, queue } = setup.context;
|
|
3576
|
+
const { renderTargetView, commandEncoder, width, height } = setup;
|
|
3577
|
+
const passEncoder = commandEncoder.beginRenderPass({
|
|
3578
|
+
colorAttachments: [
|
|
3579
|
+
{
|
|
3580
|
+
view: renderTargetView,
|
|
3581
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
3582
|
+
loadOp: "clear",
|
|
3583
|
+
storeOp: "store"
|
|
3584
|
+
}
|
|
3585
|
+
]
|
|
3586
|
+
});
|
|
3587
|
+
renderFn(passEncoder);
|
|
3588
|
+
passEncoder.end();
|
|
3589
|
+
const bytesPerPixel = 4;
|
|
3590
|
+
const unpaddedBytesPerRow = width * bytesPerPixel;
|
|
3591
|
+
const align = 256;
|
|
3592
|
+
const paddedBytesPerRow = Math.max(
|
|
3593
|
+
bytesPerPixel * width,
|
|
3594
|
+
Math.ceil(bytesPerPixel * width / align) * align
|
|
3595
|
+
);
|
|
3596
|
+
const bufferSize = paddedBytesPerRow * height;
|
|
3597
|
+
const readbackBuffer = device.createBuffer({
|
|
3598
|
+
size: bufferSize,
|
|
3599
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
3600
|
+
});
|
|
3601
|
+
commandEncoder.copyTextureToBuffer(
|
|
3602
|
+
{
|
|
3603
|
+
texture: setup.renderTarget
|
|
3604
|
+
},
|
|
3605
|
+
{
|
|
3606
|
+
buffer: readbackBuffer,
|
|
3607
|
+
bytesPerRow: paddedBytesPerRow
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
width,
|
|
3611
|
+
height,
|
|
3612
|
+
depthOrArrayLayers: 1
|
|
3613
|
+
}
|
|
3614
|
+
);
|
|
3615
|
+
queue.submit([commandEncoder.finish()]);
|
|
3616
|
+
await readbackBuffer.mapAsync(GPUMapMode.READ);
|
|
3617
|
+
const arrayBuffer = readbackBuffer.getMappedRange();
|
|
3618
|
+
const output = new Uint8ClampedArray(width * height * 4);
|
|
3619
|
+
const srcBytes = new Uint8Array(arrayBuffer);
|
|
3620
|
+
for (let y = 0; y < height; y++) {
|
|
3621
|
+
const srcOffset = y * paddedBytesPerRow;
|
|
3622
|
+
const dstOffset = y * unpaddedBytesPerRow;
|
|
3623
|
+
output.set(srcBytes.subarray(srcOffset, srcOffset + unpaddedBytesPerRow), dstOffset);
|
|
3624
|
+
}
|
|
3625
|
+
readbackBuffer.unmap();
|
|
3626
|
+
readbackBuffer.destroy();
|
|
3627
|
+
return output;
|
|
3628
|
+
}
|
|
3629
|
+
async function createComputeTestSetup(outputSize) {
|
|
3630
|
+
const setup = await initHeadlessWebGPU();
|
|
3631
|
+
const { device } = setup;
|
|
3632
|
+
const outputBuffer = device.createBuffer({
|
|
3633
|
+
size: outputSize,
|
|
3634
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
3635
|
+
});
|
|
3636
|
+
const commandEncoder = device.createCommandEncoder();
|
|
3637
|
+
const context = {
|
|
3638
|
+
adapter: setup.adapter,
|
|
3639
|
+
device: setup.device,
|
|
3640
|
+
queue: setup.device.queue
|
|
3641
|
+
};
|
|
3642
|
+
return {
|
|
3643
|
+
context,
|
|
3644
|
+
outputBuffer,
|
|
3645
|
+
commandEncoder,
|
|
3646
|
+
outputSize,
|
|
3647
|
+
cleanup: async () => {
|
|
3648
|
+
outputBuffer.destroy();
|
|
3649
|
+
await setup.cleanup();
|
|
3650
|
+
}
|
|
3651
|
+
};
|
|
3652
|
+
}
|
|
3653
|
+
async function runComputeAndReadback(setup, computeFn) {
|
|
3654
|
+
const { device, queue } = setup.context;
|
|
3655
|
+
const { outputBuffer, commandEncoder, outputSize } = setup;
|
|
3656
|
+
const passEncoder = commandEncoder.beginComputePass();
|
|
3657
|
+
computeFn(passEncoder);
|
|
3658
|
+
passEncoder.end();
|
|
3659
|
+
const stagingBuffer = device.createBuffer({
|
|
3660
|
+
size: outputSize,
|
|
3661
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
3662
|
+
});
|
|
3663
|
+
commandEncoder.copyBufferToBuffer(
|
|
3664
|
+
outputBuffer,
|
|
3665
|
+
0,
|
|
3666
|
+
stagingBuffer,
|
|
3667
|
+
0,
|
|
3668
|
+
outputSize
|
|
3669
|
+
);
|
|
3670
|
+
queue.submit([commandEncoder.finish()]);
|
|
3671
|
+
await stagingBuffer.mapAsync(GPUMapMode.READ);
|
|
3672
|
+
const mappedRange = stagingBuffer.getMappedRange();
|
|
3673
|
+
const result = mappedRange.slice(0);
|
|
3674
|
+
stagingBuffer.unmap();
|
|
3675
|
+
stagingBuffer.destroy();
|
|
3676
|
+
return result;
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
// src/engine/helpers/pipeline-test-template.ts
|
|
3680
|
+
var import_vitest16 = require("vitest");
|
|
3681
|
+
async function testPipelineRendering(name, createPipeline, setupGeometry, expectedOutput) {
|
|
3682
|
+
const setup = await createRenderTestSetup(256, 256);
|
|
3683
|
+
try {
|
|
3684
|
+
const pipeline = createPipeline(setup.context.device);
|
|
3685
|
+
const geometry = setupGeometry(setup.context.device);
|
|
3686
|
+
const pixels = await renderAndCapture(setup, (pass) => {
|
|
3687
|
+
pass.setPipeline(pipeline);
|
|
3688
|
+
pass.setVertexBuffer(0, geometry.vertexBuffer);
|
|
3689
|
+
if (geometry.indexBuffer) {
|
|
3690
|
+
pass.setIndexBuffer(geometry.indexBuffer, "uint16");
|
|
3691
|
+
pass.drawIndexed(geometry.indexCount || 0);
|
|
3692
|
+
} else {
|
|
3693
|
+
pass.draw(geometry.vertexCount);
|
|
3694
|
+
}
|
|
3695
|
+
});
|
|
3696
|
+
if (expectedOutput) {
|
|
3697
|
+
(0, import_vitest16.expect)(pixels).toEqual(expectedOutput);
|
|
3698
|
+
} else {
|
|
3699
|
+
(0, import_vitest16.expect)(pixels.length).toBe(256 * 256 * 4);
|
|
3700
|
+
}
|
|
3701
|
+
} finally {
|
|
3702
|
+
await setup.cleanup();
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
async function testComputeShader(name, createComputePipeline, inputData, expectedOutput) {
|
|
3706
|
+
const setup = await createComputeTestSetup(inputData.byteLength);
|
|
3707
|
+
const { device } = setup.context;
|
|
3708
|
+
try {
|
|
3709
|
+
const pipeline = createComputePipeline(device);
|
|
3710
|
+
const stagingBuffer = device.createBuffer({
|
|
3711
|
+
size: inputData.byteLength,
|
|
3712
|
+
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
|
|
3713
|
+
mappedAtCreation: true
|
|
3714
|
+
});
|
|
3715
|
+
new Float32Array(stagingBuffer.getMappedRange()).set(inputData);
|
|
3716
|
+
stagingBuffer.unmap();
|
|
3717
|
+
const encoder = device.createCommandEncoder();
|
|
3718
|
+
encoder.copyBufferToBuffer(stagingBuffer, 0, setup.outputBuffer, 0, inputData.byteLength);
|
|
3719
|
+
device.queue.submit([encoder.finish()]);
|
|
3720
|
+
const bindGroup = device.createBindGroup({
|
|
3721
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
3722
|
+
entries: [
|
|
3723
|
+
{
|
|
3724
|
+
binding: 0,
|
|
3725
|
+
resource: {
|
|
3726
|
+
buffer: setup.outputBuffer
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
]
|
|
3730
|
+
});
|
|
3731
|
+
const resultBuffer = await runComputeAndReadback(setup, (pass) => {
|
|
3732
|
+
pass.setPipeline(pipeline);
|
|
3733
|
+
pass.setBindGroup(0, bindGroup);
|
|
3734
|
+
pass.dispatchWorkgroups(Math.ceil(inputData.length / 64));
|
|
3735
|
+
});
|
|
3736
|
+
if (expectedOutput) {
|
|
3737
|
+
const floatResult = new Float32Array(resultBuffer);
|
|
3738
|
+
(0, import_vitest16.expect)(floatResult).toEqual(expectedOutput);
|
|
3739
|
+
}
|
|
3740
|
+
stagingBuffer.destroy();
|
|
3741
|
+
} finally {
|
|
3742
|
+
await setup.cleanup();
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
|
|
3201
3746
|
// ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
|
|
3202
3747
|
var EPSILON = 1e-6;
|
|
3203
3748
|
var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
|
|
@@ -3218,7 +3763,7 @@ __export(vec3_exports, {
|
|
|
3218
3763
|
ceil: () => ceil,
|
|
3219
3764
|
clone: () => clone,
|
|
3220
3765
|
copy: () => copy,
|
|
3221
|
-
create: () =>
|
|
3766
|
+
create: () => create2,
|
|
3222
3767
|
cross: () => cross,
|
|
3223
3768
|
dist: () => dist,
|
|
3224
3769
|
distance: () => distance,
|
|
@@ -3262,7 +3807,7 @@ __export(vec3_exports, {
|
|
|
3262
3807
|
transformQuat: () => transformQuat,
|
|
3263
3808
|
zero: () => zero
|
|
3264
3809
|
});
|
|
3265
|
-
function
|
|
3810
|
+
function create2() {
|
|
3266
3811
|
var out = new ARRAY_TYPE(3);
|
|
3267
3812
|
if (ARRAY_TYPE != Float32Array) {
|
|
3268
3813
|
out[0] = 0;
|
|
@@ -3574,7 +4119,7 @@ var sqrDist = squaredDistance;
|
|
|
3574
4119
|
var len = length;
|
|
3575
4120
|
var sqrLen = squaredLength;
|
|
3576
4121
|
var forEach = (function() {
|
|
3577
|
-
var vec =
|
|
4122
|
+
var vec = create2();
|
|
3578
4123
|
return function(a, stride, offset, count, fn, arg) {
|
|
3579
4124
|
var i, l;
|
|
3580
4125
|
if (!stride) {
|
|
@@ -3697,7 +4242,7 @@ function simulateCameraMovement(camera, input, deltaTime) {
|
|
|
3697
4242
|
}
|
|
3698
4243
|
|
|
3699
4244
|
// src/client/helpers/hud.ts
|
|
3700
|
-
var
|
|
4245
|
+
var import_vitest17 = require("vitest");
|
|
3701
4246
|
function createMockHudState(overrides) {
|
|
3702
4247
|
const defaultPs = {
|
|
3703
4248
|
damageAlpha: 0,
|
|
@@ -3732,11 +4277,11 @@ function createMockHudState(overrides) {
|
|
|
3732
4277
|
batches: 10
|
|
3733
4278
|
};
|
|
3734
4279
|
const defaultMessages = {
|
|
3735
|
-
drawCenterPrint:
|
|
3736
|
-
drawNotifications:
|
|
3737
|
-
addCenterPrint:
|
|
3738
|
-
addNotification:
|
|
3739
|
-
clear:
|
|
4280
|
+
drawCenterPrint: import_vitest17.vi.fn(),
|
|
4281
|
+
drawNotifications: import_vitest17.vi.fn(),
|
|
4282
|
+
addCenterPrint: import_vitest17.vi.fn(),
|
|
4283
|
+
addNotification: import_vitest17.vi.fn(),
|
|
4284
|
+
clear: import_vitest17.vi.fn()
|
|
3740
4285
|
};
|
|
3741
4286
|
return {
|
|
3742
4287
|
ps: overrides?.ps ?? defaultPs,
|
|
@@ -3752,7 +4297,7 @@ function createMockHudState(overrides) {
|
|
|
3752
4297
|
function createMockScoreboard(players = []) {
|
|
3753
4298
|
return {
|
|
3754
4299
|
players,
|
|
3755
|
-
draw:
|
|
4300
|
+
draw: import_vitest17.vi.fn()
|
|
3756
4301
|
};
|
|
3757
4302
|
}
|
|
3758
4303
|
function createMockChatMessage(text, sender, timestamp = Date.now()) {
|
|
@@ -3850,6 +4395,254 @@ function createMockFogData(overrides = {}) {
|
|
|
3850
4395
|
};
|
|
3851
4396
|
}
|
|
3852
4397
|
|
|
4398
|
+
// src/client/mocks/download.ts
|
|
4399
|
+
var import_vitest18 = require("vitest");
|
|
4400
|
+
function createMockDownloadManager(overrides) {
|
|
4401
|
+
return {
|
|
4402
|
+
download: import_vitest18.vi.fn().mockResolvedValue(new ArrayBuffer(0)),
|
|
4403
|
+
cancel: import_vitest18.vi.fn(),
|
|
4404
|
+
getProgress: import_vitest18.vi.fn().mockReturnValue(0),
|
|
4405
|
+
...overrides
|
|
4406
|
+
};
|
|
4407
|
+
}
|
|
4408
|
+
function createMockPrecacheList(models = [], sounds = [], images = []) {
|
|
4409
|
+
return {
|
|
4410
|
+
models,
|
|
4411
|
+
sounds,
|
|
4412
|
+
images
|
|
4413
|
+
};
|
|
4414
|
+
}
|
|
4415
|
+
async function simulateDownload(url, progressCallback) {
|
|
4416
|
+
const steps = 10;
|
|
4417
|
+
for (let i = 0; i <= steps; i++) {
|
|
4418
|
+
if (progressCallback) {
|
|
4419
|
+
progressCallback(i / steps);
|
|
4420
|
+
}
|
|
4421
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
4422
|
+
}
|
|
4423
|
+
return new ArrayBuffer(1024);
|
|
4424
|
+
}
|
|
4425
|
+
|
|
4426
|
+
// src/client/mocks/state.ts
|
|
4427
|
+
var MAX_MODELS = 256;
|
|
4428
|
+
var MAX_SOUNDS = 256;
|
|
4429
|
+
var MAX_IMAGES = 256;
|
|
4430
|
+
var MockClientConfigStrings = class {
|
|
4431
|
+
constructor() {
|
|
4432
|
+
this.strings = /* @__PURE__ */ new Map();
|
|
4433
|
+
this.models = [];
|
|
4434
|
+
this.sounds = [];
|
|
4435
|
+
this.images = [];
|
|
4436
|
+
}
|
|
4437
|
+
set(index, value) {
|
|
4438
|
+
this.strings.set(index, value);
|
|
4439
|
+
if (index >= 32 /* Models */ && index < 32 /* Models */ + MAX_MODELS) {
|
|
4440
|
+
this.models[index - 32 /* Models */] = value;
|
|
4441
|
+
} else if (index >= 288 /* Sounds */ && index < 288 /* Sounds */ + MAX_SOUNDS) {
|
|
4442
|
+
this.sounds[index - 288 /* Sounds */] = value;
|
|
4443
|
+
} else if (index >= 544 /* Images */ && index < 544 /* Images */ + MAX_IMAGES) {
|
|
4444
|
+
this.images[index - 544 /* Images */] = value;
|
|
4445
|
+
}
|
|
4446
|
+
}
|
|
4447
|
+
get(index) {
|
|
4448
|
+
return this.strings.get(index);
|
|
4449
|
+
}
|
|
4450
|
+
getModelName(index) {
|
|
4451
|
+
return this.models[index];
|
|
4452
|
+
}
|
|
4453
|
+
getSoundName(index) {
|
|
4454
|
+
return this.sounds[index];
|
|
4455
|
+
}
|
|
4456
|
+
getImageName(index) {
|
|
4457
|
+
return this.images[index];
|
|
4458
|
+
}
|
|
4459
|
+
getPlayerName(playernum) {
|
|
4460
|
+
const info = this.strings.get(800 /* Players */ + playernum);
|
|
4461
|
+
if (!info) return void 0;
|
|
4462
|
+
const parts = info.split("\\");
|
|
4463
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
4464
|
+
if (parts[i] === "name") {
|
|
4465
|
+
return parts[i + 1];
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
return void 0;
|
|
4469
|
+
}
|
|
4470
|
+
clear() {
|
|
4471
|
+
this.strings.clear();
|
|
4472
|
+
this.models.length = 0;
|
|
4473
|
+
this.sounds.length = 0;
|
|
4474
|
+
this.images.length = 0;
|
|
4475
|
+
}
|
|
4476
|
+
};
|
|
4477
|
+
var createMockClientState = (overrides) => {
|
|
4478
|
+
const configStrings = new MockClientConfigStrings();
|
|
4479
|
+
return {
|
|
4480
|
+
tickRate: 10,
|
|
4481
|
+
frameTimeMs: 100,
|
|
4482
|
+
serverFrame: 0,
|
|
4483
|
+
serverProtocol: 34,
|
|
4484
|
+
configStrings,
|
|
4485
|
+
playerNum: 0,
|
|
4486
|
+
serverTime: 0,
|
|
4487
|
+
parseEntities: 0,
|
|
4488
|
+
inAutoDemo: false,
|
|
4489
|
+
getClientName: (num) => `Player${num}`,
|
|
4490
|
+
getKeyBinding: (key) => "",
|
|
4491
|
+
...overrides
|
|
4492
|
+
};
|
|
4493
|
+
};
|
|
4494
|
+
var createMockFrame = (overrides) => ({
|
|
4495
|
+
serverFrame: 0,
|
|
4496
|
+
deltaFrame: -1,
|
|
4497
|
+
valid: true,
|
|
4498
|
+
entities: [],
|
|
4499
|
+
...overrides
|
|
4500
|
+
});
|
|
4501
|
+
var createMockClientInfo = (overrides) => ({
|
|
4502
|
+
name: "Player",
|
|
4503
|
+
skin: "male/grunt",
|
|
4504
|
+
model: "male",
|
|
4505
|
+
icon: "pics/icon.pcx",
|
|
4506
|
+
...overrides
|
|
4507
|
+
});
|
|
4508
|
+
var createMockConnectionState = (state = "connected") => ({
|
|
4509
|
+
state
|
|
4510
|
+
});
|
|
4511
|
+
|
|
4512
|
+
// src/client/mocks/console.ts
|
|
4513
|
+
var import_vitest19 = require("vitest");
|
|
4514
|
+
function createMockConsole(overrides) {
|
|
4515
|
+
const history = [];
|
|
4516
|
+
const errors = [];
|
|
4517
|
+
const commands = {};
|
|
4518
|
+
const cvars = {};
|
|
4519
|
+
return {
|
|
4520
|
+
print: import_vitest19.vi.fn((text) => {
|
|
4521
|
+
history.push(text);
|
|
4522
|
+
}),
|
|
4523
|
+
error: import_vitest19.vi.fn((text) => {
|
|
4524
|
+
errors.push(text);
|
|
4525
|
+
}),
|
|
4526
|
+
execute: import_vitest19.vi.fn((text) => {
|
|
4527
|
+
const parts = text.trim().split(/\s+/);
|
|
4528
|
+
const cmd = parts[0];
|
|
4529
|
+
const args = parts.slice(1);
|
|
4530
|
+
if (commands[cmd]) {
|
|
4531
|
+
commands[cmd](args);
|
|
4532
|
+
} else {
|
|
4533
|
+
history.push(`Unknown command "${cmd}"`);
|
|
4534
|
+
}
|
|
4535
|
+
}),
|
|
4536
|
+
addCommand: import_vitest19.vi.fn((name, handler) => {
|
|
4537
|
+
commands[name] = handler;
|
|
4538
|
+
}),
|
|
4539
|
+
getCvar: import_vitest19.vi.fn((name) => cvars[name]),
|
|
4540
|
+
setCvar: import_vitest19.vi.fn((name, value) => {
|
|
4541
|
+
cvars[name] = value;
|
|
4542
|
+
}),
|
|
4543
|
+
getHistory: () => history,
|
|
4544
|
+
clearHistory: () => {
|
|
4545
|
+
history.length = 0;
|
|
4546
|
+
errors.length = 0;
|
|
4547
|
+
},
|
|
4548
|
+
getErrors: () => errors,
|
|
4549
|
+
...overrides
|
|
4550
|
+
};
|
|
4551
|
+
}
|
|
4552
|
+
function createMockCommand(name, handler) {
|
|
4553
|
+
return { name, handler };
|
|
4554
|
+
}
|
|
4555
|
+
function createMockCvarRegistry(initialCvars) {
|
|
4556
|
+
return { ...initialCvars };
|
|
4557
|
+
}
|
|
4558
|
+
|
|
4559
|
+
// src/client/helpers/prediction.ts
|
|
4560
|
+
var createPredictionTestScenario = (lagMs = 100) => {
|
|
4561
|
+
const clientState = createMockClientState({
|
|
4562
|
+
playerNum: 0,
|
|
4563
|
+
serverTime: 1e3,
|
|
4564
|
+
getClientName: (num) => "TestPlayer"
|
|
4565
|
+
});
|
|
4566
|
+
const snapshots = [];
|
|
4567
|
+
for (let i = 0; i < 5; i++) {
|
|
4568
|
+
const frameEntities = [
|
|
4569
|
+
{
|
|
4570
|
+
number: 1,
|
|
4571
|
+
origin: { x: i * 10, y: 0, z: 0 },
|
|
4572
|
+
angles: { x: 0, y: 0, z: 0 },
|
|
4573
|
+
oldOrigin: { x: (i - 1) * 10, y: 0, z: 0 },
|
|
4574
|
+
modelIndex: 0,
|
|
4575
|
+
modelIndex2: 0,
|
|
4576
|
+
modelIndex3: 0,
|
|
4577
|
+
modelIndex4: 0,
|
|
4578
|
+
frame: 0,
|
|
4579
|
+
skinNum: 0,
|
|
4580
|
+
effects: 0,
|
|
4581
|
+
renderfx: 0,
|
|
4582
|
+
solid: 0,
|
|
4583
|
+
sound: 0,
|
|
4584
|
+
event: 0
|
|
4585
|
+
}
|
|
4586
|
+
];
|
|
4587
|
+
snapshots.push(frameEntities);
|
|
4588
|
+
}
|
|
4589
|
+
return {
|
|
4590
|
+
clientState,
|
|
4591
|
+
snapshots,
|
|
4592
|
+
lagMs
|
|
4593
|
+
};
|
|
4594
|
+
};
|
|
4595
|
+
var simulateClientPrediction = (state, input, deltaTime) => {
|
|
4596
|
+
return {
|
|
4597
|
+
...state,
|
|
4598
|
+
serverTime: state.serverTime + deltaTime * 1e3
|
|
4599
|
+
};
|
|
4600
|
+
};
|
|
4601
|
+
var createInterpolationTestData = (startState, endState, steps = 10) => {
|
|
4602
|
+
const result = [];
|
|
4603
|
+
for (let i = 0; i <= steps; i++) {
|
|
4604
|
+
const t = i / steps;
|
|
4605
|
+
const lerp2 = (a, b) => a + (b - a) * t;
|
|
4606
|
+
result.push({
|
|
4607
|
+
...startState,
|
|
4608
|
+
origin: {
|
|
4609
|
+
x: lerp2(startState.origin.x, endState.origin.x),
|
|
4610
|
+
y: lerp2(startState.origin.y, endState.origin.y),
|
|
4611
|
+
z: lerp2(startState.origin.z, endState.origin.z)
|
|
4612
|
+
},
|
|
4613
|
+
angles: {
|
|
4614
|
+
x: lerp2(startState.angles.x, endState.angles.x),
|
|
4615
|
+
y: lerp2(startState.angles.y, endState.angles.y),
|
|
4616
|
+
z: lerp2(startState.angles.z, endState.angles.z)
|
|
4617
|
+
}
|
|
4618
|
+
});
|
|
4619
|
+
}
|
|
4620
|
+
return result;
|
|
4621
|
+
};
|
|
4622
|
+
var verifySmoothing = (states) => {
|
|
4623
|
+
let maxError = 0;
|
|
4624
|
+
let totalError = 0;
|
|
4625
|
+
const jumps = [];
|
|
4626
|
+
for (let i = 1; i < states.length; i++) {
|
|
4627
|
+
const prev = states[i - 1].origin;
|
|
4628
|
+
const curr = states[i].origin;
|
|
4629
|
+
const dx = curr.x - prev.x;
|
|
4630
|
+
const dy = curr.y - prev.y;
|
|
4631
|
+
const dz = curr.z - prev.z;
|
|
4632
|
+
const dist2 = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
4633
|
+
if (dist2 > 50) {
|
|
4634
|
+
jumps.push(i);
|
|
4635
|
+
}
|
|
4636
|
+
totalError += dist2;
|
|
4637
|
+
}
|
|
4638
|
+
return {
|
|
4639
|
+
smooth: jumps.length === 0,
|
|
4640
|
+
maxError,
|
|
4641
|
+
averageError: totalError / (states.length - 1 || 1),
|
|
4642
|
+
jumps
|
|
4643
|
+
};
|
|
4644
|
+
};
|
|
4645
|
+
|
|
3853
4646
|
// src/e2e/playwright.ts
|
|
3854
4647
|
async function createPlaywrightTestClient(options = {}) {
|
|
3855
4648
|
let playwright;
|
|
@@ -4043,6 +4836,7 @@ function createVisualTestScenario(sceneName) {
|
|
|
4043
4836
|
HandshakeStage,
|
|
4044
4837
|
InputInjector,
|
|
4045
4838
|
MockAudioBufferSourceNode,
|
|
4839
|
+
MockClientConfigStrings,
|
|
4046
4840
|
MockNetDriver,
|
|
4047
4841
|
MockNetworkTransport,
|
|
4048
4842
|
MockPointerLock,
|
|
@@ -4059,6 +4853,7 @@ function createVisualTestScenario(sceneName) {
|
|
|
4059
4853
|
createBinaryWriterMock,
|
|
4060
4854
|
createBounds,
|
|
4061
4855
|
createCombatTestContext,
|
|
4856
|
+
createComputeTestSetup,
|
|
4062
4857
|
createConfigStringArrayMock,
|
|
4063
4858
|
createConfigStringMock,
|
|
4064
4859
|
createControlledTimer,
|
|
@@ -4069,33 +4864,49 @@ function createVisualTestScenario(sceneName) {
|
|
|
4069
4864
|
createEntityFactory,
|
|
4070
4865
|
createEntityStateFactory,
|
|
4071
4866
|
createGameStateSnapshotFactory,
|
|
4867
|
+
createHeadlessTestContext,
|
|
4072
4868
|
createInputInjector,
|
|
4869
|
+
createInterpolationTestData,
|
|
4073
4870
|
createItemEntityFactory,
|
|
4074
4871
|
createMessageReaderMock,
|
|
4075
4872
|
createMessageWriterMock,
|
|
4076
4873
|
createMockAI,
|
|
4077
4874
|
createMockAmmoItem,
|
|
4078
4875
|
createMockArmorItem,
|
|
4876
|
+
createMockAssetManager,
|
|
4079
4877
|
createMockAudioBuffer,
|
|
4080
4878
|
createMockAudioContext,
|
|
4879
|
+
createMockBspMap,
|
|
4081
4880
|
createMockBspPipeline,
|
|
4082
4881
|
createMockBufferSource,
|
|
4083
4882
|
createMockCamera,
|
|
4084
4883
|
createMockCanvas,
|
|
4085
4884
|
createMockCanvasContext2D,
|
|
4086
4885
|
createMockChatMessage,
|
|
4886
|
+
createMockClientInfo,
|
|
4887
|
+
createMockClientState,
|
|
4087
4888
|
createMockCollisionEntityIndex,
|
|
4889
|
+
createMockCommand,
|
|
4890
|
+
createMockCommandEncoder,
|
|
4891
|
+
createMockComputePassEncoder,
|
|
4892
|
+
createMockComputePipeline,
|
|
4088
4893
|
createMockConnection,
|
|
4894
|
+
createMockConnectionState,
|
|
4895
|
+
createMockConsole,
|
|
4896
|
+
createMockCvarRegistry,
|
|
4089
4897
|
createMockDamageIndicator,
|
|
4090
4898
|
createMockDamageInfo,
|
|
4091
4899
|
createMockDeltaFrame,
|
|
4900
|
+
createMockDownloadManager,
|
|
4092
4901
|
createMockEngine,
|
|
4093
4902
|
createMockEntityState,
|
|
4094
4903
|
createMockFogData,
|
|
4904
|
+
createMockFrame,
|
|
4095
4905
|
createMockFrameRenderer,
|
|
4096
4906
|
createMockGPUAdapter,
|
|
4097
|
-
|
|
4907
|
+
createMockGPUBuffer,
|
|
4098
4908
|
createMockGPUDevice,
|
|
4909
|
+
createMockGPUTexture,
|
|
4099
4910
|
createMockGame,
|
|
4100
4911
|
createMockGameExports,
|
|
4101
4912
|
createMockGameState,
|
|
@@ -4110,7 +4921,9 @@ function createVisualTestScenario(sceneName) {
|
|
|
4110
4921
|
createMockKeyboardEvent,
|
|
4111
4922
|
createMockLocalStorage,
|
|
4112
4923
|
createMockMasterServer,
|
|
4924
|
+
createMockMd2Model,
|
|
4113
4925
|
createMockMd2Pipeline,
|
|
4926
|
+
createMockMd3Model,
|
|
4114
4927
|
createMockMd3Pipeline,
|
|
4115
4928
|
createMockMonsterAI,
|
|
4116
4929
|
createMockMonsterMove,
|
|
@@ -4122,12 +4935,17 @@ function createVisualTestScenario(sceneName) {
|
|
|
4122
4935
|
createMockPerformance,
|
|
4123
4936
|
createMockPointerLock,
|
|
4124
4937
|
createMockPowerupItem,
|
|
4938
|
+
createMockPrecacheList,
|
|
4939
|
+
createMockQueue,
|
|
4125
4940
|
createMockRAF,
|
|
4126
4941
|
createMockRConClient,
|
|
4127
4942
|
createMockRateLimiter,
|
|
4128
4943
|
createMockRefDef,
|
|
4944
|
+
createMockRenderPassEncoder,
|
|
4945
|
+
createMockRenderPipeline,
|
|
4129
4946
|
createMockRenderer,
|
|
4130
4947
|
createMockRenderingContext,
|
|
4948
|
+
createMockSampler,
|
|
4131
4949
|
createMockScoreboard,
|
|
4132
4950
|
createMockServer,
|
|
4133
4951
|
createMockServerClient,
|
|
@@ -4137,9 +4955,12 @@ function createVisualTestScenario(sceneName) {
|
|
|
4137
4955
|
createMockServerState,
|
|
4138
4956
|
createMockServerStatic,
|
|
4139
4957
|
createMockSessionStorage,
|
|
4958
|
+
createMockShaderModule,
|
|
4140
4959
|
createMockSkyboxPipeline,
|
|
4141
4960
|
createMockSnapshot,
|
|
4142
4961
|
createMockSpritePipeline,
|
|
4962
|
+
createMockTexture,
|
|
4963
|
+
createMockTextureView,
|
|
4143
4964
|
createMockTransport,
|
|
4144
4965
|
createMockUDPSocket,
|
|
4145
4966
|
createMockUserInfo,
|
|
@@ -4147,6 +4968,7 @@ function createVisualTestScenario(sceneName) {
|
|
|
4147
4968
|
createMockWeapon,
|
|
4148
4969
|
createMockWeaponItem,
|
|
4149
4970
|
createMockWebGL2Context,
|
|
4971
|
+
createMockWebGPUContext,
|
|
4150
4972
|
createMockWheelEvent,
|
|
4151
4973
|
createMonsterEntityFactory,
|
|
4152
4974
|
createMultiplayerTestScenario,
|
|
@@ -4157,7 +4979,9 @@ function createVisualTestScenario(sceneName) {
|
|
|
4157
4979
|
createPlayerEntityFactory,
|
|
4158
4980
|
createPlayerStateFactory,
|
|
4159
4981
|
createPlaywrightTestClient,
|
|
4982
|
+
createPredictionTestScenario,
|
|
4160
4983
|
createProjectileEntityFactory,
|
|
4984
|
+
createRenderTestSetup,
|
|
4161
4985
|
createServerSnapshot,
|
|
4162
4986
|
createSpawnTestContext,
|
|
4163
4987
|
createStorageTestScenario,
|
|
@@ -4169,6 +4993,7 @@ function createVisualTestScenario(sceneName) {
|
|
|
4169
4993
|
createVector3,
|
|
4170
4994
|
createViewTestScenario,
|
|
4171
4995
|
createVisualTestScenario,
|
|
4996
|
+
initHeadlessWebGPU,
|
|
4172
4997
|
intersects,
|
|
4173
4998
|
ladderTrace,
|
|
4174
4999
|
makeAxisBrush,
|
|
@@ -4181,6 +5006,8 @@ function createVisualTestScenario(sceneName) {
|
|
|
4181
5006
|
measureSnapshotSize,
|
|
4182
5007
|
mockMonsterAttacks,
|
|
4183
5008
|
randomVector3,
|
|
5009
|
+
renderAndCapture,
|
|
5010
|
+
runComputeAndReadback,
|
|
4184
5011
|
serializeUserInfo,
|
|
4185
5012
|
setupBrowserEnvironment,
|
|
4186
5013
|
setupMockAudioContext,
|
|
@@ -4188,6 +5015,8 @@ function createVisualTestScenario(sceneName) {
|
|
|
4188
5015
|
setupWebGPUMocks,
|
|
4189
5016
|
simulateBandwidthLimit,
|
|
4190
5017
|
simulateCameraMovement,
|
|
5018
|
+
simulateClientPrediction,
|
|
5019
|
+
simulateDownload,
|
|
4191
5020
|
simulateFrames,
|
|
4192
5021
|
simulateGravity,
|
|
4193
5022
|
simulateHandshake,
|
|
@@ -4208,7 +5037,10 @@ function createVisualTestScenario(sceneName) {
|
|
|
4208
5037
|
teardownBrowserEnvironment,
|
|
4209
5038
|
teardownMockAudioContext,
|
|
4210
5039
|
teardownNodeEnvironment,
|
|
5040
|
+
testComputeShader,
|
|
5041
|
+
testPipelineRendering,
|
|
4211
5042
|
throttleBandwidth,
|
|
5043
|
+
verifySmoothing,
|
|
4212
5044
|
verifySnapshotConsistency,
|
|
4213
5045
|
waitForGameReady
|
|
4214
5046
|
});
|