quake2ts 0.0.532 → 0.0.534
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/client/dist/browser/index.global.js +9 -9
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +25 -0
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +25 -0
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/client/dist/types/index.d.ts.map +1 -1
- package/packages/game/dist/browser/index.global.js +4 -4
- package/packages/game/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/cjs/index.cjs +2 -0
- package/packages/game/dist/cjs/index.cjs.map +1 -1
- package/packages/game/dist/esm/index.js +1 -0
- package/packages/game/dist/esm/index.js.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/types/index.d.ts +1 -0
- package/packages/game/dist/types/index.d.ts.map +1 -1
- package/packages/test-utils/dist/index.cjs +51 -11
- package/packages/test-utils/dist/index.cjs.map +1 -1
- package/packages/test-utils/dist/index.d.cts +4 -9
- package/packages/test-utils/dist/index.d.ts +4 -9
- package/packages/test-utils/dist/index.js +52 -12
- package/packages/test-utils/dist/index.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mocks.ts","../src/factories.ts","../src/helpers.ts"],"sourcesContent":["import { vi } from 'vitest';\n\nexport const createBinaryWriterMock = () => ({\n writeByte: vi.fn(),\n writeShort: vi.fn(),\n writeLong: vi.fn(),\n writeString: vi.fn(),\n writeBytes: vi.fn(),\n getBuffer: vi.fn(() => new Uint8Array(0)),\n reset: vi.fn(),\n // Legacy methods (if any)\n writeInt8: vi.fn(),\n writeUint8: vi.fn(),\n writeInt16: vi.fn(),\n writeUint16: vi.fn(),\n writeInt32: vi.fn(),\n writeUint32: vi.fn(),\n writeFloat: vi.fn(),\n getData: vi.fn(() => new Uint8Array(0)),\n});\n\nexport const createNetChanMock = () => ({\n qport: 1234,\n\n // Sequencing\n incomingSequence: 0,\n outgoingSequence: 0,\n incomingAcknowledged: 0,\n\n // Reliable messaging\n incomingReliableAcknowledged: false,\n incomingReliableSequence: 0,\n outgoingReliableSequence: 0,\n reliableMessage: createBinaryWriterMock(),\n reliableLength: 0,\n\n // Fragmentation\n fragmentSendOffset: 0,\n fragmentBuffer: null,\n fragmentLength: 0,\n fragmentReceived: 0,\n\n // Timing\n lastReceived: 0,\n lastSent: 0,\n\n remoteAddress: { type: 'IP', port: 1234 },\n\n // Methods\n setup: vi.fn(),\n reset: vi.fn(),\n transmit: vi.fn(),\n process: vi.fn(),\n canSendReliable: vi.fn(() => true),\n writeReliableByte: vi.fn(),\n writeReliableShort: vi.fn(),\n writeReliableLong: vi.fn(),\n writeReliableString: vi.fn(),\n getReliableData: vi.fn(() => new Uint8Array(0)),\n needsKeepalive: vi.fn(() => false),\n isTimedOut: vi.fn(() => false),\n});\n\nexport const createBinaryStreamMock = () => ({\n getPosition: vi.fn(() => 0),\n getReadPosition: vi.fn(() => 0),\n getLength: vi.fn(() => 0),\n getRemaining: vi.fn(() => 0),\n seek: vi.fn(),\n setReadPosition: vi.fn(),\n hasMore: vi.fn(() => true),\n hasBytes: vi.fn(() => true),\n\n readChar: vi.fn(() => 0),\n readByte: vi.fn(() => 0),\n readShort: vi.fn(() => 0),\n readUShort: vi.fn(() => 0),\n readLong: vi.fn(() => 0),\n readULong: vi.fn(() => 0),\n readFloat: vi.fn(() => 0),\n\n readString: vi.fn(() => ''),\n readStringLine: vi.fn(() => ''),\n\n readCoord: vi.fn(() => 0),\n readAngle: vi.fn(() => 0),\n readAngle16: vi.fn(() => 0),\n\n readData: vi.fn(() => new Uint8Array(0)),\n\n readPos: vi.fn(),\n readDir: vi.fn(),\n});\n","import type { PlayerState, EntityState } from '@quake2ts/shared';\n\n// Define GameStateSnapshot locally if it's not exported or if we need a specific mock version\n// Assuming it matches the structure expected by the game/client\nexport interface GameStateSnapshot {\n entities: EntityState[];\n playerState: PlayerState;\n timestamp: number;\n}\n\nexport const createPlayerStateFactory = (overrides?: Partial<PlayerState>): PlayerState => ({\n pm_type: 0,\n pm_time: 0,\n pm_flags: 0,\n origin: { x: 0, y: 0, z: 0 },\n velocity: { x: 0, y: 0, z: 0 },\n viewAngles: { x: 0, y: 0, z: 0 },\n onGround: false,\n waterLevel: 0,\n mins: { x: 0, y: 0, z: 0 },\n maxs: { x: 0, y: 0, z: 0 },\n damageAlpha: 0,\n damageIndicators: [],\n blend: [0, 0, 0, 0],\n stats: [],\n kick_angles: { x: 0, y: 0, z: 0 },\n kick_origin: { x: 0, y: 0, z: 0 },\n gunoffset: { x: 0, y: 0, z: 0 },\n gunangles: { x: 0, y: 0, z: 0 },\n gunindex: 0,\n gun_frame: 0,\n rdflags: 0,\n fov: 90,\n renderfx: 0,\n ...overrides,\n});\n\nexport const createEntityStateFactory = (overrides?: Partial<EntityState>): EntityState => ({\n number: 0,\n origin: { x: 0, y: 0, z: 0 },\n angles: { x: 0, y: 0, z: 0 },\n oldOrigin: { x: 0, y: 0, z: 0 },\n modelIndex: 0,\n modelIndex2: 0,\n modelIndex3: 0,\n modelIndex4: 0,\n frame: 0,\n skinNum: 0,\n effects: 0,\n renderfx: 0,\n solid: 0,\n sound: 0,\n event: 0,\n ...overrides,\n});\n\nexport const createGameStateSnapshotFactory = (overrides?: Partial<GameStateSnapshot>): GameStateSnapshot => ({\n entities: [],\n playerState: createPlayerStateFactory(),\n timestamp: Date.now(),\n ...overrides,\n});\n","import { vi } from 'vitest';\nimport { Entity, SpawnRegistry, type SpawnContext, type EntitySystem } from '@quake2ts/game';\nimport { createRandomGenerator, type PmoveTraceFn, type PmoveTraceResult, type Vec3, CONTENTS_LADDER } from '@quake2ts/shared';\n\n// -- Shared Helpers --\n\nexport const intersects = (end: Vec3, maxs: Vec3, mins: Vec3, boxMins: Vec3, boxMaxs: Vec3): boolean => {\n return (\n end.x + maxs.x > boxMins.x &&\n end.x + mins.x < boxMaxs.x &&\n end.y + maxs.y > boxMins.y &&\n end.y + mins.y < boxMaxs.y &&\n end.z + maxs.z > boxMins.z &&\n end.z + mins.z < boxMaxs.z\n );\n};\n\nexport const stairTrace: PmoveTraceFn = (start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3): PmoveTraceResult => {\n // Default bbox if not provided\n const useMins = mins ?? { x: -16, y: -16, z: -24 };\n const useMaxs = maxs ?? { x: 16, y: 16, z: 32 };\n\n // Step: x from 0 forward, z from 0 to 8\n const STEP_HEIGHT = 8;\n const STEP_X_START = 0;\n\n const isHorizontal = Math.abs(end.z - start.z) < 1;\n const isMovingDown = end.z < start.z;\n\n // Check if trying to go below the floor\n const endMinZ = end.z + useMins.z;\n const startMinZ = start.z + useMins.z;\n const endMaxX = end.x + useMaxs.x;\n\n // If moving horizontally, check if we'd hit the vertical face of the step\n // The step only blocks if the player's origin is below the step height\n if (isHorizontal && end.z < STEP_HEIGHT && endMaxX > STEP_X_START) {\n // Check if we're crossing into the step area\n const startMaxX = start.x + useMaxs.x;\n if (startMaxX <= STEP_X_START) {\n // We're moving from before the step to past it, block\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: -1, y: 0, z: 0 },\n contents: 1,\n };\n }\n }\n\n // If moving down and over the step area, land on the step surface\n if (isMovingDown && end.x >= STEP_X_START) {\n // The step surface is at z=STEP_HEIGHT in world space\n // The player's bbox bottom reaches this plane when origin.z + mins.z = STEP_HEIGHT\n // So the player's origin should be at z = STEP_HEIGHT - mins.z\n const landZ = STEP_HEIGHT - useMins.z;\n\n // Check if we'd pass through the step surface\n // We cross the plane if start is above it and end would be below it\n if (startMinZ > STEP_HEIGHT && endMinZ < STEP_HEIGHT) {\n // Calculate the fraction along the ray where we intersect the plane\n // The bbox bottom is at: start.z + useMins.z + t * (end.z - start.z + 0) = STEP_HEIGHT\n // Solving for t: t = (STEP_HEIGHT - (start.z + useMins.z)) / ((end.z + useMins.z) - (start.z + useMins.z))\n const fraction = (STEP_HEIGHT - startMinZ) / (endMinZ - startMinZ);\n\n // Clamp to valid range [0, 1]\n const clampedFraction = Math.max(0, Math.min(1, fraction));\n\n // Calculate the endpos along the ray at this fraction\n const finalX = start.x + clampedFraction * (end.x - start.x);\n const finalY = start.y + clampedFraction * (end.y - start.y);\n const finalZ = start.z + clampedFraction * (end.z - start.z);\n\n return {\n allsolid: false,\n startsolid: false,\n fraction: clampedFraction,\n endpos: { x: finalX, y: finalY, z: finalZ },\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n }\n\n // If moving down and would go below floor level, block at floor\n if (isMovingDown && endMinZ < 0) {\n // Floor is at z=0, so player origin should be at z = -mins.z when landing\n const landZ = -useMins.z;\n\n // Only apply if we're crossing the floor plane\n if (startMinZ >= 0) {\n // Calculate fraction where bbox bottom hits z=0\n const fraction = (0 - startMinZ) / (endMinZ - startMinZ);\n const clampedFraction = Math.max(0, Math.min(1, fraction));\n\n const finalX = start.x + clampedFraction * (end.x - start.x);\n const finalY = start.y + clampedFraction * (end.y - start.y);\n const finalZ = start.z + clampedFraction * (end.z - start.z);\n\n return {\n allsolid: false,\n startsolid: false,\n fraction: clampedFraction,\n endpos: { x: finalX, y: finalY, z: finalZ },\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // Already below floor, block immediately\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // Free movement\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: 0,\n };\n};\n\nexport const ladderTrace: PmoveTraceFn = (start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3): PmoveTraceResult => {\n // Default bbox if not provided\n const useMins = mins ?? { x: -16, y: -16, z: -24 };\n const useMaxs = maxs ?? { x: 16, y: 16, z: 32 };\n\n // Define the ladder volume (x=0 to x=8, y=-16 to y=16, z=0 to z=100)\n const LADDER_X_MIN = 0;\n const LADDER_X_MAX = 8;\n const LADDER_Y_MIN = -16;\n const LADDER_Y_MAX = 16;\n const LADDER_Z_MIN = 0;\n const LADDER_Z_MAX = 100;\n\n // Check if end position is within the ladder volume\n const endInLadder =\n end.x + useMins.x < LADDER_X_MAX &&\n end.x + useMaxs.x > LADDER_X_MIN &&\n end.y + useMins.y < LADDER_Y_MAX &&\n end.y + useMaxs.y > LADDER_Y_MIN &&\n end.z + useMins.z < LADDER_Z_MAX &&\n end.z + useMaxs.z > LADDER_Z_MIN;\n\n // If moving into the ladder from outside (moving forward into it)\n const movingIntoLadder = start.x < LADDER_X_MIN && end.x >= LADDER_X_MIN;\n\n // If moving horizontally into the ladder front face, block with ladder surface\n if (movingIntoLadder && Math.abs(end.z - start.z) < 0.1) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: -1, y: 0, z: 0 },\n contents: CONTENTS_LADDER,\n };\n }\n\n // If we're in the ladder volume, return success but with CONTENTS_LADDER\n // This allows the player to detect they're on a ladder without blocking movement\n if (endInLadder) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: CONTENTS_LADDER,\n };\n }\n\n // Floor at z=0\n if (end.z + useMins.z <= 0) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // No collision - free movement\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: 0,\n };\n};\n\n// -- Game Helpers --\n\nexport function createTestContext(options?: { seed?: number, initialEntities?: Entity[] }): { entities: EntitySystem, game: any } & SpawnContext {\n const engine = {\n sound: vi.fn(),\n soundIndex: vi.fn((sound: string) => 0),\n modelIndex: vi.fn((model: string) => 0),\n centerprintf: vi.fn(),\n };\n\n const seed = options?.seed ?? 12345;\n const traceFn = vi.fn((start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3) => ({\n fraction: 1.0,\n ent: null,\n allsolid: false,\n startsolid: false,\n endpos: end, // Use end argument\n plane: { normal: { x: 0, y: 0, z: 1 }, dist: 0 },\n surfaceFlags: 0,\n contents: 0\n }));\n\n const spawnRegistry = new SpawnRegistry();\n\n const game = {\n random: createRandomGenerator({ seed }),\n registerEntitySpawn: vi.fn((classname: string, spawnFunc: (entity: Entity) => void) => {\n spawnRegistry.register(classname, (entity) => spawnFunc(entity));\n }),\n unregisterEntitySpawn: vi.fn((classname: string) => {\n spawnRegistry.unregister(classname);\n }),\n getCustomEntities: vi.fn(() => Array.from(spawnRegistry.keys()))\n };\n\n const entityList: Entity[] = options?.initialEntities ? [...options.initialEntities] : [];\n\n const entities = {\n spawn: vi.fn(() => {\n const ent = new Entity(entityList.length + 1);\n entityList.push(ent);\n return ent;\n }),\n free: vi.fn((ent: Entity) => {\n const idx = entityList.indexOf(ent);\n if (idx !== -1) {\n entityList.splice(idx, 1);\n }\n }),\n finalizeSpawn: vi.fn(),\n freeImmediate: vi.fn((ent: Entity) => {\n const idx = entityList.indexOf(ent);\n if (idx !== -1) {\n entityList.splice(idx, 1);\n }\n }),\n setSpawnRegistry: vi.fn(),\n timeSeconds: 10,\n deltaSeconds: 0.1, // Added deltaSeconds\n modelIndex: vi.fn(() => 0),\n scheduleThink: vi.fn((entity: Entity, time: number) => {\n entity.nextthink = time;\n }),\n linkentity: vi.fn(),\n trace: traceFn, // Directly provide the mock function property\n pointcontents: vi.fn(() => 0),\n multicast: vi.fn(),\n unicast: vi.fn(),\n engine, // Attach mocked engine\n game,\n sound: vi.fn((ent: Entity, chan: number, sound: string, vol: number, attn: number, timeofs: number) => {\n engine.sound(ent, chan, sound, vol, attn, timeofs);\n }),\n soundIndex: vi.fn((sound: string) => engine.soundIndex(sound)),\n useTargets: vi.fn((entity: Entity, activator: Entity | null) => {\n }),\n findByTargetName: vi.fn(() => []),\n pickTarget: vi.fn(() => null),\n killBox: vi.fn(),\n rng: createRandomGenerator({ seed }), // Use real RNG for determinism or easy mocking if we replace it\n imports: {\n configstring: vi.fn(),\n trace: traceFn, // Also in imports for good measure\n pointcontents: vi.fn(() => 0),\n },\n level: {\n intermission_angle: { x: 0, y: 0, z: 0 },\n intermission_origin: { x: 0, y: 0, z: 0 },\n },\n targetNameIndex: new Map(),\n forEachEntity: vi.fn((callback: (ent: Entity) => void) => {\n // Iterate over managed list\n entityList.forEach(callback);\n }),\n find: vi.fn((predicate: (ent: Entity) => boolean) => {\n // Find in managed list\n return entityList.find(predicate);\n }),\n beginFrame: vi.fn((timeSeconds: number) => {\n (entities as any).timeSeconds = timeSeconds;\n }),\n targetAwareness: {\n timeSeconds: 10,\n frameNumber: 1,\n sightEntity: null,\n soundEntity: null,\n }\n } as unknown as EntitySystem;\n\n return {\n keyValues: {},\n entities,\n game: game,\n health_multiplier: 1,\n warn: vi.fn(),\n free: vi.fn(),\n // Legacy support for tests that might check precache\n precacheModel: vi.fn(),\n precacheSound: vi.fn(),\n precacheImage: vi.fn(),\n } as unknown as SpawnContext & { entities: EntitySystem, game: any };\n}\n\nexport function createSpawnContext(): SpawnContext {\n return createTestContext();\n}\n\nexport function createEntity(): Entity {\n return new Entity(1);\n}\n"],"mappings":"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","names":["vi"]}
|
|
1
|
+
{"version":3,"sources":["../src/mocks.ts","../src/factories.ts","../src/helpers.ts"],"sourcesContent":["import { vi } from 'vitest';\n\nexport const createBinaryWriterMock = () => ({\n writeByte: vi.fn(),\n writeShort: vi.fn(),\n writeLong: vi.fn(),\n writeString: vi.fn(),\n writeBytes: vi.fn(),\n getBuffer: vi.fn(() => new Uint8Array(0)),\n reset: vi.fn(),\n // Legacy methods (if any)\n writeInt8: vi.fn(),\n writeUint8: vi.fn(),\n writeInt16: vi.fn(),\n writeUint16: vi.fn(),\n writeInt32: vi.fn(),\n writeUint32: vi.fn(),\n writeFloat: vi.fn(),\n getData: vi.fn(() => new Uint8Array(0)),\n});\n\nexport const createNetChanMock = () => ({\n qport: 1234,\n\n // Sequencing\n incomingSequence: 0,\n outgoingSequence: 0,\n incomingAcknowledged: 0,\n\n // Reliable messaging\n incomingReliableAcknowledged: false,\n incomingReliableSequence: 0,\n outgoingReliableSequence: 0,\n reliableMessage: createBinaryWriterMock(),\n reliableLength: 0,\n\n // Fragmentation\n fragmentSendOffset: 0,\n fragmentBuffer: null,\n fragmentLength: 0,\n fragmentReceived: 0,\n\n // Timing\n lastReceived: 0,\n lastSent: 0,\n\n remoteAddress: { type: 'IP', port: 1234 },\n\n // Methods\n setup: vi.fn(),\n reset: vi.fn(),\n transmit: vi.fn(),\n process: vi.fn(),\n canSendReliable: vi.fn(() => true),\n writeReliableByte: vi.fn(),\n writeReliableShort: vi.fn(),\n writeReliableLong: vi.fn(),\n writeReliableString: vi.fn(),\n getReliableData: vi.fn(() => new Uint8Array(0)),\n needsKeepalive: vi.fn(() => false),\n isTimedOut: vi.fn(() => false),\n});\n\nexport const createBinaryStreamMock = () => ({\n getPosition: vi.fn(() => 0),\n getReadPosition: vi.fn(() => 0),\n getLength: vi.fn(() => 0),\n getRemaining: vi.fn(() => 0),\n seek: vi.fn(),\n setReadPosition: vi.fn(),\n hasMore: vi.fn(() => true),\n hasBytes: vi.fn(() => true),\n\n readChar: vi.fn(() => 0),\n readByte: vi.fn(() => 0),\n readShort: vi.fn(() => 0),\n readUShort: vi.fn(() => 0),\n readLong: vi.fn(() => 0),\n readULong: vi.fn(() => 0),\n readFloat: vi.fn(() => 0),\n\n readString: vi.fn(() => ''),\n readStringLine: vi.fn(() => ''),\n\n readCoord: vi.fn(() => 0),\n readAngle: vi.fn(() => 0),\n readAngle16: vi.fn(() => 0),\n\n readData: vi.fn(() => new Uint8Array(0)),\n\n readPos: vi.fn(),\n readDir: vi.fn(),\n});\n","import type { PlayerState, EntityState } from '@quake2ts/shared';\nimport type { GameStateSnapshot } from '@quake2ts/game';\n\nexport const createPlayerStateFactory = (overrides?: Partial<PlayerState>): PlayerState => ({\n pm_type: 0,\n pm_time: 0,\n pm_flags: 0,\n origin: { x: 0, y: 0, z: 0 },\n velocity: { x: 0, y: 0, z: 0 },\n viewAngles: { x: 0, y: 0, z: 0 },\n onGround: false,\n waterLevel: 0,\n mins: { x: 0, y: 0, z: 0 },\n maxs: { x: 0, y: 0, z: 0 },\n damageAlpha: 0,\n damageIndicators: [],\n blend: [0, 0, 0, 0],\n stats: [],\n kick_angles: { x: 0, y: 0, z: 0 },\n kick_origin: { x: 0, y: 0, z: 0 },\n gunoffset: { x: 0, y: 0, z: 0 },\n gunangles: { x: 0, y: 0, z: 0 },\n gunindex: 0,\n gun_frame: 0,\n rdflags: 0,\n fov: 90,\n renderfx: 0,\n ...overrides,\n});\n\nexport const createEntityStateFactory = (overrides?: Partial<EntityState>): EntityState => ({\n number: 0,\n origin: { x: 0, y: 0, z: 0 },\n angles: { x: 0, y: 0, z: 0 },\n oldOrigin: { x: 0, y: 0, z: 0 },\n modelIndex: 0,\n modelIndex2: 0,\n modelIndex3: 0,\n modelIndex4: 0,\n frame: 0,\n skinNum: 0,\n effects: 0,\n renderfx: 0,\n solid: 0,\n sound: 0,\n event: 0,\n ...overrides,\n});\n\n// Note: This factory might need updates if GameStateSnapshot structure changes significantly in @quake2ts/game\nexport const createGameStateSnapshotFactory = (overrides?: Partial<GameStateSnapshot>): any => ({\n // Simplified default mock matching the interface as best as possible for basic tests\n gravity: { x: 0, y: 0, z: -800 },\n origin: { x: 0, y: 0, z: 0 },\n velocity: { x: 0, y: 0, z: 0 },\n viewangles: { x: 0, y: 0, z: 0 },\n level: { timeSeconds: 0, frameNumber: 0, previousTimeSeconds: 0 },\n entities: {\n activeCount: 0,\n worldClassname: 'worldspawn',\n },\n packetEntities: [],\n pmFlags: 0,\n pmType: 0,\n waterlevel: 0,\n deltaAngles: { x: 0, y: 0, z: 0 },\n health: 100,\n armor: 0,\n ammo: 0,\n blend: [0, 0, 0, 0],\n damageAlpha: 0,\n damageIndicators: [],\n stats: [],\n kick_angles: { x: 0, y: 0, z: 0 },\n kick_origin: { x: 0, y: 0, z: 0 },\n gunoffset: { x: 0, y: 0, z: 0 },\n gunangles: { x: 0, y: 0, z: 0 },\n gunindex: 0,\n pm_time: 0,\n gun_frame: 0,\n rdflags: 0,\n fov: 90,\n renderfx: 0,\n ...overrides,\n});\n","import { vi } from 'vitest';\nimport { Entity, SpawnRegistry, ScriptHookRegistry, type SpawnContext, type EntitySystem } from '@quake2ts/game';\nimport { createRandomGenerator, type PmoveTraceFn, type PmoveTraceResult, type Vec3, CONTENTS_LADDER } from '@quake2ts/shared';\n\n// -- Shared Helpers --\n\nexport const intersects = (end: Vec3, maxs: Vec3, mins: Vec3, boxMins: Vec3, boxMaxs: Vec3): boolean => {\n return (\n end.x + maxs.x > boxMins.x &&\n end.x + mins.x < boxMaxs.x &&\n end.y + maxs.y > boxMins.y &&\n end.y + mins.y < boxMaxs.y &&\n end.z + maxs.z > boxMins.z &&\n end.z + mins.z < boxMaxs.z\n );\n};\n\nexport const stairTrace: PmoveTraceFn = (start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3): PmoveTraceResult => {\n // Default bbox if not provided\n const useMins = mins ?? { x: -16, y: -16, z: -24 };\n const useMaxs = maxs ?? { x: 16, y: 16, z: 32 };\n\n // Step: x from 0 forward, z from 0 to 8\n const STEP_HEIGHT = 8;\n const STEP_X_START = 0;\n\n const isHorizontal = Math.abs(end.z - start.z) < 1;\n const isMovingDown = end.z < start.z;\n\n // Check if trying to go below the floor\n const endMinZ = end.z + useMins.z;\n const startMinZ = start.z + useMins.z;\n const endMaxX = end.x + useMaxs.x;\n\n // If moving horizontally, check if we'd hit the vertical face of the step\n // The step only blocks if the player's origin is below the step height\n if (isHorizontal && end.z < STEP_HEIGHT && endMaxX > STEP_X_START) {\n // Check if we're crossing into the step area\n const startMaxX = start.x + useMaxs.x;\n if (startMaxX <= STEP_X_START) {\n // We're moving from before the step to past it, block\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: -1, y: 0, z: 0 },\n contents: 1,\n };\n }\n }\n\n // If moving down and over the step area, land on the step surface\n if (isMovingDown && end.x >= STEP_X_START) {\n // The step surface is at z=STEP_HEIGHT in world space\n // The player's bbox bottom reaches this plane when origin.z + mins.z = STEP_HEIGHT\n // So the player's origin should be at z = STEP_HEIGHT - mins.z\n const landZ = STEP_HEIGHT - useMins.z;\n\n // Check if we'd pass through the step surface\n // We cross the plane if start is above it and end would be below it\n if (startMinZ > STEP_HEIGHT && endMinZ < STEP_HEIGHT) {\n // Calculate the fraction along the ray where we intersect the plane\n // The bbox bottom is at: start.z + useMins.z + t * (end.z - start.z + 0) = STEP_HEIGHT\n // Solving for t: t = (STEP_HEIGHT - (start.z + useMins.z)) / ((end.z + useMins.z) - (start.z + useMins.z))\n const fraction = (STEP_HEIGHT - startMinZ) / (endMinZ - startMinZ);\n\n // Clamp to valid range [0, 1]\n const clampedFraction = Math.max(0, Math.min(1, fraction));\n\n // Calculate the endpos along the ray at this fraction\n const finalX = start.x + clampedFraction * (end.x - start.x);\n const finalY = start.y + clampedFraction * (end.y - start.y);\n const finalZ = start.z + clampedFraction * (end.z - start.z);\n\n return {\n allsolid: false,\n startsolid: false,\n fraction: clampedFraction,\n endpos: { x: finalX, y: finalY, z: finalZ },\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n }\n\n // If moving down and would go below floor level, block at floor\n if (isMovingDown && endMinZ < 0) {\n // Floor is at z=0, so player origin should be at z = -mins.z when landing\n const landZ = -useMins.z;\n\n // Only apply if we're crossing the floor plane\n if (startMinZ >= 0) {\n // Calculate fraction where bbox bottom hits z=0\n const fraction = (0 - startMinZ) / (endMinZ - startMinZ);\n const clampedFraction = Math.max(0, Math.min(1, fraction));\n\n const finalX = start.x + clampedFraction * (end.x - start.x);\n const finalY = start.y + clampedFraction * (end.y - start.y);\n const finalZ = start.z + clampedFraction * (end.z - start.z);\n\n return {\n allsolid: false,\n startsolid: false,\n fraction: clampedFraction,\n endpos: { x: finalX, y: finalY, z: finalZ },\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // Already below floor, block immediately\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // Free movement\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: 0,\n };\n};\n\nexport const ladderTrace: PmoveTraceFn = (start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3): PmoveTraceResult => {\n // Default bbox if not provided\n const useMins = mins ?? { x: -16, y: -16, z: -24 };\n const useMaxs = maxs ?? { x: 16, y: 16, z: 32 };\n\n // Define the ladder volume (x=0 to x=8, y=-16 to y=16, z=0 to z=100)\n const LADDER_X_MIN = 0;\n const LADDER_X_MAX = 8;\n const LADDER_Y_MIN = -16;\n const LADDER_Y_MAX = 16;\n const LADDER_Z_MIN = 0;\n const LADDER_Z_MAX = 100;\n\n // Check if end position is within the ladder volume\n const endInLadder =\n end.x + useMins.x < LADDER_X_MAX &&\n end.x + useMaxs.x > LADDER_X_MIN &&\n end.y + useMins.y < LADDER_Y_MAX &&\n end.y + useMaxs.y > LADDER_Y_MIN &&\n end.z + useMins.z < LADDER_Z_MAX &&\n end.z + useMaxs.z > LADDER_Z_MIN;\n\n // If moving into the ladder from outside (moving forward into it)\n const movingIntoLadder = start.x < LADDER_X_MIN && end.x >= LADDER_X_MIN;\n\n // If moving horizontally into the ladder front face, block with ladder surface\n if (movingIntoLadder && Math.abs(end.z - start.z) < 0.1) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: -1, y: 0, z: 0 },\n contents: CONTENTS_LADDER,\n };\n }\n\n // If we're in the ladder volume, return success but with CONTENTS_LADDER\n // This allows the player to detect they're on a ladder without blocking movement\n if (endInLadder) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: CONTENTS_LADDER,\n };\n }\n\n // Floor at z=0\n if (end.z + useMins.z <= 0) {\n return {\n allsolid: false,\n startsolid: false,\n fraction: 0,\n endpos: start,\n planeNormal: { x: 0, y: 0, z: 1 },\n contents: 1,\n };\n }\n\n // No collision - free movement\n return {\n allsolid: false,\n startsolid: false,\n fraction: 1.0,\n endpos: end,\n contents: 0,\n };\n};\n\n// -- Game Helpers --\n\nexport function createTestContext(options?: { seed?: number, initialEntities?: Entity[] }): { entities: EntitySystem, game: any } & SpawnContext {\n const engine = {\n sound: vi.fn(),\n soundIndex: vi.fn((sound: string) => 0),\n modelIndex: vi.fn((model: string) => 0),\n centerprintf: vi.fn(),\n };\n\n const seed = options?.seed ?? 12345;\n const traceFn = vi.fn((start: Vec3, end: Vec3, mins?: Vec3, maxs?: Vec3) => ({\n fraction: 1.0,\n ent: null,\n allsolid: false,\n startsolid: false,\n endpos: end,\n plane: { normal: { x: 0, y: 0, z: 1 }, dist: 0 },\n surfaceFlags: 0,\n contents: 0\n }));\n\n const spawnRegistry = new SpawnRegistry();\n const hooks = new ScriptHookRegistry();\n\n const game = {\n random: createRandomGenerator({ seed }),\n registerEntitySpawn: vi.fn((classname: string, spawnFunc: (entity: Entity) => void) => {\n spawnRegistry.register(classname, (entity) => spawnFunc(entity));\n }),\n unregisterEntitySpawn: vi.fn((classname: string) => {\n spawnRegistry.unregister(classname);\n }),\n getCustomEntities: vi.fn(() => Array.from(spawnRegistry.keys())),\n hooks,\n registerHooks: vi.fn((newHooks) => hooks.register(newHooks)),\n spawnWorld: vi.fn(() => {\n hooks.onMapLoad('q2dm1');\n }),\n clientBegin: vi.fn(() => {\n hooks.onPlayerSpawn({} as any);\n }),\n damage: vi.fn((amount: number) => {\n hooks.onDamage({} as any, null, null, amount, 0, 0);\n })\n };\n\n const entityList: Entity[] = options?.initialEntities ? [...options.initialEntities] : [];\n\n const entities = {\n spawn: vi.fn(() => {\n const ent = new Entity(entityList.length + 1);\n entityList.push(ent);\n hooks.onEntitySpawn(ent);\n return ent;\n }),\n free: vi.fn((ent: Entity) => {\n const idx = entityList.indexOf(ent);\n if (idx !== -1) {\n entityList.splice(idx, 1);\n }\n hooks.onEntityRemove(ent);\n }),\n finalizeSpawn: vi.fn(),\n freeImmediate: vi.fn((ent: Entity) => {\n const idx = entityList.indexOf(ent);\n if (idx !== -1) {\n entityList.splice(idx, 1);\n }\n }),\n setSpawnRegistry: vi.fn(),\n timeSeconds: 10,\n deltaSeconds: 0.1,\n modelIndex: vi.fn(() => 0),\n scheduleThink: vi.fn((entity: Entity, time: number) => {\n entity.nextthink = time;\n }),\n linkentity: vi.fn(),\n trace: traceFn,\n pointcontents: vi.fn(() => 0),\n multicast: vi.fn(),\n unicast: vi.fn(),\n engine,\n game,\n sound: vi.fn((ent: Entity, chan: number, sound: string, vol: number, attn: number, timeofs: number) => {\n engine.sound(ent, chan, sound, vol, attn, timeofs);\n }),\n soundIndex: vi.fn((sound: string) => engine.soundIndex(sound)),\n useTargets: vi.fn((entity: Entity, activator: Entity | null) => {\n }),\n findByTargetName: vi.fn(() => []),\n pickTarget: vi.fn(() => null),\n killBox: vi.fn(),\n rng: createRandomGenerator({ seed }),\n imports: {\n configstring: vi.fn(),\n trace: traceFn,\n pointcontents: vi.fn(() => 0),\n },\n level: {\n intermission_angle: { x: 0, y: 0, z: 0 },\n intermission_origin: { x: 0, y: 0, z: 0 },\n },\n targetNameIndex: new Map(),\n forEachEntity: vi.fn((callback: (ent: Entity) => void) => {\n // Iterate over managed list\n entityList.forEach(callback);\n }),\n find: vi.fn((predicate: (ent: Entity) => boolean) => {\n return entityList.find(predicate);\n }),\n // Helper to find by classname specifically (common pattern)\n findByClassname: vi.fn((classname: string) => {\n return entityList.find(e => e.classname === classname);\n }),\n beginFrame: vi.fn((timeSeconds: number) => {\n (entities as any).timeSeconds = timeSeconds;\n }),\n targetAwareness: {\n timeSeconds: 10,\n frameNumber: 1,\n sightEntity: null,\n soundEntity: null,\n }\n } as unknown as EntitySystem;\n\n return {\n keyValues: {},\n entities,\n game: game,\n health_multiplier: 1,\n warn: vi.fn(),\n free: vi.fn(),\n precacheModel: vi.fn(),\n precacheSound: vi.fn(),\n precacheImage: vi.fn(),\n } as unknown as SpawnContext & { entities: EntitySystem, game: any };\n}\n\nexport function createSpawnContext(): SpawnContext {\n return createTestContext();\n}\n\nexport function createEntity(): Entity {\n return new Entity(1);\n}\n"],"mappings":"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","names":["vi"]}
|