R-Type 0.1
Loading...
Searching...
No Matches
factoryDataDriven.hpp
1#pragma once
2
3#include "components/NetworkEntity.hpp"
4#include <Registry.hpp>
5#include <cstdint>
6#include <fstream>
7#include <functional>
8#include <nlohmann/json.hpp>
9#include <stdexcept>
10#include <string>
11#include <string_view>
12#include <unordered_map>
13
14namespace rtk {
21using ArchetypeID = std::uint16_t;
22
32constexpr ArchetypeID hashArchetype(std::string_view name) noexcept {
33 std::uint32_t hash = 2166136261u;
34 for (char c : name) {
35 hash ^= static_cast<std::uint8_t>(c);
36 hash *= 16777619u;
37 }
38 return static_cast<ArchetypeID>((hash >> 16) ^ (hash & 0xFFFF));
39}
40
44namespace factory {
55public:
59 using json = nlohmann::json;
62 std::function<void(rtk::ecs::Registry &, std::size_t, const json &)>;
63
64private:
65 std::unordered_map<std::string, ComponentBuilder> _builders;
66 std::unordered_map<std::string, json> _blueprints;
67 std::unordered_map<ArchetypeID, std::string> _archetypes;
68
69public:
75 void registerBuilder(const std::string &name, ComponentBuilder builder) {
76 _builders[name] = builder;
77 }
78
85 ArchetypeID registerBlueprint(const std::string &blueprintName,
86 const json &blueprintJson) {
87 ArchetypeID id = hashArchetype(blueprintName);
88 _blueprints[blueprintName] = blueprintJson;
89 _archetypes[id] = blueprintName;
90 return id;
91 }
92
100 ArchetypeID loadBlueprintFromPath(const std::string &blueprintName,
101 const std::string &filepath) {
102 std::ifstream file(filepath);
103 if (!file.is_open()) {
104 throw std::runtime_error("Failed to open blueprint file: " + filepath);
105 }
106
107 json blueprintJson;
108 file >> blueprintJson;
109 std::cout << blueprintName << " Hash ID : "
110 << registerBlueprint(blueprintName, blueprintJson) << std::endl;
111 return registerBlueprint(blueprintName, blueprintJson);
112 }
113
119 [[nodiscard]] ArchetypeID
120 getArchetypeID(const std::string &blueprintName) const {
121 return hashArchetype(blueprintName);
122 }
123
130 [[nodiscard]] const std::string &
131 getBlueprintName(ArchetypeID archetypeId) const {
132 auto it = _archetypes.find(archetypeId);
133 if (it == _archetypes.end()) {
134 throw std::runtime_error("ArchetypeID not found: " +
135 std::to_string(archetypeId));
136 }
137 return it->second;
138 }
139
145 [[nodiscard]] bool hasArchetype(ArchetypeID archetypeId) const {
146 return _archetypes.contains(archetypeId);
147 }
148
154 [[nodiscard]] bool hasBlueprint(const std::string &blueprintName) const {
155 return _blueprints.contains(blueprintName);
156 }
157
165 void buildComponents(rtk::ecs::Registry &reg, std::size_t entity,
166 const json &componentsJson) {
167 for (const auto &[compName, compData] : componentsJson.items()) {
168 if (_builders.contains(compName)) {
169 _builders[compName](reg, entity, compData);
170 }
171 }
172 }
173
180 std::size_t createEntity(rtk::ecs::Registry &reg, const json &entityJson) {
181 std::size_t entity = reg.spawn_entity();
182
183 if (entityJson.contains("components"))
184 buildComponents(reg, entity, entityJson["components"]);
185 return entity;
186 }
187
195 std::size_t createFromBlueprint(rtk::ecs::Registry &reg,
196 const std::string &blueprintName) {
197 if (!_blueprints.contains(blueprintName))
198 throw std::runtime_error("Blueprint not found: " + blueprintName);
199
200 return createEntity(reg, _blueprints.at(blueprintName));
201 }
202
210 std::size_t createFromBlueprint(rtk::ecs::Registry &reg,
211 ArchetypeID archetypeId) {
212 auto it = _archetypes.find(archetypeId);
213 if (it == _archetypes.end())
214 throw std::runtime_error("ArchetypeID not found: " +
215 std::to_string(archetypeId));
216
217 return createFromBlueprint(reg, it->second);
218 }
219
228 std::size_t createNetwork(rtk::ecs::Registry &reg, ArchetypeID archetypeId,
229 std::uint32_t networkId) {
230 std::size_t entity = createFromBlueprint(reg, archetypeId);
231 reg.get_components<component::NetworkEntity>().insert_at(
232 entity, component::NetworkEntity{networkId, archetypeId});
233 return entity;
234 }
235
244 std::size_t createNetwork(rtk::ecs::Registry &reg,
245 const std::string &blueprintName,
246 std::uint32_t networkId) {
247 ArchetypeID archetypeId = getArchetypeID(blueprintName);
248 std::size_t entity = createFromBlueprint(reg, blueprintName);
249 reg.get_components<component::NetworkEntity>().insert_at(
250 entity, component::NetworkEntity{networkId, archetypeId});
251 return entity;
252 }
253};
254
256} // namespace factory
257
259} // namespace rtk
Builds entities from JSON blueprints and registered component builders.
Definition factoryDataDriven.hpp:54
const std::string & getBlueprintName(ArchetypeID archetypeId) const
Returns the blueprint name of an archetype id.
Definition factoryDataDriven.hpp:131
std::function< void(rtk::ecs::Registry &, std::size_t, const json &)> ComponentBuilder
Function that adds one component to an entity from its JSON data.
Definition factoryDataDriven.hpp:61
void registerBuilder(const std::string &name, ComponentBuilder builder)
Associates a blueprint component key with a builder.
Definition factoryDataDriven.hpp:75
std::size_t createNetwork(rtk::ecs::Registry &reg, ArchetypeID archetypeId, std::uint32_t networkId)
Spawns a replicated entity and attaches its NetworkEntity.
Definition factoryDataDriven.hpp:228
ArchetypeID getArchetypeID(const std::string &blueprintName) const
Returns the archetype id of a blueprint name.
Definition factoryDataDriven.hpp:120
bool hasBlueprint(const std::string &blueprintName) const
Tells whether a blueprint with this name is loaded.
Definition factoryDataDriven.hpp:154
ArchetypeID registerBlueprint(const std::string &blueprintName, const json &blueprintJson)
Stores a blueprint under a name.
Definition factoryDataDriven.hpp:85
ArchetypeID loadBlueprintFromPath(const std::string &blueprintName, const std::string &filepath)
Loads a blueprint from a JSON file and stores it.
Definition factoryDataDriven.hpp:100
std::size_t createFromBlueprint(rtk::ecs::Registry &reg, const std::string &blueprintName)
Spawns an entity from a loaded blueprint.
Definition factoryDataDriven.hpp:195
std::size_t createNetwork(rtk::ecs::Registry &reg, const std::string &blueprintName, std::uint32_t networkId)
Spawns a replicated entity and attaches its NetworkEntity.
Definition factoryDataDriven.hpp:244
void buildComponents(rtk::ecs::Registry &reg, std::size_t entity, const json &componentsJson)
Adds every component listed in a JSON object, unknown keys are ignored.
Definition factoryDataDriven.hpp:165
std::size_t createEntity(rtk::ecs::Registry &reg, const json &entityJson)
Spawns an entity from a blueprint document.
Definition factoryDataDriven.hpp:180
std::size_t createFromBlueprint(rtk::ecs::Registry &reg, ArchetypeID archetypeId)
Spawns an entity from a loaded blueprint.
Definition factoryDataDriven.hpp:210
rtk::ArchetypeID ArchetypeID
16-bit identifier of an entity blueprint.
Definition factoryDataDriven.hpp:57
bool hasArchetype(ArchetypeID archetypeId) const
Tells whether a blueprint with this archetype id is loaded.
Definition factoryDataDriven.hpp:145
nlohmann::json json
JSON document type.
Definition factoryDataDriven.hpp:59
std::uint16_t ArchetypeID
16-bit identifier of an entity blueprint, shared by client and server.
Definition factoryDataDriven.hpp:21
constexpr ArchetypeID hashArchetype(std::string_view name) noexcept
Hashes a blueprint name to its archetype id.
Definition factoryDataDriven.hpp:32
Links a local entity to its replicated counterpart.
Definition NetworkEntity.hpp:18