diff --git a/README.md b/README.md new file mode 100644 index 0000000..563abc7 --- /dev/null +++ b/README.md @@ -0,0 +1,198 @@ +# Project Afterlife + +Plataforma de preservacion de videojuegos con documentales interactivos. Servidores privados de juegos que ya no existen, acompanados de documentales narrativos que cuentan su historia. + +## Estado Actual + +| Servicio | Estado | Puerto | RAM | +|----------|--------|--------|-----| +| **Next.js 15** (frontend) | En linea | 3000 | ~111 MB | +| **Strapi 5** (CMS) | En linea | 1337 | ~179 MB | +| **PostgreSQL 16** | En linea | 5432 | ~57 MB | +| **MinIO** (almacenamiento) | En linea | 9000/9001 | ~144 MB | +| **OpenFusion** (FusionFall) | En linea | 23000-23001 | ~254 MB | +| **MapleStory 2 - World** | En linea | 21001 | ~126 MB | +| **MapleStory 2 - Login** | En linea | 20001 | ~100 MB | +| **MapleStory 2 - Web** | En linea | 4000 | ~70 MB | +| **MapleStory 2 - Game Ch0** | En linea | 20002/21002 | ~341 MB | +| **MapleStory 2 - MySQL** | En linea | 3307 | ~733 MB | +| **Minecraft FTB Infinity** | En linea | 25565 | ~3.5 GB | + +**Total**: ~5.6 GB RAM / 40 GB disponibles | 31 GB disco / 96 GB disponibles + +## Juegos Preservados + +### FusionFall (Cartoon Network Universe) +- **Emulador**: [OpenFusion](https://github.com/OpenFusionProject/OpenFusion) (C++) +- **Conexion**: `192.168.10.234:23000` +- **Cliente**: [FusionFall Retro Client](https://github.com/OpenFusionProject) +- **Documental**: "FusionFall: El Mundo Que No Queriamos Perder" (7 capitulos) + +### MapleStory 2 +- **Emulador**: [Maple2](https://github.com/MS2Community/Maple2) (C# .NET 8) +- **Conexion**: `192.168.10.234:20001` (Login Server) +- **Cliente**: MapleStory 2 Global Client + XML Patches +- **Documental**: "MapleStory 2: El Mundo Que Construimos Juntos" (7 capitulos) + +### Minecraft: FTB Infinity Evolved +- **Servidor**: [itzg/minecraft-server](https://github.com/itzg/docker-minecraft-server) (Java 8) +- **Conexion**: `192.168.10.234:25565` +- **Cliente**: FTB App o launcher compatible con FTB Infinity Evolved v3.1.0 +- **Modpack**: 175+ mods, Minecraft 1.7.10 + Forge 10.13.4.1614 + +## Arquitectura + +``` +project-afterlife/ +├── apps/ +│ ├── cms/ # Strapi 5 CMS (React 18) +│ └── web/ # Next.js 15 frontend (React 19) +├── packages/ +│ └── shared/ # Tipos TypeScript compartidos +├── servers/ +│ ├── openfusion/ # Servidor FusionFall (C++) +│ └── maple2/ # Servidor MapleStory 2 (C# .NET 8) +├── docker/ +│ ├── docker-compose.dev.yml # Stack local (web + CMS + juegos) +│ ├── docker-compose.maple2.yml # MapleStory 2 (separado) +│ ├── docker-compose.yml # Produccion (con Nginx + SSL) +│ └── nginx/ # Configuracion Nginx +├── docs/ # Documentacion del proyecto +└── .github/workflows/ # CI/CD deployment +``` + +### Stack Tecnologico + +| Componente | Tecnologia | Version | +|-----------|-----------|---------| +| Frontend | Next.js + TypeScript | 15.x | +| UI | Tailwind CSS | v4 | +| i18n | next-intl | 4.8.3 | +| CMS | Strapi | 5.36.0 | +| Base de datos (CMS) | PostgreSQL | 16 | +| Base de datos (MS2) | MySQL | 8.0 | +| Almacenamiento | MinIO (S3) | Latest | +| Audio | Howler.js | 2.2.4 | +| Animaciones | Framer Motion | 12.x | +| Monorepo | npm workspaces + Turborepo | - | +| CI/CD | GitHub Actions | - | +| Reverse Proxy | Nginx | Alpine | + +## Inicio Rapido + +### Requisitos +- Docker y Docker Compose v2+ +- 8 GB RAM minimo (16 GB recomendado con todos los servidores) +- 50 GB disco libre + +### 1. Clonar y configurar + +```bash +git clone https://git.consultoria-as.com/consultoria-as/project-afterlife.git +cd project-afterlife +``` + +### 2. Crear archivo de entorno + +```bash +cp docker/.env.example docker/.env +# Editar docker/.env con las claves necesarias +``` + +Variables requeridas en `docker/.env`: +```env +# Base de datos +DATABASE_NAME=afterlife +DATABASE_USERNAME=afterlife +DATABASE_PASSWORD=afterlife + +# MinIO +MINIO_ROOT_USER=afterlife +MINIO_ROOT_PASSWORD=afterlife123 + +# Strapi (generar con openssl rand -base64 32) +APP_KEYS= +API_TOKEN_SALT= +ADMIN_JWT_SECRET= +TRANSFER_TOKEN_SALT= +JWT_SECRET= + +# API Token (crear en Strapi Admin > Settings > API Tokens) +STRAPI_API_TOKEN= + +# Strapi URL publica +PUBLIC_STRAPI_URL=http://localhost:1337 + +# OpenFusion +OPENFUSION_SHARD_IP=192.168.10.234 +``` + +### 3. Levantar servicios base + +```bash +cd docker + +# Stack principal (CMS + Web + OpenFusion + Minecraft FTB) +docker compose -f docker-compose.dev.yml up -d + +# MapleStory 2 (requiere setup previo, ver docs/game-servers.md) +docker compose -f docker-compose.maple2.yml up -d +``` + +### 4. Setup inicial de Strapi + +1. Abrir http://localhost:1337/admin +2. Crear usuario administrador +3. Ir a Settings > API Tokens > Create new API Token +4. Tipo: Full access, copiar el token a `STRAPI_API_TOKEN` en `.env` +5. Reiniciar el servicio web: `docker compose -f docker-compose.dev.yml restart web` + +### 5. Verificar + +- **Frontend**: http://localhost:3000 +- **CMS Admin**: http://localhost:1337/admin +- **MinIO Console**: http://localhost:9001 + +## Documentacion Completa + +| Documento | Descripcion | +|-----------|------------| +| [README.md](README.md) | Este archivo — vision general y estado | +| [docs/architecture.md](docs/architecture.md) | Arquitectura tecnica detallada | +| [docs/game-servers.md](docs/game-servers.md) | Setup y operacion de servidores de juegos | +| [docs/cms-content.md](docs/cms-content.md) | Modelo de contenido CMS y documentales | +| [docs/deployment.md](docs/deployment.md) | Guia de despliegue a produccion | +| [docs/plans/](docs/plans/) | Documentos de diseno e implementacion | + +## Rutas de la Web + +| Ruta | Descripcion | +|------|------------| +| `/es` o `/en` | Pagina principal con hero y ultimos juegos | +| `/es/catalog` | Catalogo de juegos con filtros | +| `/es/about` | Sobre el proyecto | +| `/es/donate` | Pagina de donaciones | +| `/es/games/[slug]` | Pagina individual de juego | +| `/es/games/[slug]/documentary` | Documental interactivo | + +## Contenido en Base de Datos + +### Juegos +| Slug | Titulo | Estado | Documental | +|------|--------|--------|------------| +| `fusionfall` | FusionFall | Online | 7 capitulos | +| `maplestory2` | MapleStory 2 | Online | 7 capitulos | +| `minecraft-ftb-infinity` | Minecraft: FTB Infinity Evolved | Online | Pendiente | + +### Documentales +| Juego | Titulo | Capitulos | +|-------|--------|-----------| +| FusionFall | "El Mundo Que No Queriamos Perder" | 7 | +| MapleStory 2 | "El Mundo Que Construimos Juntos" | 7 | + +Cada documental tiene sus 7 capitulos publicados en ambos idiomas (ES/EN). + +## Licencia + +Proyecto privado. Todos los derechos reservados. +Los emuladores de juegos utilizados son proyectos open-source independientes con sus propias licencias. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..3460753 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,161 @@ +# Arquitectura Tecnica + +## Vision General + +Project Afterlife es un monorepo que combina una plataforma web de preservacion de videojuegos con los servidores de los juegos preservados. La infraestructura se gestiona completamente con Docker Compose. + +## Diagrama de Servicios + +``` + ┌─────────────────────────────────────┐ + │ USUARIO / CLIENTE │ + └───────────┬───────────┬─────────────┘ + │ │ + ┌───────────▼───┐ ┌─────▼─────────────┐ + │ Next.js :3000│ │ Clientes de juegos │ + └───────┬───────┘ └──┬──────┬─────┬───┘ + │ │ │ │ + ┌───────▼───────┐ │ │ │ + │ Strapi :1337 │ │ │ │ + └───┬───────┬───┘ │ │ │ + │ │ │ │ │ + ┌───────▼──┐ ┌──▼────┐ │ │ │ + │ PG :5432 │ │ MinIO │ │ │ │ + │ │ │ :9000 │ │ │ │ + └──────────┘ └───────┘ │ │ │ + │ │ │ + ┌──────────────────────────────┘ │ │ + │ │ │ + ┌───────▼──────────┐ ┌──────────────────┐ │ │ + │ OpenFusion │ │ MapleStory 2 │ │ │ + │ :23000-23001 │ │ Login :20001 │ │ │ + └──────────────────┘ │ World :21001 │ │ │ + │ Game :20002 │ │ │ + │ Web :4000 │ │ │ + │ MySQL :3307 │ │ │ + └──────────────────┘ │ │ + │ │ + ┌──────────────────────▼─┐ │ + │ Minecraft FTB :25565 │ │ + └────────────────────────┘ │ + │ + (Juegos futuros...) ◄──┘ +``` + +## Componentes + +### Frontend (Next.js 15) + +**Ubicacion**: `apps/web/` + +- **Framework**: Next.js 15 con App Router +- **React**: 19 (forzado via `overrides` en root `package.json`) +- **Estilos**: Tailwind CSS v4 con `@tailwindcss/postcss` +- **i18n**: next-intl con prefijo de ruta (`/es/`, `/en/`) +- **Audio**: Howler.js para reproductor de documentales +- **Animaciones**: Framer Motion + +**Estructura de rutas**: +``` +src/app/ +├── layout.tsx # Pass-through (return children) +├── globals.css # Tailwind v4 imports +├── not-found.tsx # 404 page +└── [locale]/ + ├── layout.tsx # , , providers + ├── page.tsx # Home + ├── about/page.tsx # About + ├── catalog/page.tsx # Game catalog + ├── donate/page.tsx # Donations + └── games/ + └── [slug]/ + ├── page.tsx # Game detail + └── documentary/page.tsx # Interactive documentary +``` + +**Patron de layout**: El root `layout.tsx` es un pass-through que solo retorna `children`. El layout real con ``, ``, y `NextIntlClientProvider` esta en `[locale]/layout.tsx`. Esto es necesario para que next-intl funcione correctamente con el App Router. + +### CMS (Strapi 5) + +**Ubicacion**: `apps/cms/` + +- **Version**: Strapi 5.36.0 +- **Base de datos**: PostgreSQL 16 +- **Almacenamiento**: MinIO (compatible con S3) +- **React**: 18 (admin panel, separado del frontend) +- **i18n**: Plugin nativo con locales ES/EN + +**Content Types**: +- `Game` — Entrada de juego con metadata, screenshots, estado del servidor +- `Documentary` — Documental con titulo, descripcion, relacion 1:1 con Game +- `Chapter` — Capitulo con contenido rich text, audio opcional, orden + +**Nota sobre schemas**: Los archivos `schema.json` de Strapi 5 deben copiarse manualmente al directorio `dist/` durante el build. El Dockerfile del CMS incluye este fix. + +### Tipos Compartidos + +**Ubicacion**: `packages/shared/` + +Paquete TypeScript puro (`@afterlife/shared`) con las interfaces compartidas entre web y CMS: + +```typescript +// Game, Documentary, Chapter, StrapiMedia, StrapiResponse, etc. +``` + +### Base de Datos + +**PostgreSQL 16** para el CMS: +- 44 tablas (contenido + sistema Strapi) +- Modelo i18n: cada contenido tiene filas separadas por locale (en/es) y estado (draft/published) +- Relaciones via tablas `_lnk` (e.g., `games_documentary_lnk`) + +**MySQL 8.0** para MapleStory 2: +- Dos databases: `maple-data` (datos del juego, read-only) y `game-server` (datos de jugadores) +- Puerto 3307 para evitar conflicto con PostgreSQL 5432 + +### Almacenamiento (MinIO) + +MinIO corre como servicio S3-compatible para almacenar: +- Imagenes de portada de juegos +- Screenshots +- Archivos de audio para documentales +- Cualquier otro media subido al CMS + +**Puertos**: 9000 (API), 9001 (consola web) + +## Docker Compose: Tres Archivos + +| Archivo | Proposito | Servicios | +|---------|----------|-----------| +| `docker-compose.dev.yml` | Desarrollo local | PG, MinIO, CMS, Web, OpenFusion, Minecraft FTB | +| `docker-compose.maple2.yml` | MapleStory 2 | MySQL, World, Login, Game, Web, File-Ingest | +| `docker-compose.yml` | Produccion | PG, MinIO, CMS, Web, Nginx, Certbot | + +MapleStory 2 tiene su propio compose porque son 6 servicios (demasiados para mezclar con el stack principal) y requiere su propia base de datos MySQL. + +## Red Docker + +Todos los servicios del mismo archivo compose comparten una red Docker implicita. Los servicios se referencian entre si por nombre de servicio (e.g., `cms` desde `web`, `maple2-mysql` desde `maple2-world`). + +Las variables de entorno como `DB_IP`, `GRPC_WORLD_IP` se configuran en cada servicio para apuntar al nombre de contenedor correcto dentro de la red Docker. + +## CI/CD + +**GitHub Actions** (`.github/workflows/deploy.yml`): +1. Push a `main` dispara el deploy +2. SSH al VPS +3. Pull, build, restart de servicios Docker + +## Decisiones Arquitectonicas + +### React 19 vs 18 +El monorepo tiene dos versiones de React: 19 para Next.js (web) y 18 para Strapi (admin). Resuelto con `overrides` en el root `package.json` que solo afecta al workspace de web. El CMS corre en su propio contenedor Docker con sus propias dependencias. + +### Tailwind v4 +Usa la nueva sintaxis `@import "tailwindcss"` en `globals.css` con el plugin `@tailwindcss/postcss`. No hay `tailwind.config.js`. + +### i18n con Strapi 5 +Strapi 5 maneja i18n con filas separadas por locale y un `document_id` compartido. Cada documento tiene 4 filas: draft EN, draft ES, published EN, published ES. Las relaciones (`_lnk`) conectan las filas del mismo estado/locale. + +### Servidores de juegos separados +Los servidores de juegos no son parte del build del monorepo. Son proyectos externos (OpenFusion en C++, Maple2 en C#) que se clonan en `servers/` y se ejecutan via Docker. El `.gitignore` excluye `servers/maple2/` (14 GB de datos de cliente) y los binarios de OpenFusion. diff --git a/docs/cms-content.md b/docs/cms-content.md new file mode 100644 index 0000000..719e476 --- /dev/null +++ b/docs/cms-content.md @@ -0,0 +1,145 @@ +# Modelo de Contenido CMS + +## Strapi 5 — Content Types + +### Game + +Entrada principal de cada juego preservado. + +| Campo | Tipo | Requerido | Localizado | Descripcion | +|-------|------|-----------|------------|-------------| +| title | string | si | si | Nombre del juego | +| slug | uid | si | no | URL-friendly, auto-generado desde title | +| description | richtext | no | si | Descripcion larga del juego | +| genre | enum | si | no | MMORPG, FPS, Casual, Strategy, Sports, Other | +| releaseYear | integer | si | no | Ano de lanzamiento original | +| shutdownYear | integer | si | no | Ano de cierre de servidores | +| developer | string | si | no | Estudio desarrollador | +| publisher | string | no | no | Publisher/distribuidor | +| screenshots | media[] | no | no | Capturas de pantalla (solo imagenes) | +| coverImage | media | si | no | Imagen de portada principal | +| serverStatus | enum | no | no | online, maintenance, coming_soon (default) | +| serverLink | string | no | no | IP:puerto para conectarse | +| documentary | relation | no | no | oneToOne con Documentary | + +### Documentary + +Documental interactivo asociado a un juego. + +| Campo | Tipo | Requerido | Localizado | Descripcion | +|-------|------|-----------|------------|-------------| +| title | string | si | si | Titulo del documental | +| description | text | no | si | Descripcion/subtitulo | +| game | relation | no | no | oneToOne con Game | +| chapters | relation | no | no | oneToMany con Chapter (ordenados) | + +### Chapter + +Capitulo individual de un documental. + +| Campo | Tipo | Requerido | Localizado | Descripcion | +|-------|------|-----------|------------|-------------| +| title | string | si | si | Titulo del capitulo | +| content | richtext | si | si | Contenido narrativo completo | +| audioFile | media | no | no | Archivo de audio (narracion) | +| audioDuration | integer | no | no | Duracion en segundos | +| order | integer | si | no | Orden de aparicion (1, 2, 3...) | +| coverImage | media | no | no | Imagen de portada del capitulo | +| documentary | relation | no | no | manyToOne con Documentary | + +## Modelo i18n de Strapi 5 + +Strapi 5 maneja la internacionalizacion con **filas separadas por locale**. Cada documento tiene un `document_id` compartido y multiples filas: + +``` +document_id: "abc123" +├── id: 1 (locale: en, draft) +├── id: 2 (locale: en, published) +├── id: 3 (locale: es, draft) +└── id: 4 (locale: es, published) +``` + +Las **relaciones** (`_lnk` tables) conectan las filas del mismo estado. Un juego publicado en ES se conecta al documental publicado en ES, no al draft ni al EN. + +### Tablas de enlace +- `games_documentary_lnk` — game_id ↔ documentary_id +- `chapters_documentary_lnk` — chapter_id ↔ documentary_id + chapter_ord + +## Contenido Actual + +### Juegos (3) +| Slug | document_id | Titulo | Genre | Release | Shutdown | Server | +|------|-------------|--------|-------|---------|----------|--------| +| fusionfall | sx17hshy2d... | FusionFall | MMORPG | 2009 | 2013 | online | +| maplestory2 | ms2maple2d... | MapleStory 2 | MMORPG | 2015 | 2020 | online | +| minecraft-ftb-infinity | mcftbinfd... | Minecraft: FTB Infinity Evolved | Sandbox | 2011 | - | online | + +### Documentales (2) + +#### FusionFall: "El Mundo Que No Queriamos Perder" +| # | Titulo | Contenido | +|---|--------|-----------| +| 1 | El Sueno Imposible | Origenes, Cartoon Network, Grigon Entertainment | +| 2 | Cuando los Mundos Colisionaron | Desarrollo, motor Unity, estilo anime de Midori Foo | +| 3 | Bienvenido al Futuro | Lanzamiento, viajes en el tiempo, sistema de Nanos | +| 4 | La Caida de Grigon | Quiebra del estudio, CN asume el desarrollo | +| 5 | La Academia | Free-to-play, The Academy, Adventure Time | +| 6 | Seis Dias | Cierre con 6 dias de aviso, agosto 2013 | +| 7 | Afterlife | Comunidad, FusionFall Retro/Legacy, OpenFusion | + +#### MapleStory 2: "El Mundo Que Construimos Juntos" +| # | Titulo | Contenido | +|---|--------|-----------| +| 1 | El Siguiente Nivel | De MapleStory 1 a la vision 3D de NSquare | +| 2 | Un Mundo de Cubos y Color | Arte voxel, UGC, musica, housing | +| 3 | El Amanecer Coreano | Lanzamiento Korea julio 2015, primeros problemas | +| 4 | La Conquista Global | Lanzamiento global octubre 2018, hype de Twitch | +| 5 | La Tormenta Perfecta | Declive: RNG, limites semanales, exodo | +| 6 | El Ultimo Despertar | Expansion Awakening, demasiado tarde | +| 7 | Afterlife | Cierre mayo 2020, emulador MS2Community | + +## Crear Contenido Nuevo + +### Via Strapi Admin (recomendado) +1. Ir a http://localhost:1337/admin +2. Content Manager > Game / Documentary / Chapter +3. Crear en un idioma, luego usar "Localization" para traducir + +### Via PostgreSQL (insercion directa) +Cuando la API de Strapi tiene restricciones de permisos, se puede insertar directamente en PostgreSQL. Cada contenido necesita 4 filas: + +```sql +-- Draft EN +INSERT INTO games (document_id, title, slug, ..., locale) +VALUES ('unique_doc_id', 'Title', 'slug', ..., 'en'); + +-- Draft ES +INSERT INTO games (document_id, title, slug, ..., locale) +VALUES ('unique_doc_id', 'Titulo', 'slug', ..., 'es'); + +-- Published EN (con published_at) +INSERT INTO games (document_id, title, slug, ..., published_at, locale) +VALUES ('unique_doc_id', 'Title', 'slug', ..., NOW(), 'en'); + +-- Published ES (con published_at) +INSERT INTO games (document_id, title, slug, ..., published_at, locale) +VALUES ('unique_doc_id', 'Titulo', 'slug', ..., NOW(), 'es'); +``` + +Para documentales, ademas de los inserts hay que crear las relaciones en las tablas `_lnk`: +```sql +INSERT INTO games_documentary_lnk (game_id, documentary_id) VALUES (game_id, doc_id); +INSERT INTO chapters_documentary_lnk (chapter_id, documentary_id, chapter_ord) VALUES (ch_id, doc_id, 1); +``` + +## API Endpoints + +La API de Strapi se consume desde Next.js via funciones en `apps/web/src/lib/api.ts`: + +| Funcion | Descripcion | +|---------|------------| +| `getGames(locale)` | Lista todos los juegos con portada | +| `getGameBySlug(slug, locale)` | Juego con documental y capitulos | +| `getDocumentaryByGameSlug(slug, locale)` | Documental completo de un juego | + +Todas las llamadas requieren el header `Authorization: Bearer `. diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..069b8a2 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,194 @@ +# Guia de Despliegue + +## Entornos + +| Entorno | Compose File | Servicios | +|---------|-------------|-----------| +| **Desarrollo local** | `docker-compose.dev.yml` + `docker-compose.maple2.yml` | Todos | +| **Produccion** | `docker-compose.yml` | Web + CMS + DB + Nginx + SSL | + +## Desarrollo Local + +### Requisitos +- Docker Engine 24+ +- Docker Compose v2+ +- 8 GB RAM minimo (16 GB con todos los servidores de juegos) +- 50 GB disco libre + +### Levantar todo + +```bash +cd docker/ + +# 1. Stack principal +docker compose -f docker-compose.dev.yml up -d + +# 2. MapleStory 2 (requiere setup previo, ver game-servers.md) +docker compose -f docker-compose.maple2.yml up -d + +# 3. Verificar +docker ps +``` + +### Puertos en uso +| Puerto | Servicio | +|--------|---------| +| 3000 | Next.js (frontend) | +| 1337 | Strapi (CMS admin) | +| 5432 | PostgreSQL | +| 9000 | MinIO API | +| 9001 | MinIO Console | +| 23000-23001 | OpenFusion | +| 20001 | MapleStory 2 Login | +| 21001 | MapleStory 2 World | +| 20002 | MapleStory 2 Game | +| 21002 | MapleStory 2 Game gRPC | +| 3307 | MySQL (MapleStory 2) | +| 4000 | MapleStory 2 Web | +| 25565 | Minecraft FTB | + +### Detener servicios +```bash +docker compose -f docker-compose.dev.yml down +docker compose -f docker-compose.maple2.yml down +``` + +### Reconstruir imagenes +```bash +docker compose -f docker-compose.dev.yml build --no-cache +docker compose -f docker-compose.maple2.yml build --no-cache +``` + +## Produccion + +### Archivo: docker-compose.yml + +El compose de produccion incluye: +- **Nginx** como reverse proxy (puertos 80/443) +- **Certbot** para certificados SSL Let's Encrypt +- Sin servidores de juegos (se configuran aparte segun el VPS) + +### Variables de entorno requeridas + +```env +# Base de datos +DATABASE_NAME=afterlife +DATABASE_USERNAME=afterlife +DATABASE_PASSWORD= + +# MinIO +MINIO_ROOT_USER=afterlife +MINIO_ROOT_PASSWORD= + +# Strapi keys (generar con: openssl rand -base64 32) +APP_KEYS=,,, +API_TOKEN_SALT= +ADMIN_JWT_SECRET= +TRANSFER_TOKEN_SALT= +JWT_SECRET= + +# API +STRAPI_API_TOKEN= +PUBLIC_STRAPI_URL=https://tu-dominio.com + +# Domain +DOMAIN=tu-dominio.com +``` + +### Deploy manual al VPS + +```bash +# En el VPS +cd /opt/project-afterlife +git pull origin main +docker compose build +docker compose up -d +``` + +### CI/CD Automatico + +El archivo `.github/workflows/deploy.yml` automatiza el deploy: + +1. **Trigger**: Push a `main` +2. **Accion**: SSH al VPS, pull, build, restart + +**Secrets de GitHub requeridos**: +- `VPS_HOST` — Hostname o IP del VPS +- `VPS_USER` — Usuario SSH +- `VPS_SSH_KEY` — Llave privada SSH + +### SSL con Certbot + +```bash +# Primera vez: obtener certificado +docker compose run --rm certbot certonly \ + --webroot --webroot-path=/var/www/certbot \ + -d tu-dominio.com + +# Renovacion automatica (cron) +0 0 * * * docker compose run --rm certbot renew +``` + +## Backups + +### Base de datos CMS (PostgreSQL) +```bash +# Exportar +docker exec docker-postgres-1 pg_dump -U afterlife afterlife > backup_$(date +%Y%m%d).sql + +# Importar +cat backup.sql | docker exec -i docker-postgres-1 psql -U afterlife afterlife +``` + +### Base de datos MapleStory 2 (MySQL) +```bash +# Exportar +docker exec maple2-db mysqldump -u root -pmaplestory --databases maple-data game-server > backup_ms2_$(date +%Y%m%d).sql + +# Importar +cat backup_ms2.sql | docker exec -i maple2-db mysql -u root -pmaplestory +``` + +### Mundo de Minecraft +```bash +# Exportar +docker cp minecraft-ftb:/data/world ./backup_mc_world_$(date +%Y%m%d)/ + +# Importar +docker cp ./backup_mc_world/ minecraft-ftb:/data/world +docker restart minecraft-ftb +``` + +### Volumenes Docker (completo) +```bash +# Listar volumenes +docker volume ls | grep afterlife + +# Backup de un volumen +docker run --rm -v docker_postgres_data:/data -v $(pwd):/backup \ + alpine tar czf /backup/postgres_data.tar.gz -C /data . +``` + +## Monitoreo + +### Estado de contenedores +```bash +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" +``` + +### Uso de recursos +```bash +docker stats --no-stream +``` + +### Logs en tiempo real +```bash +docker logs -f --tail 50 +``` + +### Health checks +PostgreSQL y MySQL tienen healthchecks configurados en los compose files. Verificar con: +```bash +docker inspect --format='{{.State.Health.Status}}' docker-postgres-1 +docker inspect --format='{{.State.Health.Status}}' maple2-db +``` diff --git a/docs/game-servers.md b/docs/game-servers.md new file mode 100644 index 0000000..d1c507e --- /dev/null +++ b/docs/game-servers.md @@ -0,0 +1,233 @@ +# Servidores de Juegos + +Guia de setup, operacion y troubleshooting de cada servidor de juegos. + +## OpenFusion (FusionFall) + +### Resumen +| Dato | Valor | +|------|-------| +| Emulador | [OpenFusion](https://github.com/OpenFusionProject/OpenFusion) | +| Lenguaje | C++ | +| Puerto | 23000 (login), 23001 (shard) | +| Base de datos | SQLite (embebida) | +| RAM | ~254 MB | + +### Archivos +``` +servers/openfusion/ +├── Dockerfile # Ubuntu 24.04, copia binario + config +├── docker-entrypoint.sh # Genera config.ini desde env vars +├── config.ini # Configuracion del servidor +├── fusion # Binario compilado (no en git) +├── sql/ # Migraciones SQLite +└── tdata/ # Datos del juego (NPCs, mobs, drops) +``` + +### Configuracion +Variables de entorno en `docker-compose.dev.yml`: +- `OPENFUSION_SHARD_IP`: IP publica del servidor (default: 192.168.10.234) +- `OPENFUSION_MOTD`: Mensaje del dia + +### Conexion de cliente +1. Descargar el cliente FusionFall +2. Usar el launcher de OpenFusion apuntando a `192.168.10.234:23000` + +### Troubleshooting +- **"Connection refused"**: Verificar que el contenedor esta corriendo y los puertos estan mapeados +- **Datos de juego**: Los archivos `tdata/` contienen los NPCs, mobs y drops. Si faltan, el mundo estara vacio + +--- + +## MapleStory 2 + +### Resumen +| Dato | Valor | +|------|-------| +| Emulador | [Maple2](https://github.com/MS2Community/Maple2) | +| Lenguaje | C# / .NET 8 | +| Puertos | 20001 (login), 21001 (world), 20002/21002 (game), 4000 (web) | +| Base de datos | MySQL 8.0 (puerto 3307) | +| RAM total | ~1.4 GB (5 contenedores) | + +### Arquitectura Multi-Servicio +``` +maple2-mysql (3307) + │ + ├── maple2-world (21001) ← Coordinador central, gRPC + │ │ + │ ├── maple2-login (20001) ← Autenticacion, seleccion de personaje + │ │ + │ └── maple2-game-ch0 (20002/21002) ← Canal de juego + │ + └── maple2-web (4000) ← API web auxiliar +``` + +Los servidores se comunican entre si via **gRPC** (HTTP/2). El World server actua como coordinador central. Los Game servers se conectan al World al iniciar. + +### Setup Inicial (Primera Vez) + +#### 1. Clonar el repositorio +```bash +cd servers/ +git clone --recurse-submodules https://github.com/MS2Community/Maple2.git maple2 +``` + +#### 2. Descargar datos del cliente +Se necesita el cliente de MapleStory 2 (~14 GB). Los archivos se colocan en `servers/maple2/client-data/Data/`. + +Fuentes del cliente: +- [adventure-island-online-2 releases](https://github.com/shuabritze/adventure-island-online-2/releases) (6 partes ZIP) +- Extraer todo a `servers/maple2/client-data/` + +#### 3. Aplicar XML Patches +Descargar [MapleStory2-XML v1.2.1](https://github.com/MS2Community/MapleStory2-XML/releases/tag/v1.2.1) y copiar los archivos `Server.m2d`, `Server.m2h`, `Xml.m2d`, `Xml.m2h` a `servers/maple2/client-data/Data/` (reemplazar los originales). + +#### 4. Configurar .env +```bash +cp servers/maple2/.env.example servers/maple2/.env +# Editar con las IPs correctas: +# GAME_IP=192.168.10.234 +# LOGIN_IP=192.168.10.234 +``` + +#### 5. Verificar .dockerignore +El archivo `servers/maple2/.dockerignore` DEBE incluir: +``` +client-data +client-download +xml-patches +``` +Sin esto, el build de Docker intentara copiar 14 GB de datos al contexto. + +#### 6. Ingestar datos del juego +```bash +cd docker/ +docker compose -f docker-compose.maple2.yml up -d maple2-mysql +# Esperar a que MySQL este healthy +docker compose -f docker-compose.maple2.yml run --rm maple2-file-ingest \ + bash -c "cd /app && dotnet restore && cd Maple2.File.Ingest && dotnet run" +``` +Este proceso importa todos los datos del cliente a MySQL. Toma ~10 minutos. + +#### 7. Construir y levantar servidores +```bash +docker compose -f docker-compose.maple2.yml build +docker compose -f docker-compose.maple2.yml up -d +``` + +### Conexion de cliente +1. Tener el cliente de MapleStory 2 instalado +2. El cliente debe apuntar a `192.168.10.234:20001` (Login Server) +3. Las IPs se configuran en `servers/maple2/.env` (`GAME_IP`, `LOGIN_IP`) + +### Troubleshooting + +- **"No space left on device" al buildear**: Verificar `.dockerignore` incluye `client-data` +- **"Scripting/Scripts not found"**: Ya corregido — se removio la linea COPY del Dockerfile del Game server +- **"project.assets.json not found" en file-ingest**: Ejecutar `dotnet restore` antes de `dotnet run` +- **Servidores no se conectan entre si**: Verificar que `GRPC_WORLD_IP=maple2-world` y `GRPC_GAME_IP=maple2-game-ch0` estan configurados en el compose + +### Agregar mas canales de juego +Para agregar un segundo canal, duplicar el servicio `maple2-game-ch0` en el compose cambiando: +- Nombre: `maple2-game-ch1` +- Puertos: `20003:20003` y `21003:21003` +- `GRPC_GAME_IP: maple2-game-ch1` + +--- + +## Minecraft: FTB Infinity Evolved + +### Resumen +| Dato | Valor | +|------|-------| +| Imagen Docker | itzg/minecraft-server:java8 | +| Modpack | FTB Infinity Evolved v3.1.0 | +| Minecraft | 1.7.10 | +| Forge | 10.13.4.1614 | +| Puerto | 25565 | +| RAM | ~3.5 GB (6 GB JVM heap, 8 GB limite contenedor) | +| Mods | ~175 | + +### Configuracion +El servidor se configura via variables de entorno en `docker-compose.dev.yml`: + +```yaml +environment: + EULA: "TRUE" + TYPE: FTBA + FTB_MODPACK_ID: 23 + FTB_MODPACK_VERSION_ID: 99 + MEMORY: 6G + MAX_MEMORY: 6G + MOTD: "Project Afterlife - FTB Infinity Evolved" + DIFFICULTY: normal + MAX_PLAYERS: 20 + VIEW_DISTANCE: 10 + JVM_DD_OPTS: "fml.queryResult=confirm" + PRE_LAUNCH_CMD: "cp -n /data/minecraft_server.jar /data/minecraft_server.1.7.10.jar 2>/dev/null; true" +``` + +### Fix Conocido: Classpath de Forge 1.7.10 +El MANIFEST.MF del jar de Forge 1.7.10 referencia `minecraft_server.1.7.10.jar` en su Class-Path, pero la imagen itzg renombra el archivo a `minecraft_server.jar`. Sin el fix, Forge no encuentra log4j2 y crashea con `NoClassDefFoundError`. + +**Solucion**: El `PRE_LAUNCH_CMD` copia el archivo con el nombre correcto antes de cada inicio. Si recreas el volumen, este fix se aplica automaticamente. + +### Primer inicio +El primer inicio toma 5-10 minutos porque: +1. Descarga el FTB App installer +2. Descarga los ~175 mods del modpack +3. Instala Forge 10.13.4.1614 +4. Genera el mundo + +### Conexion de cliente +1. Instalar [FTB App](https://www.feed-the-beast.com/app), MultiMC, ATLauncher, o Prism Launcher +2. Instalar modpack **FTB Infinity Evolved** version 3.1.0 +3. Multiplayer > Add Server: `192.168.10.234:25565` + +### Modo Experto +Para activar el modo experto (recetas mas complejas): +``` +/ftb_mode set expert +``` +Ejecutar desde la consola del servidor o como operador in-game. + +### Troubleshooting +- **"NoClassDefFoundError: org/apache/logging/log4j/Level"**: El fix de classpath no se aplico. Ejecutar manualmente: `docker exec minecraft-ftb cp /data/minecraft_server.jar /data/minecraft_server.1.7.10.jar` y reiniciar +- **Server lag**: Reducir `VIEW_DISTANCE` de 10 a 8, o aumentar `MEMORY` si hay RAM disponible +- **Pastebin 403**: Error inocuo — Pastebin bloquea requests automaticos. Solo afecta a los badges de FTB Utilities, no a la funcionalidad del juego + +--- + +## Operaciones Comunes + +### Ver logs de un servidor +```bash +docker logs -f minecraft-ftb # Minecraft +docker logs -f maple2-world # MapleStory 2 World +docker logs -f docker-openfusion-1 # OpenFusion +``` + +### Reiniciar un servidor +```bash +docker restart minecraft-ftb +docker restart maple2-world maple2-login docker-maple2-game-ch0-1 +docker restart docker-openfusion-1 +``` + +### Ver uso de recursos +```bash +docker stats --no-stream +``` + +### Backup de datos +```bash +# PostgreSQL (CMS) +docker exec docker-postgres-1 pg_dump -U afterlife afterlife > backup_cms.sql + +# MySQL (MapleStory 2) +docker exec maple2-db mysqldump -u root -pmaplestory --databases maple-data game-server > backup_ms2.sql + +# Minecraft (mundo completo) +docker cp minecraft-ftb:/data/world ./backup_minecraft_world/ +```