@quake2ts/test-utils 0.0.1
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/README.md +454 -0
- package/dist/index.cjs +5432 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2150 -0
- package/dist/index.d.ts +2150 -0
- package/dist/index.js +5165 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
- package/src/client/helpers/hud.ts +114 -0
- package/src/client/helpers/prediction.ts +136 -0
- package/src/client/helpers/view.ts +201 -0
- package/src/client/mocks/console.ts +75 -0
- package/src/client/mocks/download.ts +48 -0
- package/src/client/mocks/input.ts +246 -0
- package/src/client/mocks/network.ts +148 -0
- package/src/client/mocks/state.ts +148 -0
- package/src/e2e/network.ts +47 -0
- package/src/e2e/playwright.ts +90 -0
- package/src/e2e/visual.ts +172 -0
- package/src/engine/helpers/pipeline-test-template.ts +113 -0
- package/src/engine/helpers/webgpu-rendering.ts +251 -0
- package/src/engine/mocks/assets.ts +129 -0
- package/src/engine/mocks/audio.ts +152 -0
- package/src/engine/mocks/buffers.ts +88 -0
- package/src/engine/mocks/lighting.ts +64 -0
- package/src/engine/mocks/particles.ts +76 -0
- package/src/engine/mocks/renderer.ts +218 -0
- package/src/engine/mocks/webgl.ts +267 -0
- package/src/engine/mocks/webgpu.ts +262 -0
- package/src/engine/rendering.ts +103 -0
- package/src/game/factories.ts +204 -0
- package/src/game/helpers/physics.ts +171 -0
- package/src/game/helpers/save.ts +232 -0
- package/src/game/helpers.ts +310 -0
- package/src/game/mocks/ai.ts +67 -0
- package/src/game/mocks/combat.ts +61 -0
- package/src/game/mocks/items.ts +166 -0
- package/src/game/mocks.ts +105 -0
- package/src/index.ts +93 -0
- package/src/server/helpers/bandwidth.ts +127 -0
- package/src/server/helpers/multiplayer.ts +158 -0
- package/src/server/helpers/snapshot.ts +241 -0
- package/src/server/mockNetDriver.ts +106 -0
- package/src/server/mockTransport.ts +50 -0
- package/src/server/mocks/commands.ts +93 -0
- package/src/server/mocks/connection.ts +139 -0
- package/src/server/mocks/master.ts +97 -0
- package/src/server/mocks/physics.ts +32 -0
- package/src/server/mocks/state.ts +162 -0
- package/src/server/mocks/transport.ts +161 -0
- package/src/setup/audio.ts +118 -0
- package/src/setup/browser.ts +249 -0
- package/src/setup/canvas.ts +142 -0
- package/src/setup/node.ts +21 -0
- package/src/setup/storage.ts +60 -0
- package/src/setup/timing.ts +142 -0
- package/src/setup/webgl.ts +8 -0
- package/src/setup/webgpu.ts +113 -0
- package/src/shared/bsp.ts +145 -0
- package/src/shared/collision.ts +64 -0
- package/src/shared/factories.ts +88 -0
- package/src/shared/math.ts +65 -0
- package/src/shared/mocks.ts +243 -0
- package/src/shared/pak-loader.ts +45 -0
- package/src/visual/snapshots.ts +292 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AudioContextLike,
|
|
3
|
+
AudioDestinationNodeLike,
|
|
4
|
+
AudioNodeLike,
|
|
5
|
+
AudioParamLike,
|
|
6
|
+
AudioBufferSourceNodeLike,
|
|
7
|
+
AudioBufferLike,
|
|
8
|
+
GainNodeLike,
|
|
9
|
+
DynamicsCompressorNodeLike,
|
|
10
|
+
PannerNodeLike,
|
|
11
|
+
BiquadFilterNodeLike,
|
|
12
|
+
} from '@quake2ts/engine';
|
|
13
|
+
|
|
14
|
+
export class FakeAudioParam implements AudioParamLike {
|
|
15
|
+
constructor(public value: number) {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class FakeAudioNode implements AudioNodeLike {
|
|
19
|
+
readonly connections: AudioNodeLike[] = [];
|
|
20
|
+
connect(destination: AudioNodeLike): void {
|
|
21
|
+
this.connections.push(destination);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class FakeGainNode extends FakeAudioNode implements GainNodeLike, DynamicsCompressorNodeLike {
|
|
26
|
+
gain = new FakeAudioParam(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class FakePannerNode extends FakeAudioNode implements PannerNodeLike {
|
|
30
|
+
positionX = new FakeAudioParam(0);
|
|
31
|
+
positionY = new FakeAudioParam(0);
|
|
32
|
+
positionZ = new FakeAudioParam(0);
|
|
33
|
+
refDistance?: number;
|
|
34
|
+
maxDistance?: number;
|
|
35
|
+
rolloffFactor?: number;
|
|
36
|
+
distanceModel?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class FakeBiquadFilterNode extends FakeAudioNode implements BiquadFilterNodeLike {
|
|
40
|
+
frequency = new FakeAudioParam(0);
|
|
41
|
+
Q = new FakeAudioParam(0);
|
|
42
|
+
type = 'lowpass';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class FakeBufferSource extends FakeAudioNode implements AudioBufferSourceNodeLike {
|
|
46
|
+
buffer: AudioBufferLike | null = null;
|
|
47
|
+
loop = false;
|
|
48
|
+
playbackRate = new FakeAudioParam(1);
|
|
49
|
+
onended: (() => void) | null = null;
|
|
50
|
+
startedAt?: number;
|
|
51
|
+
stoppedAt?: number;
|
|
52
|
+
start(when = 0, offset?: number, duration?: number): void {
|
|
53
|
+
this.startedAt = when;
|
|
54
|
+
this.offset = offset;
|
|
55
|
+
this.duration = duration;
|
|
56
|
+
}
|
|
57
|
+
stop(when = 0): void {
|
|
58
|
+
this.stoppedAt = when;
|
|
59
|
+
this.onended?.();
|
|
60
|
+
}
|
|
61
|
+
offset?: number;
|
|
62
|
+
duration?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class FakeDestination extends FakeAudioNode implements AudioDestinationNodeLike {}
|
|
66
|
+
|
|
67
|
+
export class FakeAudioContext implements AudioContextLike {
|
|
68
|
+
readonly destination = new FakeDestination();
|
|
69
|
+
state: AudioContextLike['state'] = 'suspended';
|
|
70
|
+
currentTime = 0;
|
|
71
|
+
resumeCalls = 0;
|
|
72
|
+
readonly gains: GainNodeLike[] = [];
|
|
73
|
+
readonly sources: FakeBufferSource[] = [];
|
|
74
|
+
readonly panners: PannerNodeLike[] = [];
|
|
75
|
+
readonly filters: BiquadFilterNodeLike[] = [];
|
|
76
|
+
lastDecoded?: ArrayBuffer;
|
|
77
|
+
createPanner?: () => PannerNodeLike;
|
|
78
|
+
|
|
79
|
+
constructor(enablePanner = true) {
|
|
80
|
+
if (enablePanner) {
|
|
81
|
+
this.createPanner = () => {
|
|
82
|
+
const node = new FakePannerNode();
|
|
83
|
+
this.panners.push(node);
|
|
84
|
+
return node;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async resume(): Promise<void> {
|
|
90
|
+
this.state = 'running';
|
|
91
|
+
this.resumeCalls += 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async suspend(): Promise<void> {
|
|
95
|
+
this.state = 'suspended';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
createGain(): GainNodeLike {
|
|
99
|
+
const node = new FakeGainNode();
|
|
100
|
+
this.gains.push(node);
|
|
101
|
+
return node;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
createDynamicsCompressor(): DynamicsCompressorNodeLike {
|
|
105
|
+
const node = new FakeGainNode();
|
|
106
|
+
this.gains.push(node);
|
|
107
|
+
return node;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
createBufferSource(): AudioBufferSourceNodeLike {
|
|
111
|
+
const node = new FakeBufferSource();
|
|
112
|
+
this.sources.push(node);
|
|
113
|
+
return node;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
createBiquadFilter(): BiquadFilterNodeLike {
|
|
117
|
+
const node = new FakeBiquadFilterNode();
|
|
118
|
+
this.filters.push(node);
|
|
119
|
+
return node;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async decodeAudioData(data: ArrayBuffer): Promise<AudioBufferLike> {
|
|
123
|
+
this.lastDecoded = data;
|
|
124
|
+
return { duration: data.byteLength / 1000 };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
advanceTime(seconds: number): void {
|
|
128
|
+
this.currentTime += seconds;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const createMockAudioBuffer = (duration = 1, channels = 2, sampleRate = 44100): AudioBufferLike => ({ duration });
|
|
133
|
+
|
|
134
|
+
export const createMockAudioContext = (overrides?: Partial<AudioContext>): FakeAudioContext => new FakeAudioContext();
|
|
135
|
+
|
|
136
|
+
export const createMockPannerNode = (overrides?: Partial<PannerNode>): FakePannerNode => {
|
|
137
|
+
const node = new FakePannerNode();
|
|
138
|
+
if (overrides) {
|
|
139
|
+
Object.assign(node, overrides);
|
|
140
|
+
}
|
|
141
|
+
return node;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const createMockBufferSource = (buffer?: AudioBuffer): FakeBufferSource => {
|
|
145
|
+
const node = new FakeBufferSource();
|
|
146
|
+
if (buffer) {
|
|
147
|
+
node.buffer = buffer;
|
|
148
|
+
}
|
|
149
|
+
return node;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export { FakeBufferSource as MockAudioBufferSourceNode };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import { VertexBuffer, IndexBuffer, BufferUsage } from '@quake2ts/engine';
|
|
3
|
+
import { ShaderProgram, ShaderSources } from '@quake2ts/engine';
|
|
4
|
+
import { createMockWebGL2Context } from './webgl.js';
|
|
5
|
+
|
|
6
|
+
// Export these for use in other mocks
|
|
7
|
+
export { VertexBuffer, IndexBuffer, ShaderProgram };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Creates a mock VertexBuffer with an optional data array.
|
|
11
|
+
*/
|
|
12
|
+
export function createMockVertexBuffer(data?: Float32Array, usage?: BufferUsage): VertexBuffer {
|
|
13
|
+
const gl = createMockWebGL2Context() as unknown as WebGL2RenderingContext;
|
|
14
|
+
const vb = new VertexBuffer(gl, usage ?? gl.STATIC_DRAW);
|
|
15
|
+
|
|
16
|
+
// Spy on methods to track calls
|
|
17
|
+
vi.spyOn(vb, 'bind');
|
|
18
|
+
vi.spyOn(vb, 'upload');
|
|
19
|
+
vi.spyOn(vb, 'update');
|
|
20
|
+
vi.spyOn(vb, 'dispose');
|
|
21
|
+
|
|
22
|
+
if (data) {
|
|
23
|
+
vb.upload(data as unknown as BufferSource, usage ?? gl.STATIC_DRAW);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return vb;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a mock IndexBuffer with an optional data array.
|
|
31
|
+
*/
|
|
32
|
+
export function createMockIndexBuffer(data?: Uint16Array, usage?: BufferUsage): IndexBuffer {
|
|
33
|
+
const gl = createMockWebGL2Context() as unknown as WebGL2RenderingContext;
|
|
34
|
+
const ib = new IndexBuffer(gl, usage ?? gl.STATIC_DRAW);
|
|
35
|
+
|
|
36
|
+
// Spy on methods
|
|
37
|
+
vi.spyOn(ib, 'bind');
|
|
38
|
+
vi.spyOn(ib, 'upload');
|
|
39
|
+
vi.spyOn(ib, 'update');
|
|
40
|
+
vi.spyOn(ib, 'dispose');
|
|
41
|
+
|
|
42
|
+
if (data) {
|
|
43
|
+
ib.upload(data as unknown as BufferSource, usage ?? gl.STATIC_DRAW);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return ib;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creates a mock ShaderProgram with optional overrides.
|
|
51
|
+
*/
|
|
52
|
+
export function createMockShaderProgram(overrides?: Partial<ShaderProgram>): ShaderProgram {
|
|
53
|
+
const gl = createMockWebGL2Context() as unknown as WebGL2RenderingContext;
|
|
54
|
+
|
|
55
|
+
// Create a minimal valid program using the static create method
|
|
56
|
+
const dummySources: ShaderSources = {
|
|
57
|
+
vertex: '#version 300 es\nvoid main() {}',
|
|
58
|
+
fragment: '#version 300 es\nvoid main() {}'
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const program = ShaderProgram.create(gl, dummySources);
|
|
62
|
+
|
|
63
|
+
// Spy on methods
|
|
64
|
+
vi.spyOn(program, 'use');
|
|
65
|
+
vi.spyOn(program, 'getUniformLocation');
|
|
66
|
+
vi.spyOn(program, 'getAttributeLocation');
|
|
67
|
+
vi.spyOn(program, 'dispose');
|
|
68
|
+
|
|
69
|
+
// Apply overrides if provided
|
|
70
|
+
if (overrides) {
|
|
71
|
+
Object.assign(program, overrides);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return program;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Helper to create a mock ShaderProgram with custom source code.
|
|
79
|
+
*/
|
|
80
|
+
export function createMockShader(vertSource?: string, fragSource?: string): ShaderProgram {
|
|
81
|
+
const gl = createMockWebGL2Context() as unknown as WebGL2RenderingContext;
|
|
82
|
+
const sources: ShaderSources = {
|
|
83
|
+
vertex: vertSource ?? '#version 300 es\nvoid main() {}',
|
|
84
|
+
fragment: fragSource ?? '#version 300 es\nvoid main() {}'
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return ShaderProgram.create(gl, sources);
|
|
88
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import { Vec3 } from '@quake2ts/shared';
|
|
3
|
+
import { DLight, DynamicLightManager } from '@quake2ts/engine';
|
|
4
|
+
|
|
5
|
+
// Export types
|
|
6
|
+
export { DLight, DynamicLightManager };
|
|
7
|
+
|
|
8
|
+
// Mock Lightmap type since it's typically just a raw buffer or texture in the engine
|
|
9
|
+
// But based on the task "Add createMockLightmap() factory", we'll create a simple structure.
|
|
10
|
+
export interface Lightmap {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
data: Uint8Array;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Creates a mock DLight with default values.
|
|
18
|
+
*/
|
|
19
|
+
export function createMockDLight(
|
|
20
|
+
position: Vec3 = { x: 0, y: 0, z: 0 },
|
|
21
|
+
color: Vec3 = { x: 1, y: 1, z: 1 },
|
|
22
|
+
intensity: number = 300
|
|
23
|
+
): DLight {
|
|
24
|
+
return {
|
|
25
|
+
origin: { ...position },
|
|
26
|
+
color: { ...color },
|
|
27
|
+
intensity,
|
|
28
|
+
die: Number.MAX_SAFE_INTEGER,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Creates a mock DynamicLightManager with spy methods.
|
|
34
|
+
*/
|
|
35
|
+
export function createMockDLightManager(overrides?: Partial<DynamicLightManager>): DynamicLightManager {
|
|
36
|
+
// We can't easily spy on methods of a real instance if we just return an object literal
|
|
37
|
+
// that mimics the interface, unless we use the real class or a full mock.
|
|
38
|
+
// Since DynamicLightManager is a class with logic, let's create a real instance and spy on it,
|
|
39
|
+
// or return a complete mock object if we want to avoid logic.
|
|
40
|
+
// The task says "Add createMockDLightManager factory... Methods: addLight, removeLight, clear, getLights".
|
|
41
|
+
|
|
42
|
+
// Let's create a mock object that satisfies the public interface (structural typing).
|
|
43
|
+
|
|
44
|
+
const mockManager = {
|
|
45
|
+
addLight: vi.fn(),
|
|
46
|
+
clear: vi.fn(),
|
|
47
|
+
update: vi.fn(),
|
|
48
|
+
getActiveLights: vi.fn().mockReturnValue([]),
|
|
49
|
+
...overrides
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return mockManager as unknown as DynamicLightManager;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a mock lightmap data structure.
|
|
57
|
+
*/
|
|
58
|
+
export function createMockLightmap(width: number = 128, height: number = 128): Lightmap {
|
|
59
|
+
return {
|
|
60
|
+
width,
|
|
61
|
+
height,
|
|
62
|
+
data: new Uint8Array(width * height * 3) // RGB
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import { Vec3 } from '@quake2ts/shared';
|
|
3
|
+
import { ParticleSystem } from '@quake2ts/engine';
|
|
4
|
+
|
|
5
|
+
// Mock types since Particle/ParticleEmitter are not exported
|
|
6
|
+
export interface MockParticle {
|
|
7
|
+
position: Vec3;
|
|
8
|
+
velocity: Vec3;
|
|
9
|
+
color: [number, number, number, number];
|
|
10
|
+
size: number;
|
|
11
|
+
lifetime: number;
|
|
12
|
+
gravity: number;
|
|
13
|
+
damping: number;
|
|
14
|
+
bounce: number;
|
|
15
|
+
blendMode: 'alpha' | 'additive';
|
|
16
|
+
fade: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface MockParticleEmitter {
|
|
20
|
+
update: (dt: number) => void;
|
|
21
|
+
emit: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Export types
|
|
25
|
+
export { ParticleSystem };
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a mock Particle with default values.
|
|
29
|
+
*/
|
|
30
|
+
export function createMockParticle(overrides?: Partial<MockParticle>): MockParticle {
|
|
31
|
+
return {
|
|
32
|
+
position: { x: 0, y: 0, z: 0 },
|
|
33
|
+
velocity: { x: 0, y: 0, z: 0 },
|
|
34
|
+
color: [1, 1, 1, 1],
|
|
35
|
+
size: 1,
|
|
36
|
+
lifetime: 1,
|
|
37
|
+
gravity: 0,
|
|
38
|
+
damping: 0,
|
|
39
|
+
bounce: 0,
|
|
40
|
+
blendMode: 'alpha',
|
|
41
|
+
fade: false,
|
|
42
|
+
...overrides,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a mock ParticleEmitter.
|
|
48
|
+
*/
|
|
49
|
+
export function createMockParticleEmitter(overrides?: Partial<MockParticleEmitter>): MockParticleEmitter {
|
|
50
|
+
return {
|
|
51
|
+
update: vi.fn(),
|
|
52
|
+
emit: vi.fn(),
|
|
53
|
+
...overrides,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates a mock ParticleSystem.
|
|
59
|
+
*/
|
|
60
|
+
export function createMockParticleSystem(overrides?: Partial<ParticleSystem>): ParticleSystem {
|
|
61
|
+
return {
|
|
62
|
+
maxParticles: 1000,
|
|
63
|
+
rng: {
|
|
64
|
+
frandom: vi.fn().mockReturnValue(0.5), // Deterministic default
|
|
65
|
+
random: vi.fn().mockReturnValue(0.5),
|
|
66
|
+
seed: vi.fn(),
|
|
67
|
+
},
|
|
68
|
+
update: vi.fn(),
|
|
69
|
+
spawn: vi.fn(),
|
|
70
|
+
killAll: vi.fn(),
|
|
71
|
+
aliveCount: vi.fn().mockReturnValue(0),
|
|
72
|
+
getState: vi.fn(),
|
|
73
|
+
buildMesh: vi.fn(),
|
|
74
|
+
...overrides,
|
|
75
|
+
} as unknown as ParticleSystem;
|
|
76
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
Renderer,
|
|
4
|
+
FrameRenderer,
|
|
5
|
+
BspSurfacePipeline,
|
|
6
|
+
Md2Pipeline,
|
|
7
|
+
Md3Pipeline,
|
|
8
|
+
SpriteRenderer,
|
|
9
|
+
SkyboxPipeline,
|
|
10
|
+
RenderableEntity,
|
|
11
|
+
FrameRenderOptions,
|
|
12
|
+
RenderOptions,
|
|
13
|
+
FrameRenderStats,
|
|
14
|
+
SurfaceRenderState,
|
|
15
|
+
Md2MeshBuffers,
|
|
16
|
+
Md3SurfaceMesh,
|
|
17
|
+
Md3SurfaceMaterial,
|
|
18
|
+
SkyboxBindOptions,
|
|
19
|
+
BspSurfaceBindOptions,
|
|
20
|
+
Md2BindOptions,
|
|
21
|
+
RenderModeConfig,
|
|
22
|
+
Texture2D,
|
|
23
|
+
IndexBuffer
|
|
24
|
+
} from '@quake2ts/engine';
|
|
25
|
+
import { createMockWebGL2Context } from './webgl.js';
|
|
26
|
+
|
|
27
|
+
export function createMockRenderer(overrides?: Partial<Renderer>): Renderer {
|
|
28
|
+
return {
|
|
29
|
+
width: 800,
|
|
30
|
+
height: 600,
|
|
31
|
+
collisionVis: {
|
|
32
|
+
render: vi.fn(),
|
|
33
|
+
clear: vi.fn(),
|
|
34
|
+
shaderSize: 0,
|
|
35
|
+
dispose: vi.fn(),
|
|
36
|
+
} as any,
|
|
37
|
+
debug: {
|
|
38
|
+
render: vi.fn(),
|
|
39
|
+
clear: vi.fn(),
|
|
40
|
+
drawLine: vi.fn(),
|
|
41
|
+
drawBoundingBox: vi.fn(),
|
|
42
|
+
drawAxes: vi.fn(),
|
|
43
|
+
getLabels: vi.fn().mockReturnValue([]),
|
|
44
|
+
shaderSize: 0,
|
|
45
|
+
dispose: vi.fn(),
|
|
46
|
+
} as any,
|
|
47
|
+
particleSystem: {
|
|
48
|
+
update: vi.fn(),
|
|
49
|
+
emit: vi.fn(),
|
|
50
|
+
clear: vi.fn(),
|
|
51
|
+
count: 0
|
|
52
|
+
} as any,
|
|
53
|
+
getPerformanceReport: vi.fn().mockReturnValue({}),
|
|
54
|
+
getMemoryUsage: vi.fn().mockReturnValue({}),
|
|
55
|
+
renderFrame: vi.fn(),
|
|
56
|
+
registerPic: vi.fn().mockResolvedValue({} as any),
|
|
57
|
+
registerTexture: vi.fn().mockReturnValue({} as any),
|
|
58
|
+
begin2D: vi.fn(),
|
|
59
|
+
end2D: vi.fn(),
|
|
60
|
+
drawPic: vi.fn(),
|
|
61
|
+
drawString: vi.fn(),
|
|
62
|
+
drawCenterString: vi.fn(),
|
|
63
|
+
drawfillRect: vi.fn(),
|
|
64
|
+
setEntityHighlight: vi.fn(),
|
|
65
|
+
clearEntityHighlight: vi.fn(),
|
|
66
|
+
highlightSurface: vi.fn(),
|
|
67
|
+
removeSurfaceHighlight: vi.fn(),
|
|
68
|
+
setDebugMode: vi.fn(),
|
|
69
|
+
setBrightness: vi.fn(),
|
|
70
|
+
setGamma: vi.fn(),
|
|
71
|
+
setFullbright: vi.fn(),
|
|
72
|
+
setAmbient: vi.fn(),
|
|
73
|
+
setLightStyle: vi.fn(),
|
|
74
|
+
setUnderwaterWarp: vi.fn(),
|
|
75
|
+
setBloom: vi.fn(),
|
|
76
|
+
setBloomIntensity: vi.fn(),
|
|
77
|
+
setLodBias: vi.fn(),
|
|
78
|
+
setAreaPortalState: vi.fn(),
|
|
79
|
+
renderInstanced: vi.fn(),
|
|
80
|
+
dispose: vi.fn(),
|
|
81
|
+
...overrides,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function createMockFrameRenderer(overrides?: Partial<FrameRenderer>): FrameRenderer {
|
|
86
|
+
return {
|
|
87
|
+
renderFrame: vi.fn().mockReturnValue({
|
|
88
|
+
batches: 0,
|
|
89
|
+
facesDrawn: 0,
|
|
90
|
+
drawCalls: 0,
|
|
91
|
+
skyDrawn: false,
|
|
92
|
+
viewModelDrawn: false,
|
|
93
|
+
fps: 60,
|
|
94
|
+
vertexCount: 0,
|
|
95
|
+
} as FrameRenderStats),
|
|
96
|
+
...overrides,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createMockBspPipeline(overrides?: Partial<BspSurfacePipeline>): BspSurfacePipeline {
|
|
101
|
+
const gl = createMockWebGL2Context();
|
|
102
|
+
return {
|
|
103
|
+
gl,
|
|
104
|
+
program: {
|
|
105
|
+
use: vi.fn(),
|
|
106
|
+
dispose: vi.fn(),
|
|
107
|
+
sourceSize: 0,
|
|
108
|
+
getUniformLocation: vi.fn().mockReturnValue(null),
|
|
109
|
+
} as any,
|
|
110
|
+
shaderSize: 0,
|
|
111
|
+
bind: vi.fn().mockReturnValue({} as SurfaceRenderState),
|
|
112
|
+
draw: vi.fn(),
|
|
113
|
+
dispose: vi.fn(),
|
|
114
|
+
...overrides,
|
|
115
|
+
} as unknown as BspSurfacePipeline;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function createMockMd2Pipeline(overrides?: Partial<Md2Pipeline>): Md2Pipeline {
|
|
119
|
+
const gl = createMockWebGL2Context();
|
|
120
|
+
return {
|
|
121
|
+
gl,
|
|
122
|
+
program: {
|
|
123
|
+
use: vi.fn(),
|
|
124
|
+
dispose: vi.fn(),
|
|
125
|
+
sourceSize: 0,
|
|
126
|
+
getUniformLocation: vi.fn().mockReturnValue(null),
|
|
127
|
+
} as any,
|
|
128
|
+
shaderSize: 0,
|
|
129
|
+
bind: vi.fn(),
|
|
130
|
+
draw: vi.fn(),
|
|
131
|
+
dispose: vi.fn(),
|
|
132
|
+
...overrides,
|
|
133
|
+
} as unknown as Md2Pipeline;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function createMockMd3Pipeline(overrides?: Partial<Md3Pipeline>): Md3Pipeline {
|
|
137
|
+
const gl = createMockWebGL2Context();
|
|
138
|
+
return {
|
|
139
|
+
gl,
|
|
140
|
+
program: {
|
|
141
|
+
use: vi.fn(),
|
|
142
|
+
dispose: vi.fn(),
|
|
143
|
+
sourceSize: 0,
|
|
144
|
+
getUniformLocation: vi.fn().mockReturnValue(null),
|
|
145
|
+
} as any,
|
|
146
|
+
shaderSize: 0,
|
|
147
|
+
bind: vi.fn(),
|
|
148
|
+
drawSurface: vi.fn(),
|
|
149
|
+
dispose: vi.fn(),
|
|
150
|
+
...overrides,
|
|
151
|
+
} as unknown as Md3Pipeline;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function createMockSpritePipeline(overrides?: Partial<SpriteRenderer>): SpriteRenderer {
|
|
155
|
+
const gl = createMockWebGL2Context();
|
|
156
|
+
return {
|
|
157
|
+
gl,
|
|
158
|
+
program: {
|
|
159
|
+
use: vi.fn(),
|
|
160
|
+
dispose: vi.fn(),
|
|
161
|
+
sourceSize: 0,
|
|
162
|
+
getUniformLocation: vi.fn().mockReturnValue(null),
|
|
163
|
+
} as any,
|
|
164
|
+
shaderSize: 0,
|
|
165
|
+
vao: {
|
|
166
|
+
bind: vi.fn(),
|
|
167
|
+
dispose: vi.fn(),
|
|
168
|
+
configureAttributes: vi.fn()
|
|
169
|
+
} as any,
|
|
170
|
+
vbo: {
|
|
171
|
+
bind: vi.fn(),
|
|
172
|
+
dispose: vi.fn(),
|
|
173
|
+
upload: vi.fn()
|
|
174
|
+
} as any,
|
|
175
|
+
whiteTexture: {
|
|
176
|
+
bind: vi.fn(),
|
|
177
|
+
upload: vi.fn()
|
|
178
|
+
} as unknown as Texture2D,
|
|
179
|
+
begin: vi.fn(),
|
|
180
|
+
draw: vi.fn(),
|
|
181
|
+
drawRect: vi.fn(),
|
|
182
|
+
...overrides,
|
|
183
|
+
} as unknown as SpriteRenderer;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function createMockSkyboxPipeline(overrides?: Partial<SkyboxPipeline>): SkyboxPipeline {
|
|
187
|
+
const gl = createMockWebGL2Context();
|
|
188
|
+
return {
|
|
189
|
+
gl,
|
|
190
|
+
program: {
|
|
191
|
+
use: vi.fn(),
|
|
192
|
+
dispose: vi.fn(),
|
|
193
|
+
sourceSize: 0,
|
|
194
|
+
getUniformLocation: vi.fn().mockReturnValue(null),
|
|
195
|
+
} as any,
|
|
196
|
+
vao: {
|
|
197
|
+
bind: vi.fn(),
|
|
198
|
+
dispose: vi.fn(),
|
|
199
|
+
configureAttributes: vi.fn()
|
|
200
|
+
} as any,
|
|
201
|
+
vbo: {
|
|
202
|
+
bind: vi.fn(),
|
|
203
|
+
dispose: vi.fn(),
|
|
204
|
+
upload: vi.fn()
|
|
205
|
+
} as any,
|
|
206
|
+
cubemap: {
|
|
207
|
+
bind: vi.fn(),
|
|
208
|
+
dispose: vi.fn(),
|
|
209
|
+
setParameters: vi.fn(),
|
|
210
|
+
upload: vi.fn()
|
|
211
|
+
} as any,
|
|
212
|
+
shaderSize: 0,
|
|
213
|
+
bind: vi.fn(),
|
|
214
|
+
draw: vi.fn(),
|
|
215
|
+
dispose: vi.fn(),
|
|
216
|
+
...overrides,
|
|
217
|
+
} as unknown as SkyboxPipeline;
|
|
218
|
+
}
|