package entity import ( "github.com/bloeys/nmage/assert" ) var ( // The number of slots required to be in the free list before the free list // is used for creating new entries FreeListUsageThreshold uint32 = 20 ) type freeListitem struct { EntityIndex uint64 nextFree *freeListitem } type Registry struct { EntityCount uint64 Entities []Entity FreeList *freeListitem FreeListSize uint32 } func (r *Registry) NewEntity() *Entity { assert.T(r.EntityCount < uint64(len(r.Entities)), "Can not add more entities to registry because it is full") entityToUseIndex := uint64(0) var entityToUse *Entity = nil if r.FreeList != nil && r.FreeListSize > FreeListUsageThreshold { entityToUseIndex = r.FreeList.EntityIndex entityToUse = &r.Entities[entityToUseIndex] r.FreeList = r.FreeList.nextFree r.FreeListSize-- } else { for i := 0; i < len(r.Entities); i++ { e := &r.Entities[i] if e.HasFlag(EntityFlag_Alive) { continue } entityToUse = e entityToUseIndex = uint64(i) break } } if entityToUse == nil { panic("failed to create new entity because we did not find a free spot in the registry. Why did the assert not go off?") } r.EntityCount++ entityToUse.ID = NewEntityId(GetGeneration(entityToUse.ID)+1, EntityFlag_Alive, entityToUseIndex) assert.T(entityToUse.ID != 0, "Entity ID must not be zero") return entityToUse } func (r *Registry) GetEntity(id EntityHandle) *Entity { index := GetIndex(id) gen := GetGeneration(id) e := &r.Entities[index] eGen := GetGeneration(e.ID) if gen != eGen { return nil } return e } func (r *Registry) FreeEntity(id EntityHandle) { e := r.GetEntity(id) if e == nil { return } for i := 0; i < len(e.Comps); i++ { e.Comps[i].Destroy() } r.EntityCount-- eIndex := GetIndex(e.ID) e.Comps = []Comp{} e.ID = NewEntityId(GetGeneration(e.ID), EntityFlag_None, eIndex) r.FreeList = &freeListitem{ EntityIndex: eIndex, nextFree: r.FreeList, } r.FreeListSize++ } func NewRegistry(size uint32) *Registry { assert.T(size > 0, "Registry size must be more than zero") return &Registry{ Entities: make([]Entity, size), } }