package demonchime import "core:math" Entity_Handle :: struct { idx: u32, uses: u32, } Entity_List :: struct($T: typeid) { items: [dynamic]T, holes: [dynamic]Entity_Handle, } delete_entity_list :: proc(list: Entity_List($T)) { delete(list.items) delete(list.holes) } make_entity :: proc(list: ^Entity_List($T), ent: T) -> (Entity_Handle, ^T) { handle: Entity_Handle if len(list.holes) > 0 { handle = pop(&list.holes) handle.uses += 1 } else { // because index 0 in a handle is considered a null handle resize(&list.items, math.max(2, len(list.items) + 1)) handle.idx = u32(len(list.items) - 1) handle.uses = 1 } list.items[handle.idx] = ent list.items[handle.idx].handle = handle return handle, &list.items[handle.idx] } delete_entity :: proc(list: ^Entity_List($T), handle: Entity_Handle) { if handle.idx <= 0 || int(handle.idx) >= len(list.items) { return } if list.items[handle.idx].handle != handle { return } append(&list.holes, handle) list.items[handle.idx] = {} } get_entity :: proc(list: Entity_List($T), h: Entity_Handle) -> ^T { if h.idx < 1 || h.idx >= u32(len(list.items)) || list.items[h.idx].handle != h { return nil } return &list.items[h.idx] } active_entity_count :: proc(list: Entity_List($T)) -> int { // - 1 because there's an empty slot at the beginning return len(list.items) - len(list.holes) - 1 } Entity_List_Iter :: struct($T: typeid) { list: Entity_List(T), idx: int, } iter_entity_list :: proc(list: Entity_List($T)) -> Entity_List_Iter(T) { return Entity_List_Iter(T){list = list} } entity_list_iter :: proc(it: ^Entity_List_Iter($T)) -> (^T, bool) { for it.idx < len(it.list.items) { if it.list.items[it.idx].handle.idx > 0 { entity := &it.list.items[it.idx] it.idx += 1 return entity, true } it.idx += 1 } return nil, false }