Redo and simplify registry and move to own package

This commit is contained in:
bloeys
2023-10-06 07:28:16 +04:00
parent 1b83d7f9a7
commit 039d09f888
8 changed files with 198 additions and 178 deletions

View File

@ -1,19 +1,18 @@
package entity
import "github.com/bloeys/nmage/assert"
import "github.com/bloeys/nmage/registry"
var _ Comp = &BaseComp{}
type BaseComp struct {
Entity *BaseEntity
Handle registry.Handle
}
func (b BaseComp) baseComp() {
}
func (b *BaseComp) Init(parent *BaseEntity) {
assert.T(parent != nil, "Component was initialized with a nil parent. That is not allowed.")
b.Entity = parent
func (b *BaseComp) Init(parentHandle registry.Handle) {
b.Handle = parentHandle
}
func (b BaseComp) Name() string {

View File

@ -1,6 +1,9 @@
package entity
import "github.com/bloeys/nmage/assert"
import (
"github.com/bloeys/nmage/assert"
"github.com/bloeys/nmage/registry"
)
type Comp interface {
// This ensures that implementors of the Comp interface
@ -8,7 +11,7 @@ type Comp interface {
baseComp()
Name() string
Init(parent *BaseEntity)
Init(parentHandle registry.Handle)
Update()
Destroy()
}
@ -21,12 +24,12 @@ type CompContainer struct {
Comps []Comp
}
func AddComp[T Comp](e *BaseEntity, cc *CompContainer, c T) {
func AddComp[T Comp](entityHandle registry.Handle, cc *CompContainer, c T) {
assert.T(!HasComp[T](cc), "Entity with id '%v' already has component of type '%T'", e.ID, c)
assert.T(!HasComp[T](cc), "Entity with id '%v' already has component of type '%T'", entityHandle, c)
cc.Comps = append(cc.Comps, c)
c.Init(e)
c.Init(entityHandle)
}
func HasComp[T Comp](e *CompContainer) bool {

View File

@ -1,54 +1,7 @@
package entity
type EntityFlag byte
const (
EntityFlag_None EntityFlag = 0
EntityFlag_Alive EntityFlag = 1 << (iota - 1)
)
const (
GenerationShiftBits = 64 - 8
FlagsShiftBits = 64 - 16
IndexBitMask = 0x00_00_FFFF_FFFF_FFFF
)
import "github.com/bloeys/nmage/registry"
type Entity interface {
baseEntity()
GetHandle() EntityHandle
}
type EntityHandle uint64
var _ Entity = &BaseEntity{}
type BaseEntity struct {
// Byte 1: Generation; Byte 2: Flags; Bytes 3-8: Index
ID EntityHandle
}
func (be BaseEntity) baseEntity() {}
func (be BaseEntity) GetHandle() EntityHandle {
return be.ID
}
func (e *BaseEntity) HasFlag(ef EntityFlag) bool {
return GetFlags(e.ID)&ef > 0
}
func GetGeneration(id EntityHandle) byte {
return byte(id >> GenerationShiftBits)
}
func GetFlags(id EntityHandle) EntityFlag {
return EntityFlag(id >> FlagsShiftBits)
}
func GetIndex(id EntityHandle) uint64 {
return uint64(id & IndexBitMask)
}
func NewEntityId(generation byte, flags EntityFlag, index uint64) EntityHandle {
return EntityHandle(index | (uint64(generation) << GenerationShiftBits) | (uint64(flags) << FlagsShiftBits))
GetHandle() registry.Handle
}

View File

@ -1,104 +0,0 @@
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 []BaseEntity
FreeList *freeListitem
FreeListSize uint32
}
func (r *Registry) NewEntity() *BaseEntity {
assert.T(r.EntityCount < uint64(len(r.Entities)), "Can not add more entities to registry because it is full")
entityToUseIndex := uint64(0)
var entityToUse *BaseEntity = 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) *BaseEntity {
index := GetIndex(id)
gen := GetGeneration(id)
e := &r.Entities[index]
eGen := GetGeneration(e.ID)
if gen != eGen {
return nil
}
return e
}
// FreeEntity resets the entity flags then adds this entity to the free list
func (r *Registry) FreeEntity(id EntityHandle) {
e := r.GetEntity(id)
if e == nil {
return
}
r.EntityCount--
eIndex := GetIndex(e.ID)
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([]BaseEntity, size),
}
}