GroveEngine/include/grove/ResourceRegistry.h
StillHammer fad105afb2 feat: Implement complete IDataNode/IDataTree system with JSON backend
Major feature: Unified config/data/runtime tree system

**New System Architecture:**
- Unified data tree for config, persistent data, and runtime state
- Three separate roots: config/ (read-only + hot-reload), data/ (read-write + save), runtime/ (temporary)
- Support for modding, saves, and hot-reload in single system

**Interfaces:**
- IDataValue: Abstract data value interface (type-safe access)
- IDataNode: Tree node with navigation, search, and modification
- IDataTree: Root container with config/data/runtime management

**Concrete Implementations:**
- JsonDataValue: nlohmann::json backed value
- JsonDataNode: Full tree navigation with pattern matching & queries
- JsonDataTree: File-based JSON storage with hot-reload

**Features:**
- Pattern matching search (wildcards support)
- Property-based queries with predicates
- SHA256 hashing for validation/sync
- Hot-reload for config/ directory
- Save operations for data/ persistence
- Read-only enforcement for config/

**API Changes:**
- All namespaces changed from 'warfactory' to 'grove'
- IDataTree: Added getConfigRoot(), getDataRoot(), getRuntimeRoot()
- IDataTree: Added saveData(), saveNode() for persistence
- IDataNode: Added setChild(), removeChild(), clearChildren()
- CMakeLists.txt: Added OpenSSL dependency for hashing

**Usage:**
```cpp
auto tree = DataTreeFactory::create("json", "./gamedata");
auto config = tree->getConfigRoot();     // Read-only game config
auto data = tree->getDataRoot();         // Player saves
auto runtime = tree->getRuntimeRoot();   // Temporary state

// Hot-reload config on file changes
if (tree->reloadIfChanged()) { /* refresh modules */ }

// Save player progress
data->setChild("progress", progressNode);
tree->saveData();
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 15:36:25 +08:00

113 lines
3.5 KiB
C++

#pragma once
#include "Resource.h"
#include <vector>
#include <unordered_map>
#include <string>
#include <memory>
namespace grove {
/**
* @brief Singleton registry for all game resources with fast uint32_t ID lookup
*
* Centralizes resource management with O(1) access by numeric ID.
* Resources are loaded once at startup and accessed by ID throughout the game.
*/
class ResourceRegistry {
private:
static std::unique_ptr<ResourceRegistry> instance;
static bool initialized;
std::vector<Resource> resources; // Indexed by ID (resources[id])
std::unordered_map<std::string, uint32_t> name_to_id; // String -> ID mapping (init only)
uint32_t next_id = 1; // Start at 1 (0 = invalid/null resource)
ResourceRegistry() = default;
public:
// Singleton access
static ResourceRegistry& getInstance();
static void initialize();
static void shutdown();
// ========================================
// REGISTRATION (Initialization Phase)
// ========================================
/**
* @brief Register a resource and get its assigned ID
* @param resource The resource to register
* @return The assigned uint32_t ID for this resource
*/
uint32_t registerResource(const Resource& resource);
/**
* @brief Load resources from JSON configuration
* @param resources_json JSON object containing all resources
*/
void loadResourcesFromJson(const json& resources_json);
// ========================================
// RUNTIME ACCESS (Performance Critical)
// ========================================
/**
* @brief Get resource by ID (O(1) access)
* @param id The resource ID
* @return Pointer to resource or nullptr if not found
*/
const Resource* getResource(uint32_t id) const;
/**
* @brief Get resource ID by name (use sparingly - prefer caching IDs)
* @param name The resource name/identifier
* @return The resource ID or 0 if not found
*/
uint32_t getResourceId(const std::string& name) const;
/**
* @brief Check if resource ID is valid
*/
bool isValidResourceId(uint32_t id) const;
// ========================================
// BULK OPERATIONS
// ========================================
/**
* @brief Get all registered resource IDs
*/
std::vector<uint32_t> getAllResourceIds() const;
/**
* @brief Get total number of registered resources
*/
size_t getResourceCount() const;
/**
* @brief Clear all registered resources (testing/reset)
*/
void clear();
// ========================================
// CONVENIENCE CONSTANTS
// ========================================
static constexpr uint32_t INVALID_RESOURCE_ID = 0;
static constexpr uint32_t MAX_RESOURCES = 1000000; // 1M resources max
// Prevent copy/assignment
ResourceRegistry(const ResourceRegistry&) = delete;
ResourceRegistry& operator=(const ResourceRegistry&) = delete;
};
// ========================================
// CONVENIENCE MACROS FOR PERFORMANCE
// ========================================
#define RESOURCE_ID(name) warfactory::ResourceRegistry::getInstance().getResourceId(name)
#define GET_RESOURCE(id) warfactory::ResourceRegistry::getInstance().getResource(id)
#define VALID_RESOURCE(id) warfactory::ResourceRegistry::getInstance().isValidResourceId(id)
} // namespace grove