diff --git a/README.md b/README.md index de0ec9f..7c5f029 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,45 @@ La descarga de assets usa **únicamente HTTP**. Debes configurar un servidor pro ```text games/ street-fighter-6/ + street-fighter-6.png manifest.json fighting-characters.json characters/... tekken-8/ + tekken-8.png manifest.json ... ``` +## Logos en servidor HTTP (sin logos locales en el bundle) + +La vista de "Game Assets" carga los logos directamente desde: + +```text +{assetsBaseUrl}/games/{repoFolder}/{logoFile} +``` + +Ejemplos: + +- `http://TU_SERVIDOR/games/street-fighter-6/street-fighter-6.png` +- `http://TU_SERVIDOR/games/tekken-8/tekken-8.png` + +### Cómo guardarlos en la carpeta HTTP + +1. Crea la carpeta del juego en tu web root (si no existe). +2. Copia el logo con el nombre esperado (`logoFile` de `src/shared/fighting-games.ts`). +3. Verifica desde navegador o `curl` que responde `200`. + +Ejemplo rápido en Linux (Nginx/Apache): + +```bash +sudo mkdir -p /var/www/assets/games/street-fighter-6 +sudo cp ./street-fighter-6.png /var/www/assets/games/street-fighter-6/street-fighter-6.png +curl -I http://TU_SERVIDOR/games/street-fighter-6/street-fighter-6.png +``` + +Opcional (recomendado): añade cache HTTP (`Cache-Control`, `ETag`) en tu servidor para que el navegador no los vuelva a descargar en cada visita. + 3. Cada `manifest.json` debe ser un array con rutas relativas, o con objetos `{ "path", "size", "url" }`. Ejemplo mínimo: @@ -67,4 +98,3 @@ Ejemplo mínimo: "characters/ryu.png" ] ``` - diff --git a/src/dashboard/scoreko-dev/stores/game-assets.ts b/src/dashboard/scoreko-dev/stores/game-assets.ts index 6d94023..1450ad8 100644 --- a/src/dashboard/scoreko-dev/stores/game-assets.ts +++ b/src/dashboard/scoreko-dev/stores/game-assets.ts @@ -28,6 +28,7 @@ export const useGameAssetsStore = defineStore('game-assets', () => { const loadingByTitle = ref>({}); const removingByTitle = ref>({}); const progressByTitle = ref>({}); + const assetsBaseUrl = ref('http://localhost'); if (!progressListenerAttached) { nodecg.listenFor('scoreko-assets:downloadProgress', (payload: unknown) => { @@ -63,6 +64,10 @@ export const useGameAssetsStore = defineStore('game-assets', () => { const refreshInstalledGames = async () => { const response = await sendNodecgMessage('scoreko-assets:listInstalled'); installedGames.value = Array.isArray(response) ? response : []; + const configResponse = await sendNodecgMessage<{ assetsBaseUrl?: string }>('scoreko-assets:getAssetsBaseUrl'); + assetsBaseUrl.value = typeof configResponse?.assetsBaseUrl === 'string' && configResponse.assetsBaseUrl.trim() + ? configResponse.assetsBaseUrl + : 'http://localhost'; await refreshCharacterNamesByGame(); return installedGames.value; }; @@ -124,6 +129,7 @@ export const useGameAssetsStore = defineStore('game-assets', () => { loadingByTitle, removingByTitle, progressByTitle, + assetsBaseUrl, refreshInstalledGames, refreshCharacterNamesByGame, downloadGame, diff --git a/src/dashboard/scoreko-dev/views/GameAssets.vue b/src/dashboard/scoreko-dev/views/GameAssets.vue index a41ff3d..ba5fbd1 100644 --- a/src/dashboard/scoreko-dev/views/GameAssets.vue +++ b/src/dashboard/scoreko-dev/views/GameAssets.vue @@ -8,13 +8,12 @@ const errorMessage = ref(''); const selectedGameSlug = ref(null); const search = ref(''); -const gameLogoModules = import.meta.glob('/src/shared/game-logos/*.png', { - eager: true, - import: 'default', - query: '?url', -}) as Record; - -const getGameLogoUrl = (logoFile: string) => gameLogoModules[`/src/shared/game-logos/${logoFile}`] ?? ''; +const getGameLogoUrl = (repoFolder: string, logoFile: string) => { + const cleanBaseUrl = gameAssetsStore.assetsBaseUrl.replace(/\/+$/, ''); + const cleanRepoFolder = repoFolder.replace(/^\/+|\/+$/g, ''); + const cleanLogoFile = logoFile.replace(/^\/+/, ''); + return `${cleanBaseUrl}/games/${cleanRepoFolder}/${cleanLogoFile}`; +}; const normalizedSearch = computed(() => search.value.trim().toLowerCase()); const filteredGames = computed(() => { @@ -109,7 +108,7 @@ onMounted(async () => { >
@@ -168,7 +167,7 @@ onMounted(async () => { style="min-width: 360px; max-width: 480px" > { + if (typeof ack !== 'function') { + return; + } + + try { + ack(null, { assetsBaseUrl: getConfiguredAssetsBaseUrl() }); + } catch (error) { + ack((error as Error).message); + } +}); + nodecg.listenFor('scoreko-assets:downloadGame', async (payload: unknown, ack) => { if (typeof ack !== 'function') { return;