Add data-driven architecture implementation plan
- Created DATA_DRIVEN_IMPLEMENTATION_PLAN.md with 8-phase roadmap - Architecture: ProcessEngine for data-driven systems (MC + WF compatible) - GameModule stays hardcoded, systems become JSON-configurable - Estimated timeline: 23 days (4-5 weeks) - Phases: ProcessEngine, Crafting, Combat, Events, Storage, Integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4fd540dde6
commit
9b19242a99
605
plans/DATA_DRIVEN_IMPLEMENTATION_PLAN.md
Normal file
605
plans/DATA_DRIVEN_IMPLEMENTATION_PLAN.md
Normal file
@ -0,0 +1,605 @@
|
||||
# Mobile Command - Data-Driven Implementation Plan
|
||||
|
||||
**Date**: 2 décembre 2025
|
||||
**Architecture**: Data-driven process engine (WarFactory-inspired)
|
||||
**Status**: Planning phase - Replacing hardcoded module logic
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Vision
|
||||
|
||||
Créer un système data-driven où:
|
||||
- **GameModule** reste hardcodé (state machine C++, orchestration)
|
||||
- **Systèmes de jeu** sont data-driven (crafting, combat, events définis en JSON)
|
||||
- **ProcessEngine** interprète et exécute les process JSON
|
||||
- **WarFactory compatibility** - Architecture réutilisable entre projets
|
||||
|
||||
---
|
||||
|
||||
## 📐 Architecture Cible
|
||||
|
||||
```
|
||||
GameModule.so (C++ hardcodé)
|
||||
├─ State machine (MainMenu → TrainBuilder → Expedition → Combat)
|
||||
├─ Appelle les systèmes via IIO pub/sub
|
||||
└─ Coordonne le flow du jeu
|
||||
|
||||
ProcessEngine (lib statique partagée)
|
||||
├─ Registry: "craft_recipe" → CraftProcessor
|
||||
├─ Registry: "resolve_combat" → CombatProcessor
|
||||
├─ Registry: "trigger_event" → EventProcessor
|
||||
└─ execute(process_type, params_json, state)
|
||||
|
||||
CraftingSystemModule.so (data-driven)
|
||||
├─ CraftingState (local)
|
||||
├─ Utilise ProcessEngine
|
||||
├─ Config: recipes.json
|
||||
└─ IIO: "craft:start" → publish "craft:complete"
|
||||
|
||||
CombatSystemModule.so (data-driven)
|
||||
├─ CombatState (local)
|
||||
├─ Utilise ProcessEngine
|
||||
├─ Config: combat_scenarios.json
|
||||
└─ IIO: "combat:start" → publish "combat:ended"
|
||||
|
||||
EventSystemModule.so (data-driven)
|
||||
├─ EventState (local)
|
||||
├─ Utilise ProcessEngine
|
||||
├─ Config: events.json
|
||||
└─ IIO: "event:check" → publish "event:triggered"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Structure du Projet
|
||||
|
||||
```
|
||||
project-mobile-command/
|
||||
├── src/
|
||||
│ ├── main.cpp # GroveEngine mainloop
|
||||
│ ├── process_engine/ # Core data-driven engine
|
||||
│ │ ├── ProcessEngine.h
|
||||
│ │ ├── ProcessEngine.cpp
|
||||
│ │ ├── IProcessor.h # Interface pour processors
|
||||
│ │ └── processors/ # Process implementations
|
||||
│ │ ├── CraftProcessor.cpp
|
||||
│ │ ├── CombatProcessor.cpp
|
||||
│ │ └── EventProcessor.cpp
|
||||
│ │
|
||||
│ └── modules/
|
||||
│ ├── GameModule.cpp # Orchestrator (hardcodé)
|
||||
│ │
|
||||
│ ├── systems/ # Data-driven systems
|
||||
│ │ ├── CraftingSystemModule.cpp
|
||||
│ │ ├── CombatSystemModule.cpp
|
||||
│ │ ├── EventSystemModule.cpp
|
||||
│ │ └── StorageSystemModule.cpp
|
||||
│ │
|
||||
│ └── mc_specific/ # MC-only modules
|
||||
│ ├── TrainBuilderModule.cpp
|
||||
│ └── ExpeditionModule.cpp
|
||||
│
|
||||
├── config/
|
||||
│ ├── game.json # GameModule config
|
||||
│ ├── systems/ # System definitions
|
||||
│ │ ├── crafting_recipes.json
|
||||
│ │ ├── combat_scenarios.json
|
||||
│ │ ├── events.json
|
||||
│ │ └── storage.json
|
||||
│ │
|
||||
│ └── mc_specific/ # MC-specific configs
|
||||
│ ├── train.json
|
||||
│ └── expeditions.json
|
||||
│
|
||||
└── tests/
|
||||
├── ProcessEngineTest.cpp
|
||||
├── CraftingSystemTest.cpp
|
||||
└── IntegrationTest.cpp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 1: ProcessEngine Foundation
|
||||
|
||||
**Objectif**: Créer le moteur générique qui interprète les process JSON
|
||||
|
||||
### Tasks
|
||||
|
||||
#### 1.1 ProcessEngine Core
|
||||
```cpp
|
||||
class ProcessEngine {
|
||||
public:
|
||||
using ProcessFunc = std::function<void(
|
||||
const IDataNode& params, // JSON config
|
||||
IDataNode& state, // Module state
|
||||
IIO* io // Pub/sub
|
||||
)>;
|
||||
|
||||
void registerProcess(const std::string& type, ProcessFunc func);
|
||||
void execute(const std::string& processType,
|
||||
const IDataNode& params,
|
||||
IDataNode& state,
|
||||
IIO* io);
|
||||
};
|
||||
```
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/process_engine/ProcessEngine.h`
|
||||
- [ ] `src/process_engine/ProcessEngine.cpp`
|
||||
- [ ] `src/process_engine/IProcessor.h` (interface commune)
|
||||
|
||||
**Tests**:
|
||||
- [ ] `tests/ProcessEngineTest.cpp`
|
||||
- [ ] Test registry (register/execute)
|
||||
- [ ] Test unknown process type handling
|
||||
|
||||
#### 1.2 CMake Integration
|
||||
- [ ] Créer lib statique `ProcessEngine`
|
||||
- [ ] Link dans chaque module data-driven
|
||||
- [ ] Headers publics exposés
|
||||
|
||||
**Durée estimée**: 1-2 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 2: Crafting System (Data-Driven)
|
||||
|
||||
**Objectif**: Premier système data-driven complet
|
||||
|
||||
### 2.1 CraftProcessor
|
||||
|
||||
**Logic**:
|
||||
```cpp
|
||||
void CraftProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) {
|
||||
// 1. Parse params (recipe_id, inputs, outputs, duration)
|
||||
// 2. Check inventory in state
|
||||
// 3. Consume inputs
|
||||
// 4. Add craft job to queue
|
||||
// 5. Publish "craft:started"
|
||||
}
|
||||
```
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/process_engine/processors/CraftProcessor.cpp`
|
||||
- [ ] `src/process_engine/processors/CraftProcessor.h`
|
||||
|
||||
### 2.2 CraftingSystemModule
|
||||
|
||||
**State**:
|
||||
```json
|
||||
{
|
||||
"inventory": {
|
||||
"scrap_metal": 100,
|
||||
"ammunition": 500
|
||||
},
|
||||
"craft_queue": [
|
||||
{"recipe": "repair_kit", "time_remaining": 25.3}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Config** (`config/systems/crafting_recipes.json`):
|
||||
```json
|
||||
{
|
||||
"recipes": {
|
||||
"repair_kit": {
|
||||
"process": "craft_recipe",
|
||||
"inputs": {"scrap_metal": 5, "electronics": 1},
|
||||
"outputs": {"repair_kit": 1},
|
||||
"duration": 30.0
|
||||
},
|
||||
"drone_recon": {
|
||||
"process": "craft_recipe",
|
||||
"inputs": {"drone_parts": 3, "electronics": 2},
|
||||
"outputs": {"drone_recon": 1},
|
||||
"duration": 120.0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Topics**:
|
||||
- Subscribe: `"craft:start"` → {recipe_id}
|
||||
- Publish: `"craft:started"` → {recipe_id, duration}
|
||||
- Publish: `"craft:complete"` → {recipe_id, outputs}
|
||||
- Publish: `"inventory:changed"` → {resource_id, delta, total}
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/modules/systems/CraftingSystemModule.cpp`
|
||||
- [ ] `src/modules/systems/CraftingSystemModule.h`
|
||||
- [ ] `config/systems/crafting_recipes.json`
|
||||
|
||||
**Tests**:
|
||||
- [ ] `tests/CraftingSystemTest.cpp`
|
||||
- [ ] Test craft avec resources suffisantes
|
||||
- [ ] Test craft avec resources insuffisantes
|
||||
- [ ] Test craft queue progression
|
||||
- [ ] Test hot-reload state preservation
|
||||
|
||||
**Durée estimée**: 2-3 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 3: Combat System (Data-Driven)
|
||||
|
||||
**Objectif**: Système de combat avec formules configurables
|
||||
|
||||
### 3.1 CombatProcessor
|
||||
|
||||
**Logic**:
|
||||
```cpp
|
||||
void CombatProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) {
|
||||
// 1. Parse scenario (enemy stats, formulas)
|
||||
// 2. Setup combatants
|
||||
// 3. Resolve rounds (hit calculation, damage, casualties)
|
||||
// 4. Determine outcome (victory/defeat)
|
||||
// 5. Publish "combat:ended" avec loot/casualties
|
||||
}
|
||||
```
|
||||
|
||||
**Config** (`config/systems/combat_scenarios.json`):
|
||||
```json
|
||||
{
|
||||
"scenarios": {
|
||||
"scavenger_ambush": {
|
||||
"process": "resolve_combat",
|
||||
"enemy": {
|
||||
"firepower": 30,
|
||||
"armor": 10,
|
||||
"morale": 60,
|
||||
"count": 8
|
||||
},
|
||||
"formulas": {
|
||||
"hit_chance": "accuracy * (1.0 - cover)",
|
||||
"damage": "max(0, firepower - armor * 0.5)",
|
||||
"morale_loss": "casualties / total * 100"
|
||||
},
|
||||
"loot": {
|
||||
"scrap_metal": {"min": 10, "max": 30},
|
||||
"ammunition": {"min": 20, "max": 100}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Formula Parser**:
|
||||
- [ ] Simple expression evaluator (pour prototype)
|
||||
- [ ] Variables: `accuracy`, `cover`, `firepower`, `armor`, etc.
|
||||
- [ ] Opérations: `+`, `-`, `*`, `/`, `max()`, `min()`
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/process_engine/processors/CombatProcessor.cpp`
|
||||
- [ ] `src/process_engine/FormulaEvaluator.h` (helper)
|
||||
- [ ] `src/modules/systems/CombatSystemModule.cpp`
|
||||
- [ ] `config/systems/combat_scenarios.json`
|
||||
|
||||
**Tests**:
|
||||
- [ ] Test formulas parsing
|
||||
- [ ] Test combat resolution
|
||||
- [ ] Test loot distribution
|
||||
- [ ] Test casualties
|
||||
|
||||
**Durée estimée**: 3-4 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 4: Event System (Data-Driven)
|
||||
|
||||
**Objectif**: Système d'événements scriptés avec conditions et outcomes
|
||||
|
||||
### 4.1 EventProcessor
|
||||
|
||||
**Logic**:
|
||||
```cpp
|
||||
void EventProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) {
|
||||
// 1. Evaluate conditions (game_time, location, resources)
|
||||
// 2. Trigger event si conditions met
|
||||
// 3. Handle player choice
|
||||
// 4. Apply outcomes (resources, flags, trigger_combat)
|
||||
}
|
||||
```
|
||||
|
||||
**Config** (`config/systems/events.json`):
|
||||
```json
|
||||
{
|
||||
"events": {
|
||||
"scavenger_encounter": {
|
||||
"process": "trigger_event",
|
||||
"title": "Scavengers Spotted",
|
||||
"description": "Your scouts report a small group nearby.",
|
||||
"conditions": {
|
||||
"game_time_min": 600,
|
||||
"location_type": "urban_ruins"
|
||||
},
|
||||
"choices": [
|
||||
{
|
||||
"id": "attack",
|
||||
"text": "Attack immediately",
|
||||
"outcomes": {
|
||||
"trigger_combat": "scavenger_ambush",
|
||||
"morale": -5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "negotiate",
|
||||
"text": "Attempt to trade",
|
||||
"requirements": {"reputation": 20},
|
||||
"outcomes": {
|
||||
"resources": {"ammunition": -50, "food": +30},
|
||||
"morale": +5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "avoid",
|
||||
"text": "Move on quietly",
|
||||
"outcomes": {
|
||||
"time_cost": 60
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/process_engine/processors/EventProcessor.cpp`
|
||||
- [ ] `src/modules/systems/EventSystemModule.cpp`
|
||||
- [ ] `config/systems/events.json` (5 events minimum)
|
||||
|
||||
**Tests**:
|
||||
- [ ] Test conditions evaluation
|
||||
- [ ] Test event triggering
|
||||
- [ ] Test outcomes application
|
||||
- [ ] Test choice requirements
|
||||
|
||||
**Durée estimée**: 2-3 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 5: GameModule Integration
|
||||
|
||||
**Objectif**: GameModule orchestre tous les systèmes data-driven
|
||||
|
||||
### 5.1 GameModule Updates
|
||||
|
||||
**State Machine** (reste hardcodé):
|
||||
```cpp
|
||||
enum class GameState {
|
||||
MainMenu, TrainBuilder, Expedition, Combat, Event, Pause
|
||||
};
|
||||
|
||||
void GameModule::updateExpedition(float dt) {
|
||||
// Publish event checks
|
||||
auto checkEvent = make_unique<JsonDataNode>("check");
|
||||
checkEvent->setDouble("game_time", m_gameTime);
|
||||
checkEvent->setString("location", m_currentLocation);
|
||||
m_io->publish("event:check", move(checkEvent));
|
||||
|
||||
// Handle incoming events
|
||||
if (m_io->hasMessages()) {
|
||||
auto msg = m_io->pullMessage();
|
||||
if (msg.topic == "event:triggered") {
|
||||
transitionToState(GameState::Event);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Topics Orchestration**:
|
||||
- Subscribe à tous les `*:complete` / `*:ended`
|
||||
- Publish vers systèmes via `craft:start`, `combat:start`, etc.
|
||||
- Gère transitions d'état
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] Update `src/modules/GameModule.cpp`
|
||||
- [ ] Subscribe tous les nouveaux topics
|
||||
- [ ] Wire systems ensemble
|
||||
|
||||
**Durée estimée**: 2 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 6: Storage System
|
||||
|
||||
**Objectif**: Save/load de tous les états data-driven
|
||||
|
||||
### 6.1 Storage Format
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"timestamp": "2025-12-02T10:30:00Z",
|
||||
"game_state": "Expedition",
|
||||
"game_time": 3600.5,
|
||||
"modules": {
|
||||
"GameModule": {...},
|
||||
"CraftingSystem": {...},
|
||||
"CombatSystem": {...},
|
||||
"EventSystem": {...}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Fichiers**:
|
||||
- [ ] `src/modules/systems/StorageSystemModule.cpp`
|
||||
- [ ] Collect states via IIO broadcast
|
||||
- [ ] Save to JSON
|
||||
- [ ] Restore states on load
|
||||
|
||||
**Durée estimée**: 2 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 7: MC-Specific Modules
|
||||
|
||||
**Objectif**: Modules spécifiques Mobile Command (pas data-driven)
|
||||
|
||||
### 7.1 TrainBuilderModule
|
||||
|
||||
**Responsabilités**:
|
||||
- Balance train (latéral/longitudinal)
|
||||
- Wagon management
|
||||
- Performance malus
|
||||
|
||||
**Topics**:
|
||||
- Publish: `"train:composition_changed"`
|
||||
- Publish: `"train:performance_updated"`
|
||||
|
||||
**Config**: `config/mc_specific/train.json`
|
||||
|
||||
### 7.2 ExpeditionModule
|
||||
|
||||
**Responsabilités**:
|
||||
- Lancer expéditions
|
||||
- Team composition (humains + drones)
|
||||
- Return avec loot
|
||||
|
||||
**Topics**:
|
||||
- Subscribe: `"craft:complete"` (drones)
|
||||
- Publish: `"expedition:started"`, `"expedition:returned"`
|
||||
|
||||
**Config**: `config/mc_specific/expeditions.json`
|
||||
|
||||
**Durée estimée**: 3-4 jours
|
||||
|
||||
---
|
||||
|
||||
## 📋 Phase 8: Integration & Testing
|
||||
|
||||
**Objectif**: Loop complet fonctionnel
|
||||
|
||||
### 8.1 Integration Tests
|
||||
|
||||
- [ ] Full loop test: craft → expedition → combat → event → return
|
||||
- [ ] Save/load cycle complet
|
||||
- [ ] Hot-reload tous modules
|
||||
- [ ] Pub/sub message flow validation
|
||||
|
||||
### 8.2 Main.cpp Updates
|
||||
|
||||
```cpp
|
||||
std::vector<std::pair<std::string, std::string>> moduleList = {
|
||||
// Game orchestrator
|
||||
{"GameModule", "game.json"},
|
||||
|
||||
// Data-driven systems
|
||||
{"CraftingSystemModule", "systems/crafting_recipes.json"},
|
||||
{"CombatSystemModule", "systems/combat_scenarios.json"},
|
||||
{"EventSystemModule", "systems/events.json"},
|
||||
{"StorageSystemModule", "systems/storage.json"},
|
||||
|
||||
// MC-specific
|
||||
{"TrainBuilderModule", "mc_specific/train.json"},
|
||||
{"ExpeditionModule", "mc_specific/expeditions.json"}
|
||||
};
|
||||
```
|
||||
|
||||
**Durée estimée**: 2-3 jours
|
||||
|
||||
---
|
||||
|
||||
## 📊 Timeline Estimé
|
||||
|
||||
| Phase | Durée | Cumul | Livrable |
|
||||
|-------|-------|-------|----------|
|
||||
| Phase 1: ProcessEngine | 2 jours | 2j | Core engine fonctionnel |
|
||||
| Phase 2: Crafting | 3 jours | 5j | Premier système data-driven |
|
||||
| Phase 3: Combat | 4 jours | 9j | Combat data-driven |
|
||||
| Phase 4: Events | 3 jours | 12j | Events data-driven |
|
||||
| Phase 5: GameModule | 2 jours | 14j | Orchestration complète |
|
||||
| Phase 6: Storage | 2 jours | 16j | Save/load |
|
||||
| Phase 7: MC Modules | 4 jours | 20j | Train + Expeditions |
|
||||
| Phase 8: Integration | 3 jours | 23j | Loop complet |
|
||||
|
||||
**Total: ~23 jours de dev (4-5 semaines)**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Critères de Succès
|
||||
|
||||
### Technique
|
||||
- [ ] ProcessEngine avec 3+ processors (craft, combat, event)
|
||||
- [ ] 3+ systèmes data-driven fonctionnels
|
||||
- [ ] Hot-reload préserve état
|
||||
- [ ] Pub/sub communication fluide
|
||||
- [ ] Tests unitaires pass
|
||||
|
||||
### Gameplay
|
||||
- [ ] Craft 5+ items
|
||||
- [ ] Combat 3+ scenarios différents
|
||||
- [ ] Trigger 5+ events
|
||||
- [ ] Save/load fonctionne
|
||||
- [ ] Loop complet 30+ minutes jouable
|
||||
|
||||
### Réutilisabilité
|
||||
- [ ] ProcessEngine utilisable pour WarFactory
|
||||
- [ ] Pas de hardcode MC-specific dans systems/
|
||||
- [ ] JSON configs clairs et documentés
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Comparaison Avant/Après
|
||||
|
||||
### Avant (Architecture actuelle)
|
||||
```
|
||||
ResourceModule.cpp (478 lignes)
|
||||
├─ Logic craft hardcodée
|
||||
├─ Formulas en C++
|
||||
└─ Config JSON minimal
|
||||
|
||||
→ Changer formule = recompiler
|
||||
→ Pas réutilisable WF
|
||||
```
|
||||
|
||||
### Après (Architecture data-driven)
|
||||
```
|
||||
CraftingSystemModule.cpp (150 lignes)
|
||||
├─ Utilise ProcessEngine
|
||||
└─ Config recipes.json complet
|
||||
|
||||
CraftProcessor.cpp (100 lignes)
|
||||
└─ Logic générique réutilisable
|
||||
|
||||
→ Changer formule = edit JSON
|
||||
→ ProcessEngine réutilisable WF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Prochaines Étapes Immédiates
|
||||
|
||||
1. **Créer structure ProcessEngine** (Phase 1)
|
||||
2. **Implémenter CraftProcessor** (Phase 2)
|
||||
3. **Tester avec CraftingSystemModule** (Phase 2)
|
||||
4. **Valider hot-reload** (Phase 2)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes Importantes
|
||||
|
||||
### Design Decisions
|
||||
|
||||
1. **GameModule reste hardcodé** - State machine C++ pour clarté
|
||||
2. **Systems sont data-driven** - Réutilisabilité MC/WF
|
||||
3. **ProcessEngine est stateless** - State vit dans modules
|
||||
4. **IIO pour tout** - Découplage maximal
|
||||
|
||||
### Risks
|
||||
|
||||
- **Formula parser complexity** - Garder simple pour prototype
|
||||
- **JSON configs verbeux** - Trade-off accepté pour flexibilité
|
||||
- **Hot-reload edge cases** - Tester intensivement
|
||||
|
||||
### Future Enhancements
|
||||
|
||||
- Expression parser avancé (Lua?)
|
||||
- Visual process editor
|
||||
- Process debugging tools
|
||||
- Performance profiling
|
||||
|
||||
---
|
||||
|
||||
*Plan créé le 2 décembre 2025*
|
||||
*Architecture inspirée de WarFactory worldgen*
|
||||
Loading…
Reference in New Issue
Block a user