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>
7.2 KiB
7.2 KiB
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 :
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 :
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) :
{
"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) :
{
"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
- Core = Generic - Si tu penses "drone" ou "train", c'est game-specific
- Config > Code - Behavior via JSON, pas hardcodé
- Pub/Sub Only - Modules ne se référencent jamais directement
- Think Both Games - Chaque feature core doit avoir sens pour MC ET WF
- 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.