Preserve emit loop delay schedule across range cleanup

This commit is contained in:
Jage9
2026-02-28 02:57:50 -05:00
parent b0b6744a52
commit eb03c48e3f
2 changed files with 30 additions and 14 deletions

View File

@@ -87,20 +87,24 @@ export class ItemEmitRuntime {
private readonly getSpatialConfig: (item: WorldItem) => EmitSpatialConfig,
) {}
cleanup(itemId: string): void {
cleanup(itemId: string, options?: { preserveSchedule?: boolean }): void {
const preserveSchedule = options?.preserveSchedule === true;
const output = this.outputs.get(itemId);
if (!output) return;
output.element.pause();
output.element.removeEventListener('ended', output.onEnded);
output.element.src = '';
output.source.disconnect();
output.effectInput.disconnect();
disconnectEffectRuntime(output.effectRuntime);
output.gain.disconnect();
output.panner?.disconnect();
this.outputs.delete(itemId);
if (output) {
output.element.pause();
output.element.removeEventListener('ended', output.onEnded);
output.element.src = '';
output.source.disconnect();
output.effectInput.disconnect();
disconnectEffectRuntime(output.effectRuntime);
output.gain.disconnect();
output.panner?.disconnect();
this.outputs.delete(itemId);
}
this.pendingEmitStarts.delete(itemId);
this.nextEmitStartAtMs.delete(itemId);
if (!preserveSchedule) {
this.nextEmitStartAtMs.delete(itemId);
}
this.emitStartFailureCount.delete(itemId);
}
@@ -139,16 +143,22 @@ export class ItemEmitRuntime {
}
const listeners = this.listenerPositions;
const validIds = new Set<string>();
const seenItemIds = new Set<string>();
let audioCtx = this.audio.context;
for (const item of items) {
seenItemIds.add(item.id);
const emitSound = String(item.params.emitSound ?? item.emitSound ?? '').trim();
const enabled = item.params.enabled !== false;
const soundUrl = enabled ? this.resolveSoundUrl(emitSound) : '';
if (!soundUrl || !this.shouldKeepRuntime(item, listeners, this.outputs.has(item.id))) {
if (!soundUrl) {
this.cleanup(item.id);
continue;
}
if (!this.shouldKeepRuntime(item, listeners, this.outputs.has(item.id))) {
this.cleanup(item.id, { preserveSchedule: true });
continue;
}
validIds.add(item.id);
const existing = this.outputs.get(item.id);
if (existing && existing.soundUrl === soundUrl) {
@@ -214,6 +224,12 @@ export class ItemEmitRuntime {
this.cleanup(itemId);
}
}
for (const itemId of Array.from(this.nextEmitStartAtMs.keys())) {
if (!seenItemIds.has(itemId)) {
this.nextEmitStartAtMs.delete(itemId);
}
}
}
updateSpatialAudio(items: Map<string, WorldItem>, playerPosition: { x: number; y: number }): void {