From 4db5c89f0a3b76b8f57b5a650578cd942415b452 Mon Sep 17 00:00:00 2001 From: Pandipipas <62224708+Pandipipas@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:52:16 +0100 Subject: [PATCH] Cache game titles for offline selector labels --- src/extension/game-assets.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/extension/game-assets.ts b/src/extension/game-assets.ts index f279ed4..32de4ba 100644 --- a/src/extension/game-assets.ts +++ b/src/extension/game-assets.ts @@ -6,6 +6,7 @@ import { nodecg } from './util/nodecg.js'; const CHARACTER_NAMES_FILE = 'fighting-characters.json'; const LOCAL_MANIFEST_FILE = 'manifest.json'; const GAME_TITLES_FILE = 'games.json'; +const CACHED_GAME_TITLES_FILE = 'games-cache.json'; type RemoteGame = { title: string; @@ -211,6 +212,26 @@ const fetchCustomGameTitles = async (): Promise> => { } }; +const loadCachedGameTitles = async (): Promise> => { + await ensureAssetsStorageReady(); + const cachePath = path.join(assetsRoot, CACHED_GAME_TITLES_FILE); + + try { + const raw = await readFile(cachePath, 'utf8'); + const parsed = JSON.parse(raw) as unknown; + return parseGameTitlesMap(parsed); + } catch { + return new Map(); + } +}; + +const saveCachedGameTitles = async (titles: Map) => { + await ensureAssetsStorageReady(); + const cachePath = path.join(assetsRoot, CACHED_GAME_TITLES_FILE); + const payload = Object.fromEntries([...titles.entries()].sort((left, right) => left[0].localeCompare(right[0]))); + await writeFile(cachePath, JSON.stringify(payload, null, 2)); +}; + const listRemoteGames = async (): Promise => { const baseUrl = getConfiguredAssetsBaseUrl(); const gamesIndexUrl = `${baseUrl}/games/`; @@ -275,10 +296,11 @@ const listInstalledGames = async () => { const listInstalledGamesAsRemote = async (): Promise => { const installedGames = await listInstalledGames(); + const cachedTitles = await loadCachedGameTitles(); return installedGames.map((slug) => ({ slug, repoFolder: slug, - title: titleFromSlug(slug), + title: cachedTitles.get(slug) ?? titleFromSlug(slug), logoFile: `${slug}.png`, })); }; @@ -388,6 +410,11 @@ nodecg.listenFor('scoreko-assets:listRemoteGames', async (_payload: unknown, ack try { const remoteGames = await listRemoteGames(); + const titlesToCache = new Map(); + remoteGames.forEach((game) => { + titlesToCache.set(game.slug, game.title); + }); + await saveCachedGameTitles(titlesToCache); ack(null, remoteGames); } catch (error) { try {