71 lines
2.7 KiB
Go
71 lines
2.7 KiB
Go
package westworldwithmessaging
|
|
|
|
import "sync"
|
|
|
|
// entityManager is the Go version of the singleton class
|
|
// EntityManager. Same singleton pattern used throughout this
|
|
// package: an unexported type, one shared instance, reached only
|
|
// through the EntityManager() function below.
|
|
//
|
|
// The C++ version stores "BaseGameEntity*" pointers in its map. In
|
|
// C++, a BaseGameEntity* pointing at an actual Miner still calls
|
|
// Miner's real Update() (that's what "virtual" functions do - even
|
|
// through a base-class pointer, the real subclass's version runs).
|
|
// Go doesn't have virtual functions or base-class pointers, but our
|
|
// Entity interface (from entity.go: Update() and ID()) gives us the
|
|
// exact same behavior - a variable of type Entity holding a *Miner
|
|
// still calls *Miner's own Update(). So Entity is what we store here
|
|
// instead of *BaseGameEntity, to get the same real-subclass-runs
|
|
// behavior C++ gets from virtual dispatch.
|
|
type entityManager struct {
|
|
// entityMap cross-references entities by their ID number, same
|
|
// as the book's std::map<int, BaseGameEntity*> m_EntityMap. (The
|
|
// book's own comment above that field actually describes a
|
|
// std::vector instead - a leftover mismatch in the book's text
|
|
// itself. We're matching the real field, the map.)
|
|
entityMap map[int]Entity
|
|
}
|
|
|
|
var (
|
|
entityManagerInstance *entityManager
|
|
entityManagerOnce sync.Once
|
|
)
|
|
|
|
// EntityManager is the Go stand-in for "EntityManager::Instance()".
|
|
func EntityManager() *entityManager {
|
|
entityManagerOnce.Do(func() {
|
|
entityManagerInstance = &entityManager{
|
|
entityMap: make(map[int]Entity),
|
|
}
|
|
})
|
|
return entityManagerInstance
|
|
}
|
|
|
|
// EntityMgr is a shorthand for EntityManager(), matching the book's
|
|
// "#define EntityMgr EntityManager::Instance()" macro. Go has no
|
|
// preprocessor and no macros, so instead this is just a plain
|
|
// package-level variable, set up once when the package is loaded -
|
|
// EntityMgr.RegisterEntity(...) reads the same as the book's
|
|
// EntityMgr->RegisterEntity(...), just with a dot instead of an
|
|
// arrow (Go doesn't distinguish "." for values from "->" for
|
|
// pointers the way C++ does - it's always ".").
|
|
var EntityMgr = EntityManager()
|
|
|
|
// RegisterEntity stores an entity so it can be looked up later by
|
|
// its ID.
|
|
func (m *entityManager) RegisterEntity(newEntity Entity) {
|
|
m.entityMap[newEntity.ID()] = newEntity
|
|
}
|
|
|
|
// GetEntityFromID returns the entity with the given ID, or nil if
|
|
// none is registered under that ID (same as the C++ version
|
|
// implicitly returning nullptr for a lookup miss).
|
|
func (m *entityManager) GetEntityFromID(id int) Entity {
|
|
return m.entityMap[id]
|
|
}
|
|
|
|
// RemoveEntity removes an entity from the registry.
|
|
func (m *entityManager) RemoveEntity(entity Entity) {
|
|
delete(m.entityMap, entity.ID())
|
|
}
|