131 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| 
 | |
| #include <functional>
 | |
| #include <typeindex>
 | |
| #include <typeinfo>
 | |
| #include <unordered_map>
 | |
| #include <any>
 | |
| #include <tuple>
 | |
| #include <queue>
 | |
| #include "tser.hpp"
 | |
| #include "dbc.hpp"
 | |
| 
 | |
| namespace DinkyECS {
 | |
| 
 | |
|   typedef unsigned long Entity;
 | |
| 
 | |
|   typedef std::unordered_map<Entity, std::any> EntityMap;
 | |
| 
 | |
|   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;
 | |
| 
 | |
|     Entity entity() {
 | |
|       return ++entity_count;
 | |
|     }
 | |
| 
 | |
|     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[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), "!!!! ATTEMPT to access world fact that hasn't been set yet.");
 | |
| 
 | |
|         // 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>
 | |
|       void set(Entity ent, Comp val) {
 | |
|         EntityMap &map = entity_map_for<Comp>();
 | |
|         map[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();
 | |
|       }
 | |
|   };
 | |
| }
 | 
