Update tests for player movement validation and serialization, add migration for version 33 Player Start jump settings
This commit is contained in:
@@ -130,7 +130,9 @@ describe("validateSceneDocument", () => {
|
|||||||
bufferMs: -1,
|
bufferMs: -1,
|
||||||
coyoteTimeMs: -1,
|
coyoteTimeMs: -1,
|
||||||
variableHeight: "yes",
|
variableHeight: "yes",
|
||||||
maxHoldMs: 0
|
maxHoldMs: 0,
|
||||||
|
moveWhileJumping: "yes",
|
||||||
|
moveWhileFalling: 1
|
||||||
},
|
},
|
||||||
sprint: {
|
sprint: {
|
||||||
speedMultiplier: 0
|
speedMultiplier: 0
|
||||||
@@ -209,6 +211,12 @@ describe("validateSceneDocument", () => {
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: "invalid-player-start-variable-jump-max-hold-ms"
|
code: "invalid-player-start-variable-jump-max-hold-ms"
|
||||||
}),
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-player-start-move-while-jumping"
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-player-start-move-while-falling"
|
||||||
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: "invalid-player-start-sprint-speed-multiplier"
|
code: "invalid-player-start-sprint-speed-multiplier"
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -465,7 +465,9 @@ describe("scene document JSON", () => {
|
|||||||
bufferMs: 120,
|
bufferMs: 120,
|
||||||
coyoteTimeMs: 90,
|
coyoteTimeMs: 90,
|
||||||
variableHeight: true,
|
variableHeight: true,
|
||||||
maxHoldMs: 220
|
maxHoldMs: 220,
|
||||||
|
moveWhileJumping: false,
|
||||||
|
moveWhileFalling: false
|
||||||
},
|
},
|
||||||
sprint: {
|
sprint: {
|
||||||
speedMultiplier: 1.8
|
speedMultiplier: 1.8
|
||||||
@@ -939,6 +941,40 @@ describe("scene document JSON", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("migrates version 33 Player Start jump settings to include default air movement flags", () => {
|
||||||
|
const playerStart = createPlayerStartEntity({
|
||||||
|
id: "entity-player-start-legacy-air-move-flags",
|
||||||
|
movementTemplate: {
|
||||||
|
kind: "responsive"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const {
|
||||||
|
moveWhileJumping: _moveWhileJumping,
|
||||||
|
moveWhileFalling: _moveWhileFalling,
|
||||||
|
...legacyJump
|
||||||
|
} = playerStart.movementTemplate.jump;
|
||||||
|
const legacyDocument = {
|
||||||
|
...createEmptySceneDocument({
|
||||||
|
name: "Legacy Player Air Movement Scene"
|
||||||
|
}),
|
||||||
|
version: 33,
|
||||||
|
entities: {
|
||||||
|
[playerStart.id]: {
|
||||||
|
...playerStart,
|
||||||
|
movementTemplate: {
|
||||||
|
...playerStart.movementTemplate,
|
||||||
|
jump: legacyJump
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const migratedDocument = migrateSceneDocument(legacyDocument);
|
||||||
|
|
||||||
|
expect(migratedDocument.version).toBe(SCENE_DOCUMENT_VERSION);
|
||||||
|
expect(migratedDocument.entities[playerStart.id]).toEqual(playerStart);
|
||||||
|
});
|
||||||
|
|
||||||
it("round-trips authored third-person Player Start navigation", () => {
|
it("round-trips authored third-person Player Start navigation", () => {
|
||||||
const playerStart = createPlayerStartEntity({
|
const playerStart = createPlayerStartEntity({
|
||||||
id: "entity-player-start-third-person",
|
id: "entity-player-start-third-person",
|
||||||
|
|||||||
@@ -382,6 +382,67 @@ describe("player-locomotion", () => {
|
|||||||
expect(step?.verticalVelocity).toBeLessThan(0);
|
expect(step?.verticalVelocity).toBeLessThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("disables jump-phase air movement when move while jumping is off", () => {
|
||||||
|
const step = stepPlayerLocomotion({
|
||||||
|
dt: 0.1,
|
||||||
|
feetPosition: {
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
movementYawRadians: 0,
|
||||||
|
standingShape: FIRST_PERSON_PLAYER_SHAPE,
|
||||||
|
verticalVelocity: 2,
|
||||||
|
previousLocomotionState: createIdleRuntimeLocomotionState("airborne"),
|
||||||
|
previousPlanarDisplacement: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
jumpBufferRemainingMs: 0,
|
||||||
|
coyoteTimeRemainingMs: 0,
|
||||||
|
jumpHoldRemainingMs: 0,
|
||||||
|
crouched: false,
|
||||||
|
wasJumpPressed: false,
|
||||||
|
input: FORWARD_INPUT,
|
||||||
|
movement: {
|
||||||
|
...DEFAULT_MOVEMENT,
|
||||||
|
jump: {
|
||||||
|
...DEFAULT_MOVEMENT.jump,
|
||||||
|
moveWhileJumping: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolveMotion: (feetPosition, motion): ResolvedPlayerMotion => ({
|
||||||
|
feetPosition: {
|
||||||
|
x: feetPosition.x + motion.x,
|
||||||
|
y: feetPosition.y + motion.y,
|
||||||
|
z: feetPosition.z + motion.z
|
||||||
|
},
|
||||||
|
grounded: false,
|
||||||
|
collisionCount: 0,
|
||||||
|
groundCollisionNormal: null,
|
||||||
|
collidedAxes: {
|
||||||
|
x: false,
|
||||||
|
y: false,
|
||||||
|
z: false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
resolveVolumeState: () => createVolumeState(),
|
||||||
|
probeGround: () => ({
|
||||||
|
grounded: false,
|
||||||
|
distance: null,
|
||||||
|
normal: null,
|
||||||
|
slopeDegrees: null
|
||||||
|
}),
|
||||||
|
canOccupyShape: () => true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(step).not.toBeNull();
|
||||||
|
expect(step?.locomotionState.locomotionMode).toBe("airborne");
|
||||||
|
expect(step?.planarDisplacement.z).toBeCloseTo(0);
|
||||||
|
expect(step?.locomotionState.planarSpeed).toBeCloseTo(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("keeps falling when airborne input pushes into a wall and the pre-move probe flickers grounded", () => {
|
it("keeps falling when airborne input pushes into a wall and the pre-move probe flickers grounded", () => {
|
||||||
let probeCount = 0;
|
let probeCount = 0;
|
||||||
|
|
||||||
@@ -452,6 +513,67 @@ describe("player-locomotion", () => {
|
|||||||
expect(step?.verticalVelocity).toBeLessThan(-1.5);
|
expect(step?.verticalVelocity).toBeLessThan(-1.5);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("disables falling air movement when move while falling is off", () => {
|
||||||
|
const step = stepPlayerLocomotion({
|
||||||
|
dt: 0.1,
|
||||||
|
feetPosition: {
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
movementYawRadians: 0,
|
||||||
|
standingShape: FIRST_PERSON_PLAYER_SHAPE,
|
||||||
|
verticalVelocity: -2,
|
||||||
|
previousLocomotionState: createIdleRuntimeLocomotionState("airborne"),
|
||||||
|
previousPlanarDisplacement: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
jumpBufferRemainingMs: 0,
|
||||||
|
coyoteTimeRemainingMs: 0,
|
||||||
|
jumpHoldRemainingMs: 0,
|
||||||
|
crouched: false,
|
||||||
|
wasJumpPressed: false,
|
||||||
|
input: FORWARD_INPUT,
|
||||||
|
movement: {
|
||||||
|
...DEFAULT_MOVEMENT,
|
||||||
|
jump: {
|
||||||
|
...DEFAULT_MOVEMENT.jump,
|
||||||
|
moveWhileFalling: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolveMotion: (feetPosition, motion): ResolvedPlayerMotion => ({
|
||||||
|
feetPosition: {
|
||||||
|
x: feetPosition.x + motion.x,
|
||||||
|
y: feetPosition.y + motion.y,
|
||||||
|
z: feetPosition.z + motion.z
|
||||||
|
},
|
||||||
|
grounded: false,
|
||||||
|
collisionCount: 0,
|
||||||
|
groundCollisionNormal: null,
|
||||||
|
collidedAxes: {
|
||||||
|
x: false,
|
||||||
|
y: false,
|
||||||
|
z: false
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
resolveVolumeState: () => createVolumeState(),
|
||||||
|
probeGround: () => ({
|
||||||
|
grounded: false,
|
||||||
|
distance: null,
|
||||||
|
normal: null,
|
||||||
|
slopeDegrees: null
|
||||||
|
}),
|
||||||
|
canOccupyShape: () => true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(step).not.toBeNull();
|
||||||
|
expect(step?.locomotionState.locomotionMode).toBe("airborne");
|
||||||
|
expect(step?.planarDisplacement.z).toBeCloseTo(0);
|
||||||
|
expect(step?.locomotionState.planarSpeed).toBeCloseTo(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("sinks toward the water surface while keeping the head above water", () => {
|
it("sinks toward the water surface while keeping the head above water", () => {
|
||||||
const step = stepPlayerLocomotion({
|
const step = stepPlayerLocomotion({
|
||||||
dt: 0.1,
|
dt: 0.1,
|
||||||
|
|||||||
Reference in New Issue
Block a user