#pragma once #include #include #include #include #include #include #include namespace DinkyECS { typedef unsigned long Entity; typedef std::unordered_map EntityMap; struct Event { int event = 0; Entity entity = 0; }; typedef std::queue EventQueue; struct World { unsigned long entity_count = 0; std::unordered_map $components; std::unordered_map $facts; std::unordered_map $events; Entity entity() { return ++entity_count; } 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[std::type_index(typeid(Comp))] = val; } template Comp &get_the() { // use .at to get std::out_of_range if fact not set std::any &res = $facts.at(std::type_index(typeid(Comp))); return std::any_cast(res); } template void set(Entity ent, Comp val) { EntityMap &map = entity_map_for(); map[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 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) { EventQueue &queue = queue_map_for(); queue.push({event, entity}); } 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(); } }; }