@minicode-dev/chat 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/chunks/{BattleshipGameCard-B-B4r7lK.js → BattleshipGameCard-8H-sBCsv.js} +3 -3
  2. package/dist/chunks/{BattleshipGameCard-B-B4r7lK.js.map → BattleshipGameCard-8H-sBCsv.js.map} +1 -1
  3. package/dist/chunks/{ChatContext-DQtKsR6Z.js → ChatContext-CVW58bzC.js} +2 -2
  4. package/dist/chunks/{ChatContext-DQtKsR6Z.js.map → ChatContext-CVW58bzC.js.map} +1 -1
  5. package/dist/chunks/{RacingLiveGameCard-c1G7uoDI.js → RacingLiveGameCard-8j9QLnxW.js} +4 -4
  6. package/dist/chunks/{RacingLiveGameCard-c1G7uoDI.js.map → RacingLiveGameCard-8j9QLnxW.js.map} +1 -1
  7. package/dist/chunks/{TanksGameCard-CvTaF7tu.js → TanksGameCard-DnCufSH6.js} +12 -12
  8. package/dist/chunks/{TanksGameCard-CvTaF7tu.js.map → TanksGameCard-DnCufSH6.js.map} +1 -1
  9. package/dist/chunks/TanksLiveGameCard-D_27Jomp.js +1274 -0
  10. package/dist/chunks/TanksLiveGameCard-D_27Jomp.js.map +1 -0
  11. package/dist/chunks/{avalancheScene3d-Z5QyZIid.js → avalancheScene3d-CIE2WKQn.js} +51 -50
  12. package/dist/chunks/{avalancheScene3d-Z5QyZIid.js.map → avalancheScene3d-CIE2WKQn.js.map} +1 -1
  13. package/dist/chunks/cars-D1PM7mVD.js +340 -0
  14. package/dist/chunks/cars-D1PM7mVD.js.map +1 -0
  15. package/dist/chunks/{connect4Sounds-DmD-E9kX.js → connect4Sounds-BqEHULjv.js} +2 -2
  16. package/dist/chunks/{connect4Sounds-DmD-E9kX.js.map → connect4Sounds-BqEHULjv.js.map} +1 -1
  17. package/dist/chunks/createLiveScene-MTGRv8rx.js +758 -0
  18. package/dist/chunks/createLiveScene-MTGRv8rx.js.map +1 -0
  19. package/dist/chunks/{createRaceScene-C7Rw89kj.js → createRaceScene-BiEtQsVs.js} +4 -3
  20. package/dist/chunks/{createRaceScene-C7Rw89kj.js.map → createRaceScene-BiEtQsVs.js.map} +1 -1
  21. package/dist/chunks/fx-DhXerGyt.js +248 -0
  22. package/dist/chunks/fx-DhXerGyt.js.map +1 -0
  23. package/dist/chunks/{games-BvYTWgaR.js → games-Bl_8raG6.js} +1147 -574
  24. package/dist/chunks/games-Bl_8raG6.js.map +1 -0
  25. package/dist/chunks/{tanksSounds-DwjfSp3W.js → tanksSounds-DTnidbiq.js} +5 -5
  26. package/dist/chunks/{tanksSounds-DwjfSp3W.js.map → tanksSounds-DTnidbiq.js.map} +1 -1
  27. package/dist/index.js +28 -28
  28. package/dist/index.js.map +1 -1
  29. package/dist/styles.css +1 -1
  30. package/package.json +1 -1
  31. package/dist/chunks/TanksLiveGameCard-COr9Oay5.js +0 -1011
  32. package/dist/chunks/TanksLiveGameCard-COr9Oay5.js.map +0 -1
  33. package/dist/chunks/createLiveScene-CWBunxPi.js +0 -367
  34. package/dist/chunks/createLiveScene-CWBunxPi.js.map +0 -1
  35. package/dist/chunks/fx-UZwhOmdl.js +0 -584
  36. package/dist/chunks/fx-UZwhOmdl.js.map +0 -1
  37. package/dist/chunks/games-BvYTWgaR.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import { t as e } from "./games-BvYTWgaR.js";
2
- import { i as t, o as n } from "./ChatContext-DQtKsR6Z.js";
3
- import { a as r, t as i } from "./connect4Sounds-DmD-E9kX.js";
1
+ import { t as e } from "./games-Bl_8raG6.js";
2
+ import { i as t, o as n } from "./ChatContext-CVW58bzC.js";
3
+ import { a as r, t as i } from "./connect4Sounds-BqEHULjv.js";
4
4
  // src/games/tanks/sound/cues.js
