Refactor NPC presence and scheduling logic in runtime-host.ts

This commit is contained in:
2026-04-14 01:57:44 +02:00
parent 86259a1277
commit 937bb64508

View File

@@ -2198,16 +2198,12 @@ export class RuntimeHost {
}
if (this.currentClockState !== null) {
const previousTimeOfDayHours = this.currentClockState.timeOfDayHours;
this.currentClockState = advanceRuntimeClockState(
this.currentClockState,
dt
);
if (this.sceneReady) {
this.updateRuntimeNpcPresenceAfterClockAdvance(
previousTimeOfDayHours,
this.currentClockState.timeOfDayHours
);
this.syncRuntimeNpcScheduleToCurrentClock();
}
this.applyDayNightLighting();
this.clockPublishAccumulator += dt;
@@ -2276,63 +2272,39 @@ export class RuntimeHost {
this.firstPersonController.teleportTo(target.position, target.yawDegrees);
}
private syncRuntimeNpcPresenceToCurrentClock() {
private syncRuntimeNpcScheduleToCurrentClock() {
if (this.runtimeScene === null || this.currentClockState === null) {
return;
}
const nextResolvedScheduler = resolveRuntimeProjectScheduleState({
scheduler: this.runtimeScene.scheduler.document,
actorIds: this.runtimeScene.npcDefinitions.map((npc) => npc.actorId),
dayNumber: this.currentClockState.dayCount + 1,
timeOfDayHours: this.currentClockState.timeOfDayHours
});
const actorStates = new Map(
nextResolvedScheduler.actors.map((state) => [state.actorId, state])
);
let changed = false;
for (const npc of this.runtimeScene.npcDefinitions) {
const nextActive = resolveNpcPresenceActive(
npc.presence,
this.currentClockState.timeOfDayHours
);
const actorState = actorStates.get(npc.actorId);
const nextActive = actorState?.active ?? true;
const nextRoutineId = actorState?.activeRoutineId ?? null;
const nextRoutineTitle = actorState?.activeRoutineTitle ?? null;
if (npc.active === nextActive) {
continue;
}
npc.active = nextActive;
changed = true;
}
if (changed) {
this.refreshRuntimeNpcCollections();
}
}
private updateRuntimeNpcPresenceAfterClockAdvance(
previousTimeOfDayHours: number,
currentTimeOfDayHours: number
) {
if (this.runtimeScene === null) {
return;
}
let changed = false;
for (const npc of this.runtimeScene.npcDefinitions) {
if (
!hasNpcPresenceActivityChanged(
npc.presence,
previousTimeOfDayHours,
currentTimeOfDayHours
)
npc.active === nextActive &&
npc.activeRoutineId === nextRoutineId &&
npc.activeRoutineTitle === nextRoutineTitle
) {
continue;
}
const nextActive = resolveNpcPresenceActive(
npc.presence,
currentTimeOfDayHours
);
if (npc.active === nextActive) {
continue;
}
npc.active = nextActive;
npc.activeRoutineId = nextRoutineId;
npc.activeRoutineTitle = nextRoutineTitle;
changed = true;
const renderGroup = this.modelRenderObjects.get(npc.entityId);
@@ -2341,12 +2313,16 @@ export class RuntimeHost {
}
}
if (!changed) {
return;
}
this.runtimeScene.scheduler.resolved = nextResolvedScheduler;
this.runtimeScene.control.resolved = applyRuntimeProjectScheduleToControlState(
this.runtimeScene.control.resolved,
nextResolvedScheduler
);
this.refreshRuntimeNpcCollections();
this.refreshCollisionWorldForNpcPresence();
if (changed) {
this.refreshRuntimeNpcCollections();
this.refreshCollisionWorldForNpcSchedule();
}
}
private refreshRuntimeNpcCollections() {
@@ -2365,7 +2341,7 @@ export class RuntimeHost {
];
}
private refreshCollisionWorldForNpcPresence() {
private refreshCollisionWorldForNpcSchedule() {
if (this.runtimeScene === null) {
return;
}