228 lines
7.3 KiB
TypeScript
228 lines
7.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
DEFAULT_CAMERA_RIG_DEFAULT_ACTIVE,
|
|
DEFAULT_CAMERA_RIG_LOOK_AROUND_ENABLED,
|
|
DEFAULT_CAMERA_RIG_LOOK_AROUND_PITCH_LIMIT_DEGREES,
|
|
DEFAULT_CAMERA_RIG_LOOK_AROUND_RECENTER_SPEED,
|
|
DEFAULT_CAMERA_RIG_LOOK_AROUND_YAW_LIMIT_DEGREES,
|
|
DEFAULT_CAMERA_RIG_PRIORITY,
|
|
DEFAULT_CAMERA_RIG_TARGET_OFFSET,
|
|
DEFAULT_CAMERA_RIG_TRANSITION_DURATION_SECONDS,
|
|
DEFAULT_CAMERA_RIG_TRANSITION_MODE,
|
|
DEFAULT_POINT_LIGHT_COLOR_HEX,
|
|
DEFAULT_POINT_LIGHT_DISTANCE,
|
|
DEFAULT_POINT_LIGHT_INTENSITY,
|
|
DEFAULT_PLAYER_START_BOX_SIZE,
|
|
DEFAULT_PLAYER_START_CAPSULE_HEIGHT,
|
|
DEFAULT_PLAYER_START_CAPSULE_RADIUS,
|
|
DEFAULT_PLAYER_START_CROUCH_SETTINGS,
|
|
DEFAULT_PLAYER_START_EYE_HEIGHT,
|
|
DEFAULT_PLAYER_START_ALLOW_LOOK_INPUT_TARGET_SWITCH,
|
|
DEFAULT_PLAYER_START_INTERACTION_ANGLE_DEGREES,
|
|
DEFAULT_PLAYER_START_INTERACTION_REACH_METERS,
|
|
DEFAULT_PLAYER_START_JUMP_SETTINGS,
|
|
DEFAULT_PLAYER_START_MOVE_SPEED,
|
|
DEFAULT_PLAYER_START_MOVEMENT_CAPABILITIES,
|
|
DEFAULT_PLAYER_START_SPRINT_SETTINGS,
|
|
DEFAULT_PLAYER_START_TARGET_BUTTON_CYCLES_ACTIVE_TARGET,
|
|
DEFAULT_SPOT_LIGHT_ANGLE_DEGREES,
|
|
DEFAULT_SPOT_LIGHT_COLOR_HEX,
|
|
DEFAULT_SPOT_LIGHT_DISTANCE,
|
|
DEFAULT_SPOT_LIGHT_DIRECTION,
|
|
DEFAULT_SPOT_LIGHT_INTENSITY,
|
|
DEFAULT_INTERACTABLE_PROMPT,
|
|
DEFAULT_NPC_YAW_DEGREES,
|
|
DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
|
|
DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
|
|
DEFAULT_SOUND_EMITTER_REF_DISTANCE,
|
|
DEFAULT_SOUND_EMITTER_VOLUME,
|
|
DEFAULT_TRIGGER_VOLUME_SIZE,
|
|
createPointLightEntity,
|
|
createDefaultEntityInstance,
|
|
createInteractableEntity,
|
|
createNpcEntity,
|
|
createSpotLightEntity,
|
|
getEntityRegistryEntry
|
|
} from "../../src/entities/entity-instances";
|
|
|
|
describe("entity registry defaults", () => {
|
|
it("creates explicit typed defaults for each supported entity kind", () => {
|
|
expect(createDefaultEntityInstance("playerStart")).toMatchObject({
|
|
kind: "playerStart",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
yawDegrees: 0,
|
|
navigationMode: "firstPerson",
|
|
interactionReachMeters: DEFAULT_PLAYER_START_INTERACTION_REACH_METERS,
|
|
interactionAngleDegrees: DEFAULT_PLAYER_START_INTERACTION_ANGLE_DEGREES,
|
|
allowLookInputTargetSwitch:
|
|
DEFAULT_PLAYER_START_ALLOW_LOOK_INPUT_TARGET_SWITCH,
|
|
targetButtonCyclesActiveTarget:
|
|
DEFAULT_PLAYER_START_TARGET_BUTTON_CYCLES_ACTIVE_TARGET,
|
|
movementTemplate: {
|
|
kind: "default",
|
|
moveSpeed: DEFAULT_PLAYER_START_MOVE_SPEED,
|
|
capabilities: DEFAULT_PLAYER_START_MOVEMENT_CAPABILITIES,
|
|
jump: DEFAULT_PLAYER_START_JUMP_SETTINGS,
|
|
sprint: DEFAULT_PLAYER_START_SPRINT_SETTINGS,
|
|
crouch: DEFAULT_PLAYER_START_CROUCH_SETTINGS
|
|
},
|
|
collider: {
|
|
mode: "capsule",
|
|
eyeHeight: DEFAULT_PLAYER_START_EYE_HEIGHT,
|
|
capsuleRadius: DEFAULT_PLAYER_START_CAPSULE_RADIUS,
|
|
capsuleHeight: DEFAULT_PLAYER_START_CAPSULE_HEIGHT,
|
|
boxSize: DEFAULT_PLAYER_START_BOX_SIZE
|
|
},
|
|
inputBindings: {
|
|
keyboard: {
|
|
moveForward: "KeyW",
|
|
moveBackward: "KeyS",
|
|
moveLeft: "KeyA",
|
|
moveRight: "KeyD",
|
|
jump: "Space",
|
|
sprint: "ShiftLeft",
|
|
crouch: "ControlLeft",
|
|
interact: "MouseLeft",
|
|
clearTarget: "KeyQ",
|
|
pauseTime: "KeyP"
|
|
},
|
|
gamepad: {
|
|
moveForward: "leftStickUp",
|
|
moveBackward: "leftStickDown",
|
|
moveLeft: "leftStickLeft",
|
|
moveRight: "leftStickRight",
|
|
jump: "buttonSouth",
|
|
sprint: "leftStickPress",
|
|
crouch: "buttonEast",
|
|
interact: "buttonWest",
|
|
clearTarget: "buttonNorth",
|
|
pauseTime: "buttonMenu",
|
|
cameraLook: "rightStick"
|
|
}
|
|
}
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("pointLight")).toMatchObject({
|
|
kind: "pointLight",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
colorHex: DEFAULT_POINT_LIGHT_COLOR_HEX,
|
|
intensity: DEFAULT_POINT_LIGHT_INTENSITY,
|
|
distance: DEFAULT_POINT_LIGHT_DISTANCE
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("cameraRig")).toMatchObject({
|
|
kind: "cameraRig",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
rigType: "fixed",
|
|
priority: DEFAULT_CAMERA_RIG_PRIORITY,
|
|
defaultActive: DEFAULT_CAMERA_RIG_DEFAULT_ACTIVE,
|
|
target: {
|
|
kind: "player"
|
|
},
|
|
targetOffset: DEFAULT_CAMERA_RIG_TARGET_OFFSET,
|
|
transitionMode: DEFAULT_CAMERA_RIG_TRANSITION_MODE,
|
|
transitionDurationSeconds: DEFAULT_CAMERA_RIG_TRANSITION_DURATION_SECONDS,
|
|
lookAround: {
|
|
enabled: DEFAULT_CAMERA_RIG_LOOK_AROUND_ENABLED,
|
|
yawLimitDegrees: DEFAULT_CAMERA_RIG_LOOK_AROUND_YAW_LIMIT_DEGREES,
|
|
pitchLimitDegrees: DEFAULT_CAMERA_RIG_LOOK_AROUND_PITCH_LIMIT_DEGREES,
|
|
recenterSpeed: DEFAULT_CAMERA_RIG_LOOK_AROUND_RECENTER_SPEED
|
|
}
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("spotLight")).toMatchObject({
|
|
kind: "spotLight",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
direction: DEFAULT_SPOT_LIGHT_DIRECTION,
|
|
colorHex: DEFAULT_SPOT_LIGHT_COLOR_HEX,
|
|
intensity: DEFAULT_SPOT_LIGHT_INTENSITY,
|
|
distance: DEFAULT_SPOT_LIGHT_DISTANCE,
|
|
angleDegrees: DEFAULT_SPOT_LIGHT_ANGLE_DEGREES
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("soundEmitter")).toMatchObject({
|
|
kind: "soundEmitter",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
audioAssetId: DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
|
|
volume: DEFAULT_SOUND_EMITTER_VOLUME,
|
|
refDistance: DEFAULT_SOUND_EMITTER_REF_DISTANCE,
|
|
maxDistance: DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
|
|
autoplay: false,
|
|
loop: false
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("triggerVolume")).toMatchObject({
|
|
kind: "triggerVolume",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
size: DEFAULT_TRIGGER_VOLUME_SIZE,
|
|
triggerOnEnter: true,
|
|
triggerOnExit: false
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("teleportTarget")).toMatchObject({
|
|
kind: "teleportTarget",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
yawDegrees: 0
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("npc")).toMatchObject({
|
|
kind: "npc",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
yawDegrees: DEFAULT_NPC_YAW_DEGREES,
|
|
modelAssetId: null
|
|
});
|
|
|
|
expect(createDefaultEntityInstance("interactable")).toMatchObject({
|
|
kind: "interactable",
|
|
position: { x: 0, y: 0, z: 0 },
|
|
radius: 1.5,
|
|
prompt: DEFAULT_INTERACTABLE_PROMPT,
|
|
enabled: true
|
|
});
|
|
});
|
|
|
|
it("keeps entity metadata and prompt validation explicit", () => {
|
|
expect(getEntityRegistryEntry("triggerVolume")).toMatchObject({
|
|
kind: "triggerVolume",
|
|
label: "Trigger Volume"
|
|
});
|
|
|
|
expect(
|
|
createInteractableEntity({
|
|
prompt: " Open "
|
|
}).prompt
|
|
).toBe("Open");
|
|
|
|
expect(() =>
|
|
createInteractableEntity({
|
|
prompt: " "
|
|
})
|
|
).toThrow("Interactable prompt must be non-empty.");
|
|
|
|
expect(() =>
|
|
createPointLightEntity({
|
|
distance: 0
|
|
})
|
|
).toThrow(
|
|
"Point Light distance must be a finite number greater than zero."
|
|
);
|
|
|
|
expect(() =>
|
|
createSpotLightEntity({
|
|
direction: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}
|
|
})
|
|
).toThrow("Spot Light direction must not be the zero vector.");
|
|
|
|
expect(() =>
|
|
createNpcEntity({
|
|
actorId: " "
|
|
})
|
|
).toThrow("NPC actorId must be a non-empty string.");
|
|
});
|
|
});
|