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
|
@@ -463,6 +463,7 @@ function createTestContext(options) {
|
|
|
463
463
|
const entities = {
|
|
464
464
|
spawn: vi2.fn(() => {
|
|
465
465
|
const ent = new Entity2(entityList.length + 1);
|
|
466
|
+
ent.inUse = true;
|
|
466
467
|
entityList.push(ent);
|
|
467
468
|
hooks.onEntitySpawn(ent);
|
|
468
469
|
return ent;
|
|
@@ -472,6 +473,7 @@ function createTestContext(options) {
|
|
|
472
473
|
if (idx !== -1) {
|
|
473
474
|
entityList.splice(idx, 1);
|
|
474
475
|
}
|
|
476
|
+
ent.inUse = false;
|
|
475
477
|
hooks.onEntityRemove(ent);
|
|
476
478
|
}),
|
|
477
479
|
finalizeSpawn: vi2.fn(),
|
|
@@ -480,6 +482,7 @@ function createTestContext(options) {
|
|
|
480
482
|
if (idx !== -1) {
|
|
481
483
|
entityList.splice(idx, 1);
|
|
482
484
|
}
|
|
485
|
+
ent.inUse = false;
|
|
483
486
|
}),
|
|
484
487
|
setSpawnRegistry: vi2.fn(),
|
|
485
488
|
timeSeconds: 10,
|
|
@@ -2317,99 +2320,280 @@ function createMockImage(width = 100, height = 100, src = "") {
|
|
|
2317
2320
|
return img;
|
|
2318
2321
|
}
|
|
2319
2322
|
|
|
2320
|
-
//
|
|
2321
|
-
import {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2323
|
+
// ../../node_modules/.pnpm/webgpu@0.3.8/node_modules/webgpu/index.js
|
|
2324
|
+
import { dirname, join } from "path";
|
|
2325
|
+
import { fileURLToPath } from "url";
|
|
2326
|
+
import { createRequire } from "module";
|
|
2327
|
+
var require2 = createRequire(import.meta.url);
|
|
2328
|
+
var isMac = process.platform === "darwin";
|
|
2329
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
2330
|
+
var arch = isMac ? "universal" : process.arch;
|
|
2331
|
+
var dawnNodePath = join(__dirname, "dist", `${process.platform}-${arch}.dawn.node`);
|
|
2332
|
+
var { create, globals } = require2(dawnNodePath);
|
|
2333
|
+
|
|
2334
|
+
// src/setup/webgpu.ts
|
|
2335
|
+
async function initHeadlessWebGPU(options) {
|
|
2336
|
+
if (typeof process === "undefined" || process.release?.name !== "node") {
|
|
2337
|
+
throw new Error("initHeadlessWebGPU should only be called in a Node.js environment");
|
|
2338
|
+
}
|
|
2339
|
+
if (!globalThis.navigator) {
|
|
2340
|
+
globalThis.navigator = {};
|
|
2341
|
+
}
|
|
2342
|
+
if (!globalThis.navigator.gpu) {
|
|
2343
|
+
const gpu = create([]);
|
|
2344
|
+
try {
|
|
2345
|
+
Object.defineProperty(globalThis.navigator, "gpu", {
|
|
2346
|
+
value: gpu,
|
|
2347
|
+
writable: true,
|
|
2348
|
+
configurable: true
|
|
2349
|
+
});
|
|
2350
|
+
} catch (e) {
|
|
2351
|
+
console.warn("Could not define navigator.gpu, trying direct assignment");
|
|
2352
|
+
globalThis.navigator.gpu = gpu;
|
|
2353
|
+
}
|
|
2354
|
+
Object.assign(globalThis, globals);
|
|
2355
|
+
}
|
|
2356
|
+
const adapter = await navigator.gpu.requestAdapter({
|
|
2357
|
+
powerPreference: options?.powerPreference || "high-performance"
|
|
2358
|
+
});
|
|
2359
|
+
if (!adapter) {
|
|
2360
|
+
throw new Error("Failed to create WebGPU adapter");
|
|
2361
|
+
}
|
|
2362
|
+
const device = await adapter.requestDevice({
|
|
2363
|
+
requiredFeatures: options?.requiredFeatures || []
|
|
2364
|
+
});
|
|
2365
|
+
if (!device) {
|
|
2366
|
+
throw new Error("Failed to create WebGPU device");
|
|
2367
|
+
}
|
|
2335
2368
|
return {
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
lost: new Promise(() => {
|
|
2341
|
-
}),
|
|
2342
|
-
// Pending promise
|
|
2343
|
-
createShaderModule: vi12.fn(),
|
|
2344
|
-
createBindGroupLayout: vi12.fn(),
|
|
2345
|
-
createPipelineLayout: vi12.fn(),
|
|
2346
|
-
createRenderPipeline: vi12.fn(),
|
|
2347
|
-
createCommandEncoder: vi12.fn().mockReturnValue({
|
|
2348
|
-
copyTextureToBuffer: vi12.fn(),
|
|
2349
|
-
finish: vi12.fn()
|
|
2350
|
-
}),
|
|
2351
|
-
createBuffer: vi12.fn(),
|
|
2352
|
-
createTexture: vi12.fn().mockReturnValue({
|
|
2353
|
-
createView: vi12.fn()
|
|
2354
|
-
}),
|
|
2355
|
-
queue: {
|
|
2356
|
-
submit: vi12.fn(),
|
|
2357
|
-
writeBuffer: vi12.fn(),
|
|
2358
|
-
writeTexture: vi12.fn()
|
|
2369
|
+
adapter,
|
|
2370
|
+
device,
|
|
2371
|
+
cleanup: async () => {
|
|
2372
|
+
device.destroy();
|
|
2359
2373
|
}
|
|
2360
2374
|
};
|
|
2361
2375
|
}
|
|
2362
|
-
function
|
|
2376
|
+
async function createHeadlessTestContext() {
|
|
2377
|
+
const { adapter, device } = await initHeadlessWebGPU();
|
|
2363
2378
|
return {
|
|
2364
|
-
|
|
2365
|
-
|
|
2379
|
+
adapter,
|
|
2380
|
+
device,
|
|
2381
|
+
queue: device.queue
|
|
2366
2382
|
};
|
|
2367
2383
|
}
|
|
2384
|
+
|
|
2385
|
+
// src/engine/mocks/webgpu.ts
|
|
2386
|
+
import { vi as vi12 } from "vitest";
|
|
2368
2387
|
function setupWebGPUMocks() {
|
|
2369
|
-
|
|
2388
|
+
Object.assign(globalThis, globals);
|
|
2370
2389
|
const mockGpu = {
|
|
2371
|
-
requestAdapter: vi12.fn()
|
|
2390
|
+
requestAdapter: vi12.fn(),
|
|
2372
2391
|
getPreferredCanvasFormat: vi12.fn().mockReturnValue("bgra8unorm")
|
|
2373
2392
|
};
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
});
|
|
2381
|
-
if (typeof GPUTextureUsage === "undefined") {
|
|
2382
|
-
global.GPUTextureUsage = {
|
|
2383
|
-
COPY_SRC: 1,
|
|
2384
|
-
COPY_DST: 2,
|
|
2385
|
-
TEXTURE_BINDING: 4,
|
|
2386
|
-
STORAGE_BINDING: 8,
|
|
2387
|
-
RENDER_ATTACHMENT: 16
|
|
2388
|
-
};
|
|
2389
|
-
}
|
|
2390
|
-
if (typeof GPUBufferUsage === "undefined") {
|
|
2391
|
-
global.GPUBufferUsage = {
|
|
2392
|
-
MAP_READ: 1,
|
|
2393
|
-
MAP_WRITE: 2,
|
|
2394
|
-
COPY_SRC: 4,
|
|
2395
|
-
COPY_DST: 8,
|
|
2396
|
-
INDEX: 16,
|
|
2397
|
-
VERTEX: 32,
|
|
2398
|
-
UNIFORM: 64,
|
|
2399
|
-
STORAGE: 128,
|
|
2400
|
-
INDIRECT: 256,
|
|
2401
|
-
QUERY_RESOLVE: 512
|
|
2402
|
-
};
|
|
2393
|
+
const mockAdapter = createMockGPUAdapter();
|
|
2394
|
+
const mockDevice = createMockGPUDevice();
|
|
2395
|
+
mockGpu.requestAdapter.mockResolvedValue(mockAdapter);
|
|
2396
|
+
mockAdapter.requestDevice.mockResolvedValue(mockDevice);
|
|
2397
|
+
if (!globalThis.navigator) {
|
|
2398
|
+
globalThis.navigator = {};
|
|
2403
2399
|
}
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2400
|
+
try {
|
|
2401
|
+
Object.defineProperty(globalThis.navigator, "gpu", {
|
|
2402
|
+
value: mockGpu,
|
|
2403
|
+
writable: true,
|
|
2404
|
+
configurable: true
|
|
2405
|
+
});
|
|
2406
|
+
} catch (e) {
|
|
2407
|
+
globalThis.navigator.gpu = mockGpu;
|
|
2409
2408
|
}
|
|
2410
2409
|
return {
|
|
2411
2410
|
mockGpu,
|
|
2412
|
-
mockAdapter
|
|
2411
|
+
mockAdapter,
|
|
2412
|
+
mockDevice
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
function createMockGPUAdapter(options = {}) {
|
|
2416
|
+
return {
|
|
2417
|
+
features: /* @__PURE__ */ new Set(),
|
|
2418
|
+
limits: {},
|
|
2419
|
+
isFallbackAdapter: false,
|
|
2420
|
+
requestDevice: vi12.fn().mockResolvedValue(createMockGPUDevice()),
|
|
2421
|
+
requestAdapterInfo: vi12.fn().mockResolvedValue({}),
|
|
2422
|
+
...options
|
|
2423
|
+
};
|
|
2424
|
+
}
|
|
2425
|
+
function createMockGPUDevice(features = /* @__PURE__ */ new Set()) {
|
|
2426
|
+
const queue = createMockQueue();
|
|
2427
|
+
return {
|
|
2428
|
+
features,
|
|
2429
|
+
limits: {},
|
|
2430
|
+
queue,
|
|
2431
|
+
destroy: vi12.fn(),
|
|
2432
|
+
createBuffer: vi12.fn((descriptor) => createMockGPUBuffer(descriptor)),
|
|
2433
|
+
createTexture: vi12.fn((descriptor) => createMockGPUTexture(descriptor)),
|
|
2434
|
+
createSampler: vi12.fn(() => createMockSampler()),
|
|
2435
|
+
createBindGroupLayout: vi12.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2436
|
+
createPipelineLayout: vi12.fn(() => ({ label: "mock-pipeline-layout" })),
|
|
2437
|
+
createBindGroup: vi12.fn(() => ({ label: "mock-bind-group" })),
|
|
2438
|
+
createShaderModule: vi12.fn((descriptor) => createMockShaderModule(descriptor)),
|
|
2439
|
+
createComputePipeline: vi12.fn(() => createMockComputePipeline()),
|
|
2440
|
+
createRenderPipeline: vi12.fn(() => createMockRenderPipeline()),
|
|
2441
|
+
createComputePipelineAsync: vi12.fn().mockResolvedValue(createMockComputePipeline()),
|
|
2442
|
+
createRenderPipelineAsync: vi12.fn().mockResolvedValue(createMockRenderPipeline()),
|
|
2443
|
+
createCommandEncoder: vi12.fn(() => createMockCommandEncoder()),
|
|
2444
|
+
createQuerySet: vi12.fn(() => ({ label: "mock-query-set" })),
|
|
2445
|
+
pushErrorScope: vi12.fn(),
|
|
2446
|
+
popErrorScope: vi12.fn().mockResolvedValue(null),
|
|
2447
|
+
addEventListener: vi12.fn(),
|
|
2448
|
+
removeEventListener: vi12.fn(),
|
|
2449
|
+
dispatchEvent: vi12.fn(),
|
|
2450
|
+
onuncapturederror: null,
|
|
2451
|
+
label: "",
|
|
2452
|
+
lost: Promise.resolve({ reason: "destroyed", message: "Device lost" })
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2455
|
+
function createMockQueue() {
|
|
2456
|
+
return {
|
|
2457
|
+
submit: vi12.fn(),
|
|
2458
|
+
onSubmittedWorkDone: vi12.fn().mockResolvedValue(void 0),
|
|
2459
|
+
writeBuffer: vi12.fn(),
|
|
2460
|
+
writeTexture: vi12.fn(),
|
|
2461
|
+
copyExternalImageToTexture: vi12.fn(),
|
|
2462
|
+
label: ""
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
function createMockGPUBuffer(descriptor) {
|
|
2466
|
+
return {
|
|
2467
|
+
size: descriptor.size,
|
|
2468
|
+
usage: descriptor.usage,
|
|
2469
|
+
mapState: "unmapped",
|
|
2470
|
+
mapAsync: vi12.fn().mockResolvedValue(void 0),
|
|
2471
|
+
getMappedRange: vi12.fn(() => new ArrayBuffer(descriptor.size)),
|
|
2472
|
+
unmap: vi12.fn(),
|
|
2473
|
+
destroy: vi12.fn(),
|
|
2474
|
+
label: descriptor.label || ""
|
|
2475
|
+
};
|
|
2476
|
+
}
|
|
2477
|
+
function createMockGPUTexture(descriptor) {
|
|
2478
|
+
const size = descriptor.size;
|
|
2479
|
+
let width = 0;
|
|
2480
|
+
let height = 0;
|
|
2481
|
+
let depthOrArrayLayers = 1;
|
|
2482
|
+
if (Array.isArray(size) || size instanceof Float32Array || size instanceof Uint32Array) {
|
|
2483
|
+
const arr = Array.from(size);
|
|
2484
|
+
width = arr[0] || 0;
|
|
2485
|
+
height = arr[1] || 1;
|
|
2486
|
+
depthOrArrayLayers = arr[2] || 1;
|
|
2487
|
+
} else if (typeof size === "object") {
|
|
2488
|
+
const dict = size;
|
|
2489
|
+
width = dict.width;
|
|
2490
|
+
height = dict.height || 1;
|
|
2491
|
+
depthOrArrayLayers = dict.depthOrArrayLayers || 1;
|
|
2492
|
+
}
|
|
2493
|
+
return {
|
|
2494
|
+
width,
|
|
2495
|
+
height,
|
|
2496
|
+
depthOrArrayLayers,
|
|
2497
|
+
mipLevelCount: descriptor.mipLevelCount || 1,
|
|
2498
|
+
sampleCount: descriptor.sampleCount || 1,
|
|
2499
|
+
dimension: descriptor.dimension || "2d",
|
|
2500
|
+
format: descriptor.format,
|
|
2501
|
+
usage: descriptor.usage,
|
|
2502
|
+
createView: vi12.fn(() => createMockTextureView()),
|
|
2503
|
+
destroy: vi12.fn(),
|
|
2504
|
+
label: descriptor.label || ""
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
function createMockTextureView() {
|
|
2508
|
+
return {
|
|
2509
|
+
label: ""
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
function createMockSampler() {
|
|
2513
|
+
return {
|
|
2514
|
+
label: ""
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
function createMockShaderModule(descriptor) {
|
|
2518
|
+
return {
|
|
2519
|
+
getCompilationInfo: vi12.fn().mockResolvedValue({ messages: [] }),
|
|
2520
|
+
label: descriptor.label || ""
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
function createMockComputePipeline() {
|
|
2524
|
+
return {
|
|
2525
|
+
getBindGroupLayout: vi12.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2526
|
+
label: ""
|
|
2527
|
+
};
|
|
2528
|
+
}
|
|
2529
|
+
function createMockRenderPipeline() {
|
|
2530
|
+
return {
|
|
2531
|
+
getBindGroupLayout: vi12.fn(() => ({ label: "mock-bind-group-layout" })),
|
|
2532
|
+
label: ""
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
function createMockCommandEncoder() {
|
|
2536
|
+
return {
|
|
2537
|
+
beginRenderPass: vi12.fn(() => createMockRenderPassEncoder()),
|
|
2538
|
+
beginComputePass: vi12.fn(() => createMockComputePassEncoder()),
|
|
2539
|
+
copyBufferToBuffer: vi12.fn(),
|
|
2540
|
+
copyBufferToTexture: vi12.fn(),
|
|
2541
|
+
copyTextureToBuffer: vi12.fn(),
|
|
2542
|
+
copyTextureToTexture: vi12.fn(),
|
|
2543
|
+
clearBuffer: vi12.fn(),
|
|
2544
|
+
writeTimestamp: vi12.fn(),
|
|
2545
|
+
resolveQuerySet: vi12.fn(),
|
|
2546
|
+
finish: vi12.fn(() => ({ label: "mock-command-buffer" })),
|
|
2547
|
+
pushDebugGroup: vi12.fn(),
|
|
2548
|
+
popDebugGroup: vi12.fn(),
|
|
2549
|
+
insertDebugMarker: vi12.fn(),
|
|
2550
|
+
label: ""
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
function createMockRenderPassEncoder() {
|
|
2554
|
+
return {
|
|
2555
|
+
setPipeline: vi12.fn(),
|
|
2556
|
+
setIndexBuffer: vi12.fn(),
|
|
2557
|
+
setVertexBuffer: vi12.fn(),
|
|
2558
|
+
setBindGroup: vi12.fn(),
|
|
2559
|
+
setViewport: vi12.fn(),
|
|
2560
|
+
setScissorRect: vi12.fn(),
|
|
2561
|
+
setBlendConstant: vi12.fn(),
|
|
2562
|
+
setStencilReference: vi12.fn(),
|
|
2563
|
+
beginOcclusionQuery: vi12.fn(),
|
|
2564
|
+
endOcclusionQuery: vi12.fn(),
|
|
2565
|
+
executeBundles: vi12.fn(),
|
|
2566
|
+
draw: vi12.fn(),
|
|
2567
|
+
drawIndexed: vi12.fn(),
|
|
2568
|
+
drawIndirect: vi12.fn(),
|
|
2569
|
+
drawIndexedIndirect: vi12.fn(),
|
|
2570
|
+
end: vi12.fn(),
|
|
2571
|
+
pushDebugGroup: vi12.fn(),
|
|
2572
|
+
popDebugGroup: vi12.fn(),
|
|
2573
|
+
insertDebugMarker: vi12.fn(),
|
|
2574
|
+
label: ""
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
function createMockComputePassEncoder() {
|
|
2578
|
+
return {
|
|
2579
|
+
setPipeline: vi12.fn(),
|
|
2580
|
+
setBindGroup: vi12.fn(),
|
|
2581
|
+
dispatchWorkgroups: vi12.fn(),
|
|
2582
|
+
dispatchWorkgroupsIndirect: vi12.fn(),
|
|
2583
|
+
end: vi12.fn(),
|
|
2584
|
+
pushDebugGroup: vi12.fn(),
|
|
2585
|
+
popDebugGroup: vi12.fn(),
|
|
2586
|
+
insertDebugMarker: vi12.fn(),
|
|
2587
|
+
label: ""
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
function createMockWebGPUContext() {
|
|
2591
|
+
const adapter = createMockGPUAdapter();
|
|
2592
|
+
const device = createMockGPUDevice();
|
|
2593
|
+
return {
|
|
2594
|
+
adapter,
|
|
2595
|
+
device,
|
|
2596
|
+
queue: device.queue
|
|
2413
2597
|
};
|
|
2414
2598
|
}
|
|
2415
2599
|
|
|
@@ -2813,20 +2997,140 @@ function createMockSkyboxPipeline(overrides) {
|
|
|
2813
2997
|
};
|
|
2814
2998
|
}
|
|
2815
2999
|
|
|
2816
|
-
// src/engine/
|
|
3000
|
+
// src/engine/mocks/assets.ts
|
|
2817
3001
|
import { vi as vi14 } from "vitest";
|
|
3002
|
+
function createMockAssetManager(overrides) {
|
|
3003
|
+
return {
|
|
3004
|
+
textures: {
|
|
3005
|
+
get: vi14.fn(),
|
|
3006
|
+
set: vi14.fn(),
|
|
3007
|
+
has: vi14.fn(),
|
|
3008
|
+
clear: vi14.fn(),
|
|
3009
|
+
memoryUsage: 0
|
|
3010
|
+
},
|
|
3011
|
+
audio: {
|
|
3012
|
+
load: vi14.fn(),
|
|
3013
|
+
get: vi14.fn(),
|
|
3014
|
+
clearAll: vi14.fn()
|
|
3015
|
+
},
|
|
3016
|
+
loadTexture: vi14.fn().mockResolvedValue({}),
|
|
3017
|
+
registerTexture: vi14.fn(),
|
|
3018
|
+
loadSound: vi14.fn().mockResolvedValue({}),
|
|
3019
|
+
loadMd2Model: vi14.fn().mockResolvedValue({}),
|
|
3020
|
+
getMd2Model: vi14.fn(),
|
|
3021
|
+
loadMd3Model: vi14.fn().mockResolvedValue({}),
|
|
3022
|
+
getMd3Model: vi14.fn(),
|
|
3023
|
+
loadSprite: vi14.fn().mockResolvedValue({}),
|
|
3024
|
+
loadMap: vi14.fn().mockResolvedValue({}),
|
|
3025
|
+
getMap: vi14.fn(),
|
|
3026
|
+
loadPalette: vi14.fn().mockResolvedValue(void 0),
|
|
3027
|
+
isAssetLoaded: vi14.fn().mockReturnValue(true),
|
|
3028
|
+
listFiles: vi14.fn().mockReturnValue([]),
|
|
3029
|
+
resetForLevelChange: vi14.fn(),
|
|
3030
|
+
getMemoryUsage: vi14.fn().mockReturnValue({ textures: 0, audio: 0 }),
|
|
3031
|
+
clearCache: vi14.fn(),
|
|
3032
|
+
preloadAssets: vi14.fn().mockResolvedValue(void 0),
|
|
3033
|
+
queueLoad: vi14.fn().mockImplementation((path2) => Promise.resolve({})),
|
|
3034
|
+
...overrides
|
|
3035
|
+
};
|
|
3036
|
+
}
|
|
3037
|
+
function createMockTexture(width = 1, height = 1, data) {
|
|
3038
|
+
return {
|
|
3039
|
+
width,
|
|
3040
|
+
height,
|
|
3041
|
+
data: data || new Uint8Array(width * height * 4).fill(255),
|
|
3042
|
+
format: 0,
|
|
3043
|
+
// RGBA
|
|
3044
|
+
name: "mock_texture",
|
|
3045
|
+
uploaded: false
|
|
3046
|
+
};
|
|
3047
|
+
}
|
|
3048
|
+
function createMockMd2Model(overrides) {
|
|
3049
|
+
return {
|
|
3050
|
+
header: {
|
|
3051
|
+
skinWidth: 0,
|
|
3052
|
+
skinHeight: 0,
|
|
3053
|
+
frameSize: 0,
|
|
3054
|
+
numSkins: 0,
|
|
3055
|
+
numVertices: 0,
|
|
3056
|
+
numSt: 0,
|
|
3057
|
+
numTriangles: 0,
|
|
3058
|
+
numGlCmds: 0,
|
|
3059
|
+
numFrames: 0,
|
|
3060
|
+
offsetSkins: 0,
|
|
3061
|
+
offsetSt: 0,
|
|
3062
|
+
offsetTriangles: 0,
|
|
3063
|
+
offsetFrames: 0,
|
|
3064
|
+
offsetGlCmds: 0,
|
|
3065
|
+
offsetEnd: 0
|
|
3066
|
+
},
|
|
3067
|
+
skins: [],
|
|
3068
|
+
texCoords: [],
|
|
3069
|
+
triangles: [],
|
|
3070
|
+
frames: [],
|
|
3071
|
+
glCommands: new Int32Array(0),
|
|
3072
|
+
...overrides
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
3075
|
+
function createMockMd3Model(overrides) {
|
|
3076
|
+
return {
|
|
3077
|
+
header: {
|
|
3078
|
+
ident: 0,
|
|
3079
|
+
version: 0,
|
|
3080
|
+
name: "",
|
|
3081
|
+
flags: 0,
|
|
3082
|
+
numFrames: 0,
|
|
3083
|
+
numTags: 0,
|
|
3084
|
+
numSurfaces: 0,
|
|
3085
|
+
numSkins: 0,
|
|
3086
|
+
offsetFrames: 0,
|
|
3087
|
+
offsetTags: 0,
|
|
3088
|
+
offsetSurfaces: 0,
|
|
3089
|
+
offsetEnd: 0
|
|
3090
|
+
},
|
|
3091
|
+
frames: [],
|
|
3092
|
+
tags: [],
|
|
3093
|
+
surfaces: [],
|
|
3094
|
+
...overrides
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
function createMockBspMap(overrides) {
|
|
3098
|
+
return {
|
|
3099
|
+
version: 38,
|
|
3100
|
+
entities: [],
|
|
3101
|
+
planes: [],
|
|
3102
|
+
vertices: [],
|
|
3103
|
+
visibility: new Uint8Array(0),
|
|
3104
|
+
nodes: [],
|
|
3105
|
+
texInfo: [],
|
|
3106
|
+
faces: [],
|
|
3107
|
+
lightmaps: [],
|
|
3108
|
+
leafs: [],
|
|
3109
|
+
leafFaces: [],
|
|
3110
|
+
leafBrushes: [],
|
|
3111
|
+
edges: [],
|
|
3112
|
+
faceEdges: [],
|
|
3113
|
+
models: [],
|
|
3114
|
+
brushes: [],
|
|
3115
|
+
brushSides: [],
|
|
3116
|
+
...overrides
|
|
3117
|
+
};
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3120
|
+
// src/engine/rendering.ts
|
|
3121
|
+
import { vi as vi15 } from "vitest";
|
|
2818
3122
|
function createMockRenderingContext() {
|
|
2819
3123
|
const gl = createMockWebGL2Context();
|
|
2820
3124
|
const camera = {
|
|
2821
|
-
update:
|
|
2822
|
-
getViewMatrix:
|
|
2823
|
-
getProjectionMatrix:
|
|
2824
|
-
getViewProjectionMatrix:
|
|
2825
|
-
getPosition:
|
|
2826
|
-
getForward:
|
|
2827
|
-
getRight:
|
|
2828
|
-
getUp:
|
|
2829
|
-
extractFrustumPlanes:
|
|
3125
|
+
update: vi15.fn(),
|
|
3126
|
+
getViewMatrix: vi15.fn().mockReturnValue(new Float32Array(16)),
|
|
3127
|
+
getProjectionMatrix: vi15.fn().mockReturnValue(new Float32Array(16)),
|
|
3128
|
+
getViewProjectionMatrix: vi15.fn().mockReturnValue(new Float32Array(16)),
|
|
3129
|
+
getPosition: vi15.fn().mockReturnValue([0, 0, 0]),
|
|
3130
|
+
getForward: vi15.fn().mockReturnValue([0, 0, -1]),
|
|
3131
|
+
getRight: vi15.fn().mockReturnValue([1, 0, 0]),
|
|
3132
|
+
getUp: vi15.fn().mockReturnValue([0, 1, 0]),
|
|
3133
|
+
extractFrustumPlanes: vi15.fn(),
|
|
2830
3134
|
transform: {
|
|
2831
3135
|
origin: [0, 0, 0],
|
|
2832
3136
|
angles: [0, 0, 0],
|
|
@@ -2834,29 +3138,29 @@ function createMockRenderingContext() {
|
|
|
2834
3138
|
}
|
|
2835
3139
|
};
|
|
2836
3140
|
const md2 = {
|
|
2837
|
-
render:
|
|
2838
|
-
init:
|
|
2839
|
-
resize:
|
|
3141
|
+
render: vi15.fn(),
|
|
3142
|
+
init: vi15.fn(),
|
|
3143
|
+
resize: vi15.fn()
|
|
2840
3144
|
};
|
|
2841
3145
|
const bsp = {
|
|
2842
|
-
render:
|
|
2843
|
-
init:
|
|
2844
|
-
resize:
|
|
3146
|
+
render: vi15.fn(),
|
|
3147
|
+
init: vi15.fn(),
|
|
3148
|
+
resize: vi15.fn()
|
|
2845
3149
|
};
|
|
2846
3150
|
const sprite = {
|
|
2847
|
-
render:
|
|
2848
|
-
init:
|
|
2849
|
-
resize:
|
|
3151
|
+
render: vi15.fn(),
|
|
3152
|
+
init: vi15.fn(),
|
|
3153
|
+
resize: vi15.fn()
|
|
2850
3154
|
};
|
|
2851
3155
|
const poly = {
|
|
2852
|
-
render:
|
|
2853
|
-
init:
|
|
2854
|
-
resize:
|
|
3156
|
+
render: vi15.fn(),
|
|
3157
|
+
init: vi15.fn(),
|
|
3158
|
+
resize: vi15.fn()
|
|
2855
3159
|
};
|
|
2856
3160
|
const particle = {
|
|
2857
|
-
render:
|
|
2858
|
-
init:
|
|
2859
|
-
resize:
|
|
3161
|
+
render: vi15.fn(),
|
|
3162
|
+
init: vi15.fn(),
|
|
3163
|
+
resize: vi15.fn()
|
|
2860
3164
|
};
|
|
2861
3165
|
return {
|
|
2862
3166
|
gl,
|
|
@@ -3009,6 +3313,207 @@ function captureAudioEvents(context) {
|
|
|
3009
3313
|
return [];
|
|
3010
3314
|
}
|
|
3011
3315
|
|
|
3316
|
+
// src/engine/helpers/webgpu-rendering.ts
|
|
3317
|
+
async function createRenderTestSetup(width = 256, height = 256) {
|
|
3318
|
+
const setup = await initHeadlessWebGPU();
|
|
3319
|
+
const { device } = setup;
|
|
3320
|
+
const renderTarget = device.createTexture({
|
|
3321
|
+
size: { width, height, depthOrArrayLayers: 1 },
|
|
3322
|
+
format: "rgba8unorm",
|
|
3323
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC
|
|
3324
|
+
});
|
|
3325
|
+
const renderTargetView = renderTarget.createView();
|
|
3326
|
+
const commandEncoder = device.createCommandEncoder();
|
|
3327
|
+
const context = {
|
|
3328
|
+
adapter: setup.adapter,
|
|
3329
|
+
device: setup.device,
|
|
3330
|
+
queue: setup.device.queue
|
|
3331
|
+
};
|
|
3332
|
+
return {
|
|
3333
|
+
context,
|
|
3334
|
+
renderTarget,
|
|
3335
|
+
renderTargetView,
|
|
3336
|
+
commandEncoder,
|
|
3337
|
+
width,
|
|
3338
|
+
height,
|
|
3339
|
+
cleanup: async () => {
|
|
3340
|
+
renderTarget.destroy();
|
|
3341
|
+
await setup.cleanup();
|
|
3342
|
+
}
|
|
3343
|
+
};
|
|
3344
|
+
}
|
|
3345
|
+
async function renderAndCapture(setup, renderFn) {
|
|
3346
|
+
const { device, queue } = setup.context;
|
|
3347
|
+
const { renderTargetView, commandEncoder, width, height } = setup;
|
|
3348
|
+
const passEncoder = commandEncoder.beginRenderPass({
|
|
3349
|
+
colorAttachments: [
|
|
3350
|
+
{
|
|
3351
|
+
view: renderTargetView,
|
|
3352
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
3353
|
+
loadOp: "clear",
|
|
3354
|
+
storeOp: "store"
|
|
3355
|
+
}
|
|
3356
|
+
]
|
|
3357
|
+
});
|
|
3358
|
+
renderFn(passEncoder);
|
|
3359
|
+
passEncoder.end();
|
|
3360
|
+
const bytesPerPixel = 4;
|
|
3361
|
+
const unpaddedBytesPerRow = width * bytesPerPixel;
|
|
3362
|
+
const align = 256;
|
|
3363
|
+
const paddedBytesPerRow = Math.max(
|
|
3364
|
+
bytesPerPixel * width,
|
|
3365
|
+
Math.ceil(bytesPerPixel * width / align) * align
|
|
3366
|
+
);
|
|
3367
|
+
const bufferSize = paddedBytesPerRow * height;
|
|
3368
|
+
const readbackBuffer = device.createBuffer({
|
|
3369
|
+
size: bufferSize,
|
|
3370
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
3371
|
+
});
|
|
3372
|
+
commandEncoder.copyTextureToBuffer(
|
|
3373
|
+
{
|
|
3374
|
+
texture: setup.renderTarget
|
|
3375
|
+
},
|
|
3376
|
+
{
|
|
3377
|
+
buffer: readbackBuffer,
|
|
3378
|
+
bytesPerRow: paddedBytesPerRow
|
|
3379
|
+
},
|
|
3380
|
+
{
|
|
3381
|
+
width,
|
|
3382
|
+
height,
|
|
3383
|
+
depthOrArrayLayers: 1
|
|
3384
|
+
}
|
|
3385
|
+
);
|
|
3386
|
+
queue.submit([commandEncoder.finish()]);
|
|
3387
|
+
await readbackBuffer.mapAsync(GPUMapMode.READ);
|
|
3388
|
+
const arrayBuffer = readbackBuffer.getMappedRange();
|
|
3389
|
+
const output = new Uint8ClampedArray(width * height * 4);
|
|
3390
|
+
const srcBytes = new Uint8Array(arrayBuffer);
|
|
3391
|
+
for (let y = 0; y < height; y++) {
|
|
3392
|
+
const srcOffset = y * paddedBytesPerRow;
|
|
3393
|
+
const dstOffset = y * unpaddedBytesPerRow;
|
|
3394
|
+
output.set(srcBytes.subarray(srcOffset, srcOffset + unpaddedBytesPerRow), dstOffset);
|
|
3395
|
+
}
|
|
3396
|
+
readbackBuffer.unmap();
|
|
3397
|
+
readbackBuffer.destroy();
|
|
3398
|
+
return output;
|
|
3399
|
+
}
|
|
3400
|
+
async function createComputeTestSetup(outputSize) {
|
|
3401
|
+
const setup = await initHeadlessWebGPU();
|
|
3402
|
+
const { device } = setup;
|
|
3403
|
+
const outputBuffer = device.createBuffer({
|
|
3404
|
+
size: outputSize,
|
|
3405
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
|
|
3406
|
+
});
|
|
3407
|
+
const commandEncoder = device.createCommandEncoder();
|
|
3408
|
+
const context = {
|
|
3409
|
+
adapter: setup.adapter,
|
|
3410
|
+
device: setup.device,
|
|
3411
|
+
queue: setup.device.queue
|
|
3412
|
+
};
|
|
3413
|
+
return {
|
|
3414
|
+
context,
|
|
3415
|
+
outputBuffer,
|
|
3416
|
+
commandEncoder,
|
|
3417
|
+
outputSize,
|
|
3418
|
+
cleanup: async () => {
|
|
3419
|
+
outputBuffer.destroy();
|
|
3420
|
+
await setup.cleanup();
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
async function runComputeAndReadback(setup, computeFn) {
|
|
3425
|
+
const { device, queue } = setup.context;
|
|
3426
|
+
const { outputBuffer, commandEncoder, outputSize } = setup;
|
|
3427
|
+
const passEncoder = commandEncoder.beginComputePass();
|
|
3428
|
+
computeFn(passEncoder);
|
|
3429
|
+
passEncoder.end();
|
|
3430
|
+
const stagingBuffer = device.createBuffer({
|
|
3431
|
+
size: outputSize,
|
|
3432
|
+
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
|
|
3433
|
+
});
|
|
3434
|
+
commandEncoder.copyBufferToBuffer(
|
|
3435
|
+
outputBuffer,
|
|
3436
|
+
0,
|
|
3437
|
+
stagingBuffer,
|
|
3438
|
+
0,
|
|
3439
|
+
outputSize
|
|
3440
|
+
);
|
|
3441
|
+
queue.submit([commandEncoder.finish()]);
|
|
3442
|
+
await stagingBuffer.mapAsync(GPUMapMode.READ);
|
|
3443
|
+
const mappedRange = stagingBuffer.getMappedRange();
|
|
3444
|
+
const result = mappedRange.slice(0);
|
|
3445
|
+
stagingBuffer.unmap();
|
|
3446
|
+
stagingBuffer.destroy();
|
|
3447
|
+
return result;
|
|
3448
|
+
}
|
|
3449
|
+
|
|
3450
|
+
// src/engine/helpers/pipeline-test-template.ts
|
|
3451
|
+
import { expect } from "vitest";
|
|
3452
|
+
async function testPipelineRendering(name, createPipeline, setupGeometry, expectedOutput) {
|
|
3453
|
+
const setup = await createRenderTestSetup(256, 256);
|
|
3454
|
+
try {
|
|
3455
|
+
const pipeline = createPipeline(setup.context.device);
|
|
3456
|
+
const geometry = setupGeometry(setup.context.device);
|
|
3457
|
+
const pixels = await renderAndCapture(setup, (pass) => {
|
|
3458
|
+
pass.setPipeline(pipeline);
|
|
3459
|
+
pass.setVertexBuffer(0, geometry.vertexBuffer);
|
|
3460
|
+
if (geometry.indexBuffer) {
|
|
3461
|
+
pass.setIndexBuffer(geometry.indexBuffer, "uint16");
|
|
3462
|
+
pass.drawIndexed(geometry.indexCount || 0);
|
|
3463
|
+
} else {
|
|
3464
|
+
pass.draw(geometry.vertexCount);
|
|
3465
|
+
}
|
|
3466
|
+
});
|
|
3467
|
+
if (expectedOutput) {
|
|
3468
|
+
expect(pixels).toEqual(expectedOutput);
|
|
3469
|
+
} else {
|
|
3470
|
+
expect(pixels.length).toBe(256 * 256 * 4);
|
|
3471
|
+
}
|
|
3472
|
+
} finally {
|
|
3473
|
+
await setup.cleanup();
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
async function testComputeShader(name, createComputePipeline, inputData, expectedOutput) {
|
|
3477
|
+
const setup = await createComputeTestSetup(inputData.byteLength);
|
|
3478
|
+
const { device } = setup.context;
|
|
3479
|
+
try {
|
|
3480
|
+
const pipeline = createComputePipeline(device);
|
|
3481
|
+
const stagingBuffer = device.createBuffer({
|
|
3482
|
+
size: inputData.byteLength,
|
|
3483
|
+
usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE,
|
|
3484
|
+
mappedAtCreation: true
|
|
3485
|
+
});
|
|
3486
|
+
new Float32Array(stagingBuffer.getMappedRange()).set(inputData);
|
|
3487
|
+
stagingBuffer.unmap();
|
|
3488
|
+
const encoder = device.createCommandEncoder();
|
|
3489
|
+
encoder.copyBufferToBuffer(stagingBuffer, 0, setup.outputBuffer, 0, inputData.byteLength);
|
|
3490
|
+
device.queue.submit([encoder.finish()]);
|
|
3491
|
+
const bindGroup = device.createBindGroup({
|
|
3492
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
3493
|
+
entries: [
|
|
3494
|
+
{
|
|
3495
|
+
binding: 0,
|
|
3496
|
+
resource: {
|
|
3497
|
+
buffer: setup.outputBuffer
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
]
|
|
3501
|
+
});
|
|
3502
|
+
const resultBuffer = await runComputeAndReadback(setup, (pass) => {
|
|
3503
|
+
pass.setPipeline(pipeline);
|
|
3504
|
+
pass.setBindGroup(0, bindGroup);
|
|
3505
|
+
pass.dispatchWorkgroups(Math.ceil(inputData.length / 64));
|
|
3506
|
+
});
|
|
3507
|
+
if (expectedOutput) {
|
|
3508
|
+
const floatResult = new Float32Array(resultBuffer);
|
|
3509
|
+
expect(floatResult).toEqual(expectedOutput);
|
|
3510
|
+
}
|
|
3511
|
+
stagingBuffer.destroy();
|
|
3512
|
+
} finally {
|
|
3513
|
+
await setup.cleanup();
|
|
3514
|
+
}
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3012
3517
|
// ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
|
|
3013
3518
|
var EPSILON = 1e-6;
|
|
3014
3519
|
var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array;
|
|
@@ -3029,7 +3534,7 @@ __export(vec3_exports, {
|
|
|
3029
3534
|
ceil: () => ceil,
|
|
3030
3535
|
clone: () => clone,
|
|
3031
3536
|
copy: () => copy,
|
|
3032
|
-
create: () =>
|
|
3537
|
+
create: () => create2,
|
|
3033
3538
|
cross: () => cross,
|
|
3034
3539
|
dist: () => dist,
|
|
3035
3540
|
distance: () => distance,
|
|
@@ -3073,7 +3578,7 @@ __export(vec3_exports, {
|
|
|
3073
3578
|
transformQuat: () => transformQuat,
|
|
3074
3579
|
zero: () => zero
|
|
3075
3580
|
});
|
|
3076
|
-
function
|
|
3581
|
+
function create2() {
|
|
3077
3582
|
var out = new ARRAY_TYPE(3);
|
|
3078
3583
|
if (ARRAY_TYPE != Float32Array) {
|
|
3079
3584
|
out[0] = 0;
|
|
@@ -3385,7 +3890,7 @@ var sqrDist = squaredDistance;
|
|
|
3385
3890
|
var len = length;
|
|
3386
3891
|
var sqrLen = squaredLength;
|
|
3387
3892
|
var forEach = (function() {
|
|
3388
|
-
var vec =
|
|
3893
|
+
var vec = create2();
|
|
3389
3894
|
return function(a, stride, offset, count, fn, arg) {
|
|
3390
3895
|
var i, l;
|
|
3391
3896
|
if (!stride) {
|
|
@@ -3508,7 +4013,7 @@ function simulateCameraMovement(camera, input, deltaTime) {
|
|
|
3508
4013
|
}
|
|
3509
4014
|
|
|
3510
4015
|
// src/client/helpers/hud.ts
|
|
3511
|
-
import { vi as
|
|
4016
|
+
import { vi as vi16 } from "vitest";
|
|
3512
4017
|
function createMockHudState(overrides) {
|
|
3513
4018
|
const defaultPs = {
|
|
3514
4019
|
damageAlpha: 0,
|
|
@@ -3543,11 +4048,11 @@ function createMockHudState(overrides) {
|
|
|
3543
4048
|
batches: 10
|
|
3544
4049
|
};
|
|
3545
4050
|
const defaultMessages = {
|
|
3546
|
-
drawCenterPrint:
|
|
3547
|
-
drawNotifications:
|
|
3548
|
-
addCenterPrint:
|
|
3549
|
-
addNotification:
|
|
3550
|
-
clear:
|
|
4051
|
+
drawCenterPrint: vi16.fn(),
|
|
4052
|
+
drawNotifications: vi16.fn(),
|
|
4053
|
+
addCenterPrint: vi16.fn(),
|
|
4054
|
+
addNotification: vi16.fn(),
|
|
4055
|
+
clear: vi16.fn()
|
|
3551
4056
|
};
|
|
3552
4057
|
return {
|
|
3553
4058
|
ps: overrides?.ps ?? defaultPs,
|
|
@@ -3563,7 +4068,7 @@ function createMockHudState(overrides) {
|
|
|
3563
4068
|
function createMockScoreboard(players = []) {
|
|
3564
4069
|
return {
|
|
3565
4070
|
players,
|
|
3566
|
-
draw:
|
|
4071
|
+
draw: vi16.fn()
|
|
3567
4072
|
};
|
|
3568
4073
|
}
|
|
3569
4074
|
function createMockChatMessage(text, sender, timestamp = Date.now()) {
|
|
@@ -3664,6 +4169,254 @@ function createMockFogData(overrides = {}) {
|
|
|
3664
4169
|
};
|
|
3665
4170
|
}
|
|
3666
4171
|
|
|
4172
|
+
// src/client/mocks/download.ts
|
|
4173
|
+
import { vi as vi17 } from "vitest";
|
|
4174
|
+
function createMockDownloadManager(overrides) {
|
|
4175
|
+
return {
|
|
4176
|
+
download: vi17.fn().mockResolvedValue(new ArrayBuffer(0)),
|
|
4177
|
+
cancel: vi17.fn(),
|
|
4178
|
+
getProgress: vi17.fn().mockReturnValue(0),
|
|
4179
|
+
...overrides
|
|
4180
|
+
};
|
|
4181
|
+
}
|
|
4182
|
+
function createMockPrecacheList(models = [], sounds = [], images = []) {
|
|
4183
|
+
return {
|
|
4184
|
+
models,
|
|
4185
|
+
sounds,
|
|
4186
|
+
images
|
|
4187
|
+
};
|
|
4188
|
+
}
|
|
4189
|
+
async function simulateDownload(url, progressCallback) {
|
|
4190
|
+
const steps = 10;
|
|
4191
|
+
for (let i = 0; i <= steps; i++) {
|
|
4192
|
+
if (progressCallback) {
|
|
4193
|
+
progressCallback(i / steps);
|
|
4194
|
+
}
|
|
4195
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
4196
|
+
}
|
|
4197
|
+
return new ArrayBuffer(1024);
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4200
|
+
// src/client/mocks/state.ts
|
|
4201
|
+
var MAX_MODELS = 256;
|
|
4202
|
+
var MAX_SOUNDS = 256;
|
|
4203
|
+
var MAX_IMAGES = 256;
|
|
4204
|
+
var MockClientConfigStrings = class {
|
|
4205
|
+
constructor() {
|
|
4206
|
+
this.strings = /* @__PURE__ */ new Map();
|
|
4207
|
+
this.models = [];
|
|
4208
|
+
this.sounds = [];
|
|
4209
|
+
this.images = [];
|
|
4210
|
+
}
|
|
4211
|
+
set(index, value) {
|
|
4212
|
+
this.strings.set(index, value);
|
|
4213
|
+
if (index >= 32 /* Models */ && index < 32 /* Models */ + MAX_MODELS) {
|
|
4214
|
+
this.models[index - 32 /* Models */] = value;
|
|
4215
|
+
} else if (index >= 288 /* Sounds */ && index < 288 /* Sounds */ + MAX_SOUNDS) {
|
|
4216
|
+
this.sounds[index - 288 /* Sounds */] = value;
|
|
4217
|
+
} else if (index >= 544 /* Images */ && index < 544 /* Images */ + MAX_IMAGES) {
|
|
4218
|
+
this.images[index - 544 /* Images */] = value;
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
get(index) {
|
|
4222
|
+
return this.strings.get(index);
|
|
4223
|
+
}
|
|
4224
|
+
getModelName(index) {
|
|
4225
|
+
return this.models[index];
|
|
4226
|
+
}
|
|
4227
|
+
getSoundName(index) {
|
|
4228
|
+
return this.sounds[index];
|
|
4229
|
+
}
|
|
4230
|
+
getImageName(index) {
|
|
4231
|
+
return this.images[index];
|
|
4232
|
+
}
|
|
4233
|
+
getPlayerName(playernum) {
|
|
4234
|
+
const info = this.strings.get(800 /* Players */ + playernum);
|
|
4235
|
+
if (!info) return void 0;
|
|
4236
|
+
const parts = info.split("\\");
|
|
4237
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
4238
|
+
if (parts[i] === "name") {
|
|
4239
|
+
return parts[i + 1];
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
return void 0;
|
|
4243
|
+
}
|
|
4244
|
+
clear() {
|
|
4245
|
+
this.strings.clear();
|
|
4246
|
+
this.models.length = 0;
|
|
4247
|
+
this.sounds.length = 0;
|
|
4248
|
+
this.images.length = 0;
|
|
4249
|
+
}
|
|
4250
|
+
};
|
|
4251
|
+
var createMockClientState = (overrides) => {
|
|
4252
|
+
const configStrings = new MockClientConfigStrings();
|
|
4253
|
+
return {
|
|
4254
|
+
tickRate: 10,
|
|
4255
|
+
frameTimeMs: 100,
|
|
4256
|
+
serverFrame: 0,
|
|
4257
|
+
serverProtocol: 34,
|
|
4258
|
+
configStrings,
|
|
4259
|
+
playerNum: 0,
|
|
4260
|
+
serverTime: 0,
|
|
4261
|
+
parseEntities: 0,
|
|
4262
|
+
inAutoDemo: false,
|
|
4263
|
+
getClientName: (num) => `Player${num}`,
|
|
4264
|
+
getKeyBinding: (key) => "",
|
|
4265
|
+
...overrides
|
|
4266
|
+
};
|
|
4267
|
+
};
|
|
4268
|
+
var createMockFrame = (overrides) => ({
|
|
4269
|
+
serverFrame: 0,
|
|
4270
|
+
deltaFrame: -1,
|
|
4271
|
+
valid: true,
|
|
4272
|
+
entities: [],
|
|
4273
|
+
...overrides
|
|
4274
|
+
});
|
|
4275
|
+
var createMockClientInfo = (overrides) => ({
|
|
4276
|
+
name: "Player",
|
|
4277
|
+
skin: "male/grunt",
|
|
4278
|
+
model: "male",
|
|
4279
|
+
icon: "pics/icon.pcx",
|
|
4280
|
+
...overrides
|
|
4281
|
+
});
|
|
4282
|
+
var createMockConnectionState = (state = "connected") => ({
|
|
4283
|
+
state
|
|
4284
|
+
});
|
|
4285
|
+
|
|
4286
|
+
// src/client/mocks/console.ts
|
|
4287
|
+
import { vi as vi18 } from "vitest";
|
|
4288
|
+
function createMockConsole(overrides) {
|
|
4289
|
+
const history = [];
|
|
4290
|
+
const errors = [];
|
|
4291
|
+
const commands = {};
|
|
4292
|
+
const cvars = {};
|
|
4293
|
+
return {
|
|
4294
|
+
print: vi18.fn((text) => {
|
|
4295
|
+
history.push(text);
|
|
4296
|
+
}),
|
|
4297
|
+
error: vi18.fn((text) => {
|
|
4298
|
+
errors.push(text);
|
|
4299
|
+
}),
|
|
4300
|
+
execute: vi18.fn((text) => {
|
|
4301
|
+
const parts = text.trim().split(/\s+/);
|
|
4302
|
+
const cmd = parts[0];
|
|
4303
|
+
const args = parts.slice(1);
|
|
4304
|
+
if (commands[cmd]) {
|
|
4305
|
+
commands[cmd](args);
|
|
4306
|
+
} else {
|
|
4307
|
+
history.push(`Unknown command "${cmd}"`);
|
|
4308
|
+
}
|
|
4309
|
+
}),
|
|
4310
|
+
addCommand: vi18.fn((name, handler) => {
|
|
4311
|
+
commands[name] = handler;
|
|
4312
|
+
}),
|
|
4313
|
+
getCvar: vi18.fn((name) => cvars[name]),
|
|
4314
|
+
setCvar: vi18.fn((name, value) => {
|
|
4315
|
+
cvars[name] = value;
|
|
4316
|
+
}),
|
|
4317
|
+
getHistory: () => history,
|
|
4318
|
+
clearHistory: () => {
|
|
4319
|
+
history.length = 0;
|
|
4320
|
+
errors.length = 0;
|
|
4321
|
+
},
|
|
4322
|
+
getErrors: () => errors,
|
|
4323
|
+
...overrides
|
|
4324
|
+
};
|
|
4325
|
+
}
|
|
4326
|
+
function createMockCommand(name, handler) {
|
|
4327
|
+
return { name, handler };
|
|
4328
|
+
}
|
|
4329
|
+
function createMockCvarRegistry(initialCvars) {
|
|
4330
|
+
return { ...initialCvars };
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4333
|
+
// src/client/helpers/prediction.ts
|
|
4334
|
+
var createPredictionTestScenario = (lagMs = 100) => {
|
|
4335
|
+
const clientState = createMockClientState({
|
|
4336
|
+
playerNum: 0,
|
|
4337
|
+
serverTime: 1e3,
|
|
4338
|
+
getClientName: (num) => "TestPlayer"
|
|
4339
|
+
});
|
|
4340
|
+
const snapshots = [];
|
|
4341
|
+
for (let i = 0; i < 5; i++) {
|
|
4342
|
+
const frameEntities = [
|
|
4343
|
+
{
|
|
4344
|
+
number: 1,
|
|
4345
|
+
origin: { x: i * 10, y: 0, z: 0 },
|
|
4346
|
+
angles: { x: 0, y: 0, z: 0 },
|
|
4347
|
+
oldOrigin: { x: (i - 1) * 10, y: 0, z: 0 },
|
|
4348
|
+
modelIndex: 0,
|
|
4349
|
+
modelIndex2: 0,
|
|
4350
|
+
modelIndex3: 0,
|
|
4351
|
+
modelIndex4: 0,
|
|
4352
|
+
frame: 0,
|
|
4353
|
+
skinNum: 0,
|
|
4354
|
+
effects: 0,
|
|
4355
|
+
renderfx: 0,
|
|
4356
|
+
solid: 0,
|
|
4357
|
+
sound: 0,
|
|
4358
|
+
event: 0
|
|
4359
|
+
}
|
|
4360
|
+
];
|
|
4361
|
+
snapshots.push(frameEntities);
|
|
4362
|
+
}
|
|
4363
|
+
return {
|
|
4364
|
+
clientState,
|
|
4365
|
+
snapshots,
|
|
4366
|
+
lagMs
|
|
4367
|
+
};
|
|
4368
|
+
};
|
|
4369
|
+
var simulateClientPrediction = (state, input, deltaTime) => {
|
|
4370
|
+
return {
|
|
4371
|
+
...state,
|
|
4372
|
+
serverTime: state.serverTime + deltaTime * 1e3
|
|
4373
|
+
};
|
|
4374
|
+
};
|
|
4375
|
+
var createInterpolationTestData = (startState, endState, steps = 10) => {
|
|
4376
|
+
const result = [];
|
|
4377
|
+
for (let i = 0; i <= steps; i++) {
|
|
4378
|
+
const t = i / steps;
|
|
4379
|
+
const lerp2 = (a, b) => a + (b - a) * t;
|
|
4380
|
+
result.push({
|
|
4381
|
+
...startState,
|
|
4382
|
+
origin: {
|
|
4383
|
+
x: lerp2(startState.origin.x, endState.origin.x),
|
|
4384
|
+
y: lerp2(startState.origin.y, endState.origin.y),
|
|
4385
|
+
z: lerp2(startState.origin.z, endState.origin.z)
|
|
4386
|
+
},
|
|
4387
|
+
angles: {
|
|
4388
|
+
x: lerp2(startState.angles.x, endState.angles.x),
|
|
4389
|
+
y: lerp2(startState.angles.y, endState.angles.y),
|
|
4390
|
+
z: lerp2(startState.angles.z, endState.angles.z)
|
|
4391
|
+
}
|
|
4392
|
+
});
|
|
4393
|
+
}
|
|
4394
|
+
return result;
|
|
4395
|
+
};
|
|
4396
|
+
var verifySmoothing = (states) => {
|
|
4397
|
+
let maxError = 0;
|
|
4398
|
+
let totalError = 0;
|
|
4399
|
+
const jumps = [];
|
|
4400
|
+
for (let i = 1; i < states.length; i++) {
|
|
4401
|
+
const prev = states[i - 1].origin;
|
|
4402
|
+
const curr = states[i].origin;
|
|
4403
|
+
const dx = curr.x - prev.x;
|
|
4404
|
+
const dy = curr.y - prev.y;
|
|
4405
|
+
const dz = curr.z - prev.z;
|
|
4406
|
+
const dist2 = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
4407
|
+
if (dist2 > 50) {
|
|
4408
|
+
jumps.push(i);
|
|
4409
|
+
}
|
|
4410
|
+
totalError += dist2;
|
|
4411
|
+
}
|
|
4412
|
+
return {
|
|
4413
|
+
smooth: jumps.length === 0,
|
|
4414
|
+
maxError,
|
|
4415
|
+
averageError: totalError / (states.length - 1 || 1),
|
|
4416
|
+
jumps
|
|
4417
|
+
};
|
|
4418
|
+
};
|
|
4419
|
+
|
|
3667
4420
|
// src/e2e/playwright.ts
|
|
3668
4421
|
async function createPlaywrightTestClient(options = {}) {
|
|
3669
4422
|
let playwright;
|
|
@@ -3856,6 +4609,7 @@ export {
|
|
|
3856
4609
|
HandshakeStage,
|
|
3857
4610
|
InputInjector,
|
|
3858
4611
|
FakeBufferSource as MockAudioBufferSourceNode,
|
|
4612
|
+
MockClientConfigStrings,
|
|
3859
4613
|
MockNetDriver,
|
|
3860
4614
|
MockNetworkTransport,
|
|
3861
4615
|
MockPointerLock,
|
|
@@ -3872,6 +4626,7 @@ export {
|
|
|
3872
4626
|
createBinaryWriterMock,
|
|
3873
4627
|
createBounds,
|
|
3874
4628
|
createCombatTestContext,
|
|
4629
|
+
createComputeTestSetup,
|
|
3875
4630
|
createConfigStringArrayMock,
|
|
3876
4631
|
createConfigStringMock,
|
|
3877
4632
|
createControlledTimer,
|
|
@@ -3882,33 +4637,49 @@ export {
|
|
|
3882
4637
|
createEntityFactory,
|
|
3883
4638
|
createEntityStateFactory,
|
|
3884
4639
|
createGameStateSnapshotFactory,
|
|
4640
|
+
createHeadlessTestContext,
|
|
3885
4641
|
createInputInjector,
|
|
4642
|
+
createInterpolationTestData,
|
|
3886
4643
|
createItemEntityFactory,
|
|
3887
4644
|
createMessageReaderMock,
|
|
3888
4645
|
createMessageWriterMock,
|
|
3889
4646
|
createMockAI,
|
|
3890
4647
|
createMockAmmoItem,
|
|
3891
4648
|
createMockArmorItem,
|
|
4649
|
+
createMockAssetManager,
|
|
3892
4650
|
createMockAudioBuffer,
|
|
3893
4651
|
createMockAudioContext,
|
|
4652
|
+
createMockBspMap,
|
|
3894
4653
|
createMockBspPipeline,
|
|
3895
4654
|
createMockBufferSource,
|
|
3896
4655
|
createMockCamera,
|
|
3897
4656
|
createMockCanvas,
|
|
3898
4657
|
createMockCanvasContext2D,
|
|
3899
4658
|
createMockChatMessage,
|
|
4659
|
+
createMockClientInfo,
|
|
4660
|
+
createMockClientState,
|
|
3900
4661
|
createMockCollisionEntityIndex,
|
|
4662
|
+
createMockCommand,
|
|
4663
|
+
createMockCommandEncoder,
|
|
4664
|
+
createMockComputePassEncoder,
|
|
4665
|
+
createMockComputePipeline,
|
|
3901
4666
|
createMockConnection,
|
|
4667
|
+
createMockConnectionState,
|
|
4668
|
+
createMockConsole,
|
|
4669
|
+
createMockCvarRegistry,
|
|
3902
4670
|
createMockDamageIndicator,
|
|
3903
4671
|
createMockDamageInfo,
|
|
3904
4672
|
createMockDeltaFrame,
|
|
4673
|
+
createMockDownloadManager,
|
|
3905
4674
|
createMockEngine,
|
|
3906
4675
|
createMockEntityState,
|
|
3907
4676
|
createMockFogData,
|
|
4677
|
+
createMockFrame,
|
|
3908
4678
|
createMockFrameRenderer,
|
|
3909
4679
|
createMockGPUAdapter,
|
|
3910
|
-
|
|
4680
|
+
createMockGPUBuffer,
|
|
3911
4681
|
createMockGPUDevice,
|
|
4682
|
+
createMockGPUTexture,
|
|
3912
4683
|
createMockGame,
|
|
3913
4684
|
createMockGameExports,
|
|
3914
4685
|
createMockGameState,
|
|
@@ -3923,7 +4694,9 @@ export {
|
|
|
3923
4694
|
createMockKeyboardEvent,
|
|
3924
4695
|
createMockLocalStorage,
|
|
3925
4696
|
createMockMasterServer,
|
|
4697
|
+
createMockMd2Model,
|
|
3926
4698
|
createMockMd2Pipeline,
|
|
4699
|
+
createMockMd3Model,
|
|
3927
4700
|
createMockMd3Pipeline,
|
|
3928
4701
|
createMockMonsterAI,
|
|
3929
4702
|
createMockMonsterMove,
|
|
@@ -3935,12 +4708,17 @@ export {
|
|
|
3935
4708
|
createMockPerformance,
|
|
3936
4709
|
createMockPointerLock,
|
|
3937
4710
|
createMockPowerupItem,
|
|
4711
|
+
createMockPrecacheList,
|
|
4712
|
+
createMockQueue,
|
|
3938
4713
|
createMockRAF,
|
|
3939
4714
|
createMockRConClient,
|
|
3940
4715
|
createMockRateLimiter,
|
|
3941
4716
|
createMockRefDef,
|
|
4717
|
+
createMockRenderPassEncoder,
|
|
4718
|
+
createMockRenderPipeline,
|
|
3942
4719
|
createMockRenderer,
|
|
3943
4720
|
createMockRenderingContext,
|
|
4721
|
+
createMockSampler,
|
|
3944
4722
|
createMockScoreboard,
|
|
3945
4723
|
createMockServer,
|
|
3946
4724
|
createMockServerClient,
|
|
@@ -3950,9 +4728,12 @@ export {
|
|
|
3950
4728
|
createMockServerState,
|
|
3951
4729
|
createMockServerStatic,
|
|
3952
4730
|
createMockSessionStorage,
|
|
4731
|
+
createMockShaderModule,
|
|
3953
4732
|
createMockSkyboxPipeline,
|
|
3954
4733
|
createMockSnapshot,
|
|
3955
4734
|
createMockSpritePipeline,
|
|
4735
|
+
createMockTexture,
|
|
4736
|
+
createMockTextureView,
|
|
3956
4737
|
createMockTransport,
|
|
3957
4738
|
createMockUDPSocket,
|
|
3958
4739
|
createMockUserInfo,
|
|
@@ -3960,6 +4741,7 @@ export {
|
|
|
3960
4741
|
createMockWeapon,
|
|
3961
4742
|
createMockWeaponItem,
|
|
3962
4743
|
createMockWebGL2Context,
|
|
4744
|
+
createMockWebGPUContext,
|
|
3963
4745
|
createMockWheelEvent,
|
|
3964
4746
|
createMonsterEntityFactory,
|
|
3965
4747
|
createMultiplayerTestScenario,
|
|
@@ -3970,7 +4752,9 @@ export {
|
|
|
3970
4752
|
createPlayerEntityFactory,
|
|
3971
4753
|
createPlayerStateFactory,
|
|
3972
4754
|
createPlaywrightTestClient,
|
|
4755
|
+
createPredictionTestScenario,
|
|
3973
4756
|
createProjectileEntityFactory,
|
|
4757
|
+
createRenderTestSetup,
|
|
3974
4758
|
createServerSnapshot,
|
|
3975
4759
|
createSpawnTestContext,
|
|
3976
4760
|
createStorageTestScenario,
|
|
@@ -3982,6 +4766,7 @@ export {
|
|
|
3982
4766
|
createVector3,
|
|
3983
4767
|
createViewTestScenario,
|
|
3984
4768
|
createVisualTestScenario,
|
|
4769
|
+
initHeadlessWebGPU,
|
|
3985
4770
|
intersects,
|
|
3986
4771
|
ladderTrace,
|
|
3987
4772
|
makeAxisBrush,
|
|
@@ -3994,6 +4779,8 @@ export {
|
|
|
3994
4779
|
measureSnapshotSize,
|
|
3995
4780
|
mockMonsterAttacks,
|
|
3996
4781
|
randomVector3,
|
|
4782
|
+
renderAndCapture,
|
|
4783
|
+
runComputeAndReadback,
|
|
3997
4784
|
serializeUserInfo,
|
|
3998
4785
|
setupBrowserEnvironment,
|
|
3999
4786
|
setupMockAudioContext,
|
|
@@ -4001,6 +4788,8 @@ export {
|
|
|
4001
4788
|
setupWebGPUMocks,
|
|
4002
4789
|
simulateBandwidthLimit,
|
|
4003
4790
|
simulateCameraMovement,
|
|
4791
|
+
simulateClientPrediction,
|
|
4792
|
+
simulateDownload,
|
|
4004
4793
|
simulateFrames,
|
|
4005
4794
|
simulateGravity,
|
|
4006
4795
|
simulateHandshake,
|
|
@@ -4021,7 +4810,10 @@ export {
|
|
|
4021
4810
|
teardownBrowserEnvironment,
|
|
4022
4811
|
teardownMockAudioContext,
|
|
4023
4812
|
teardownNodeEnvironment,
|
|
4813
|
+
testComputeShader,
|
|
4814
|
+
testPipelineRendering,
|
|
4024
4815
|
throttleBandwidth,
|
|
4816
|
+
verifySmoothing,
|
|
4025
4817
|
verifySnapshotConsistency,
|
|
4026
4818
|
waitForGameReady
|
|
4027
4819
|
};
|