5
5
  var a = [
6
6
  "engine_loop",
@@ -204,6 +204,6 @@ function V(e, t) {
204
204
  function H(e, t) {
205
205
  B(d(e), t);
206
206
  }
207
- export { z as a, M as i, V as n, F as o, H as r, E as t };
207
+ export { L as a, R as c, I as i, F as l, V as n, M as o, H as r, z as s, E as t };
208
208
 
209
- //# sourceMappingURL=tanksSounds-DwjfSp3W.js.map
209
+ //# sourceMappingURL=tanksSounds-DTnidbiq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tanksSounds-DwjfSp3W.js","names":["chatSoundUrl","isSoundEnabled","subscribeSoundPreference","createSoundManager","connect4Sounds","TANKS_LOOPS","play","loopStart","loopStop","IMPACT_SOUNDS","sceneEventToCues","event","name","outcomeToCues","result","TANKS_SOUND_NAMES","LEVELS","DELIVERED_TANKS_SOUNDS","RETRIGGER_MS","LOOP_RAMPS","MP3_LOOP_TRIM","YIELDS_TO","supportsOgg","files","fileFor","extension","configured","format","configureTanksSounds","overrides","available","file","manager","getTanksSoundManager","hidden","canPlay","wantedLoops","syncLoops","allowed","started","startTanksSounds","lastPlayed","suppressedUntil","suppressTanksCue","ms","playTanksCue","key","now","played","startTanksLoop","stopTanksLoop","stopAllTanksLoops","names","runCues","cues","action","handleSceneEvent","suffix","playOutcome"],"sources":["../../src/games/tanks/sound/cues.js","../../src/games/tanks/sound/tanksSounds.js"],"sourcesContent":["// Pure sound choreography for Tanks (no audio, no DOM): maps scene events to\n// one-shot plays and loop start/stop actions.\n\nexport const TANKS_LOOPS = ['engine_loop', 'tracks_loop', 'turret_loop'];\n\nconst play = (name) => ({ name, action: 'play' });\nconst loopStart = (name) => ({ name, action: 'loop_start' });\nconst loopStop = (name) => ({ name, action: 'loop_stop' });\n\nconst IMPACT_SOUNDS = { terrain: 'terrain_impact', obstacle: 'terrain_impact', ground: 'terrain_impact' };\n\n/** Scene onEvent ({ type, ... } or a bare type string) → ordered cues. */\nexport function sceneEventToCues(event) {\n const type = typeof event === 'string' ? event : event?.type;\n switch (type) {\n case 'engine_start': return [play('engine_start')];\n case 'move_start': return [loopStart('engine_loop'), loopStart('tracks_loop')];\n case 'move_end': return [loopStop('tracks_loop'), loopStop('engine_loop')];\n case 'turret_start': return [loopStart('turret_loop')];\n case 'turret_end': return [loopStop('turret_loop')];\n case 'fire': return [play('cannon_fire')];\n case 'projectile_start': return [play('projectile_whistle')];\n case 'impact': {\n const name = IMPACT_SOUNDS[event?.kind];\n return name ? [play(name)] : [];\n }\n case 'tank_hit': return [play('tank_hit')];\n case 'big_explosion': return [play('big_explosion')];\n case 'destroyed': return [play('tank_destroyed')];\n default: return [];\n }\n}\n\n/** 'victory' | 'defeat' → cues; anything else (draw, unknown) stays silent. */\nexport function outcomeToCues(result) {\n if (result === 'victory' || result === 'defeat') return [...TANKS_LOOPS.map(loopStop), play(result)];\n return [];\n}\n","// Tanks (3D) sound layer.\n//\n// Expected files (host serves them from <assets>/sounds/tanks/, i.e. the\n// package's assets/sounds/tanks/), each as .ogg and .mp3: OGG Vorbis is used where\n// the browser supports it, MP3 otherwise. Only names listed in `available` are\n// fetched, so sounds not delivered (the optional UI cues) cost no requests and never error.\n// Format: 44.1 kHz, mono. True peak <= -1 dBTP; loops cut at zero crossings so\n// they repeat without clicks.\n//\n// name duration loudness\n// engine_start 1.5-2.5 s -20 LUFS\n// engine_loop 2-4 s (loop) -24 LUFS\n// tracks_loop 1-2 s (loop) -24 LUFS\n// turret_loop 1-2 s (loop) -26 LUFS\n// cannon_fire 1.5-2.5 s -16 LUFS\n// projectile_whistle 1.5-3 s -22 LUFS\n// terrain_impact 1-2 s -17 LUFS\n// tank_hit 1-2 s -16 LUFS\n// big_explosion 2.5-4 s -14 LUFS\n// tank_destroyed 3-5 s -18 LUFS\n// victory 3-4 s -18 LUFS\n// defeat 2.5-4 s -19 LUFS\n// Tanques LIVE (lives, shield, destructibles): life_lost, respawn, shield_loop (loop),\n// shield_end, health_pickup, crate_break, barrel_explode, wall_hit, last_life\n// optional: turn_start, your_turn, timer_warning (short UI cues, ~-22 LUFS)\n//\n// Gating: the games' shared mute/volume (connect4Sounds) applies through the\n// manager; the GLOBAL chat mute (isSoundEnabled) and a hidden page silence\n// every play and stop all loops.\n\nimport { createSoundManager } from '../../../audio/createSoundManager.js';\nimport { connect4Sounds } from '../../connect4/connect4Sounds.js';\nimport { chatSoundUrl } from '../../../assets/chatAssets.js';\nimport { isSoundEnabled, subscribeSoundPreference } from '../../../notifications/chatSounds.js';\nimport { outcomeToCues, sceneEventToCues, TANKS_LOOPS } from './cues.js';\n\nexport { outcomeToCues, sceneEventToCues } from './cues.js';\n\nexport const TANKS_SOUND_NAMES = [\n 'engine_start', 'engine_loop', 'tracks_loop', 'turret_loop', 'cannon_fire', 'projectile_whistle',\n 'terrain_impact', 'tank_hit', 'big_explosion', 'tank_destroyed', 'victory', 'defeat',\n 'turn_start', 'your_turn', 'timer_warning',\n 'life_lost', 'respawn', 'shield_loop', 'shield_end', 'health_pickup', 'crate_break', 'barrel_explode', 'wall_hit', 'last_life',\n];\n\n// Relative mix, set from the delivered files' measured loudness (blasts ~-16 LUFS,\n// impacts/stingers ~-20, loops -23..-25) so weapons lead and the engine sits under them.\nconst LEVELS = {\n engine_start: 0.6, engine_loop: 0.45, tracks_loop: 0.5, turret_loop: 0.5, cannon_fire: 0.8,\n projectile_whistle: 0.6, terrain_impact: 0.85, tank_hit: 0.85, big_explosion: 0.9, tank_destroyed: 1,\n victory: 0.8, defeat: 0.8, turn_start: 0.35, your_turn: 0.4, timer_warning: 0.35,\n life_lost: 0.8, respawn: 0.7, shield_loop: 0.4, shield_end: 0.55, health_pickup: 0.6, crate_break: 0.75,\n barrel_explode: 0.9, wall_hit: 0.6, last_life: 0.75,\n};\n\n// Sounds shipped in assets/sounds/tanks/ (the UI cues are optional and not delivered).\nexport const DELIVERED_TANKS_SOUNDS = [\n 'engine_start', 'engine_loop', 'tracks_loop', 'turret_loop', 'cannon_fire', 'projectile_whistle',\n 'terrain_impact', 'tank_hit', 'big_explosion', 'tank_destroyed', 'victory', 'defeat',\n 'life_lost', 'respawn', 'shield_loop', 'shield_end', 'health_pickup', 'crate_break', 'barrel_explode', 'wall_hit', 'last_life',\n];\n// The same sound within this window (cluster bomblets, impact + blast in one frame) plays once.\nconst RETRIGGER_MS = 120;\n// Short ramps so loops follow the animation without clicks (defaults are ambient-slow).\nconst LOOP_RAMPS = {\n engine_loop: { fadeIn: 0.5, fadeOut: 0.35 },\n tracks_loop: { fadeIn: 0.12, fadeOut: 0.2 },\n turret_loop: { fadeIn: 0.06, fadeOut: 0.12 },\n shield_loop: { fadeIn: 0.15, fadeOut: 0.25 },\n};\n// MP3 decoders pad both ends; trimming that keeps the Safari loops gapless.\nconst MP3_LOOP_TRIM = 0.03;\n// tank_destroyed is the cinematic destruction sound: big_explosion yields to it.\nconst YIELDS_TO = { tank_destroyed: { name: 'big_explosion', ms: 1500 } };\n\nconst supportsOgg = () => {\n try {\n return typeof Audio !== 'undefined' && new Audio().canPlayType('audio/ogg; codecs=\"vorbis\"') !== '';\n } catch {\n return false;\n }\n};\n\n// Shared by reference with the manager, so configure() still applies to files\n// not fetched yet.\nconst files = {};\nconst fileFor = (name, extension) => `${name}.${String(extension).replace(/^\\./, '')}`;\n\nlet configured = false;\nlet format = 'ogg';\n/**\n * Call before first use to change the format ('auto' | 'ogg' | 'mp3'), the delivered\n * names, or override files ({ name: 'file.ext' | null }).\n */\nexport function configureTanksSounds({ extension = 'auto', available = DELIVERED_TANKS_SOUNDS, files: overrides } = {}) {\n configured = true;\n format = extension === 'auto' ? (supportsOgg() ? 'ogg' : 'mp3') : extension;\n TANKS_SOUND_NAMES.forEach((name) => {\n if (available.includes(name)) files[name] = fileFor(name, format);\n else delete files[name];\n });\n Object.entries(overrides || {}).forEach(([name, file]) => {\n if (file) files[name] = String(file);\n else delete files[name];\n });\n}\n\nlet manager = null;\nexport function getTanksSoundManager() {\n if (!configured) configureTanksSounds();\n if (!manager) {\n manager = createSoundManager({\n id: 'tanks',\n baseUrl: () => chatSoundUrl('tanks'), // resolved lazily at fetch time\n settingsFrom: connect4Sounds, // one mute/volume preference for every chat game\n sounds: files,\n levels: LEVELS,\n });\n }\n return manager;\n}\n\nconst hidden = () => typeof document !== 'undefined' && document.hidden;\nconst canPlay = () => isSoundEnabled() && !hidden();\n\n// Loops the game currently wants; they only sound while canPlay().\nconst wantedLoops = new Set();\nconst syncLoops = () => {\n if (!manager) return;\n const allowed = canPlay();\n new Set([...TANKS_LOOPS, ...wantedLoops]).forEach((name) => {\n if (allowed && wantedLoops.has(name)) manager.startLoop(name, { ...LOOP_RAMPS[name], trim: format === 'mp3' ? MP3_LOOP_TRIM : 0 });\n else manager.stopLoop(name);\n });\n};\n\nlet started = false;\nlet unsubscribePreference = null;\n\n/** Idempotent: starts the manager, preloads files and links mute/visibility. */\nexport function startTanksSounds() {\n const sounds = getTanksSoundManager();\n sounds.preload();\n if (started) return;\n started = true;\n unsubscribePreference = subscribeSoundPreference(syncLoops);\n if (typeof document !== 'undefined') document.addEventListener('visibilitychange', syncLoops);\n}\n\n/** Stops loops and unlinks listeners (the manager restarts on next use). */\nexport function disposeTanksSounds() {\n wantedLoops.clear();\n syncLoops();\n if (unsubscribePreference) { unsubscribePreference(); unsubscribePreference = null; }\n if (typeof document !== 'undefined') document.removeEventListener('visibilitychange', syncLoops);\n started = false;\n manager?.dispose();\n}\n\nconst lastPlayed = new Map();\nconst suppressedUntil = new Map();\n\n/** Silences `name` for `ms` (e.g. a turn whose destruction already has its own sound). */\nexport function suppressTanksCue(name, ms) {\n suppressedUntil.set(name, Math.max(suppressedUntil.get(name) ?? 0, Date.now() + ms));\n}\n\n/** One-shot cue, deduplicated by key when given. Returns true when scheduled. */\nexport function playTanksCue(name, key) {\n if (!configured) configureTanksSounds();\n if (Date.now() < (suppressedUntil.get(name) ?? 0)) return false;\n if (!canPlay()) {\n // Keep keyed cues from replaying once the page/sound comes back.\n if (key != null) getTanksSoundManager().markPlayed(name, key);\n return false;\n }\n const now = Date.now();\n if (now - (lastPlayed.get(name) ?? 0) < RETRIGGER_MS) return false;\n const played = getTanksSoundManager().play(name, key != null ? { key } : undefined);\n if (played) {\n lastPlayed.set(name, now);\n if (YIELDS_TO[name]) suppressTanksCue(YIELDS_TO[name].name, YIELDS_TO[name].ms);\n }\n return played;\n}\n\nexport function startTanksLoop(name) {\n wantedLoops.add(name);\n getTanksSoundManager();\n syncLoops();\n}\n\nexport function stopTanksLoop(name) {\n wantedLoops.delete(name);\n manager?.stopLoop(name);\n}\n\nexport function stopAllTanksLoops() {\n const names = [...TANKS_LOOPS, ...wantedLoops];\n wantedLoops.clear();\n names.forEach((name) => manager?.stopLoop(name));\n}\n\nconst runCues = (cues, key) => cues.forEach(({ name, action }) => {\n if (action === 'loop_start') startTanksLoop(name);\n else if (action === 'loop_stop') stopTanksLoop(name);\n else playTanksCue(name, key != null ? `${key}:${name}` : undefined);\n});\n\n/** Maps a scene onEvent ({ type, kind?, tankId? }) to sounds. `key` dedupes one-shots (e.g. turn id). */\nexport function handleSceneEvent(event, key) {\n const suffix = event?.tankId != null ? `:${event.tankId}` : '';\n runCues(sceneEventToCues(event), key != null ? `${key}${suffix}` : undefined);\n}\n\n/** 'victory' | 'defeat': stops every loop and plays the outcome once per key. */\nexport function playOutcome(result, key) {\n runCues(outcomeToCues(result), key);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tanksSounds-DTnidbiq.js","names":["chatSoundUrl","isSoundEnabled","subscribeSoundPreference","createSoundManager","connect4Sounds","TANKS_LOOPS","play","loopStart","loopStop","IMPACT_SOUNDS","sceneEventToCues","event","name","outcomeToCues","result","TANKS_SOUND_NAMES","LEVELS","DELIVERED_TANKS_SOUNDS","RETRIGGER_MS","LOOP_RAMPS","MP3_LOOP_TRIM","YIELDS_TO","supportsOgg","files","fileFor","extension","configured","format","configureTanksSounds","overrides","available","file","manager","getTanksSoundManager","hidden","canPlay","wantedLoops","syncLoops","allowed","started","startTanksSounds","lastPlayed","suppressedUntil","suppressTanksCue","ms","playTanksCue","key","now","played","startTanksLoop","stopTanksLoop","stopAllTanksLoops","names","runCues","cues","action","handleSceneEvent","suffix","playOutcome"],"sources":["../../src/games/tanks/sound/cues.js","../../src/games/tanks/sound/tanksSounds.js"],"sourcesContent":["// Pure sound choreography for Tanks (no audio, no DOM): maps scene events to\n// one-shot plays and loop start/stop actions.\n\nexport const TANKS_LOOPS = ['engine_loop', 'tracks_loop', 'turret_loop'];\n\nconst play = (name) => ({ name, action: 'play' });\nconst loopStart = (name) => ({ name, action: 'loop_start' });\nconst loopStop = (name) => ({ name, action: 'loop_stop' });\n\nconst IMPACT_SOUNDS = { terrain: 'terrain_impact', obstacle: 'terrain_impact', ground: 'terrain_impact' };\n\n/** Scene onEvent ({ type, ... } or a bare type string) → ordered cues. */\nexport function sceneEventToCues(event) {\n const type = typeof event === 'string' ? event : event?.type;\n switch (type) {\n case 'engine_start': return [play('engine_start')];\n case 'move_start': return [loopStart('engine_loop'), loopStart('tracks_loop')];\n case 'move_end': return [loopStop('tracks_loop'), loopStop('engine_loop')];\n case 'turret_start': return [loopStart('turret_loop')];\n case 'turret_end': return [loopStop('turret_loop')];\n case 'fire': return [play('cannon_fire')];\n case 'projectile_start': return [play('projectile_whistle')];\n case 'impact': {\n const name = IMPACT_SOUNDS[event?.kind];\n return name ? [play(name)] : [];\n }\n case 'tank_hit': return [play('tank_hit')];\n case 'big_explosion': return [play('big_explosion')];\n case 'destroyed': return [play('tank_destroyed')];\n default: return [];\n }\n}\n\n/** 'victory' | 'defeat' → cues; anything else (draw, unknown) stays silent. */\nexport function outcomeToCues(result) {\n if (result === 'victory' || result === 'defeat') return [...TANKS_LOOPS.map(loopStop), play(result)];\n return [];\n}\n","// Tanks (3D) sound layer.\n//\n// Expected files (host serves them from <assets>/sounds/tanks/, i.e. the\n// package's assets/sounds/tanks/), each as .ogg and .mp3: OGG Vorbis is used where\n// the browser supports it, MP3 otherwise. Only names listed in `available` are\n// fetched, so sounds not delivered (the optional UI cues) cost no requests and never error.\n// Format: 44.1 kHz, mono. True peak <= -1 dBTP; loops cut at zero crossings so\n// they repeat without clicks.\n//\n// name duration loudness\n// engine_start 1.5-2.5 s -20 LUFS\n// engine_loop 2-4 s (loop) -24 LUFS\n// tracks_loop 1-2 s (loop) -24 LUFS\n// turret_loop 1-2 s (loop) -26 LUFS\n// cannon_fire 1.5-2.5 s -16 LUFS\n// projectile_whistle 1.5-3 s -22 LUFS\n// terrain_impact 1-2 s -17 LUFS\n// tank_hit 1-2 s -16 LUFS\n// big_explosion 2.5-4 s -14 LUFS\n// tank_destroyed 3-5 s -18 LUFS\n// victory 3-4 s -18 LUFS\n// defeat 2.5-4 s -19 LUFS\n// Tanques LIVE (lives, shield, destructibles): life_lost, respawn, shield_loop (loop),\n// shield_end, health_pickup, crate_break, barrel_explode, wall_hit, last_life\n// optional: turn_start, your_turn, timer_warning (short UI cues, ~-22 LUFS)\n//\n// Gating: the games' shared mute/volume (connect4Sounds) applies through the\n// manager; the GLOBAL chat mute (isSoundEnabled) and a hidden page silence\n// every play and stop all loops.\n\nimport { createSoundManager } from '../../../audio/createSoundManager.js';\nimport { connect4Sounds } from '../../connect4/connect4Sounds.js';\nimport { chatSoundUrl } from '../../../assets/chatAssets.js';\nimport { isSoundEnabled, subscribeSoundPreference } from '../../../notifications/chatSounds.js';\nimport { outcomeToCues, sceneEventToCues, TANKS_LOOPS } from './cues.js';\n\nexport { outcomeToCues, sceneEventToCues } from './cues.js';\n\nexport const TANKS_SOUND_NAMES = [\n 'engine_start', 'engine_loop', 'tracks_loop', 'turret_loop', 'cannon_fire', 'projectile_whistle',\n 'terrain_impact', 'tank_hit', 'big_explosion', 'tank_destroyed', 'victory', 'defeat',\n 'turn_start', 'your_turn', 'timer_warning',\n 'life_lost', 'respawn', 'shield_loop', 'shield_end', 'health_pickup', 'crate_break', 'barrel_explode', 'wall_hit', 'last_life',\n];\n\n// Relative mix, set from the delivered files' measured loudness (blasts ~-16 LUFS,\n// impacts/stingers ~-20, loops -23..-25) so weapons lead and the engine sits under them.\nconst LEVELS = {\n engine_start: 0.6, engine_loop: 0.45, tracks_loop: 0.5, turret_loop: 0.5, cannon_fire: 0.8,\n projectile_whistle: 0.6, terrain_impact: 0.85, tank_hit: 0.85, big_explosion: 0.9, tank_destroyed: 1,\n victory: 0.8, defeat: 0.8, turn_start: 0.35, your_turn: 0.4, timer_warning: 0.35,\n life_lost: 0.8, respawn: 0.7, shield_loop: 0.4, shield_end: 0.55, health_pickup: 0.6, crate_break: 0.75,\n barrel_explode: 0.9, wall_hit: 0.6, last_life: 0.75,\n};\n\n// Sounds shipped in assets/sounds/tanks/ (the UI cues are optional and not delivered).\nexport const DELIVERED_TANKS_SOUNDS = [\n 'engine_start', 'engine_loop', 'tracks_loop', 'turret_loop', 'cannon_fire', 'projectile_whistle',\n 'terrain_impact', 'tank_hit', 'big_explosion', 'tank_destroyed', 'victory', 'defeat',\n 'life_lost', 'respawn', 'shield_loop', 'shield_end', 'health_pickup', 'crate_break', 'barrel_explode', 'wall_hit', 'last_life',\n];\n// The same sound within this window (cluster bomblets, impact + blast in one frame) plays once.\nconst RETRIGGER_MS = 120;\n// Short ramps so loops follow the animation without clicks (defaults are ambient-slow).\nconst LOOP_RAMPS = {\n engine_loop: { fadeIn: 0.5, fadeOut: 0.35 },\n tracks_loop: { fadeIn: 0.12, fadeOut: 0.2 },\n turret_loop: { fadeIn: 0.06, fadeOut: 0.12 },\n shield_loop: { fadeIn: 0.15, fadeOut: 0.25 },\n};\n// MP3 decoders pad both ends; trimming that keeps the Safari loops gapless.\nconst MP3_LOOP_TRIM = 0.03;\n// tank_destroyed is the cinematic destruction sound: big_explosion yields to it.\nconst YIELDS_TO = { tank_destroyed: { name: 'big_explosion', ms: 1500 } };\n\nconst supportsOgg = () => {\n try {\n return typeof Audio !== 'undefined' && new Audio().canPlayType('audio/ogg; codecs=\"vorbis\"') !== '';\n } catch {\n return false;\n }\n};\n\n// Shared by reference with the manager, so configure() still applies to files\n// not fetched yet.\nconst files = {};\nconst fileFor = (name, extension) => `${name}.${String(extension).replace(/^\\./, '')}`;\n\nlet configured = false;\nlet format = 'ogg';\n/**\n * Call before first use to change the format ('auto' | 'ogg' | 'mp3'), the delivered\n * names, or override files ({ name: 'file.ext' | null }).\n */\nexport function configureTanksSounds({ extension = 'auto', available = DELIVERED_TANKS_SOUNDS, files: overrides } = {}) {\n configured = true;\n format = extension === 'auto' ? (supportsOgg() ? 'ogg' : 'mp3') : extension;\n TANKS_SOUND_NAMES.forEach((name) => {\n if (available.includes(name)) files[name] = fileFor(name, format);\n else delete files[name];\n });\n Object.entries(overrides || {}).forEach(([name, file]) => {\n if (file) files[name] = String(file);\n else delete files[name];\n });\n}\n\nlet manager = null;\nexport function getTanksSoundManager() {\n if (!configured) configureTanksSounds();\n if (!manager) {\n manager = createSoundManager({\n id: 'tanks',\n baseUrl: () => chatSoundUrl('tanks'), // resolved lazily at fetch time\n settingsFrom: connect4Sounds, // one mute/volume preference for every chat game\n sounds: files,\n levels: LEVELS,\n });\n }\n return manager;\n}\n\nconst hidden = () => typeof document !== 'undefined' && document.hidden;\nconst canPlay = () => isSoundEnabled() && !hidden();\n\n// Loops the game currently wants; they only sound while canPlay().\nconst wantedLoops = new Set();\nconst syncLoops = () => {\n if (!manager) return;\n const allowed = canPlay();\n new Set([...TANKS_LOOPS, ...wantedLoops]).forEach((name) => {\n if (allowed && wantedLoops.has(name)) manager.startLoop(name, { ...LOOP_RAMPS[name], trim: format === 'mp3' ? MP3_LOOP_TRIM : 0 });\n else manager.stopLoop(name);\n });\n};\n\nlet started = false;\nlet unsubscribePreference = null;\n\n/** Idempotent: starts the manager, preloads files and links mute/visibility. */\nexport function startTanksSounds() {\n const sounds = getTanksSoundManager();\n sounds.preload();\n if (started) return;\n started = true;\n unsubscribePreference = subscribeSoundPreference(syncLoops);\n if (typeof document !== 'undefined') document.addEventListener('visibilitychange', syncLoops);\n}\n\n/** Stops loops and unlinks listeners (the manager restarts on next use). */\nexport function disposeTanksSounds() {\n wantedLoops.clear();\n syncLoops();\n if (unsubscribePreference) { unsubscribePreference(); unsubscribePreference = null; }\n if (typeof document !== 'undefined') document.removeEventListener('visibilitychange', syncLoops);\n started = false;\n manager?.dispose();\n}\n\nconst lastPlayed = new Map();\nconst suppressedUntil = new Map();\n\n/** Silences `name` for `ms` (e.g. a turn whose destruction already has its own sound). */\nexport function suppressTanksCue(name, ms) {\n suppressedUntil.set(name, Math.max(suppressedUntil.get(name) ?? 0, Date.now() + ms));\n}\n\n/** One-shot cue, deduplicated by key when given. Returns true when scheduled. */\nexport function playTanksCue(name, key) {\n if (!configured) configureTanksSounds();\n if (Date.now() < (suppressedUntil.get(name) ?? 0)) return false;\n if (!canPlay()) {\n // Keep keyed cues from replaying once the page/sound comes back.\n if (key != null) getTanksSoundManager().markPlayed(name, key);\n return false;\n }\n const now = Date.now();\n if (now - (lastPlayed.get(name) ?? 0) < RETRIGGER_MS) return false;\n const played = getTanksSoundManager().play(name, key != null ? { key } : undefined);\n if (played) {\n lastPlayed.set(name, now);\n if (YIELDS_TO[name]) suppressTanksCue(YIELDS_TO[name].name, YIELDS_TO[name].ms);\n }\n return played;\n}\n\nexport function startTanksLoop(name) {\n wantedLoops.add(name);\n getTanksSoundManager();\n syncLoops();\n}\n\nexport function stopTanksLoop(name) {\n wantedLoops.delete(name);\n manager?.stopLoop(name);\n}\n\nexport function stopAllTanksLoops() {\n const names = [...TANKS_LOOPS, ...wantedLoops];\n wantedLoops.clear();\n names.forEach((name) => manager?.stopLoop(name));\n}\n\nconst runCues = (cues, key) => cues.forEach(({ name, action }) => {\n if (action === 'loop_start') startTanksLoop(name);\n else if (action === 'loop_stop') stopTanksLoop(name);\n else playTanksCue(name, key != null ? `${key}:${name}` : undefined);\n});\n\n/** Maps a scene onEvent ({ type, kind?, tankId? }) to sounds. `key` dedupes one-shots (e.g. turn id). */\nexport function handleSceneEvent(event, key) {\n const suffix = event?.tankId != null ? `:${event.tankId}` : '';\n runCues(sceneEventToCues(event), key != null ? `${key}${suffix}` : undefined);\n}\n\n/** 'victory' | 'defeat': stops every loop and plays the outcome once per key. */\nexport function playOutcome(result, key) {\n runCues(outcomeToCues(result), key);\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { _ as e, a as t, g as n, h as r, i, n as a, r as o, t as s, v as c } from "./chunks/games-BvYTWgaR.js";
1
+ import { _ as e, a as t, g as n, h as r, i, k as a, n as o, r as s, t as c } from "./chunks/games-Bl_8raG6.js";
2
2
  import { a as l, c as u, i as d, n as f, o as p, s as m, t as h } from "./chunks/createPeerLink-DBVs_yvQ.js";
3
- import { a as g, i as _, n as v, o as y, r as b, s as x, t as S } from "./chunks/ChatContext-DQtKsR6Z.js";
3
+ import { a as g, i as _, n as v, o as y, r as b, s as x, t as S } from "./chunks/ChatContext-CVW58bzC.js";
4
4
  import { i as C, n as w, r as T } from "./chunks/timeline-BLBedCYj.js";
5
5
  import { n as E, r as D, t as O } from "./chunks/connectionStore-DwgIUl30.js";
6
6
  import { a as k, c as A, l as j, n as M, o as ee, r as N, s as P, t as te } from "./chunks/gameStatus-BChd29yI.js";
7
- import { i as ne, n as re, o as F, r as ie, t as ae } from "./chunks/connect4Sounds-DmD-E9kX.js";
7
+ import { i as ne, n as re, o as F, r as ie, t as ae } from "./chunks/connect4Sounds-BqEHULjv.js";
8
8
  import { t as I } from "./chunks/signalFaults-Dv2YjjKy.js";
9
9
  import { Component as L, Suspense as R, createContext as oe, lazy as se, memo as z, useCallback as B, useContext as V, useEffect as H, useId as ce, useMemo as U, useRef as W, useState as G, useSyncExternalStore as K } from "react";
10
10
  import { createStore as le } from "zustand/vanilla";
@@ -657,15 +657,15 @@ var Un = (e, t) => Ln?.scope === e && String(Ln.room) === String(t) && Ln.open &
657
657
  function Kn() {
658
658
  Fn.forEach((e) => e.close()), Fn.clear(), Ln = null;
659
659
  }
660
- async function qn(e, { scope: t, room: n, id: r, onClick: i, connectedAt: a, isCurrent: o }) {
661
- let s = zn();
662
- if (!s.supported || !s.enabled || s.permission !== "granted" || n == null || !r) return;
660
+ async function qn(e, { scope: t, room: n, id: r, onClick: i, connectedAt: o, isCurrent: s }) {
661
+ let c = zn();
662
+ if (!c.supported || !c.enabled || c.permission !== "granted" || n == null || !r) return;
663
663
  let l = Date.parse(e.timestamp);
664
- if (!Number.isFinite(l) || l < a || e.localOnly || e.optimistic || e.is_history || e.history) return;
664
+ if (!Number.isFinite(l) || l < o || e.localOnly || e.optimistic || e.is_history || e.history) return;
665
665
  let u = `${t}:${r}`;
666
666
  if (Pn.has(u)) return;
667
667
  Pn.add(u), Pn.size > 500 && Pn.delete(Pn.values().next().value);
668
- let d = Un(t, n), f = c();
668
+ let d = Un(t, n), f = a();
669
669
  if (In.set(f, () => {
670
670
  d = !0;
671
671
  }), Nn?.postMessage({
@@ -673,7 +673,7 @@ async function qn(e, { scope: t, room: n, id: r, onClick: i, connectedAt: a, isC
673
673
  id: f,
674
674
  scope: t,
675
675
  room: n
676
- }), await Gn(150), In.delete(f), d || Un(t, n) || !o()) return;
676
+ }), await Gn(150), In.delete(f), d || Un(t, n) || !s()) return;
677
677
  let p = async () => {
678
678
  let r = `lira-chat-desktop-seen:${u}`;
679
679
  try {
@@ -684,16 +684,16 @@ async function qn(e, { scope: t, room: n, id: r, onClick: i, connectedAt: a, isC
684
684
  } catch {
685
685
  return;
686
686
  }
687
- if (!o() || !zn().enabled || Notification.permission !== "granted" || Un(t, n)) return;
688
- let a = Rn(Mn) && !String(n).startsWith("private") && !e.private && !e.sensitive, s = String(e.username || "Nuevo mensaje").replace(/\s+/g, " ").slice(0, 70), c = a ? String(e.message || e.text || "Archivo adjunto").replace(/\s+/g, " ").slice(0, 140) : "Tienes un nuevo mensaje en LIRA Chat";
687
+ if (!s() || !zn().enabled || Notification.permission !== "granted" || Un(t, n)) return;
688
+ let a = Rn(Mn) && !String(n).startsWith("private") && !e.private && !e.sensitive, o = String(e.username || "Nuevo mensaje").replace(/\s+/g, " ").slice(0, 70), c = a ? String(e.message || e.text || "Archivo adjunto").replace(/\s+/g, " ").slice(0, 140) : "Tienes un nuevo mensaje en LIRA Chat";
689
689
  try {
690
- let e = new Notification(a ? s : "LIRA Chat", {
690
+ let e = new Notification(a ? o : "LIRA Chat", {
691
691
  body: c,
692
692
  tag: u,
693
693
  silent: !0
694
694
  });
695
695
  Fn.add(e), e.onclose = () => Fn.delete(e), e.onclick = () => {
696
- e.close(), o() && (window.focus(), i());
696
+ e.close(), s() && (window.focus(), i());
697
697
  }, Nn?.postMessage({
698
698
  type: "shown",
699
699
  id: u
@@ -1299,13 +1299,13 @@ var jr = /* @__PURE__ */ new Map([
1299
1299
  function Mr(e, { volume: t = .4, onBlocked: n, onPlaying: r } = {}) {
1300
1300
  let i = jr.get(e);
1301
1301
  if (!i) return () => {};
1302
- let a, o = !1, c = !1, l = () => {
1303
- !o && !c && (c = !0, n?.());
1302
+ let a, o = !1, s = !1, l = () => {
1303
+ !o && !s && (s = !0, n?.());
1304
1304
  }, u = () => {
1305
1305
  o || r?.(a);
1306
1306
  };
1307
1307
  try {
1308
- a = new Audio(s(`effects/${i.file}`)), a.volume = Math.max(0, Math.min(1, (Number(t) || 0) * (i.level ?? 1))), a.preload = "auto", a.addEventListener("error", l), a.addEventListener("playing", u), a.play()?.catch(l);
1308
+ a = new Audio(c(`effects/${i.file}`)), a.volume = Math.max(0, Math.min(1, (Number(t) || 0) * (i.level ?? 1))), a.preload = "auto", a.addEventListener("error", l), a.addEventListener("playing", u), a.play()?.catch(l);
1309
1309
  } catch {
1310
1310
  l();
1311
1311
  }
@@ -1800,7 +1800,7 @@ function Zr({ clockRef: e, waitForAudio: t = !0 }) {
1800
1800
  }, y = (e) => {
1801
1801
  e && (c.add(e), e.onfinish = () => c.delete(e));
1802
1802
  };
1803
- import("./chunks/avalancheScene3d-Z5QyZIid.js").then(({ createAvalancheScene: e }) => {
1803
+ import("./chunks/avalancheScene3d-CIE2WKQn.js").then(({ createAvalancheScene: e }) => {
1804
1804
  d || (u = document.createElement("canvas"), u.className = "lira-avalanche-canvas", u.addEventListener("webglcontextlost", v), i.prepend(u), l = e(u), l.resize(i.clientWidth || 1, i.clientHeight || 1));
1805
1805
  }).catch(_);
1806
1806
  let b = (e) => {
@@ -5911,19 +5911,19 @@ function Is(e, t, n) {
5911
5911
  var Ls = {
5912
5912
  racing_live: {
5913
5913
  title: "Carreras LIVE 🏎️",
5914
- load: () => se(() => import("./chunks/RacingLiveGameCard-c1G7uoDI.js").then((e) => e.t))
5914
+ load: () => se(() => import("./chunks/RacingLiveGameCard-8j9QLnxW.js").then((e) => e.t))
5915
5915
  },
5916
5916
  battleship: {
5917
5917
  title: "Batalla Naval",
5918
- load: () => se(() => import("./chunks/BattleshipGameCard-B-B4r7lK.js"))
5918
+ load: () => se(() => import("./chunks/BattleshipGameCard-8H-sBCsv.js"))
5919
5919
  },
5920
5920
  tanks_live: {
5921
5921
  title: "Tanques LIVE 3D",
5922
- load: () => se(() => import("./chunks/TanksLiveGameCard-COr9Oay5.js").then((e) => e.t))
5922
+ load: () => se(() => import("./chunks/TanksLiveGameCard-D_27Jomp.js").then((e) => e.t))
5923
5923
  },
5924
5924
  tanks: {
5925
5925
  title: "Tanques de guerra",
5926
- load: () => se(() => import("./chunks/TanksGameCard-CvTaF7tu.js"))
5926
+ load: () => se(() => import("./chunks/TanksGameCard-DnCufSH6.js"))
5927
5927
  }
5928
5928
  }, Rs = {}, zs = (e) => (Rs[e] ?? (Rs[e] = Ls[e].load()), Rs[e]);
5929
5929
  function Bs({ title: e }) {
@@ -11362,7 +11362,7 @@ var Yu = 10485760, Xu = /* @__PURE__ */ new WeakMap(), Zu = (e) => (Xu.has(e) ||
11362
11362
  }), Xu.get(e));
11363
11363
  function Qu(e, t, n) {
11364
11364
  if (e?.readyState !== WebSocket.OPEN) return Promise.reject(/* @__PURE__ */ Error("Sin conexión"));
11365
- let r = Zu(e), i = c();
11365
+ let r = Zu(e), i = a();
11366
11366
  return new Promise((a, o) => {
11367
11367
  let s = setTimeout(() => {
11368
11368
  r.pending.delete(i), o(/* @__PURE__ */ Error("El servidor no confirmó el envío. Conservamos el borrador."));
@@ -11443,20 +11443,20 @@ async function nd(e, t, n, r = []) {
11443
11443
  }
11444
11444
  let r = n.file;
11445
11445
  if (!(r instanceof Blob) || !r.size || r.size > Yu) throw Error("El archivo debe pesar entre 1 byte y 10 MB.");
11446
- let a = c();
11447
- for (let i = 0, o = 0; i < r.size; i += 32768, o++) {
11446
+ let o = a();
11447
+ for (let i = 0, a = 0; i < r.size; i += 32768, a++) {
11448
11448
  let s = new Uint8Array(await r.slice(i, i + 32768).arrayBuffer()), c = btoa(String.fromCharCode(...s));
11449
11449
  await Qu(e, "CHAT_FILE", {
11450
- id: a,
11450
+ id: o,
11451
11451
  room_id: t,
11452
11452
  size: r.size,
11453
11453
  type: r.type || "application/octet-stream",
11454
11454
  name: n.name,
11455
- index: o,
11455
+ index: a,
11456
11456
  chunk: c
11457
11457
  });
11458
11458
  }
11459
- i.push({ id: a });
11459
+ i.push({ id: o });
11460
11460
  }
11461
11461
  await Qu(e, "CHAT_MESSAGE", {
11462
11462
  room_id: t,
@@ -11466,6 +11466,6 @@ async function nd(e, t, n, r = []) {
11466
11466
  }
11467
11467
  // src/net/webrtc/index.js
11468
11468
  var rd = se(() => import("./chunks/WebRtcLab-ClRSYt4E.js")), id = "0.1.0", ad = () => import("./chunks/BattleshipPrototype-CmQd5AUO.js");
11469
- export { Uu as ChatButton, S as ChatContext, Ju as ChatNotifications, Hu as ChatPage, ys as ChatPeopleContext, Vu as ChatWindow, bu as ChatWindowShell, Mt as DEFAULT_CONFIG, h as DEFAULT_ICE_SERVERS, pn as EDIT_PREFIX, kr as EFFECT_CATALOG, ri as EFFECT_PREFIX, gs as EmojiPicker, Pl as GifPicker, Mi as LiraChatProvider, Qn as MAX_CHAT_MESSAGES, d as MAX_SIGNAL_LENGTH, id as MINICODE_CHAT_VERSION, Es as MessageBubble, vu as MessageComposer, Ks as MessageList, mn as REACT_PREFIX, vn as STICKER_NAME_PREFIX, ru as StickerPicker, Ni as TRANSPORT_STATUSES, l as WEBRTC_PREFIX, rd as WebRtcLab, Fi as assertTransport, O as chatConnectionStore, i as chatGamesStore, Nu as chatUiStore, td as closeRelay, Vi as configureKlipy, $u as consumeRelayEvent, n as createChatSignaling, dr as createChatStore, f as createPeerLink, Gt as createStandaloneTransport, li as decodeEffect, p as decodeSignal, Cn as encodeEdit, ci as encodeEffect, wn as encodeReaction, m as encodeSignal, a as getChatAssetsBaseUrl, Ar as getChatEffect, kn as groupReactions, ed as hydrateRelayMessage, xn as isMessageAction, yn as isStickerAttachment, u as isWebrtcMessage, ad as loadBattleshipPreview, Rt as normalizeConfig, Pt as normalizeUser, ku as openChatWindow, Tn as parseMessageAction, Au as registerChatWorker, e as rtcSignals, nd as sendRelayMessage, o as setChatAssetsBaseUrl, E as setChatConnectionStatus, qu as startAppBadge, Eu as startChatApp, ne as startConnect4Sounds, Zn as startDesktopNotifications, ss as startEmojiPreferencesSync, Hc as startGifLibrarySync, fn as startUnreadStorageSync, nn as totalUnread, Zt as unreadScope, mr as useChatConfig, xr as useChatConnection, D as useChatConnectionStatus, v as useChatContext, t as useChatGames, wr as useChatIdentity, Du as useChatInstall, _r as useChatStore, vr as useChatStoreApi, hr as useChatTransport, Fu as useChatUi, dn as useChatUnread, Cr as useChatUnreadTotal, I as withSignalFaults };
11469
+ export { Uu as ChatButton, S as ChatContext, Ju as ChatNotifications, Hu as ChatPage, ys as ChatPeopleContext, Vu as ChatWindow, bu as ChatWindowShell, Mt as DEFAULT_CONFIG, h as DEFAULT_ICE_SERVERS, pn as EDIT_PREFIX, kr as EFFECT_CATALOG, ri as EFFECT_PREFIX, gs as EmojiPicker, Pl as GifPicker, Mi as LiraChatProvider, Qn as MAX_CHAT_MESSAGES, d as MAX_SIGNAL_LENGTH, id as MINICODE_CHAT_VERSION, Es as MessageBubble, vu as MessageComposer, Ks as MessageList, mn as REACT_PREFIX, vn as STICKER_NAME_PREFIX, ru as StickerPicker, Ni as TRANSPORT_STATUSES, l as WEBRTC_PREFIX, rd as WebRtcLab, Fi as assertTransport, O as chatConnectionStore, i as chatGamesStore, Nu as chatUiStore, td as closeRelay, Vi as configureKlipy, $u as consumeRelayEvent, n as createChatSignaling, dr as createChatStore, f as createPeerLink, Gt as createStandaloneTransport, li as decodeEffect, p as decodeSignal, Cn as encodeEdit, ci as encodeEffect, wn as encodeReaction, m as encodeSignal, o as getChatAssetsBaseUrl, Ar as getChatEffect, kn as groupReactions, ed as hydrateRelayMessage, xn as isMessageAction, yn as isStickerAttachment, u as isWebrtcMessage, ad as loadBattleshipPreview, Rt as normalizeConfig, Pt as normalizeUser, ku as openChatWindow, Tn as parseMessageAction, Au as registerChatWorker, e as rtcSignals, nd as sendRelayMessage, s as setChatAssetsBaseUrl, E as setChatConnectionStatus, qu as startAppBadge, Eu as startChatApp, ne as startConnect4Sounds, Zn as startDesktopNotifications, ss as startEmojiPreferencesSync, Hc as startGifLibrarySync, fn as startUnreadStorageSync, nn as totalUnread, Zt as unreadScope, mr as useChatConfig, xr as useChatConnection, D as useChatConnectionStatus, v as useChatContext, t as useChatGames, wr as useChatIdentity, Du as useChatInstall, _r as useChatStore, vr as useChatStoreApi, hr as useChatTransport, Fu as useChatUi, dn as useChatUnread, Cr as useChatUnreadTotal, I as withSignalFaults };
11470
11470
 
11471
11471
  //# sourceMappingURL=index.js.map