#pragma once #include #include #include #include #include namespace DinkyECS { typedef unsigned long Entity; typedef std::unordered_map EntityMap; struct World { unsigned long entity_count = 0; std::unordered_map $components; std::unordered_map $facts; Entity entity() { return ++entity_count; } template EntityMap& entity_map_for() { return $components[std::type_index(typeid(Comp))]; } template void set(Comp val) { $facts[std::type_index(typeid(Comp))] = val; } template Comp &get() { // 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 assign(Entity ent, Comp val) { EntityMap &map = entity_map_for(); map[ent] = val; } template Comp &component(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 system(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 remove(Entity ent) { EntityMap &map = entity_map_for(); map.erase(ent); } template void system(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 = component(entity); cb(entity, res_a, res_b); } } } template std::function runner(std::function cb) { return [&]{ system(cb); }; } }; }