diff --git a/frontend/src/components/BotList.svelte b/frontend/src/components/BotList.svelte index 7086e6a..50a19c2 100644 --- a/frontend/src/components/BotList.svelte +++ b/frontend/src/components/BotList.svelte @@ -32,6 +32,8 @@ let { orangePlayers = $bindable(), map, duplicateAgentIds = new Set(), + getLatestBotInfo, + getLatestScriptInfo, }: { bots: DraggablePlayer[]; scripts: ToggleableScript[]; @@ -43,6 +45,8 @@ let { orangePlayers: DraggablePlayer[]; map: string; duplicateAgentIds: Set; + getLatestBotInfo?: (tomlPath: string) => Promise; + getLatestScriptInfo?: (tomlPath: string) => Promise; } = $props(); const flipDurationMs = 100; @@ -250,14 +254,42 @@ function toggleScript(id: string) { enabledScripts[id] = !enabledScripts[id]; } -function handleBotInfoClick(bot: DraggablePlayer) { +async function handleBotInfoClick(bot: DraggablePlayer) { if (bot.info instanceof BotInfo) { + + try { + if (getLatestBotInfo) { + const refreshed = await getLatestBotInfo(bot.info.tomlPath); + if (refreshed) { + selectedAgent = [refreshed, refreshed.config?.settings?.name ?? bot.displayName, (refreshed as any).icon ?? bot.icon]; + showInfoModal = true; + return; + } + } + } catch (err) { + toast.error("Failed to get latest bot info: " + err, { duration: 10000 }); + } + selectedAgent = [bot.info, bot.displayName, bot.icon]; showInfoModal = true; } } -function handleScriptInfoClick(script: ToggleableScript) { +async function handleScriptInfoClick(script: ToggleableScript) { + + try { + if (getLatestScriptInfo) { + const refreshed = await getLatestScriptInfo(script.info.tomlPath); + if (refreshed) { + selectedAgent = [refreshed, refreshed.config?.settings?.name ?? script.displayName, (refreshed as any).icon ?? script.icon]; + showInfoModal = true; + return; + } + } + } catch (err) { + toast.error("Failed to get latest script info: " + err, { duration: 10000 }); + } + selectedAgent = [script.info, script.displayName, script.icon]; showInfoModal = true; } diff --git a/frontend/src/pages/Home.svelte b/frontend/src/pages/Home.svelte index 435f7bb..598367b 100644 --- a/frontend/src/pages/Home.svelte +++ b/frontend/src/pages/Home.svelte @@ -317,6 +317,79 @@ async function updateScripts() { loadingScripts = false; } +async function getLatestBotInfo(tomlPath: string): Promise { + try { + const result = await App.GetBots([tomlPath]); + + const found = result.find((b) => b.tomlPath === tomlPath); + if (!found) return null; // No bot found + + const botInfo = new BotInfo(found); + + const index = players.findIndex( + (p) => p.info instanceof BotInfo && p.info.tomlPath === tomlPath, + ); + + if (index !== -1) { + players[index] = { + ...players[index], + displayName: found.config.settings.name, + icon: found.icon, + info: botInfo, + tags: found.config.details.tags, + }; + + players = [...players]; + bluePlayers = updateTeam(bluePlayers); + orangePlayers = updateTeam(orangePlayers); + } + + return botInfo; + } catch (err) { + console.error("Failed to get latest bot info: ", err); + return null; + } +} + +async function getLatestScriptInfo(tomlPath: string): Promise { + try { + const result = await App.GetScripts([tomlPath]); + + const found = result.find((s) => s.tomlPath === tomlPath); + if (!found) return null; // No script found + + const index = scripts.findIndex((s) => s.info.tomlPath === tomlPath); + + if (index !== -1) { + const oldAgentId = scripts[index].info.config.settings.agentId; + const newAgentId = found.config.settings.agentId; + + scripts[index] = { + ...scripts[index], + displayName: found.config.settings.name, + icon: found.config.settings.logoFile, + info: found, + tags: found.config.details.tags, + }; + + scripts = [...scripts]; + + if (enabledScripts[newAgentId] === undefined) { + enabledScripts[newAgentId] = false; + } + + if (oldAgentId !== newAgentId && enabledScripts[oldAgentId] === undefined) { + enabledScripts[oldAgentId] = false; + } + } + + return found; + } catch (err) { + console.error("Failed to get latest script info: ", err); + return null; + } +} + $effect(() => { localStorage.setItem("BOT_SEARCH_PATHS", JSON.stringify(paths)); updateBots(); @@ -373,6 +446,28 @@ async function onMatchStart(randomizeMap: boolean) { ]; } + // Update bots and scripts + const botsInMatch = [ + ...new Set( + [...bluePlayers, ...orangePlayers] + .filter((p) => p.info instanceof BotInfo) + .map((p) => (p.info as BotInfo).tomlPath), + ), + ]; + + const scriptsInMatch = [ + ...new Set( + scripts // We could reuse this for StartMatchOptions, and not map twice + .filter((x) => enabledScripts[x.info.config.settings.agentId]) + .map((x) => x.info.tomlPath), + ), + ]; + + await Promise.all([ + ...botsInMatch.map((tomlPath) => getLatestBotInfo(tomlPath)), + ...scriptsInMatch.map((tomlPath) => getLatestScriptInfo(tomlPath)), + ]); + const options: StartMatchOptions = { map: $mapStore, gameMode: mode, @@ -476,6 +571,8 @@ function handleSearch(event: Event) { selectedTeam={selectedTeam} map={$mapStore} {duplicateAgentIds} + getLatestBotInfo={getLatestBotInfo} + getLatestScriptInfo={getLatestScriptInfo} />