#ifndef world_hpp #define world_hpp struct Arena; #include #include #include using Component_Mask = uint64_t; using Entity_Id = uint32_t; #define max_entities 1024 #define pool_cap 128 #define max_components 64 struct Pool { Component_Mask mask; Pool* next; void* data; Entity_Id entities[pool_cap]; int mapping[max_entities]; int offsets[max_components]; int size, count; void init(Arena* a, Component_Mask m); void* add(Arena* a, Entity_Id eid); void* get(Entity_Id eid, int cid); void* get(Entity_Id eid); void remove(Entity_Id eid); }; int entity_version(Entity_Id e); int entity_index(Entity_Id e); Entity_Id entity_id(int index, int version); int get_new_component_id(int size); struct World { static constexpr int max_pools = 32; Pool pools[max_pools]; Component_Mask masks[max_entities]; uint8_t versions[max_entities]; Entity_Id entities[max_entities]; Entity_Id freelist[max_entities]; Arena* arena; int count, free_count; void init(Arena* a); uint64_t hash_mask(Component_Mask m); Pool& get_pool(Component_Mask m); template int get_component_id() { static int id = get_new_component_id(sizeof(T)); return id; } Entity_Id create_entity(); template Component_Mask get_mask() { return (... | ((Component_Mask)1 << get_component_id())); } template std::tuple add(Entity_Id e) { Component_Mask m = get_mask(); add(e, m); Pool& p = get_pool(masks[entity_index(e)]); return { *(T*)p.get(e, get_component_id())... }; } template T& get(Entity_Id e) { int id = get_component_id(); return *(T*)get(e, id); } template void remove(Entity_Id e) { int id = get_component_id(); remove(e, id); } template bool has(Entity_Id e) { int id = get_component_id(); Component_Mask m = masks[entity_index(e)]; return (m & ((Component_Mask)1 << id)) != 0; } void* add(Entity_Id eid, Component_Mask m); void* get(Entity_Id eid, int cid); void remove(Entity_Id eid, int cid); void destroy(Entity_Id e); struct View { World* w; Pool* pools[max_pools]; int pool_count; struct Iter { View* v; int ptr, ind; bool equals(const Iter& other) { return ptr == other.ptr && ind == other.ind; } bool operator==(const Iter& other) { return equals(other); } bool operator!=(const Iter& other) { return !equals(other); } Iter operator++() { Pool* p = v->pools[ind]; ptr++; if (ptr == p->count) { ptr = 0; ind++; } return *this; } template C& get() { Pool* p = v->pools[ind]; return *(C*)( (char*)p->data + ptr * p->size + p->offsets[v->w->get_component_id()] ); } Iter& operator*() { return *this; } Entity_Id entity() { Pool* p = v->pools[ind]; return p->entities[ptr]; } }; Iter begin() { Iter i; i.v = this; i.ind = 0; i.ptr = 0; return i; } Iter end() { Iter i; i.v = this; i.ind = pool_count; i.ptr = 0; return i; } }; template View view() { int i; auto m = get_mask(); View v; v.w = this; v.pool_count = 0; for (i = 0; i < max_pools; i++) { Pool& p = pools[i]; if (p.count && m == (p.mask & m)) v.pools[v.pool_count++] = &p; } return v; } }; #endif