Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
**/coverage
**/.env*
screenshots
frontend/public/maps_optimized
api
database
docs
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ jobs:
working-directory: frontend
run: pnpm exec tsc --noEmit

- name: Export optimized maps
working-directory: server
run: |
pnpm install --frozen-lockfile
pnpm export-frontend-maps

- name: Build
working-directory: frontend
env:
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ pnpm dev

Abrir `http://localhost:3000`.

Los mapas optimizados (`frontend/public/maps_optimized`) no están en git. Docker los genera al construir la imagen. Para un build de producción en local:

```bash
cd server
pnpm install
pnpm export-frontend-maps
```

## Arquitectura

| Componente | Carpeta | Puerto |
Expand Down
17 changes: 17 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ ENV PATH="$PNPM_HOME:$PATH"

RUN corepack enable

FROM base AS maps
WORKDIR /work/server

COPY server/src/mapNpcStorage.ts src/mapNpcStorage.ts
COPY server/src/scripts/exportFrontendOptimizedMaps.ts src/scripts/exportFrontendOptimizedMaps.ts
COPY server/mapas_source/ mapas_source/

RUN pnpm dlx tsx@4.22.1 src/scripts/exportFrontendOptimizedMaps.ts --output-dir=/maps_optimized \
&& test -f /maps_optimized/mapa_1.json \
&& SOURCE_COUNT="$(find mapas_source -mindepth 1 -maxdepth 1 -type d -name 'mapa_*' | wc -l)" \
&& OUTPUT_COUNT="$(find /maps_optimized -maxdepth 1 -type f -name 'mapa_*.json' | wc -l)" \
&& echo "Export check: ${SOURCE_COUNT} dirs en mapas_source, ${OUTPUT_COUNT} mapa_*.json" \
&& test "${SOURCE_COUNT}" -eq "${OUTPUT_COUNT}"

FROM base AS deps
WORKDIR /app/frontend

Expand Down Expand Up @@ -44,6 +58,9 @@ ENV GAME_DATA_ADMIN_PROXY_TOKEN=$GAME_DATA_ADMIN_PROXY_TOKEN

COPY packages/protocol /app/packages/protocol
COPY frontend .
RUN rm -rf ./public/maps_optimized
COPY --from=maps /maps_optimized ./public/maps_optimized
RUN node ./scripts/require-optimized-maps.mjs
RUN pnpm build

FROM base AS runtime
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"protocol:build": "pnpm exec tsc -p ../packages/protocol/tsconfig.json",
"predev": "pnpm run protocol:build",
"dev": "next dev --turbopack --hostname 0.0.0.0",
"prebuild": "pnpm run protocol:build",
"prebuild": "pnpm run protocol:build && node ./scripts/require-optimized-maps.mjs",
"check:maps": "node ./scripts/require-optimized-maps.mjs",
"build": "next build",
"start": "next start",
"lint": "eslint",
Expand Down
62 changes: 62 additions & 0 deletions frontend/scripts/require-optimized-maps.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import fs from "node:fs";
import path from "node:path";

const MAPS_DIR = path.resolve(process.cwd(), "public/maps_optimized");
const SAMPLE_NAME = "mapa_1.json";
const MAP_JSON_PATTERN = /^mapa_\d+\.json$/i;

function fail(message) {
console.error(message);
process.exit(1);
}

function isOptimizedMapShape(value) {
return (
Boolean(value) &&
typeof value === "object" &&
typeof value.id === "number" &&
typeof value.w === "number" &&
typeof value.h === "number" &&
Array.isArray(value.d)
);
}

if (!fs.existsSync(MAPS_DIR) || !fs.statSync(MAPS_DIR).isDirectory()) {
fail(
`No está ${MAPS_DIR}. Los mapas optimizados no van en git: generálos con \`cd server && pnpm export-frontend-maps\`. Docker los arma solo al construir la imagen.`,
);
}

const mapFiles = fs.readdirSync(MAPS_DIR).filter((name) => MAP_JSON_PATTERN.test(name));

if (mapFiles.length === 0) {
fail(
`La carpeta ${MAPS_DIR} no tiene ningún mapa_*.json. Corré \`cd server && pnpm export-frontend-maps\` antes del build de producción.`,
);
}

const samplePath = path.join(MAPS_DIR, SAMPLE_NAME);

if (!fs.existsSync(samplePath)) {
fail(
`Falta ${samplePath}. El export quedó incompleto: volvé a correr \`pnpm export-frontend-maps\` desde server/.`,
);
}

let sample;

try {
sample = JSON.parse(fs.readFileSync(samplePath, "utf8"));
} catch {
fail(
`${SAMPLE_NAME} no es JSON válido. El export salió mal; borralo y volvé a generar los mapas.`,
);
}

if (!isOptimizedMapShape(sample)) {
fail(
`${SAMPLE_NAME} no tiene la forma esperada ({ id: number, w: number, h: number, d: array }). El archivo no es un mapa optimizado válido.`,
);
}

console.log(`Mapas optimizados OK: ${mapFiles.length} archivos en ${MAPS_DIR}`);