Arquitectura General - vykymoon/rpg-character-creator GitHub Wiki
La aplicación tiene dos estilos de organización que conviven, porque el proyecto creció en dos etapas:
- Corte 1 (creador de personajes): organización por patrón/función (
ui,builder,factory,singleton,prototype,dao,model). - Modo LAN: organización por capas hexagonales (
domain,application,adapters).
Vista general
flowchart TB
subgraph UI["ui/ (JavaFX)"]
Main[MainApp] --> Gallery[GalleryController]
Gallery --> Wizard[Step1..Step5 + WizardSession]
Gallery --> Template[TemplateGalleryController]
Gallery --> Play[PlayController]
Gallery --> GameApp[GameApp - LAN]
Play --> Battle[BattleController]
end
subgraph Core["Núcleo del creador"]
Builder[builder/CharacterBuilder]
Proto[prototype/CharacterPrototype]
Catalog[singleton/CatalogManager]
Factories[factory/*Factory]
Model[model/*]
DAO[dao/CharacterDAO]
end
subgraph Game["game/ (un jugador)"]
GPlayer[Player, GameMap, InputHandler, Command]
end
subgraph LAN["LAN (hexagonal)"]
Adapters[adapters/server + client]
App[application/GameSessionService]
Domain[domain/GameMap, MovementRules, PlayerState]
end
Wizard --> Builder --> Model
Wizard --> Catalog --> Factories --> JSON[(data/*.json)]
Gallery --> DAO --> Chars[(characters.json)]
Template --> Proto
Play --> GPlayer
GameApp -->|WebSocket| Adapters --> App --> Domain
GameApp -.lee.-> Chars
Paquetes (com.proyecto.rpg)
| Paquete | Responsabilidad |
|---|---|
ui |
Controladores JavaFX, navegación entre pantallas, carga de sprites, MainApp y GameApp |
model |
Entidades del dominio del creador: Character, Race, CharacterClass, Skill, Outfit y la regla CatalogRestriction |
builder |
CharacterBuilder: construcción paso a paso y validación |
prototype |
CharacterPrototype: plantillas de NPC clonables |
singleton |
CatalogManager: catálogo cacheado en memoria |
factory |
Factories que convierten los JSON del catálogo en objetos del modelo |
dao |
Persistencia: interfaz CharacterDAO e implementación JSON |
game |
Modo un jugador: movimiento continuo, comandos, zona de encuentro |
domain |
(LAN) Mapa por celdas, reglas de movimiento, estado de jugador |
application |
(LAN) GameSessionService, fuente de verdad del servidor |
adapters |
(LAN) Servidor y cliente WebSocket |
Nota: hay dos clases llamadas
GameMap.game.GameMap(modo un jugador) trabaja con píxeles (double);domain.GameMap(LAN) trabaja con celdas (int) y terreno. No comparten código.
Flujo de datos principal
CatalogManager(Singleton) carga los 4 catálogos JSON mediante las Factories.- El wizard lee el catálogo, filtra según raza/clase y acumula las elecciones en
WizardSession. - Al confirmar,
CharacterBuildervalida y construye elCharacter, yCharacterDAOlo guarda encharacters.json. - La galería lee los personajes con el DAO y permite verlos, eliminarlos, clonarlos o jugarlos.
- Jugar abre el modo un jugador con el
Characterelegido; Multijugador LAN leecharacters.jsonde forma independiente (CharacterLoader) y manda al servidor solo nombre, raza, clase e ítems.
Navegación entre pantallas
SceneNavigator.goTo(stage|event, fxmlPath, controller) carga un FXML, le asigna el controlador ya instanciado (con sus dependencias por constructor) y reemplaza la raíz de la escena. Por eso los controladores no declaran fx:controller en el FXML: se inyectan por código.
Decisiones de arquitectura destacadas
| Decisión | Motivo |
|---|---|
Catálogos en JSON en vez de enum + switch |
Agregar contenido sin recompilar (principio Abierto/Cerrado) |
CharacterDAO como interfaz |
Poder cambiar JSON por otro motor sin tocar la UI (Inversión de Dependencias) |
| Un controlador por paso del wizard | Responsabilidad única por pantalla |
| Servidor autoritativo en LAN (ADR-001) | Una sola fuente de verdad; los clientes no pueden decidir el estado |
| WebSocket + JSON | Protocolo simple, depurable y sin dependencias pesadas |
Más detalle en Patrones de Diseño y SOLID.