Core Modules (game-agnostic, reusable for WarFactory): - ResourceModule: Inventory, crafting system (465 lines) - StorageModule: Save/load with pub/sub state collection (424 lines) - CombatModule: Combat resolver, damage/armor/morale (580 lines) - EventModule: JSON event scripting with choices/outcomes (651 lines) MC-Specific Modules: - GameModule v2: State machine + event subscriptions (updated) - TrainBuilderModule: 3 wagons, 2-axis balance, performance malus (530 lines) - ExpeditionModule: A→B expeditions, team management, events integration (641 lines) Features: - All modules hot-reload compatible (state preservation) - Pure pub/sub architecture (zero direct coupling) - 7 config files (resources, storage, combat, events, train, expeditions) - 7 test suites (GameModuleTest: 12/12 PASSED) - CMakeLists.txt updated for all modules + tests Total: ~3,500 lines of production code + comprehensive tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <grove/IModule.h>
|
|
#include <grove/JsonDataNode.h>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <chrono>
|
|
|
|
/**
|
|
* StorageModule - Game-agnostic save/load system
|
|
*
|
|
* GAME-AGNOSTIC CORE MODULE
|
|
* This module is shared between Mobile Command and WarFactory.
|
|
* DO NOT add game-specific logic here.
|
|
*
|
|
* Responsibilities:
|
|
* - Save game state to JSON files
|
|
* - Load game state from JSON files
|
|
* - Auto-save with configurable interval
|
|
* - Version management for save files
|
|
* - State collection from all modules via pub/sub
|
|
*
|
|
* Usage Examples:
|
|
*
|
|
* MOBILE COMMAND:
|
|
* - Saves: train state, expedition progress, timeline position
|
|
* - Load: Restores train composition, resources, crew
|
|
* - Auto-save: Every 5 minutes during gameplay
|
|
*
|
|
* WARFACTORY (Future):
|
|
* - Saves: factory state, production queues, research progress
|
|
* - Load: Restores assembly lines, resource stockpiles
|
|
* - Auto-save: Every 5 minutes during factory operation
|
|
*
|
|
* Pub/Sub Communication:
|
|
* - Subscribe: "game:request_save", "game:request_load"
|
|
* - Publish: "storage:save_complete", "storage:load_complete", "storage:save_failed"
|
|
* - Collect: "storage:collect_states" -> modules respond with their state
|
|
* - Restore: "storage:restore_state:{moduleName}" -> restore specific module
|
|
*/
|
|
class StorageModule : public grove::IModule {
|
|
public:
|
|
StorageModule();
|
|
~StorageModule() override = default;
|
|
|
|
// IModule interface
|
|
void setConfiguration(const grove::IDataNode& config, grove::IIO* io, grove::ITaskScheduler* scheduler) override;
|
|
void process(const grove::IDataNode& input) override;
|
|
void shutdown() override;
|
|
std::unique_ptr<grove::IDataNode> getState() override;
|
|
void setState(const grove::IDataNode& state) override;
|
|
const grove::IDataNode& getConfiguration() override;
|
|
std::unique_ptr<grove::IDataNode> getHealthStatus() override;
|
|
std::string getType() const override;
|
|
bool isIdle() const override;
|
|
|
|
private:
|
|
// Core save/load functionality
|
|
void saveGame(const std::string& filename = "");
|
|
void loadGame(const std::string& filename);
|
|
void autoSave();
|
|
|
|
// State collection via pub/sub
|
|
void collectModuleStates();
|
|
void restoreModuleStates(const grove::IDataNode& savedData);
|
|
|
|
// File operations
|
|
void ensureSaveDirectoryExists();
|
|
std::string getSaveFilePath(const std::string& filename) const;
|
|
std::string generateAutoSaveFilename() const;
|
|
|
|
// Message handlers
|
|
void handleMessages();
|
|
void onRequestSave(const grove::IDataNode& data);
|
|
void onRequestLoad(const grove::IDataNode& data);
|
|
void onModuleState(const grove::IDataNode& data);
|
|
|
|
// Member variables
|
|
grove::IIO* m_io = nullptr;
|
|
grove::ITaskScheduler* m_scheduler = nullptr;
|
|
grove::JsonDataNode m_config{"config"};
|
|
|
|
// Configuration
|
|
std::string m_savePath;
|
|
float m_autoSaveInterval; // seconds
|
|
int m_maxAutoSaves;
|
|
|
|
// State tracking
|
|
float m_timeSinceLastAutoSave;
|
|
std::map<std::string, std::unique_ptr<grove::IDataNode>> m_collectedStates;
|
|
bool m_collectingStates;
|
|
std::chrono::steady_clock::time_point m_collectionStartTime;
|
|
};
|