Update documentation to emphasize core modules reusability: - ARCHITECTURE.md: New file explaining game-agnostic principles - CLAUDE.md: Add strict rules for core modules, pub/sub patterns - README.md: Update roadmap with Phase 1-4, clarify status Core modules (ResourceModule, StorageModule, etc.) will be reusable between Mobile Command and WarFactory via pub/sub. Game-specific logic stays in GameModule via event subscriptions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
234 lines
7.2 KiB
Markdown
234 lines
7.2 KiB
Markdown
# Architecture Game-Agnostic
|
|
|
|
**Date** : 2 décembre 2025
|
|
**Version** : 0.1.0
|
|
|
|
## Principe Fondamental
|
|
|
|
Les modules **core** sont game-agnostic et réutilisables entre Mobile Command et WarFactory.
|
|
La logique spécifique au jeu se fait via **pub/sub** dans GameModule.
|
|
|
|
## Structure
|
|
|
|
```
|
|
┌──────────────────────────────────────┐
|
|
│ GameModule (MC-specific) │
|
|
│ ┌────────────────────────────────┐ │
|
|
│ │ Subscribe aux events core │ │
|
|
│ │ Applique logique MC │ │
|
|
│ │ (drones, train, expeditions) │ │
|
|
│ └────────────────────────────────┘ │
|
|
└────────────┬─────────────────────────┘
|
|
│ pub/sub via grove::IIO
|
|
│
|
|
┌────────────▼─────────────────────────┐
|
|
│ Core Modules (Game-Agnostic) │
|
|
│ ┌────────────────────────────────┐ │
|
|
│ │ ResourceModule │ │
|
|
│ │ - Inventaire │ │
|
|
│ │ - Craft │ │
|
|
│ │ - Quality │ │
|
|
│ │ │ │
|
|
│ │ Publie: resource:* │ │
|
|
│ │ PAS de logique MC/WF │ │
|
|
│ └────────────────────────────────┘ │
|
|
│ ┌────────────────────────────────┐ │
|
|
│ │ StorageModule │ │
|
|
│ │ CombatModule │ │
|
|
│ │ EventModule │ │
|
|
│ └────────────────────────────────┘ │
|
|
└──────────────────────────────────────┘
|
|
```
|
|
|
|
## Exemples
|
|
|
|
### ResourceModule (Core - Game-Agnostic)
|
|
|
|
**Ce qu'il FAIT** :
|
|
```cpp
|
|
class ResourceModule : public grove::IModule {
|
|
bool addResource(string id, int quantity);
|
|
bool removeResource(string id, int quantity);
|
|
bool canCraft(string recipeId);
|
|
void startCraft(string recipeId);
|
|
|
|
void process(float dt) {
|
|
updateCrafting(dt);
|
|
if (craftComplete) {
|
|
io->publish("resource:craft_complete", craftData);
|
|
}
|
|
}
|
|
};
|
|
```
|
|
|
|
**Ce qu'il NE FAIT PAS** :
|
|
- ❌ Savoir ce qu'est un "drone" ou un "tank"
|
|
- ❌ Connaître les expéditions ou factories
|
|
- ❌ Gérer le train ou les wagons
|
|
- ❌ Appliquer fame bonus
|
|
- ❌ Contenir logique MC ou WF
|
|
|
|
### GameModule (MC-Specific)
|
|
|
|
**Ce qu'il FAIT** :
|
|
```cpp
|
|
class GameModule : public grove::IModule {
|
|
void initialize() {
|
|
// Subscribe aux events core
|
|
io->subscribe("resource:craft_complete", [this](const IDataNode& data) {
|
|
string recipe = data.getString("recipe");
|
|
|
|
// LOGIQUE MC ICI
|
|
if (recipe == "drone_recon") {
|
|
// MC: Ajouter aux expéditions
|
|
m_availableDrones["recon"]++;
|
|
io->publish("expedition:drone_available", droneData);
|
|
|
|
// MC: Fame bonus si 2024+
|
|
if (m_timeline.year >= 2024) {
|
|
io->publish("fame:gain", fameData);
|
|
}
|
|
}
|
|
});
|
|
|
|
io->subscribe("resource:inventory_low", [this](const IDataNode& data) {
|
|
// MC: Warning train storage
|
|
showWarning("Fuel bas ! Retour au train recommandé.");
|
|
});
|
|
}
|
|
};
|
|
```
|
|
|
|
## Topics Pub/Sub
|
|
|
|
### ResourceModule
|
|
- `resource:craft_complete` - {recipe, result, quantity}
|
|
- `resource:craft_started` - {recipe, duration}
|
|
- `resource:inventory_changed` - {resource_id, delta, total}
|
|
- `resource:inventory_low` - {resource_id, threshold}
|
|
- `resource:storage_full` - {}
|
|
|
|
### StorageModule
|
|
- `storage:save_complete` - {filename, timestamp}
|
|
- `storage:load_complete` - {filename, version}
|
|
- `storage:save_failed` - {error}
|
|
|
|
### CombatModule
|
|
- `combat:started` - {location, combatants}
|
|
- `combat:round_complete` - {casualties, damage}
|
|
- `combat:ended` - {victory, loot, casualties}
|
|
|
|
### EventModule
|
|
- `event:triggered` - {event_id, conditions}
|
|
- `event:choice_made` - {event_id, choice_id}
|
|
- `event:outcome` - {resources, flags}
|
|
|
|
## Configuration
|
|
|
|
### Core Modules
|
|
Config JSON pure, pas de hardcoded behavior.
|
|
|
|
**resources.json (MC)** :
|
|
```json
|
|
{
|
|
"resources": {
|
|
"scrap_metal": {"maxStack": 100, "weight": 1.5},
|
|
"drone_parts": {"maxStack": 50, "weight": 0.5}
|
|
},
|
|
"recipes": {
|
|
"drone_recon": {
|
|
"inputs": {"drone_parts": 3, "electronics": 2},
|
|
"outputs": {"drone_recon": 1},
|
|
"time": 120
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**resources.json (WF - futur)** :
|
|
```json
|
|
{
|
|
"resources": {
|
|
"iron_ore": {"maxStack": 1000, "weight": 2.0},
|
|
"steel_plates": {"maxStack": 500, "weight": 5.0}
|
|
},
|
|
"recipes": {
|
|
"tank_t72": {
|
|
"inputs": {"steel_plates": 50, "engine": 1},
|
|
"outputs": {"tank_t72": 1},
|
|
"time": 600
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Même code ResourceModule, configs différentes → Comportements différents.
|
|
|
|
## Checklist Module Core
|
|
|
|
Avant de commiter un module core :
|
|
|
|
- [ ] ❌ Aucune mention de "Mobile Command", "WarFactory", "train", "factory", "drone", "tank"
|
|
- [ ] ✅ Interface pure (fonctions publiques génériques)
|
|
- [ ] ✅ Tout comportement via config JSON
|
|
- [ ] ✅ Communication via pub/sub uniquement
|
|
- [ ] ✅ Topics documentés en commentaires
|
|
- [ ] ✅ Exemple usage MC + WF en commentaires
|
|
- [ ] ✅ Hot-reload state preservation
|
|
- [ ] ✅ Tests basiques passent
|
|
|
|
## Règles d'Or
|
|
|
|
1. **Core = Generic** - Si tu penses "drone" ou "train", c'est game-specific
|
|
2. **Config > Code** - Behavior via JSON, pas hardcodé
|
|
3. **Pub/Sub Only** - Modules ne se référencent jamais directement
|
|
4. **Think Both Games** - Chaque feature core doit avoir sens pour MC ET WF
|
|
5. **Test Reusability** - Si tu ne peux pas imaginer WF l'utiliser, refactor
|
|
|
|
## Bénéfices
|
|
|
|
### Court Terme (Prototype MC)
|
|
- Architecture propre, modules découplés
|
|
- Hot-reload rapide (modules petits)
|
|
- Tests unitaires faciles
|
|
|
|
### Moyen Terme (MVP MC)
|
|
- Code stable, bien testé
|
|
- Pas de spaghetti code
|
|
- Maintenance simplifiée
|
|
|
|
### Long Terme (WF + MC)
|
|
- **Réutilisation massive** : WF bénéficie du code MC
|
|
- **Bugs fixés une fois** : Profit aux deux projets
|
|
- **Features partagées** : Economy, storage, combat
|
|
- **Extraction library** : grove-modules/ opensource possible
|
|
|
|
## Future: grove-modules/ Library
|
|
|
|
Quand modules stabilisés (Post-MVP MC) :
|
|
|
|
```
|
|
../grove-modules/ # Bibliothèque partagée
|
|
├── core/
|
|
│ ├── ResourceModule/
|
|
│ ├── StorageModule/
|
|
│ ├── CombatModule/
|
|
│ └── EventModule/
|
|
└── README.md
|
|
|
|
../mobilecommand/
|
|
└── external/
|
|
├── GroveEngine/
|
|
└── grove-modules/ # Symlink
|
|
|
|
../warfactoryracine/
|
|
└── external/
|
|
└── grove-modules/ # Symlink
|
|
```
|
|
|
|
**Plan complet** : Voir `plans/SHARED_MODULES_PLAN.md`
|
|
|
|
---
|
|
|
|
**TL;DR** : Core modules = Generic library. Game logic = GameModule via pub/sub.
|