Preload teleport destination streams and mute teleport footsteps

This commit is contained in:
Jage9
2026-02-22 20:07:02 -05:00
parent 5ff805e847
commit ed0fc07728
2 changed files with 18 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
// Maintainer-controlled web client version. // Maintainer-controlled web client version.
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
window.CHGRID_WEB_VERSION = "2026.02.22 R181"; window.CHGRID_WEB_VERSION = "2026.02.22 R182";
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
window.CHGRID_TIME_ZONE = "America/Detroit"; window.CHGRID_TIME_ZONE = "America/Detroit";

View File

@@ -227,7 +227,6 @@ let activeTeleport:
targetY: number; targetY: number;
startedAtMs: number; startedAtMs: number;
durationMs: number; durationMs: number;
lastStepAtMs: number;
lastSyncAtMs: number; lastSyncAtMs: number;
lastSentX: number; lastSentX: number;
lastSentY: number; lastSentY: number;
@@ -557,12 +556,12 @@ async function applyAudioLayerState(): Promise<void> {
await itemEmitRuntime.setLayerEnabled(audioLayers.item, state.items.values(), listenerPosition); await itemEmitRuntime.setLayerEnabled(audioLayers.item, state.items.values(), listenerPosition);
} }
/** Refreshes distance-gated radio/item stream subscriptions on movement or timer cadence. */ /** Refreshes distance-gated radio/item stream subscriptions for a listener position. */
async function refreshAudioSubscriptions(force = false): Promise<void> { async function refreshAudioSubscriptionsAt(listenerPosition: { x: number; y: number }, force = false): Promise<void> {
if (!state.running) return; if (!state.running) return;
const now = Date.now(); const now = Date.now();
const tileX = Math.round(state.player.x); const tileX = Math.round(listenerPosition.x);
const tileY = Math.round(state.player.y); const tileY = Math.round(listenerPosition.y);
const moved = tileX !== lastSubscriptionRefreshTileX || tileY !== lastSubscriptionRefreshTileY; const moved = tileX !== lastSubscriptionRefreshTileX || tileY !== lastSubscriptionRefreshTileY;
if (!force && !moved && now - lastSubscriptionRefreshAt < AUDIO_SUBSCRIPTION_REFRESH_MS) { if (!force && !moved && now - lastSubscriptionRefreshAt < AUDIO_SUBSCRIPTION_REFRESH_MS) {
return; return;
@@ -575,7 +574,6 @@ async function refreshAudioSubscriptions(force = false): Promise<void> {
lastSubscriptionRefreshAt = now; lastSubscriptionRefreshAt = now;
lastSubscriptionRefreshTileX = tileX; lastSubscriptionRefreshTileX = tileX;
lastSubscriptionRefreshTileY = tileY; lastSubscriptionRefreshTileY = tileY;
const listenerPosition = { x: state.player.x, y: state.player.y };
try { try {
await radioRuntime.sync(state.items.values(), listenerPosition); await radioRuntime.sync(state.items.values(), listenerPosition);
await itemEmitRuntime.sync(state.items.values(), listenerPosition); await itemEmitRuntime.sync(state.items.values(), listenerPosition);
@@ -588,6 +586,15 @@ async function refreshAudioSubscriptions(force = false): Promise<void> {
} }
} }
/** Refreshes distance-gated radio/item stream subscriptions on movement or timer cadence. */
async function refreshAudioSubscriptions(force = false): Promise<void> {
if (activeTeleport) {
await refreshAudioSubscriptionsAt({ x: activeTeleport.targetX, y: activeTeleport.targetY }, force);
return;
}
await refreshAudioSubscriptionsAt({ x: state.player.x, y: state.player.y }, force);
}
/** Toggles a single audio layer and applies the change immediately. */ /** Toggles a single audio layer and applies the change immediately. */
function toggleAudioLayer(layer: keyof AudioLayerState): void { function toggleAudioLayer(layer: keyof AudioLayerState): void {
audioLayers = { ...audioLayers, [layer]: !audioLayers[layer] }; audioLayers = { ...audioLayers, [layer]: !audioLayers[layer] };
@@ -1103,12 +1110,12 @@ function startTeleportTo(targetX: number, targetY: number, completionStatus: str
targetY, targetY,
startedAtMs: nowMs, startedAtMs: nowMs,
durationMs, durationMs,
lastStepAtMs: nowMs,
lastSyncAtMs: nowMs, lastSyncAtMs: nowMs,
lastSentX: Math.round(startX), lastSentX: Math.round(startX),
lastSentY: Math.round(startY), lastSentY: Math.round(startY),
completionStatus, completionStatus,
}; };
void refreshAudioSubscriptionsAt({ x: targetX, y: targetY }, true);
state.keysPressed.ArrowUp = false; state.keysPressed.ArrowUp = false;
state.keysPressed.ArrowDown = false; state.keysPressed.ArrowDown = false;
state.keysPressed.ArrowLeft = false; state.keysPressed.ArrowLeft = false;
@@ -1125,11 +1132,6 @@ function updateTeleport(): void {
state.player.x = activeTeleport.startX + (activeTeleport.targetX - activeTeleport.startX) * progress; state.player.x = activeTeleport.startX + (activeTeleport.targetX - activeTeleport.startX) * progress;
state.player.y = activeTeleport.startY + (activeTeleport.targetY - activeTeleport.startY) * progress; state.player.y = activeTeleport.startY + (activeTeleport.targetY - activeTeleport.startY) * progress;
if (nowMs - activeTeleport.lastStepAtMs >= MOVE_COOLDOWN_MS) {
activeTeleport.lastStepAtMs = nowMs;
void audio.playSample(randomFootstepUrl(), FOOTSTEP_GAIN, MOVE_COOLDOWN_MS);
}
if (nowMs - activeTeleport.lastSyncAtMs >= TELEPORT_SYNC_INTERVAL_MS) { if (nowMs - activeTeleport.lastSyncAtMs >= TELEPORT_SYNC_INTERVAL_MS) {
activeTeleport.lastSyncAtMs = nowMs; activeTeleport.lastSyncAtMs = nowMs;
const syncX = Math.round(state.player.x); const syncX = Math.round(state.player.x);
@@ -1160,7 +1162,9 @@ function gameLoop(): void {
if (!state.running) return; if (!state.running) return;
updateTeleport(); updateTeleport();
handleMovement(); handleMovement();
void refreshAudioSubscriptions(); if (!activeTeleport) {
void refreshAudioSubscriptions();
}
audio.updateSpatialAudio(peerManager.getPeers(), { x: state.player.x, y: state.player.y }); audio.updateSpatialAudio(peerManager.getPeers(), { x: state.player.x, y: state.player.y });
radioRuntime.updateSpatialAudio(state.items, { x: state.player.x, y: state.player.y }); radioRuntime.updateSpatialAudio(state.items, { x: state.player.x, y: state.player.y });
itemEmitRuntime.updateSpatialAudio(state.items, { x: state.player.x, y: state.player.y }); itemEmitRuntime.updateSpatialAudio(state.items, { x: state.player.x, y: state.player.y });