Improve entity flags+add freeListSize to registry

This commit is contained in:
bloeys
2022-12-06 04:51:03 +04:00
parent 36488ead04
commit 23a6689346
2 changed files with 21 additions and 12 deletions

View File

@ -3,9 +3,8 @@ package entity
type EntityFlag byte type EntityFlag byte
const ( const (
EntityFlag_Unknown EntityFlag = 0 EntityFlag_None EntityFlag = 0
EntityFlag_Dead EntityFlag = 1 << (iota - 1) EntityFlag_Alive EntityFlag = 1 << (iota - 1)
EntityFlag_Alive
) )
const ( const (
@ -25,8 +24,8 @@ func GetGeneration(id uint64) byte {
return byte(id >> GenerationShiftBits) return byte(id >> GenerationShiftBits)
} }
func GetFlags(id uint64) byte { func GetFlags(id uint64) EntityFlag {
return byte(id >> FlagsShiftBits) return EntityFlag(id >> FlagsShiftBits)
} }
func GetIndex(id uint64) uint64 { func GetIndex(id uint64) uint64 {
@ -34,10 +33,10 @@ func GetIndex(id uint64) uint64 {
} }
func (e *Entity) HasFlag(ef EntityFlag) bool { func (e *Entity) HasFlag(ef EntityFlag) bool {
return GetFlags(e.ID)&byte(ef) > 0 return GetFlags(e.ID)&ef > 0
} }
func NewEntityId(generation, flags byte, index uint64) uint64 { func NewEntityId(generation byte, flags EntityFlag, index uint64) uint64 {
return index | (uint64(generation) << GenerationShiftBits) | (uint64(flags) << FlagsShiftBits) return index | (uint64(generation) << GenerationShiftBits) | (uint64(flags) << FlagsShiftBits)
} }

View File

@ -4,6 +4,12 @@ import (
"github.com/bloeys/nmage/assert" "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 { type freeListitem struct {
EntityIndex uint64 EntityIndex uint64
nextFree *freeListitem nextFree *freeListitem
@ -12,7 +18,9 @@ type freeListitem struct {
type Registry struct { type Registry struct {
EntityCount uint64 EntityCount uint64
Entities []Entity Entities []Entity
FreeList *freeListitem
FreeList *freeListitem
FreeListSize uint32
} }
func (r *Registry) NewEntity() *Entity { func (r *Registry) NewEntity() *Entity {
@ -22,17 +30,18 @@ func (r *Registry) NewEntity() *Entity {
entityToUseIndex := uint64(0) entityToUseIndex := uint64(0)
var entityToUse *Entity = nil var entityToUse *Entity = nil
if r.FreeList != nil { if r.FreeList != nil && r.FreeListSize > FreeListUsageThreshold {
entityToUseIndex = r.FreeList.EntityIndex entityToUseIndex = r.FreeList.EntityIndex
entityToUse = &r.Entities[entityToUseIndex] entityToUse = &r.Entities[entityToUseIndex]
r.FreeList = r.FreeList.nextFree r.FreeList = r.FreeList.nextFree
r.FreeListSize--
} else { } else {
for i := 0; i < len(r.Entities); i++ { for i := 0; i < len(r.Entities); i++ {
e := &r.Entities[i] e := &r.Entities[i]
if GetFlags(e.ID) != byte(EntityFlag_Unknown) && !e.HasFlag(EntityFlag_Dead) { if e.HasFlag(EntityFlag_Alive) {
continue continue
} }
@ -47,7 +56,7 @@ func (r *Registry) NewEntity() *Entity {
} }
r.EntityCount++ r.EntityCount++
entityToUse.ID = NewEntityId(GetGeneration(entityToUse.ID)+1, byte(EntityFlag_Alive), entityToUseIndex) entityToUse.ID = NewEntityId(GetGeneration(entityToUse.ID)+1, EntityFlag_Alive, entityToUseIndex)
assert.T(entityToUse.ID != 0, "Entity ID must not be zero") assert.T(entityToUse.ID != 0, "Entity ID must not be zero")
return entityToUse return entityToUse
} }
@ -78,12 +87,13 @@ func (r *Registry) FreeEntity(id uint64) {
eIndex := GetIndex(e.ID) eIndex := GetIndex(e.ID)
e.Comps = []Comp{} e.Comps = []Comp{}
e.ID = NewEntityId(GetGeneration(e.ID), byte(EntityFlag_Dead), eIndex) e.ID = NewEntityId(GetGeneration(e.ID), EntityFlag_None, eIndex)
r.FreeList = &freeListitem{ r.FreeList = &freeListitem{
EntityIndex: eIndex, EntityIndex: eIndex,
nextFree: r.FreeList, nextFree: r.FreeList,
} }
r.FreeListSize++
} }
func NewRegistry(size uint32) *Registry { func NewRegistry(size uint32) *Registry {