Add NPC presence support in scene document

This commit is contained in:
2026-04-13 23:48:16 +02:00
parent 5a6a708c07
commit 6847d7c211
2 changed files with 35 additions and 1 deletions

View File

@@ -24,12 +24,15 @@ import {
import { import {
DEFAULT_PLAYER_START_GAMEPAD_BINDINGS, DEFAULT_PLAYER_START_GAMEPAD_BINDINGS,
DEFAULT_PLAYER_START_KEYBOARD_BINDINGS, DEFAULT_PLAYER_START_KEYBOARD_BINDINGS,
createNpcAlwaysPresence,
createNpcEntity, createNpcEntity,
createNpcColliderSettings, createNpcColliderSettings,
createNpcTimeWindowPresence,
createPlayerStartColliderSettings, createPlayerStartColliderSettings,
createPlayerStartInputBindings, createPlayerStartInputBindings,
createPlayerStartMovementTemplate, createPlayerStartMovementTemplate,
createInteractableEntity, createInteractableEntity,
isNpcPresenceMode,
normalizeEntityName, normalizeEntityName,
createPointLightEntity, createPointLightEntity,
createPlayerStartEntity, createPlayerStartEntity,
@@ -49,6 +52,7 @@ import {
isPlayerStartMovementTemplateKind, isPlayerStartMovementTemplateKind,
isPlayerStartNavigationMode, isPlayerStartNavigationMode,
type EntityInstance, type EntityInstance,
type NpcPresence,
type PlayerStartGamepadActionBinding, type PlayerStartGamepadActionBinding,
type PlayerStartGamepadBinding, type PlayerStartGamepadBinding,
type PlayerStartGamepadCameraLookBinding, type PlayerStartGamepadCameraLookBinding,
@@ -116,6 +120,7 @@ import {
PROJECT_NAME_SCENE_DOCUMENT_VERSION, PROJECT_NAME_SCENE_DOCUMENT_VERSION,
NPC_COLLIDER_SCENE_DOCUMENT_VERSION, NPC_COLLIDER_SCENE_DOCUMENT_VERSION,
NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION, NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION,
NPC_PRESENCE_SCENE_DOCUMENT_VERSION,
SCENE_DOCUMENT_VERSION, SCENE_DOCUMENT_VERSION,
STATIC_SIMPLE_MODEL_COLLIDERS_SCENE_DOCUMENT_VERSION, STATIC_SIMPLE_MODEL_COLLIDERS_SCENE_DOCUMENT_VERSION,
TRIGGER_ACTION_TARGET_FOUNDATION_SCENE_DOCUMENT_VERSION, TRIGGER_ACTION_TARGET_FOUNDATION_SCENE_DOCUMENT_VERSION,
@@ -2621,6 +2626,7 @@ function readNpcEntity(value: unknown, label: string): EntityInstance {
), ),
position: readVec3(value.position, `${label}.position`), position: readVec3(value.position, `${label}.position`),
actorId: expectString(value.actorId, `${label}.actorId`), actorId: expectString(value.actorId, `${label}.actorId`),
presence: readNpcPresence(value.presence, `${label}.presence`),
yawDegrees: expectFiniteNumber(value.yawDegrees, `${label}.yawDegrees`), yawDegrees: expectFiniteNumber(value.yawDegrees, `${label}.yawDegrees`),
modelAssetId: modelAssetId:
value.modelAssetId === undefined || value.modelAssetId === null value.modelAssetId === undefined || value.modelAssetId === null
@@ -2636,6 +2642,32 @@ function readNpcEntity(value: unknown, label: string): EntityInstance {
return entity; return entity;
} }
function readNpcPresence(value: unknown, label: string): NpcPresence {
if (value === undefined) {
return createNpcAlwaysPresence();
}
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
}
const mode = expectString(value.mode, `${label}.mode`);
if (!isNpcPresenceMode(mode)) {
throw new Error(`${label}.mode must be always or timeWindow.`);
}
switch (mode) {
case "always":
return createNpcAlwaysPresence();
case "timeWindow":
return createNpcTimeWindowPresence({
startHour: expectFiniteNumber(value.startHour, `${label}.startHour`),
endHour: expectFiniteNumber(value.endHour, `${label}.endHour`)
});
}
}
function readSceneExitEntity(value: unknown, label: string): EntityInstance { function readSceneExitEntity(value: unknown, label: string): EntityInstance {
if (!isRecord(value)) { if (!isRecord(value)) {
throw new Error(`${label} must be an object.`); throw new Error(`${label} must be an object.`);
@@ -3403,6 +3435,7 @@ export function migrateSceneDocument(source: unknown): SceneDocument {
if ( if (
source.version !== SCENE_DOCUMENT_VERSION && source.version !== SCENE_DOCUMENT_VERSION &&
source.version !== NPC_PRESENCE_SCENE_DOCUMENT_VERSION &&
source.version !== NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION && source.version !== NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION &&
source.version !== WORLD_TIME_ENVIRONMENT_SCENE_DOCUMENT_VERSION && source.version !== WORLD_TIME_ENVIRONMENT_SCENE_DOCUMENT_VERSION &&
source.version !== PROJECT_TIME_NIGHT_BACKGROUND_SCENE_DOCUMENT_VERSION && source.version !== PROJECT_TIME_NIGHT_BACKGROUND_SCENE_DOCUMENT_VERSION &&

View File

@@ -20,7 +20,8 @@ import {
} from "./project-time-settings"; } from "./project-time-settings";
import { type ScenePath } from "./paths"; import { type ScenePath } from "./paths";
export const SCENE_DOCUMENT_VERSION = 43 as const; export const SCENE_DOCUMENT_VERSION = 44 as const;
export const NPC_PRESENCE_SCENE_DOCUMENT_VERSION = 44 as const;
export const PATH_FOUNDATION_SCENE_DOCUMENT_VERSION = 43 as const; export const PATH_FOUNDATION_SCENE_DOCUMENT_VERSION = 43 as const;
export const NPC_COLLIDER_SCENE_DOCUMENT_VERSION = 42 as const; export const NPC_COLLIDER_SCENE_DOCUMENT_VERSION = 42 as const;
export const NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION = 41 as const; export const NPC_ENTITY_FOUNDATION_SCENE_DOCUMENT_VERSION = 41 as const;