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