gohan/component.go

80 lines
1.8 KiB
Go

package gohan
import (
"reflect"
)
// componentID is a component identifier. Each Component is assigned a unique ID
// via world.NewComponentID, and implements a componentID method returning its ID.
type componentID int
// newComponentID returns the next available componentID.
func newComponentID() componentID {
w.maxComponentID++
for i := Entity(1); i <= w.maxEntityID; i++ {
w.components[i] = append(w.components[i], nil)
}
return w.maxComponentID
}
func componentIDByValue(v interface{}) componentID {
sV := reflect.ValueOf(v)
sT := reflect.TypeOf(v)
if sV.Kind() == reflect.Ptr {
sV = sV.Elem()
sT = sT.Elem()
}
componentName := sV.Type().String()
return componentIDByName(componentName)
}
func componentIDByName(name string) componentID {
if len(name) == 0 {
return 0
}
if name[0:1] == "*" {
name = name[1:]
}
if !w.haveSystemComponentName[name] {
w.systemComponentNames = append(w.systemComponentNames, name)
w.haveSystemComponentName[name] = true
id := newComponentID() // ComponentNames index now aligns with componentID
return id
}
for i, savedName := range w.systemComponentNames {
if savedName == name {
return componentID(i)
}
}
return 0
}
// AddComponent adds a Component to an Entity.
func (entity Entity) AddComponent(component interface{}) {
w.componentMutex.Lock()
defer w.componentMutex.Unlock()
id := componentIDByValue(component)
w.components[entity][id] = component
w.entityMutex.Lock()
defer w.entityMutex.Unlock()
w.modifiedEntities = append(w.modifiedEntities, entity)
}
// getComponent gets a Component of an Entity.
func (entity Entity) getComponent(componentID componentID) interface{} {
components := w.components[entity]
if components == nil {
return nil
}
return components[componentID]
}