Add dinkyecs.hpp
This commit is contained in:
		
							parent
							
								
									0ccadc9274
								
							
						
					
					
						commit
						9b4b52bc9f
					
				
					 1 changed files with 156 additions and 0 deletions
				
			
		
							
								
								
									
										156
									
								
								dinkyecs.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								dinkyecs.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,156 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <functional> | ||||
| #include <typeindex> | ||||
| #include <typeinfo> | ||||
| #include <unordered_map> | ||||
| #include <any> | ||||
| #include <tuple> | ||||
| #include <queue> | ||||
| #include "dbc.hpp" | ||||
| 
 | ||||
| namespace DinkyECS { | ||||
|   typedef unsigned long Entity; | ||||
| 
 | ||||
|   using EntityMap = std::unordered_map<Entity, std::any>; | ||||
| 
 | ||||
|   struct Event { | ||||
|     int event = 0; | ||||
|     Entity entity = 0; | ||||
|     std::any data; | ||||
|   }; | ||||
| 
 | ||||
|   typedef std::queue<Event> EventQueue; | ||||
| 
 | ||||
|   struct World { | ||||
|     unsigned long entity_count = 0; | ||||
|     std::unordered_map<std::type_index, EntityMap> $components; | ||||
|     std::unordered_map<std::type_index, std::any> $facts; | ||||
|     std::unordered_map<std::type_index, EventQueue> $events; | ||||
|     std::vector<Entity> $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 <typename Comp> | ||||
|       EntityMap& entity_map_for() { | ||||
|         return $components[std::type_index(typeid(Comp))]; | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       EventQueue& queue_map_for() { | ||||
|         return $events[std::type_index(typeid(Comp))]; | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       void remove(Entity ent) { | ||||
|         EntityMap &map = entity_map_for<Comp>(); | ||||
|         map.erase(ent); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       void set_the(Comp val) { | ||||
|         $facts.insert_or_assign(std::type_index(typeid(Comp)), val); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       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<Comp&>(res); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       bool has_the() { | ||||
|         auto comp_id = std::type_index(typeid(Comp)); | ||||
|         return $facts.contains(comp_id); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       void set(Entity ent, Comp val) { | ||||
|         EntityMap &map = entity_map_for<Comp>(); | ||||
|         map.insert_or_assign(ent, val); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       Comp &get(Entity ent) { | ||||
|         EntityMap &map = entity_map_for<Comp>(); | ||||
|         // use .at for bounds checking
 | ||||
|         std::any &res = map.at(ent); | ||||
|         return std::any_cast<Comp&>(res); | ||||
|       } | ||||
| 
 | ||||
|     template <typename Comp> | ||||
|       bool has(Entity ent) { | ||||
|         EntityMap &map = entity_map_for<Comp>(); | ||||
|         return map.contains(ent); | ||||
|       } | ||||
| 
 | ||||
|     template<typename Comp> | ||||
|       void query(std::function<void(const Entity&, Comp&)> cb) { | ||||
|         EntityMap &map = entity_map_for<Comp>(); | ||||
|         for(auto& [entity, any_comp] : map) { | ||||
|           Comp &res = std::any_cast<Comp&>(any_comp); | ||||
|           cb(entity, res); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|     template<typename CompA, typename CompB> | ||||
|       void query(std::function<void(const Entity&, CompA&, CompB&)> cb) { | ||||
|         EntityMap &map_a = entity_map_for<CompA>(); | ||||
|         EntityMap &map_b = entity_map_for<CompB>(); | ||||
| 
 | ||||
|         for(auto& [entity, any_a] : map_a) { | ||||
|           if(map_b.contains(entity)) { | ||||
|             CompA &res_a = std::any_cast<CompA&>(any_a); | ||||
|             CompB &res_b = get<CompB>(entity); | ||||
|             cb(entity, res_a, res_b); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|     template<typename Comp> | ||||
|       void send(Comp event, Entity entity, std::any data) { | ||||
|         EventQueue &queue = queue_map_for<Comp>(); | ||||
|         queue.push({event, entity, data}); | ||||
|       } | ||||
| 
 | ||||
|     template<typename Comp> | ||||
|       Event recv() { | ||||
|         EventQueue &queue = queue_map_for<Comp>(); | ||||
|         Event evt = queue.front(); | ||||
|         queue.pop(); | ||||
|         return evt; | ||||
|       } | ||||
| 
 | ||||
|     template<typename Comp> | ||||
|       bool has_event() { | ||||
|         EventQueue &queue = queue_map_for<Comp>(); | ||||
|         return !queue.empty(); | ||||
|       } | ||||
|   }; | ||||
| } | ||||
		Loading…
	
		Reference in a new issue