From 9b4b52bc9f20d3caed809908f381caee6dfa48ef Mon Sep 17 00:00:00 2001 From: NukeBird Date: Thu, 13 Feb 2025 18:55:56 +0300 Subject: [PATCH] Add dinkyecs.hpp --- dinkyecs.hpp | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 dinkyecs.hpp diff --git a/dinkyecs.hpp b/dinkyecs.hpp new file mode 100644 index 0000000..c8dc3bc --- /dev/null +++ b/dinkyecs.hpp @@ -0,0 +1,156 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "dbc.hpp" + +namespace DinkyECS { + typedef unsigned long Entity; + + using EntityMap = std::unordered_map; + + struct Event { + int event = 0; + Entity entity = 0; + std::any data; + }; + + typedef std::queue EventQueue; + + struct World { + unsigned long entity_count = 0; + std::unordered_map $components; + std::unordered_map $facts; + std::unordered_map $events; + std::vector $constants; + + Entity entity() { + return ++entity_count; + } + + void clone_into(DinkyECS::World &to_world) { + to_world.$constants = $constants; + to_world.$facts = $facts; + to_world.entity_count = entity_count; + + for(auto eid : $constants) { + for(const auto &[tid, eid_map] : $components) { + auto& their_map = to_world.$components[tid]; + if(eid_map.contains(eid)) { + their_map.insert_or_assign(eid, eid_map.at(eid)); + } + } + } + } + + void make_constant(DinkyECS::Entity entity) { + $constants.push_back(entity); + } + + template + EntityMap& entity_map_for() { + return $components[std::type_index(typeid(Comp))]; + } + + template + EventQueue& queue_map_for() { + return $events[std::type_index(typeid(Comp))]; + } + + template + void remove(Entity ent) { + EntityMap &map = entity_map_for(); + map.erase(ent); + } + + template + void set_the(Comp val) { + $facts.insert_or_assign(std::type_index(typeid(Comp)), val); + } + + template + Comp &get_the() { + auto comp_id = std::type_index(typeid(Comp)); + dbc::check($facts.contains(comp_id), + fmt::format("!!!! ATTEMPT to access world fact that hasn't been set yet: {}", typeid(Comp).name())); + + // use .at to get std::out_of_range if fact not set + std::any &res = $facts.at(comp_id); + return std::any_cast(res); + } + + template + bool has_the() { + auto comp_id = std::type_index(typeid(Comp)); + return $facts.contains(comp_id); + } + + template + void set(Entity ent, Comp val) { + EntityMap &map = entity_map_for(); + map.insert_or_assign(ent, val); + } + + template + Comp &get(Entity ent) { + EntityMap &map = entity_map_for(); + // use .at for bounds checking + std::any &res = map.at(ent); + return std::any_cast(res); + } + + template + bool has(Entity ent) { + EntityMap &map = entity_map_for(); + return map.contains(ent); + } + + template + void query(std::function cb) { + EntityMap &map = entity_map_for(); + for(auto& [entity, any_comp] : map) { + Comp &res = std::any_cast(any_comp); + cb(entity, res); + } + } + + template + void query(std::function cb) { + EntityMap &map_a = entity_map_for(); + EntityMap &map_b = entity_map_for(); + + for(auto& [entity, any_a] : map_a) { + if(map_b.contains(entity)) { + CompA &res_a = std::any_cast(any_a); + CompB &res_b = get(entity); + cb(entity, res_a, res_b); + } + } + } + + template + void send(Comp event, Entity entity, std::any data) { + EventQueue &queue = queue_map_for(); + queue.push({event, entity, data}); + } + + template + Event recv() { + EventQueue &queue = queue_map_for(); + Event evt = queue.front(); + queue.pop(); + return evt; + } + + template + bool has_event() { + EventQueue &queue = queue_map_for(); + return !queue.empty(); + } + }; +}