- Merge GroveEngine.md, GroveEngine_RenderModule.md, grove-sup.md into single comprehensive doc - Add detailed architecture (13 interfaces, hot-reload, IIO pub/sub, data system) - Document known technical issues (API mismatch, cross-platform, state preservation) - Remove redundant files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
18 KiB
GroveEngine - Framework C++ Modulaire
Type : Game Engine Framework
Stack : C++17, bgfx, SDL2, nlohmann_json, spdlog
Repo : ../GroveEngine/
Status : Core validé, Rendering en développement
Dernière mise à jour : 27 novembre 2025
Vue d'ensemble
GroveEngine est un moteur de jeu C++17 modulaire conçu pour :
- Hot-reload ultra-rapide : 0.4ms validé (5000x plus rapide qu'un cycle edit-build-test classique)
- AI-optimized : Micro-modules (200-300 lignes) parfaits pour développement assisté Claude
- Scalabilité transparente : Du debug local au cluster distribué sans modifier le code modules
- Data-driven : Config/YAML/JSON pour tout le contenu (LLM peut créer sans toucher C++)
Nom : "Grove" = bosquet où les modules poussent comme des arbres indépendants.
Architecture Core
Philosophie : 13 Interfaces
L'architecture repose sur 13 interfaces abstraites permettant de swap les implémentations sans modifier le code métier.
┌─────────────────────────────────────────────────────────────┐
│ Application (ex: aissia-core.exe, warfactory.exe) │
│ └─ main() → EngineFactory::create() │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ IEngine (orchestration) │
│ ├─ IModuleSystem (stratégie d'exécution) │
│ ├─ IIO (communication pub/sub) │
│ ├─ IDataTree (configuration hiérarchique) │
│ └─ Game loop │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Modules (DLL/SO hot-reloadable, 200-300 lignes chacun) │
│ ├─ module_a.dll → IModule::process() │
│ ├─ module_b.dll → IModule::process() │
│ └─ module_c.dll → IModule::process() │
│ Communication via IIO (pub/sub topics) │
└─────────────────────────────────────────────────────────────┘
Les 13 Interfaces
| Interface | Rôle | Implémentations |
|---|---|---|
| IEngine | Orchestration système, main loop | DebugEngine ✅, HighPerfEngine (planned), DataOrientedEngine (planned) |
| IModule | Logique métier (micro-modules) | Custom modules (.dll/.so) |
| IModuleSystem | Stratégie d'exécution modules | SequentialModuleSystem ✅, ThreadedModuleSystem (planned), ClusterModuleSystem (planned) |
| IIO | Communication pub/sub | IntraIO ✅ (même process), LocalIO (planned), NetworkIO (planned) |
| IDataTree | Racine configuration | JsonDataTree ✅ |
| IDataNode | Noeud configuration | JsonDataNode ✅ |
| ITaskScheduler | Délégation tâches async | (planned) |
| IUI | Abstraction UI | ImGuiUI ✅ |
| ISerializable | Sérialisation état | JSON-based |
| ICoordinationModule | Coordination inter-modules | (planned) |
Scalabilité Transparente
MVP Debug: DebugEngine + SequentialModuleSystem + IntraIO
(Single-thread, même process, logging verbose)
Production: HighPerfEngine + ThreadedModuleSystem + LocalIO
(Multi-thread, named pipes/sockets)
Cloud/MMO: DataOrientedEngine + ClusterModuleSystem + NetworkIO
(Distribué, TCP/WebSocket)
Aucun changement de code dans les modules - Juste swap des implémentations via config.
Hot-Reload System
Performance Validée
| Métrique | Valeur |
|---|---|
| Temps moyen | 0.4ms |
| Meilleur cas | 0.055ms |
| State preservation | 100% (via ISerializable) |
| Commit validation | fc28009 (24 Sept 2025) |
Mécanisme
// 1. Détection changement fichier DLL
if (filesystem::last_write_time("module.dll") > last_load_time) {
// 2. Sauvegarder état via ISerializable
nlohmann::json state;
old_module->serialize(state);
// 3. Shutdown module actuel
old_module->shutdown();
// 4. Unload DLL
#ifdef _WIN32
FreeLibrary(dll_handle);
#else
dlclose(dll_handle);
#endif
// 5. Reload nouvelle DLL
#ifdef _WIN32
dll_handle = LoadLibrary("module.dll");
#else
dll_handle = dlopen("./module.so", RTLD_NOW);
#endif
// 6. Initialize nouveau module avec état restauré
new_module->initialize(config, io);
new_module->deserialize(state);
// Total: 0.4ms
}
Interface IModule
class IModule {
public:
virtual ~IModule() = default;
// Lifecycle
virtual void initialize(const IDataNode& config, IIO* io) = 0;
virtual void process(float dt) = 0;
virtual void shutdown() = 0;
// Hot-reload state preservation
virtual nlohmann::json getState() const = 0;
virtual void setState(const nlohmann::json& state) = 0;
// Metadata
virtual std::string getName() const = 0;
virtual int getVersion() const = 0;
virtual std::vector<std::string> getDependencies() const = 0;
};
Contraintes Micro-Modules
- 200-300 lignes max par module (AI-friendly)
- Zero parent dependencies : Pas de
#include "../" - JSON-only inter-module : Communication via IIO topics
- Build autonome :
cmake .depuis le dossier module
Communication Inter-Modules (IIO)
TopicTree : Pub/Sub Ultra-Rapide
Bibliothèque interne : StillHammer::topictree Performance : O(k) où k = profondeur topic (pas O(n) patterns)
// Publisher (Module A)
io->publish("game/player/position", position_json);
io->publish("game/enemy/42/health", health_json);
// Subscriber (Module B) - Wildcards supportés
io->subscribe("game/player/*", [](const Message& msg) {
// Reçoit tous les messages player
});
io->subscribe("game/enemy/+/health", [](const Message& msg) {
// + = single level wildcard
// Reçoit health de tous les enemies
});
Performance TopicTree
| Patterns | Temps matching |
|---|---|
| 1,000 | < 1ms |
| 10,000 | < 5ms |
Design Pull-Based
- Synchrone : Messages collectés, traités en batch
- Low-frequency : Optimisé pour 60 FPS game loop, pas high-frequency trading
- Découplage total : Modules ignorent l'existence des autres
Data System (IDataTree / IDataNode)
Configuration Hiérarchique Type-Safe
// Lecture config
void MyModule::initialize(const IDataNode& config, IIO* io) {
int width = config.get("window.width", 1280);
std::string title = config.get("window.title", "GroveEngine");
bool vsync = config.get("rendering.vsync", true);
// Navigation arbre
auto& enemies = config.getChild("enemies");
for (const auto& enemy : enemies.getChildren()) {
std::string type = enemy.get("type", "basic");
int hp = enemy.get("hp", 100);
}
}
Backed by JSON Files
{
"window": {
"width": 1280,
"height": 720,
"title": "My Game"
},
"rendering": {
"vsync": true,
"clear_color": "#303030"
},
"enemies": [
{"type": "basic", "hp": 100},
{"type": "heavy", "hp": 500}
]
}
Structure Projet
GroveEngine/
├── include/grove/ # 32 headers (interfaces + impls)
│ ├── IEngine.h
│ ├── IModule.h
│ ├── IModuleSystem.h
│ ├── IIO.h
│ ├── IDataTree.h
│ ├── IDataNode.h
│ ├── ITaskScheduler.h
│ ├── IUI.h
│ ├── ISerializable.h
│ └── ...
│
├── src/ # Implémentations concrètes
│ ├── DebugEngine.cpp
│ ├── SequentialModuleSystem.cpp
│ ├── IntraIO.cpp
│ ├── IntraIOManager.cpp
│ ├── JsonDataNode.cpp
│ ├── JsonDataTree.cpp
│ ├── ModuleFactory.cpp
│ ├── EngineFactory.cpp
│ └── ...
│
├── modules/ # Modules hot-reloadables
│ └── BgfxRenderer/ # Module rendering 2D (WIP)
│ ├── BgfxRendererModule.cpp
│ ├── RHI/ # Render Hardware Interface
│ ├── Shaders/ # Pre-compiled (GL/Vulkan/DX11/Metal)
│ ├── Passes/ # Clear, Sprite, Debug
│ ├── RenderGraph/ # Dependency ordering
│ └── Scene/ # Message collection from IIO
│
├── external/StillHammer/ # Libs internes
│ ├── topictree/ # O(k) topic matching
│ └── logger/ # spdlog wrapper
│
├── tests/ # Test suite (Catch2)
│ ├── benchmarks/
│ ├── hotreload/
│ └── helpers/
│
├── docs/ # Documentation
│ ├── architecture/
│ ├── implementation/
│ └── plans/
│
└── CMakeLists.txt # Build system
Module Rendering (BgfxRenderer)
Stack Rendering
- bgfx : Abstraction multi-backend (Vulkan/DX12/Metal/OpenGL)
- SDL2 : Window + input management
- stb_image : Texture loading
Architecture RenderModule
class BgfxRendererModule : public grove::IModule {
public:
// IModule interface
void initialize(const IDataNode& config, IIO* io) override;
void process(float dt) override;
void shutdown() override;
// Rendering API (via IIO messages)
// Autres modules publient sur "render/sprite", "render/rect", etc.
// BgfxRenderer subscribe et render tout en batch
private:
SDL_Window* window;
bgfx::ViewId main_view;
// Render passes
ClearPass clear_pass;
SpritePass sprite_pass;
DebugPass debug_pass;
// Scene collector (from IIO)
SceneCollector scene;
};
Rendering Pipeline
void BgfxRendererModule::process(float dt) {
// 1. Collecter messages rendering depuis IIO
scene.CollectFromIO(io);
// 2. Exécuter passes
clear_pass.Execute(main_view);
sprite_pass.Execute(main_view, scene.sprites);
debug_pass.Execute(main_view, scene.debug_shapes);
// 3. Submit frame
bgfx::frame();
// 4. Clear scene pour prochain frame
scene.Clear();
}
Shaders Pre-Compilés
Shaders compilés pour tous backends via shaderc :
Shaders/
├── vs_sprite.bin.gl # OpenGL
├── vs_sprite.bin.vk # Vulkan
├── vs_sprite.bin.dx11 # DirectX 11
├── vs_sprite.bin.mtl # Metal
├── fs_sprite.bin.gl
├── fs_sprite.bin.vk
├── fs_sprite.bin.dx11
└── fs_sprite.bin.mtl
Camera 2D
class Camera2D {
public:
Vec2 position{0, 0};
float zoom = 1.0f;
Mat4 GetViewMatrix() const {
return Mat4::Translation(-position.x, -position.y, 0);
}
Mat4 GetProjectionMatrix(int width, int height) const {
float halfW = (width / zoom) * 0.5f;
float halfH = (height / zoom) * 0.5f;
return Mat4::Ortho(-halfW, halfW, -halfH, halfH, -1, 1);
}
};
Architecture AI-Friendly (Data-Driven)
Principe
LLM peut créer/modifier game content sans toucher au code C++.
Entity System (YAML)
# entities/wagons/wagon_armored.yaml
entity: wagon_armored
components:
- type: visual
sprite: wagon_armored.png
size: [20, 6]
- type: balance
weight: 7.5
center_of_mass: [10, 3]
- type: health
hp_max: 200
armor: 50
- type: slots
grid: [20, 6]
specialization: military
UI Layouts (JSON)
{
"screen": "train_builder",
"elements": [
{
"type": "panel",
"id": "wagon_view",
"rect": [0, 0, 800, 600],
"background": "#2a2a2a"
},
{
"type": "gauge",
"id": "balance_lateral",
"rect": [820, 20, 160, 40],
"label": "Balance G/D",
"value_binding": "wagon.balance.lateral"
}
]
}
Missions/Events (YAML)
mission:
id: scavenge_kyiv
name: "Colonne russe détruite"
difficulty: easy
rewards:
metal: [50, 100]
electronics: [20, 40]
events:
- trigger: mission_start
choices:
- id: approach_cautious
text: "Approche prudente"
risk_modifier: -0.5
- id: rush
text: "Rush rapide"
risk_modifier: +0.8
Asset Manifests (TOML)
[wagon_armored]
file = "textures/wagon_armored.png"
size = [400, 120]
pivot = [200, 60]
tags = ["wagon", "armored", "heavy"]
weight_modifier = 1.5
Dépendances
Core (FetchContent CMake)
| Library | Version | Usage |
|---|---|---|
| nlohmann_json | 3.11.3 | JSON processing |
| spdlog | 1.12.0 | Logging |
| Catch2 | 3.5+ | Testing |
Rendering (Optionnel)
| Library | Usage |
|---|---|
| bgfx | Multi-backend rendering |
| bx | Base library (bgfx dep) |
| bimg | Image loading (bgfx dep) |
| SDL2 | Windowing + input |
| stb_image | Texture loading |
Internal (StillHammer)
| Library | Usage |
|---|---|
| topictree | O(k) pub/sub topic matching |
| logger | Domain-organized spdlog wrapper |
Optionnel Futur
| Library | Usage |
|---|---|
| yaml-cpp | YAML parsing (entities) |
| TOML++ | Config files |
| ImGui | Debug UI |
| Lua | Scripting (si nécessaire) |
| stb_truetype / FreeType | Font rendering |
Build System
CMake Options
# Core
GROVE_BUILD_IMPLEMENTATIONS # Compile implémentations core
GROVE_BUILD_TESTS # Compile test suite
# Modules
GROVE_BUILD_MODULES # Compile hot-reloadable modules
GROVE_BUILD_BGFX_RENDERER # Compile rendering module
# Debug
GROVE_ENABLE_TSAN # ThreadSanitizer
GROVE_ENABLE_HELGRIND # Helgrind deadlock detection
Build Commands
# Configuration
cmake -B build -DGROVE_BUILD_IMPLEMENTATIONS=ON -DGROVE_BUILD_TESTS=ON
# Build
cmake --build build
# Tests
cd build && ctest
# Module seul (build autonome)
cd modules/BgfxRenderer && cmake . && make
Platforms Supportées
| Platform | Status | Toolchain |
|---|---|---|
| Windows | ✅ Validé | MSVC, MinGW |
| Linux | ✅ Validé | GCC, Clang |
| WSL2 | ✅ Validé | GCC |
| macOS | ⏳ Non testé | Clang |
| WebAssembly | 🔮 Futur | Emscripten |
État Développement
Validé (Production-Ready)
- ✅ Hot-reload 0.4ms avec state preservation
- ✅ DebugEngine avec logging complet
- ✅ SequentialModuleSystem (single-thread)
- ✅ IntraIO pub/sub avec TopicTree
- ✅ JsonDataNode/JsonDataTree configuration
- ✅ Dynamic module loading (dlopen/LoadLibrary)
- ✅ Test suite (Catch2)
En Développement
- 🔄 BgfxRenderer module
- ✅ Skeleton + RHI layer
- ✅ Shaders pre-compiled
- 🔄 SpritePass implementation
- ⏳ TextPass, TilemapPass
Planned
- ⏳ ThreadedModuleSystem (each module own thread)
- ⏳ MultithreadedModuleSystem (thread pool)
- ⏳ LocalIO (named pipes/sockets)
- ⏳ NetworkIO (TCP/WebSocket)
- ⏳ Entity Component System (YAML-driven)
- ⏳ UI System (JSON layouts)
Projets Utilisateurs
| Projet | Type | Status |
|---|---|---|
| AISSIA | AI Assistant | En développement |
| Pokrovsk: Iron Line | Survival/Management | Concept |
| WarFactory | Source originale | Extraction faite |
Problèmes Techniques Connus
1. API Mismatch IDataTree
Situation : Certaines implémentations utilisent l'ancienne API nlohmann::json au lieu de IDataNode.
// Ancien (certains fichiers)
void initialize(const nlohmann::json& config, IIO* io);
// Nouveau (interface actuelle)
void initialize(const IDataNode& config, IIO* io);
Status : Migration en cours, wrapper temporaire disponible.
2. Cross-Platform Hot-Reload
| Platform | API | Status |
|---|---|---|
| Windows | LoadLibrary/FreeLibrary | ✅ Validé |
| Linux | dlopen/dlclose | ✅ Validé |
| macOS | dlopen/dlclose | ⏳ Non testé |
| WASM | N/A | ⚠️ Architecture différente requise |
3. State Preservation Limits
- Pointeurs : Invalides après reload → Utiliser ID-based references
- Handles externes : (GPU textures, file handles) → Recréer après reload
Commits Git Importants
| Commit | Date | Description |
|---|---|---|
| fc28009 | 24 Sept 2025 | Hot-reload 0.4ms validé, DebugEngine fonctionnel |
| fb49fb2 | Sept 2025 | IntraIO implementation |
| f6c3b34 | 27 Sept 2025 | IDataTree ajouté (breaking change) |
| 27 Oct 2025 | - | Extraction GroveEngine depuis WarFactory |
Ressources
Documentation Interne
GroveEngine/docs/architecture/: Guides architectureGroveEngine/docs/implementation/: Guides implémentationGroveEngine/README.md: Quick start
Références Externes
- bgfx : https://github.com/bkaradzic/bgfx
- bgfx docs : https://bkaradzic.github.io/bgfx/
- SDL2 : https://wiki.libsdl.org/
- nlohmann/json : https://github.com/nlohmann/json
Liens Projets Associés
- AISSIA :
Projects/WIP/AISSIA.md - Pokrovsk :
Projects/CONCEPT/pokrovsk_iron_line_v2.md
Créé : 27 octobre 2025 Consolidé : 27 novembre 2025 Stack : C++17, CMake, bgfx, nlohmann_json, spdlog Performance : Hot-reload 0.4ms validé