diff --git a/d2core/d2components/all_component_ids.go b/d2core/d2components/all_component_ids.go deleted file mode 100644 index 4d8ea764..00000000 --- a/d2core/d2components/all_component_ids.go +++ /dev/null @@ -1,41 +0,0 @@ -package d2components - -import ( - "github.com/gravestench/akara" -) - -// Component type ID's -const ( - GameConfigCID akara.ComponentID = iota - FilePathCID - FileTypeCID - FileSourceCID - FileHandleCID - AssetStringTableCID - AssetFontTableCID - AssetDataDictionaryCID - AssetPaletteCID - AssetPaletteTransformCID - AssetCofCID - AssetDc6CID - AssetDccCID - AssetDs1CID - AssetDt1CID - AssetWavCID - AssetD2AnimDataCID - PositionCID - VelocityCID - DirtyCID - PriorityCID - RenderableCID - CameraCID - ViewportCID - ViewportFilterCID - MainViewportCID - OriginCID - SizeCID - AnimationCID - ScaleCID - AlphaCID - SegmentedSpriteCID -) diff --git a/d2core/d2components/alpha.go b/d2core/d2components/alpha.go index 4632486c..82a8c51a 100644 --- a/d2core/d2components/alpha.go +++ b/d2core/d2components/alpha.go @@ -5,60 +5,40 @@ import ( "github.com/gravestench/akara" ) -// static check that AlphaComponent implements Component -var _ akara.Component = &AlphaComponent{} +// static check that Alpha implements Component +var _ akara.Component = &Alpha{} -// static check that AlphaMap implements ComponentMap -var _ akara.ComponentMap = &AlphaMap{} - -// AlphaComponent is a component that contains an embedded cof struct -type AlphaComponent struct { - *akara.BaseComponent +// Alpha is a component that contains normalized alpha transparency (0.0 ... 1.0) +type Alpha struct { Alpha float64 } -// AlphaMap is a map of entity ID's to Alpha -type AlphaMap struct { - *akara.BaseComponentMap -} +// New creates a new alpha component instance. The default alpha is opaque with value 1.0 +func (*Alpha) New() akara.Component { + const defaultAlpha = 1.0 -// AddAlpha adds a new AlphaComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *AlphaComponent instead of an akara.Component -func (cm *AlphaMap) AddAlpha(id akara.EID) *AlphaComponent { - c := cm.Add(id).(*AlphaComponent) - - c.Alpha = 1 - - return c -} - -// GetAlpha returns the AlphaComponent associated with the given entity id -func (cm *AlphaMap) GetAlpha(id akara.EID) (*AlphaComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*AlphaComponent), found -} - -// Alpha is a convenient reference to be used as a component identifier -var Alpha = newAlpha() // nolint:gochecknoglobals // global by design - -func newAlpha() akara.Component { - return &AlphaComponent{ - BaseComponent: akara.NewBaseComponent(AlphaCID, newAlpha, newAlphaMap), + return &Alpha{ + Alpha: defaultAlpha, } } -func newAlphaMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AlphaCID, newAlpha, newAlphaMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// AlphaFactory is a wrapper for the generic component factory that returns Alpha component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Alpha. +type AlphaFactory struct { + Alpha *akara.ComponentFactory +} - cm := &AlphaMap{ - BaseComponentMap: baseMap, +// AddAlpha adds a Alpha component to the given entity and returns it +func (m *AlphaFactory) AddAlpha(id akara.EID) *Alpha { + return m.Alpha.Add(id).(*Alpha) +} + +// GetAlpha returns the Alpha component for the given entity, and a bool for whether or not it exists +func (m *AlphaFactory) GetAlpha(id akara.EID) (*Alpha, bool) { + component, found := m.Alpha.Get(id) + if !found { + return nil, found } - return cm + return component.(*Alpha), found } diff --git a/d2core/d2components/animation.go b/d2core/d2components/animation.go index 2befa3f7..12373ee5 100644 --- a/d2core/d2components/animation.go +++ b/d2core/d2components/animation.go @@ -8,55 +8,35 @@ import ( ) // static check that AnimationComponent implements Component -var _ akara.Component = &AnimationComponent{} +var _ akara.Component = &Animation{} -// static check that AnimationMap implements ComponentMap -var _ akara.ComponentMap = &AnimationMap{} - -// AnimationComponent is a component that contains a width and height -type AnimationComponent struct { - *akara.BaseComponent +// Animation is a component that contains a width and height +type Animation struct { d2interface.Animation } -// AnimationMap is a map of entity ID's to Animation -type AnimationMap struct { - *akara.BaseComponentMap +// New returns an animation component. By default, it contains a nil instance of an animation. +func (*Animation) New() akara.Component { + return &Animation{} } -// AddAnimation adds a new AnimationComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *AnimationComponent instead of an akara.Component -func (cm *AnimationMap) AddAnimation(id akara.EID) *AnimationComponent { - return cm.Add(id).(*AnimationComponent) +// AnimationFactory is a wrapper for the generic component factory that returns Animation component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Animation. +type AnimationFactory struct { + Animation *akara.ComponentFactory } -// GetAnimation returns the AnimationComponent associated with the given entity id -func (cm *AnimationMap) GetAnimation(id akara.EID) (*AnimationComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddAnimation adds a Animation component to the given entity and returns it +func (m *AnimationFactory) AddAnimation(id akara.EID) *Animation { + return m.Animation.Add(id).(*Animation) +} + +// GetAnimation returns the Animation component for the given entity, and a bool for whether or not it exists +func (m *AnimationFactory) GetAnimation(id akara.EID) (*Animation, bool) { + component, found := m.Animation.Get(id) + if !found { + return nil, found } - return entry.(*AnimationComponent), found -} - -// Animation is a convenient reference to be used as a component identifier -var Animation = newAnimation() // nolint:gochecknoglobals // global by design - -func newAnimation() akara.Component { - return &AnimationComponent{ - BaseComponent: akara.NewBaseComponent(AnimationCID, newAnimation, newAnimationMap), - } -} - -func newAnimationMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AnimationCID, newAnimation, newAnimationMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &AnimationMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Animation), found } diff --git a/d2core/d2components/asset_cof.go b/d2core/d2components/asset_cof.go index b393ca51..2525b30a 100644 --- a/d2core/d2components/asset_cof.go +++ b/d2core/d2components/asset_cof.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof" ) -// static check that CofComponent implements Component -var _ akara.Component = &CofComponent{} +// static check that Cof implements Component +var _ akara.Component = &Cof{} -// static check that CofMap implements ComponentMap -var _ akara.ComponentMap = &CofMap{} - -// CofComponent is a component that contains an embedded cof struct -type CofComponent struct { - *akara.BaseComponent +// Cof is a component that contains an embedded cof struct +type Cof struct { *d2cof.COF } -// CofMap is a map of entity ID's to Cof -type CofMap struct { - *akara.BaseComponentMap +// New returns a new Cof component. By default, it contains a nil instance. +func (*Cof) New() akara.Component { + return &Cof{} } -// AddCof adds a new CofComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *CofComponent instead of an akara.Component -func (cm *CofMap) AddCof(id akara.EID) *CofComponent { - return cm.Add(id).(*CofComponent) +// CofFactory is a wrapper for the generic component factory that returns Cof component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Cof. +type CofFactory struct { + Cof *akara.ComponentFactory } -// GetCof returns the CofComponent associated with the given entity id -func (cm *CofMap) GetCof(id akara.EID) (*CofComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddCof adds a Cof component to the given entity and returns it +func (m *CofFactory) AddCof(id akara.EID) *Cof { + return m.Cof.Add(id).(*Cof) +} + +// GetCof returns the Cof component for the given entity, and a bool for whether or not it exists +func (m *CofFactory) GetCof(id akara.EID) (*Cof, bool) { + component, found := m.Cof.Get(id) + if !found { + return nil, found } - return entry.(*CofComponent), found -} - -// Cof is a convenient reference to be used as a component identifier -var Cof = newCof() // nolint:gochecknoglobals // global by design - -func newCof() akara.Component { - return &CofComponent{ - BaseComponent: akara.NewBaseComponent(AssetCofCID, newCof, newCofMap), - } -} - -func newCofMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetCofCID, newCof, newCofMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &CofMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Cof), found } diff --git a/d2core/d2components/asset_d2animdata.go b/d2core/d2components/asset_d2animdata.go index 18521fe4..5dc638fe 100644 --- a/d2core/d2components/asset_d2animdata.go +++ b/d2core/d2components/asset_d2animdata.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2animdata" ) -// static check that AnimDataComponent implements Component -var _ akara.Component = &AnimDataComponent{} +// static check that AnimationData implements Component +var _ akara.Component = &AnimationData{} -// static check that AnimDataMap implements ComponentMap -var _ akara.ComponentMap = &AnimDataMap{} - -// AnimDataComponent is a component that contains an embedded AnimationData struct -type AnimDataComponent struct { - *akara.BaseComponent +// AnimationData is a component that contains an embedded AnimationData struct +type AnimationData struct { *d2animdata.AnimationData } -// AnimDataMap is a map of entity ID's to AnimData -type AnimDataMap struct { - *akara.BaseComponentMap +// New returns an AnimationData component. By default, it contains a nil instance. +func (*AnimationData) New() akara.Component { + return &AnimationData{} } -// AddAnimData adds a new AnimDataComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *AnimDataComponent instead of an akara.Component -func (cm *AnimDataMap) AddAnimData(id akara.EID) *AnimDataComponent { - return cm.Add(id).(*AnimDataComponent) +// AnimationDataFactory is a wrapper for the generic component factory that returns AnimationData component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a AnimationData. +type AnimationDataFactory struct { + AnimationData *akara.ComponentFactory } -// GetAnimData returns the AnimDataComponent associated with the given entity id -func (cm *AnimDataMap) GetAnimData(id akara.EID) (*AnimDataComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddAnimationData adds a AnimationData component to the given entity and returns it +func (m *AnimationDataFactory) AddAnimationData(id akara.EID) *AnimationData { + return m.AnimationData.Add(id).(*AnimationData) +} + +// GetAnimationData returns the AnimationData component for the given entity, and a bool for whether or not it exists +func (m *AnimationDataFactory) GetAnimationData(id akara.EID) (*AnimationData, bool) { + component, found := m.AnimationData.Get(id) + if !found { + return nil, found } - return entry.(*AnimDataComponent), found -} - -// AnimData is a convenient reference to be used as a component identifier -var AnimData = newAnimData() // nolint:gochecknoglobals // global by design - -func newAnimData() akara.Component { - return &AnimDataComponent{ - BaseComponent: akara.NewBaseComponent(AssetD2AnimDataCID, newAnimData, newAnimDataMap), - } -} - -func newAnimDataMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetD2AnimDataCID, newAnimData, newAnimDataMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &AnimDataMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*AnimationData), found } diff --git a/d2core/d2components/asset_data_dictionary.go b/d2core/d2components/asset_data_dictionary.go index 17419a2e..99edb252 100644 --- a/d2core/d2components/asset_data_dictionary.go +++ b/d2core/d2components/asset_data_dictionary.go @@ -8,55 +8,35 @@ import ( ) // static check that DataDictionaryComponent implements Component -var _ akara.Component = &DataDictionaryComponent{} +var _ akara.Component = &DataDictionary{} -// static check that DataDictionaryMap implements ComponentMap -var _ akara.ComponentMap = &DataDictionaryMap{} - -// DataDictionaryComponent is a component that contains an embedded txt data dictionary struct -type DataDictionaryComponent struct { - *akara.BaseComponent +// DataDictionary is a component that contains an embedded txt data dictionary struct +type DataDictionary struct { *d2txt.DataDictionary } -// DataDictionaryMap is a map of entity ID's to DataDictionary -type DataDictionaryMap struct { - *akara.BaseComponentMap +// New returns a DataDictionary component. By default, it contains a nil instance. +func (*DataDictionary) New() akara.Component { + return &AnimationData{} } -// AddDataDictionary adds a new DataDictionaryComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *DataDictionaryComponent instead of an akara.Component -func (cm *DataDictionaryMap) AddDataDictionary(id akara.EID) *DataDictionaryComponent { - return cm.Add(id).(*DataDictionaryComponent) +// DataDictionaryFactory is a wrapper for the generic component factory that returns DataDictionary component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a DataDictionary. +type DataDictionaryFactory struct { + DataDictionary *akara.ComponentFactory } -// GetDataDictionary returns the DataDictionaryComponent associated with the given entity id -func (cm *DataDictionaryMap) GetDataDictionary(id akara.EID) (*DataDictionaryComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDataDictionary adds a DataDictionary component to the given entity and returns it +func (m *DataDictionaryFactory) AddDataDictionary(id akara.EID) *DataDictionary { + return m.DataDictionary.Add(id).(*DataDictionary) +} + +// GetDataDictionary returns the DataDictionary component for the given entity, and a bool for whether or not it exists +func (m *DataDictionaryFactory) GetDataDictionary(id akara.EID) (*DataDictionary, bool) { + component, found := m.DataDictionary.Get(id) + if !found { + return nil, found } - return entry.(*DataDictionaryComponent), found -} - -// DataDictionary is a convenient reference to be used as a component identifier -var DataDictionary = newDataDictionary() // nolint:gochecknoglobals // global by design - -func newDataDictionary() akara.Component { - return &DataDictionaryComponent{ - BaseComponent: akara.NewBaseComponent(AssetDataDictionaryCID, newDataDictionary, newDataDictionaryMap), - } -} - -func newDataDictionaryMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetDataDictionaryCID, newDataDictionary, newDataDictionaryMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &DataDictionaryMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*DataDictionary), found } diff --git a/d2core/d2components/asset_dc6.go b/d2core/d2components/asset_dc6.go index 6ed43b20..2f02e53a 100644 --- a/d2core/d2components/asset_dc6.go +++ b/d2core/d2components/asset_dc6.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6" ) -// static check that Dc6Component implements Component -var _ akara.Component = &Dc6Component{} +// static check that Dc6 implements Component +var _ akara.Component = &Dc6{} -// static check that Dc6Map implements ComponentMap -var _ akara.ComponentMap = &Dc6Map{} - -// Dc6Component is a component that contains an embedded DC6 struct -type Dc6Component struct { - *akara.BaseComponent +// Dc6 is a component that contains an embedded DC6 struct +type Dc6 struct { *d2dc6.DC6 } -// Dc6Map is a map of entity ID's to Dc6 -type Dc6Map struct { - *akara.BaseComponentMap +// New returns a Dc6 component. By default, it contains a nil instance. +func (*Dc6) New() akara.Component { + return &Dc6{} } -// AddDc6 adds a new Dc6Component for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *Dc6Component instead of an akara.Component -func (cm *Dc6Map) AddDc6(id akara.EID) *Dc6Component { - return cm.Add(id).(*Dc6Component) +// Dc6Factory is a wrapper for the generic component factory that returns Dc6 component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Dc6. +type Dc6Factory struct { + Dc6 *akara.ComponentFactory } -// GetDc6 returns the Dc6Component associated with the given entity id -func (cm *Dc6Map) GetDc6(id akara.EID) (*Dc6Component, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDc6 adds a Dc6 component to the given entity and returns it +func (m *Dc6Factory) AddDc6(id akara.EID) *Dc6 { + return m.Dc6.Add(id).(*Dc6) +} + +// GetDc6 returns the Dc6 component for the given entity, and a bool for whether or not it exists +func (m *Dc6Factory) GetDc6(id akara.EID) (*Dc6, bool) { + component, found := m.Dc6.Get(id) + if !found { + return nil, found } - return entry.(*Dc6Component), found -} - -// Dc6 is a convenient reference to be used as a component identifier -var Dc6 = newDc6() // nolint:gochecknoglobals // global by design - -func newDc6() akara.Component { - return &Dc6Component{ - BaseComponent: akara.NewBaseComponent(AssetDc6CID, newDc6, newDc6Map), - } -} - -func newDc6Map() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetDc6CID, newDc6, newDc6Map) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &Dc6Map{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Dc6), found } diff --git a/d2core/d2components/asset_dcc.go b/d2core/d2components/asset_dcc.go index 5eb0f18f..e1b1bf87 100644 --- a/d2core/d2components/asset_dcc.go +++ b/d2core/d2components/asset_dcc.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc" ) -// static check that DccComponent implements Component -var _ akara.Component = &DccComponent{} +// static check that Dcc implements Component +var _ akara.Component = &Dcc{} -// static check that DccMap implements ComponentMap -var _ akara.ComponentMap = &DccMap{} - -// DccComponent is a component that contains an embedded DCC struct -type DccComponent struct { - *akara.BaseComponent +// Dcc is a component that contains an embedded DCC struct +type Dcc struct { *d2dcc.DCC } -// DccMap is a map of entity ID's to Dcc -type DccMap struct { - *akara.BaseComponentMap +// New returns a Dcc component. By default, it contains a nil instance. +func (*Dcc) New() akara.Component { + return &Dcc{} } -// AddDcc adds a new DccComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *DccComponent instead of an akara.Component -func (cm *DccMap) AddDcc(id akara.EID) *DccComponent { - return cm.Add(id).(*DccComponent) +// DccFactory is a wrapper for the generic component factory that returns Dcc component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Dcc. +type DccFactory struct { + Dcc *akara.ComponentFactory } -// GetDcc returns the DccComponent associated with the given entity id -func (cm *DccMap) GetDcc(id akara.EID) (*DccComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDcc adds a Dcc component to the given entity and returns it +func (m *DccFactory) AddDcc(id akara.EID) *Dcc { + return m.Dcc.Add(id).(*Dcc) +} + +// GetDcc returns the Dcc component for the given entity, and a bool for whether or not it exists +func (m *DccFactory) GetDcc(id akara.EID) (*Dcc, bool) { + component, found := m.Dcc.Get(id) + if !found { + return nil, found } - return entry.(*DccComponent), found -} - -// Dcc is a convenient reference to be used as a component identifier -var Dcc = newDcc() // nolint:gochecknoglobals // global by design - -func newDcc() akara.Component { - return &DccComponent{ - BaseComponent: akara.NewBaseComponent(AssetDccCID, newDcc, newDccMap), - } -} - -func newDccMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetDccCID, newDcc, newDccMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &DccMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Dcc), found } diff --git a/d2core/d2components/asset_ds1.go b/d2core/d2components/asset_ds1.go index 90b70632..92e2adf8 100644 --- a/d2core/d2components/asset_ds1.go +++ b/d2core/d2components/asset_ds1.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1" ) -// static check that Ds1Component implements Component -var _ akara.Component = &Ds1Component{} +// static check that Ds1 implements Component +var _ akara.Component = &Ds1{} -// static check that Ds1Map implements ComponentMap -var _ akara.ComponentMap = &Ds1Map{} - -// Ds1Component is a component that contains an embedded DS1 struct -type Ds1Component struct { - *akara.BaseComponent +// Ds1 is a component that contains an embedded DS1 struct +type Ds1 struct { *d2ds1.DS1 } -// Ds1Map is a map of entity ID's to Ds1 -type Ds1Map struct { - *akara.BaseComponentMap +// New returns a Ds1 component. By default, it contains a nil instance. +func (*Ds1) New() akara.Component { + return &Ds1{} } -// AddDs1 adds a new Ds1Component for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *Ds1Component instead of an akara.Component -func (cm *Ds1Map) AddDs1(id akara.EID) *Ds1Component { - return cm.Add(id).(*Ds1Component) +// Ds1Factory is a wrapper for the generic component factory that returns Ds1 component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Ds1. +type Ds1Factory struct { + Ds1 *akara.ComponentFactory } -// GetDs1 returns the Ds1Component associated with the given entity id -func (cm *Ds1Map) GetDs1(id akara.EID) (*Ds1Component, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDs1 adds a Ds1 component to the given entity and returns it +func (m *Ds1Factory) AddDs1(id akara.EID) *Ds1 { + return m.Ds1.Add(id).(*Ds1) +} + +// GetDs1 returns the Ds1 component for the given entity, and a bool for whether or not it exists +func (m *Ds1Factory) GetDs1(id akara.EID) (*Ds1, bool) { + component, found := m.Ds1.Get(id) + if !found { + return nil, found } - return entry.(*Ds1Component), found -} - -// Ds1 is a convenient reference to be used as a component identifier -var Ds1 = newDs1() // nolint:gochecknoglobals // global by design - -func newDs1() akara.Component { - return &Ds1Component{ - BaseComponent: akara.NewBaseComponent(AssetDs1CID, newDs1, newDs1Map), - } -} - -func newDs1Map() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetDs1CID, newDs1, newDs1Map) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &Ds1Map{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Ds1), found } diff --git a/d2core/d2components/asset_dt1.go b/d2core/d2components/asset_dt1.go index de6116de..67563a1b 100644 --- a/d2core/d2components/asset_dt1.go +++ b/d2core/d2components/asset_dt1.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1" ) -// static check that Dt1Component implements Component -var _ akara.Component = &Dt1Component{} +// static check that Dt1 implements Component +var _ akara.Component = &Dt1{} -// static check that Dt1Map implements ComponentMap -var _ akara.ComponentMap = &Dt1Map{} - -// Dt1Component is a component that contains an embedded DT1 struct -type Dt1Component struct { - *akara.BaseComponent +// Dt1 is a component that contains an embedded DT1 struct +type Dt1 struct { *d2dt1.DT1 } -// Dt1Map is a map of entity ID's to Dt1 -type Dt1Map struct { - *akara.BaseComponentMap +// New returns a Dt1 component. By default, it contains a nil instance. +func (*Dt1) New() akara.Component { + return &Dt1{} } -// AddDt1 adds a new Dt1Component for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *Dt1Component instead of an akara.Component -func (cm *Dt1Map) AddDt1(id akara.EID) *Dt1Component { - return cm.Add(id).(*Dt1Component) +// Dt1Factory is a wrapper for the generic component factory that returns Dt1 component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Dt1. +type Dt1Factory struct { + Dt1 *akara.ComponentFactory } -// GetDt1 returns the Dt1Component associated with the given entity id -func (cm *Dt1Map) GetDt1(id akara.EID) (*Dt1Component, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDt1 adds a Dt1 component to the given entity and returns it +func (m *Dt1Factory) AddDt1(id akara.EID) *Dt1 { + return m.Dt1.Add(id).(*Dt1) +} + +// GetDt1 returns the Dt1 component for the given entity, and a bool for whether or not it exists +func (m *Dt1Factory) GetDt1(id akara.EID) (*Dt1, bool) { + component, found := m.Dt1.Get(id) + if !found { + return nil, found } - return entry.(*Dt1Component), found -} - -// Dt1 is a convenient reference to be used as a component identifier -var Dt1 = newDt1() // nolint:gochecknoglobals // global by design - -func newDt1() akara.Component { - return &Dt1Component{ - BaseComponent: akara.NewBaseComponent(AssetDt1CID, newDt1, newDt1Map), - } -} - -func newDt1Map() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetDt1CID, newDt1, newDt1Map) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &Dt1Map{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Dt1), found } diff --git a/d2core/d2components/asset_font_table.go b/d2core/d2components/asset_font_table.go index 1b32ae7d..cabf6037 100644 --- a/d2core/d2components/asset_font_table.go +++ b/d2core/d2components/asset_font_table.go @@ -5,56 +5,36 @@ import ( "github.com/gravestench/akara" ) -// static check that FontTableComponent implements Component -var _ akara.Component = &FontTableComponent{} +// static check that FontTable implements Component +var _ akara.Component = &FontTable{} -// static check that FontTableMap implements ComponentMap -var _ akara.ComponentMap = &FontTableMap{} - -// FontTableComponent is a component that contains font table data as a byte slice -type FontTableComponent struct { - *akara.BaseComponent +// FontTable is a component that contains font table data as a byte slice +type FontTable struct { Data []byte } -// FontTableMap is a map of entity ID's to FontTable -type FontTableMap struct { - *akara.BaseComponentMap +// New returns a FontTable component. By default, Data is a nil instance. +func (*FontTable) New() akara.Component { + return &FontTable{} } -// AddFontTable adds a new FontTableComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *FontTableComponent instead of an akara.Component -func (cm *FontTableMap) AddFontTable(id akara.EID) *FontTableComponent { - return cm.Add(id).(*FontTableComponent) +// FontTableFactory is a wrapper for the generic component factory that returns FontTable component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a FontTable. +type FontTableFactory struct { + FontTable *akara.ComponentFactory } -// GetFontTable returns the FontTableComponent associated with the given entity id -func (cm *FontTableMap) GetFontTable(id akara.EID) (*FontTableComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddFontTable adds a FontTable component to the given entity and returns it +func (m *FontTableFactory) AddFontTable(id akara.EID) *FontTable { + return m.FontTable.Add(id).(*FontTable) +} + +// GetFontTable returns the FontTable component for the given entity, and a bool for whether or not it exists +func (m *FontTableFactory) GetFontTable(id akara.EID) (*FontTable, bool) { + component, found := m.FontTable.Get(id) + if !found { + return nil, found } - return entry.(*FontTableComponent), found -} - -// FontTable is a convenient reference to be used as a component identifier -var FontTable = newFontTable() // nolint:gochecknoglobals // global by design - -func newFontTable() akara.Component { - return &FontTableComponent{ - BaseComponent: akara.NewBaseComponent(AssetFontTableCID, newFontTable, newFontTableMap), - } -} - -func newFontTableMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetFontTableCID, newFontTable, newFontTableMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &FontTableMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*FontTable), found } diff --git a/d2core/d2components/asset_palette.go b/d2core/d2components/asset_palette.go index edfaff09..1e5de0a3 100644 --- a/d2core/d2components/asset_palette.go +++ b/d2core/d2components/asset_palette.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" ) -// static check that PaletteComponent implements Component -var _ akara.Component = &PaletteComponent{} +// static check that Palette implements Component +var _ akara.Component = &Palette{} -// static check that PaletteMap implements ComponentMap -var _ akara.ComponentMap = &PaletteMap{} - -// PaletteComponent is a component that contains an embedded palette interface -type PaletteComponent struct { - *akara.BaseComponent +// Palette is a component that contains an embedded palette interface +type Palette struct { d2interface.Palette } -// PaletteMap is a map of entity ID's to Palette -type PaletteMap struct { - *akara.BaseComponentMap +// New returns a new Palette component. By default, it contains a nil instance. +func (*Palette) New() akara.Component { + return &Palette{} } -// AddPalette adds a new PaletteComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *PaletteComponent instead of an akara.Component -func (cm *PaletteMap) AddPalette(id akara.EID) *PaletteComponent { - return cm.Add(id).(*PaletteComponent) +// PaletteFactory is a wrapper for the generic component factory that returns Palette component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Palette. +type PaletteFactory struct { + Palette *akara.ComponentFactory } -// GetPalette returns the PaletteComponent associated with the given entity id -func (cm *PaletteMap) GetPalette(id akara.EID) (*PaletteComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddPalette adds a Palette component to the given entity and returns it +func (m *PaletteFactory) AddPalette(id akara.EID) *Palette { + return m.Palette.Add(id).(*Palette) +} + +// GetPalette returns the Palette component for the given entity, and a bool for whether or not it exists +func (m *PaletteFactory) GetPalette(id akara.EID) (*Palette, bool) { + component, found := m.Palette.Get(id) + if !found { + return nil, found } - return entry.(*PaletteComponent), found -} - -// Palette is a convenient reference to be used as a component identifier -var Palette = newPalette() // nolint:gochecknoglobals // global by design - -func newPalette() akara.Component { - return &PaletteComponent{ - BaseComponent: akara.NewBaseComponent(AssetPaletteCID, newPalette, newPaletteMap), - } -} - -func newPaletteMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetPaletteCID, newPalette, newPaletteMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &PaletteMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Palette), found } diff --git a/d2core/d2components/asset_palette_transform.go b/d2core/d2components/asset_palette_transform.go index fa807a9e..e0d263f1 100644 --- a/d2core/d2components/asset_palette_transform.go +++ b/d2core/d2components/asset_palette_transform.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2" ) -// static check that PaletteTransformComponent implements Component -var _ akara.Component = &PaletteTransformComponent{} +// static check that PaletteTransform implements Component +var _ akara.Component = &PaletteTransform{} -// static check that PaletteTransformMap implements ComponentMap -var _ akara.ComponentMap = &PaletteTransformMap{} - -// PaletteTransformComponent is a component that contains an embedded palette transform (pl2) struct -type PaletteTransformComponent struct { - *akara.BaseComponent - Transform *d2pl2.PL2 +// PaletteTransform is a component that contains an embedded palette transform (pl2) struct +type PaletteTransform struct { + *d2pl2.PL2 } -// PaletteTransformMap is a map of entity ID's to PaletteTransform -type PaletteTransformMap struct { - *akara.BaseComponentMap +// New returns a new PaletteTransform component. By default, it contains a nil instance. +func (*PaletteTransform) New() akara.Component { + return &PaletteTransform{} } -// AddPaletteTransform adds a new PaletteTransformComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *PaletteTransformComponent instead of an akara.Component -func (cm *PaletteTransformMap) AddPaletteTransform(id akara.EID) *PaletteTransformComponent { - return cm.Add(id).(*PaletteTransformComponent) +// PaletteTransformFactory is a wrapper for the generic component factory that returns PaletteTransform component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a PaletteTransform. +type PaletteTransformFactory struct { + PaletteTransform *akara.ComponentFactory } -// GetPaletteTransform returns the PaletteTransformComponent associated with the given entity id -func (cm *PaletteTransformMap) GetPaletteTransform(id akara.EID) (*PaletteTransformComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddPaletteTransform adds a PaletteTransform component to the given entity and returns it +func (m *PaletteTransformFactory) AddPaletteTransform(id akara.EID) *PaletteTransform { + return m.PaletteTransform.Add(id).(*PaletteTransform) +} + +// GetPaletteTransform returns the PaletteTransform component for the given entity, and a bool for whether or not it exists +func (m *PaletteTransformFactory) GetPaletteTransform(id akara.EID) (*PaletteTransform, bool) { + component, found := m.PaletteTransform.Get(id) + if !found { + return nil, found } - return entry.(*PaletteTransformComponent), found -} - -// PaletteTransform is a convenient reference to be used as a component identifier -var PaletteTransform = newPaletteTransform() // nolint:gochecknoglobals // global by design - -func newPaletteTransform() akara.Component { - return &PaletteTransformComponent{ - BaseComponent: akara.NewBaseComponent(AssetPaletteTransformCID, newPaletteTransform, newPaletteTransformMap), - } -} - -func newPaletteTransformMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetPaletteTransformCID, newPaletteTransform, newPaletteTransformMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &PaletteTransformMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*PaletteTransform), found } diff --git a/d2core/d2components/asset_string_table.go b/d2core/d2components/asset_string_table.go index db1d29fc..2ec08a97 100644 --- a/d2core/d2components/asset_string_table.go +++ b/d2core/d2components/asset_string_table.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl" ) -// static check that StringTableComponent implements Component -var _ akara.Component = &StringTableComponent{} +// static check that StringTable implements Component +var _ akara.Component = &StringTable{} -// static check that StringTableMap implements ComponentMap -var _ akara.ComponentMap = &StringTableMap{} - -// StringTableComponent is a component that contains an embedded text table struct -type StringTableComponent struct { - *akara.BaseComponent +// StringTable is a component that contains an embedded text table struct +type StringTable struct { *d2tbl.TextDictionary } -// StringTableMap is a map of entity ID's to StringTable -type StringTableMap struct { - *akara.BaseComponentMap +// New returns a new StringTable component. By default, it contains a nil instance. +func (*StringTable) New() akara.Component { + return &StringTable{} } -// AddStringTable adds a new StringTableComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *StringTableComponent instead of an akara.Component -func (cm *StringTableMap) AddStringTable(id akara.EID) *StringTableComponent { - return cm.Add(id).(*StringTableComponent) +// StringTableFactory is a wrapper for the generic component factory that returns StringTable component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a StringTable. +type StringTableFactory struct { + StringTable *akara.ComponentFactory } -// GetStringTable returns the StringTableComponent associated with the given entity id -func (cm *StringTableMap) GetStringTable(id akara.EID) (*StringTableComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddStringTable adds a StringTable component to the given entity and returns it +func (m *StringTableFactory) AddStringTable(id akara.EID) *StringTable { + return m.StringTable.Add(id).(*StringTable) +} + +// GetStringTable returns the StringTable component for the given entity, and a bool for whether or not it exists +func (m *StringTableFactory) GetStringTable(id akara.EID) (*StringTable, bool) { + component, found := m.StringTable.Get(id) + if !found { + return nil, found } - return entry.(*StringTableComponent), found -} - -// StringTable is a convenient reference to be used as a component identifier -var StringTable = newStringTable() // nolint:gochecknoglobals // global by design - -func newStringTable() akara.Component { - return &StringTableComponent{ - BaseComponent: akara.NewBaseComponent(AssetStringTableCID, newStringTable, newStringTableMap), - } -} - -func newStringTableMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetStringTableCID, newStringTable, newStringTableMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &StringTableMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*StringTable), found } diff --git a/d2core/d2components/asset_wav.go b/d2core/d2components/asset_wav.go index 78254152..510cbed4 100644 --- a/d2core/d2components/asset_wav.go +++ b/d2core/d2components/asset_wav.go @@ -7,56 +7,36 @@ import ( "github.com/gravestench/akara" ) -// static check that WavComponent implements Component -var _ akara.Component = &WavComponent{} +// static check that Wav implements Component +var _ akara.Component = &Wav{} -// static check that WavMap implements ComponentMap -var _ akara.ComponentMap = &WavMap{} - -// WavComponent is a component that contains an embedded io.ReadSeeker for streaming wav audio files -type WavComponent struct { - *akara.BaseComponent +// Wav is a component that contains an embedded io.ReadSeeker for streaming wav audio files +type Wav struct { Data io.ReadSeeker } -// WavMap is a map of entity ID's to Wav -type WavMap struct { - *akara.BaseComponentMap +// New returns a new Wav component. By default, it contains a nil instance. +func (*Wav) New() akara.Component { + return &Wav{} } -// AddWav adds a new WavComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *WavComponent instead of an akara.Component -func (cm *WavMap) AddWav(id akara.EID) *WavComponent { - return cm.Add(id).(*WavComponent) +// WavFactory is a wrapper for the generic component factory that returns Wav component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Wav. +type WavFactory struct { + Wav *akara.ComponentFactory } -// GetWav returns the WavComponent associated with the given entity id -func (cm *WavMap) GetWav(id akara.EID) (*WavComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddWav adds a Wav component to the given entity and returns it +func (m *WavFactory) AddWav(id akara.EID) *Wav { + return m.Wav.Add(id).(*Wav) +} + +// GetWav returns the Wav component for the given entity, and a bool for whether or not it exists +func (m *WavFactory) GetWav(id akara.EID) (*Wav, bool) { + component, found := m.Wav.Get(id) + if !found { + return nil, found } - return entry.(*WavComponent), found -} - -// Wav is a convenient reference to be used as a component identifier -var Wav = newWav() // nolint:gochecknoglobals // global by design - -func newWav() akara.Component { - return &WavComponent{ - BaseComponent: akara.NewBaseComponent(AssetWavCID, newWav, newWavMap), - } -} - -func newWavMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(AssetWavCID, newWav, newWavMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &WavMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Wav), found } diff --git a/d2core/d2components/camera.go b/d2core/d2components/camera.go index 4308263e..ca83e73e 100644 --- a/d2core/d2components/camera.go +++ b/d2core/d2components/camera.go @@ -7,63 +7,51 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that CameraComponent implements Component -var _ akara.Component = &CameraComponent{} +const ( + defaultCameraWidth = 800 + defaultCameraHeight = 600 + defaultCameraZoom = 1.0 +) -// static check that CameraMap implements ComponentMap -var _ akara.ComponentMap = &CameraMap{} +// static check that Camera implements Component +var _ akara.Component = &Camera{} -// CameraComponent represents a camera that can be rendered to -type CameraComponent struct { - *akara.BaseComponent +// Camera represents a camera that can be rendered to +type Camera struct { *d2vector.Vector Width int Height int Zoom float64 } -// CameraMap is a map of entity ID's to Camera -type CameraMap struct { - *akara.BaseComponentMap -} - -// AddCamera adds a new CameraComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *CameraComponent instead of an akara.Component -func (cm *CameraMap) AddCamera(id akara.EID) *CameraComponent { - camera := cm.Add(id).(*CameraComponent) - - camera.Vector = d2vector.NewVector(0, 0) - - return camera -} - -// GetCamera returns the CameraComponent associated with the given entity id -func (cm *CameraMap) GetCamera(id akara.EID) (*CameraComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*CameraComponent), found -} - -// Camera is a convenient reference to be used as a component identifier -var Camera = newCamera() // nolint:gochecknoglobals // global by design - -func newCamera() akara.Component { - return &CameraComponent{ - BaseComponent: akara.NewBaseComponent(CameraCID, newCamera, newCameraMap), +// New returns a new Camera component. +// The camera defaults to position (0,0), 800x600 resolution, and zoom of 1.0 +func (*Camera) New() akara.Component { + return &Camera{ + Vector: d2vector.NewVector(0, 0), + Width: defaultCameraWidth, + Height: defaultCameraHeight, + Zoom: defaultCameraZoom, } } -func newCameraMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(CameraCID, newCamera, newCameraMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// CameraFactory is a wrapper for the generic component factory that returns Camera component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Camera. +type CameraFactory struct { + Camera *akara.ComponentFactory +} - cm := &CameraMap{ - BaseComponentMap: baseMap, +// AddCamera adds a Camera component to the given entity and returns it +func (m *CameraFactory) AddCamera(id akara.EID) *Camera { + return m.Camera.Add(id).(*Camera) +} + +// GetCamera returns the Camera component for the given entity, and a bool for whether or not it exists +func (m *CameraFactory) GetCamera(id akara.EID) (*Camera, bool) { + component, found := m.Camera.Get(id) + if !found { + return nil, found } - return cm + return component.(*Camera), found } diff --git a/d2core/d2components/dirty.go b/d2core/d2components/dirty.go index b4ebb8a3..c1b9c311 100644 --- a/d2core/d2components/dirty.go +++ b/d2core/d2components/dirty.go @@ -5,56 +5,36 @@ import ( "github.com/gravestench/akara" ) -// static check that DirtyComponent implements Component -var _ akara.Component = &DirtyComponent{} +// static check that Dirty implements Component +var _ akara.Component = &Dirty{} -// static check that DirtyMap implements ComponentMap -var _ akara.ComponentMap = &DirtyMap{} - -// DirtyComponent is a flag component that is used to denote a "dirty" state -type DirtyComponent struct { - *akara.BaseComponent +// Dirty is a flag component that is used to denote a "dirty" state +type Dirty struct { IsDirty bool } -// DirtyMap is a map of entity ID's to Dirty -type DirtyMap struct { - *akara.BaseComponentMap +// New creates a new Dirty. By default, IsDirty is false. +func (*Dirty) New() akara.Component { + return &Dirty{} } -// AddDirty adds a new DirtyComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *DirtyComponent instead of an akara.Component -func (cm *DirtyMap) AddDirty(id akara.EID) *DirtyComponent { - return cm.Add(id).(*DirtyComponent) +// DirtyFactory is a wrapper for the generic component factory that returns Dirty component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Dirty. +type DirtyFactory struct { + Dirty *akara.ComponentFactory } -// GetDirty returns the DirtyComponent associated with the given entity id -func (cm *DirtyMap) GetDirty(id akara.EID) (*DirtyComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddDirty adds a Dirty component to the given entity and returns it +func (m *DirtyFactory) AddDirty(id akara.EID) *Dirty { + return m.Dirty.Add(id).(*Dirty) +} + +// GetDirty returns the Dirty component for the given entity, and a bool for whether or not it exists +func (m *DirtyFactory) GetDirty(id akara.EID) (*Dirty, bool) { + component, found := m.Dirty.Get(id) + if !found { + return nil, found } - return entry.(*DirtyComponent), found -} - -// Dirty is a convenient reference to be used as a component identifier -var Dirty = newDirty() // nolint:gochecknoglobals // global by design - -func newDirty() akara.Component { - return &DirtyComponent{ - BaseComponent: akara.NewBaseComponent(DirtyCID, newDirty, newDirtyMap), - } -} - -func newDirtyMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(DirtyCID, newDirty, newDirtyMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &DirtyMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Dirty), found } diff --git a/d2core/d2components/file_handle.go b/d2core/d2components/file_handle.go index 7139f959..fa41407d 100644 --- a/d2core/d2components/file_handle.go +++ b/d2core/d2components/file_handle.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" ) -// static check that FileHandleComponent implements Component -var _ akara.Component = &FileHandleComponent{} +// static check that FileHandle implements Component +var _ akara.Component = &FileHandle{} -// static check that FileHandleMap implements ComponentMap -var _ akara.ComponentMap = &FileHandleMap{} - -// FileHandleComponent is a component that contains a data stream for file data -type FileHandleComponent struct { - *akara.BaseComponent +// FileHandle is a component that contains a data stream for file data +type FileHandle struct { Data d2interface.DataStream } -// FileHandleMap is a map of entity ID's to FileHandle -type FileHandleMap struct { - *akara.BaseComponentMap +// New returns a FileHandle component. By default, it contains a nil instance. +func (*FileHandle) New() akara.Component { + return &FileHandle{} } -// AddFileHandle adds a new FileHandleComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *FileHandleComponent instead of an akara.Component -func (cm *FileHandleMap) AddFileHandle(id akara.EID) *FileHandleComponent { - return cm.Add(id).(*FileHandleComponent) +// FileHandleFactory is a wrapper for the generic component factory that returns FileHandle component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a FileHandle. +type FileHandleFactory struct { + FileHandle *akara.ComponentFactory } -// GetFileHandle returns the FileHandleComponent associated with the given entity id -func (cm *FileHandleMap) GetFileHandle(id akara.EID) (*FileHandleComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddFileHandle adds a FileHandle component to the given entity and returns it +func (m *FileHandleFactory) AddFileHandle(id akara.EID) *FileHandle { + return m.FileHandle.Add(id).(*FileHandle) +} + +// GetFileHandle returns the FileHandle component for the given entity, and a bool for whether or not it exists +func (m *FileHandleFactory) GetFileHandle(id akara.EID) (*FileHandle, bool) { + component, found := m.FileHandle.Get(id) + if !found { + return nil, found } - return entry.(*FileHandleComponent), found -} - -// FileHandle is a convenient reference to be used as a component identifier -var FileHandle = newFileHandle() // nolint:gochecknoglobals // global by design - -func newFileHandle() akara.Component { - return &FileHandleComponent{ - BaseComponent: akara.NewBaseComponent(FileHandleCID, newFileHandle, newFileHandleMap), - } -} - -func newFileHandleMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(FileHandleCID, newFileHandle, newFileHandleMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &FileHandleMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*FileHandle), found } diff --git a/d2core/d2components/file_path.go b/d2core/d2components/file_path.go index 6c5fa53e..d4c3ba74 100644 --- a/d2core/d2components/file_path.go +++ b/d2core/d2components/file_path.go @@ -5,56 +5,36 @@ import ( "github.com/gravestench/akara" ) -// static check that FilePathComponent implements Component -var _ akara.Component = &FilePathComponent{} +// static check that FilePath implements Component +var _ akara.Component = &FilePath{} -// static check that FilePathMap implements ComponentMap -var _ akara.ComponentMap = &FilePathMap{} - -// FilePathComponent represents a file path for a file -type FilePathComponent struct { - *akara.BaseComponent +// FilePath represents a file path for a file +type FilePath struct { Path string } -// FilePathMap is a map of entity ID's to FilePath -type FilePathMap struct { - *akara.BaseComponentMap +// New returns a FilePath component. By default, it contains an empty string. +func (*FilePath) New() akara.Component { + return &FilePath{} } -// AddFilePath adds a new FilePathComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *FilePathComponent instead of an akara.Component -func (cm *FilePathMap) AddFilePath(id akara.EID) *FilePathComponent { - return cm.Add(id).(*FilePathComponent) +// FilePathFactory is a wrapper for the generic component factory that returns FilePath component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a FilePath. +type FilePathFactory struct { + FilePath *akara.ComponentFactory } -// GetFilePath returns the FilePathComponent associated with the given entity id -func (cm *FilePathMap) GetFilePath(id akara.EID) (*FilePathComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddFilePath adds a FilePath component to the given entity and returns it +func (m *FilePathFactory) AddFilePath(id akara.EID) *FilePath { + return m.FilePath.Add(id).(*FilePath) +} + +// GetFilePath returns the FilePath component for the given entity, and a bool for whether or not it exists +func (m *FilePathFactory) GetFilePath(id akara.EID) (*FilePath, bool) { + component, found := m.FilePath.Get(id) + if !found { + return nil, found } - return entry.(*FilePathComponent), found -} - -// FilePath is a convenient reference to be used as a component identifier -var FilePath = newFilePath() // nolint:gochecknoglobals // global by design - -func newFilePath() akara.Component { - return &FilePathComponent{ - BaseComponent: akara.NewBaseComponent(FilePathCID, newFilePath, newFilePathMap), - } -} - -func newFilePathMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(FilePathCID, newFilePath, newFilePathMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &FilePathMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*FilePath), found } diff --git a/d2core/d2components/file_source.go b/d2core/d2components/file_source.go index cc4caa96..af227bc0 100644 --- a/d2core/d2components/file_source.go +++ b/d2core/d2components/file_source.go @@ -7,62 +7,42 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" ) +// static check that FileSource implements Component +var _ akara.Component = &FileSource{} + // AbstractSource is the abstract representation of what a file source is type AbstractSource interface { Path() string // the path of the source itself - Open(path *FilePathComponent) (d2interface.DataStream, error) + Open(path *FilePath) (d2interface.DataStream, error) } -// static check that FileSourceComponent implements Component -var _ akara.Component = &FileSourceComponent{} - -// static check that FileSourceMap implements ComponentMap -var _ akara.ComponentMap = &FileSourceMap{} - -// FileSourceComponent contains an embedded file source interface, something that can open files -type FileSourceComponent struct { - *akara.BaseComponent +// FileSource contains an embedded file source interface, something that can open files +type FileSource struct { AbstractSource } -// FileSourceMap is a map of entity ID's to FileSource -type FileSourceMap struct { - *akara.BaseComponentMap +// New returns a FileSource component. By default, it contains a nil instance. +func (*FileSource) New() akara.Component { + return &FileSource{} } -// AddFileSource adds a new FileSourceComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *FileSourceComponent instead of an akara.Component -func (cm *FileSourceMap) AddFileSource(id akara.EID) *FileSourceComponent { - return cm.Add(id).(*FileSourceComponent) +// FileSourceFactory is a wrapper for the generic component factory that returns FileSource component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a FileSource. +type FileSourceFactory struct { + FileSource *akara.ComponentFactory } -// GetFileSource returns the FileSourceComponent associated with the given entity id -func (cm *FileSourceMap) GetFileSource(id akara.EID) (*FileSourceComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddFileSource adds a FileSource component to the given entity and returns it +func (m *FileSourceFactory) AddFileSource(id akara.EID) *FileSource { + return m.FileSource.Add(id).(*FileSource) +} + +// GetFileSource returns the FileSource component for the given entity, and a bool for whether or not it exists +func (m *FileSourceFactory) GetFileSource(id akara.EID) (*FileSource, bool) { + component, found := m.FileSource.Get(id) + if !found { + return nil, found } - return entry.(*FileSourceComponent), found -} - -// FileSource is a convenient reference to be used as a component identifier -var FileSource = newFileSource() // nolint:gochecknoglobals // global by design - -func newFileSource() akara.Component { - return &FileSourceComponent{ - BaseComponent: akara.NewBaseComponent(FileSourceCID, newFileSource, newFileSourceMap), - } -} - -func newFileSourceMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(FileSourceCID, newFileSource, newFileSourceMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &FileSourceMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*FileSource), found } diff --git a/d2core/d2components/file_type.go b/d2core/d2components/file_type.go index 32d1147e..361f4c41 100644 --- a/d2core/d2components/file_type.go +++ b/d2core/d2components/file_type.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" ) -// static check that FileTypeComponent implements Component -var _ akara.Component = &FileTypeComponent{} +// static check that FileType implements Component +var _ akara.Component = &FileType{} -// static check that FileTypeMap implements ComponentMap -var _ akara.ComponentMap = &FileTypeMap{} - -// FileTypeComponent is used to flag file entities with a file type -type FileTypeComponent struct { - *akara.BaseComponent +// FileType is used to flag file entities with a file type +type FileType struct { Type d2enum.FileType } -// FileTypeMap is a map of entity ID's to FileType -type FileTypeMap struct { - *akara.BaseComponentMap +// New returns a FileType component. By default, it contains a nil instance. +func (*FileType) New() akara.Component { + return &FileType{} } -// AddFileType adds a new FileTypeComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *FileTypeComponent instead of an akara.Component -func (cm *FileTypeMap) AddFileType(id akara.EID) *FileTypeComponent { - return cm.Add(id).(*FileTypeComponent) +// FileTypeFactory is a wrapper for the generic component factory that returns FileType component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a FileType. +type FileTypeFactory struct { + FileType *akara.ComponentFactory } -// GetFileType returns the FileTypeComponent associated with the given entity id -func (cm *FileTypeMap) GetFileType(id akara.EID) (*FileTypeComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddFileType adds a FileType component to the given entity and returns it +func (m *FileTypeFactory) AddFileType(id akara.EID) *FileType { + return m.FileType.Add(id).(*FileType) +} + +// GetFileType returns the FileType component for the given entity, and a bool for whether or not it exists +func (m *FileTypeFactory) GetFileType(id akara.EID) (*FileType, bool) { + component, found := m.FileType.Get(id) + if !found { + return nil, found } - return entry.(*FileTypeComponent), found -} - -// FileType is a convenient reference to be used as a component identifier -var FileType = newFileType() // nolint:gochecknoglobals // global by design - -func newFileType() akara.Component { - return &FileTypeComponent{ - BaseComponent: akara.NewBaseComponent(FileTypeCID, newFileType, newFileTypeMap), - } -} - -func newFileTypeMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(FileTypeCID, newFileType, newFileTypeMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &FileTypeMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*FileType), found } diff --git a/d2core/d2components/game_config.go b/d2core/d2components/game_config.go index cc7a5eeb..ca6e075a 100644 --- a/d2core/d2components/game_config.go +++ b/d2core/d2components/game_config.go @@ -6,20 +6,16 @@ import ( "path" "runtime" - "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" - "github.com/gravestench/akara" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" ) -// static check that GameConfigComponent implements Component -var _ akara.Component = &GameConfigComponent{} +// static check that GameConfig implements Component +var _ akara.Component = &GameConfig{} -// static check that GameConfigMap implements ComponentMap -var _ akara.ComponentMap = &GameConfigMap{} - -// GameConfigComponent represents an OpenDiablo2 game configuration -type GameConfigComponent struct { - *akara.BaseComponent +// GameConfig represents an OpenDiablo2 game configuration +type GameConfig struct { MpqLoadOrder []string MpqPath string TicksPerSecond int @@ -33,54 +29,15 @@ type GameConfigComponent struct { LogLevel d2util.LogLevel } -// GameConfigMap is a map of entity ID's to GameConfig -type GameConfigMap struct { - *akara.BaseComponentMap -} - -// AddGameConfig adds a new GameConfigComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *GameConfigComponent instead of an akara.Component -func (cm *GameConfigMap) AddGameConfig(id akara.EID) *GameConfigComponent { - return defaultConfig(cm.Add(id).(*GameConfigComponent)) -} - -// GetGameConfig returns the GameConfigComponent associated with the given entity id -func (cm *GameConfigMap) GetGameConfig(id akara.EID) (*GameConfigComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*GameConfigComponent), found -} - -// GameConfig is a convenient reference to be used as a component identifier -var GameConfig = newGameConfig() // nolint:gochecknoglobals // global by design - -func newGameConfig() akara.Component { - return &GameConfigComponent{ - BaseComponent: akara.NewBaseComponent(GameConfigCID, newGameConfig, newGameConfigMap), - } -} - -func newGameConfigMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(GameConfigCID, newGameConfig, newGameConfigMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &GameConfigMap{ - BaseComponentMap: baseMap, - } - - return cm -} - -func defaultConfig(config *GameConfigComponent) *GameConfigComponent { +// New creates the default GameConfig +func (*GameConfig) New() akara.Component { const ( defaultSfxVolume = 1.0 defaultBgmVolume = 0.3 ) + config := &GameConfig{} + config.FullScreen = false config.TicksPerSecond = -1 config.RunInBackground = true @@ -132,3 +89,24 @@ func defaultConfig(config *GameConfigComponent) *GameConfigComponent { return config } + +// GameConfigFactory is a wrapper for the generic component factory that returns GameConfig component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a GameConfig. +type GameConfigFactory struct { + GameConfig *akara.ComponentFactory +} + +// AddGameConfig adds a GameConfig component to the given entity and returns it +func (m *GameConfigFactory) AddGameConfig(id akara.EID) *GameConfig { + return m.GameConfig.Add(id).(*GameConfig) +} + +// GetGameConfig returns the GameConfig component for the given entity, and a bool for whether or not it exists +func (m *GameConfigFactory) GetGameConfig(id akara.EID) (*GameConfig, bool) { + component, found := m.GameConfig.Get(id) + if !found { + return nil, found + } + + return component.(*GameConfig), found +} diff --git a/d2core/d2components/origin.go b/d2core/d2components/origin.go index 885e641b..adb8bde0 100644 --- a/d2core/d2components/origin.go +++ b/d2core/d2components/origin.go @@ -3,60 +3,44 @@ package d2components import ( "github.com/gravestench/akara" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that OriginComponent implements Component -var _ akara.Component = &OriginComponent{} +// static check that Origin implements Component +var _ akara.Component = &Origin{} -// static check that OriginMap implements ComponentMap -var _ akara.ComponentMap = &OriginMap{} - -// OriginComponent is a component that describes the origin point of an entity. -// The values are normalized to the display width/height. -// For example, origin (0,0) is top-left corner, (0.5, 0.5) is center -type OriginComponent struct { - *akara.BaseComponent - X, Y float64 +// Origin is a component that describes the origin point of an entity as a vector. +// The values should be interpreted as normalized to the width/height of the entity (depends on other components...). +// For example, origin (0,0) should be top-left corner, (0.5, 0.5) should be center. +type Origin struct { + *d2vector.Vector } -// OriginMap is a map of entity ID's to Origin -type OriginMap struct { - *akara.BaseComponentMap -} - -// AddOrigin adds a new OriginComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *OriginComponent instead of an akara.Component -func (cm *OriginMap) AddOrigin(id akara.EID) *OriginComponent { - return cm.Add(id).(*OriginComponent) -} - -// GetOrigin returns the OriginComponent associated with the given entity id -func (cm *OriginMap) GetOrigin(id akara.EID) (*OriginComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*OriginComponent), found -} - -// Origin is a convenient reference to be used as a component identifier -var Origin = newOrigin() // nolint:gochecknoglobals // global by design - -func newOrigin() akara.Component { - return &OriginComponent{ - BaseComponent: akara.NewBaseComponent(OriginCID, newOrigin, newOriginMap), +// New creates a new Origin. By default, the origin is the top-left corner (0,0) +func (*Origin) New() akara.Component { + return &Origin{ + Vector: d2vector.NewVector(0, 0), } } -func newOriginMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(OriginCID, newOrigin, newOriginMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// OriginFactory is a wrapper for the generic component factory that returns Origin component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Origin. +type OriginFactory struct { + Origin *akara.ComponentFactory +} - cm := &OriginMap{ - BaseComponentMap: baseMap, +// AddOrigin adds a Origin component to the given entity and returns it +func (m *OriginFactory) AddOrigin(id akara.EID) *Origin { + return m.Origin.Add(id).(*Origin) +} + +// GetOrigin returns the Origin component for the given entity, and a bool for whether or not it exists +func (m *OriginFactory) GetOrigin(id akara.EID) (*Origin, bool) { + component, found := m.Origin.Get(id) + if !found { + return nil, found } - return cm + return component.(*Origin), found } diff --git a/d2core/d2components/position.go b/d2core/d2components/position.go index 10b313e6..ebcc09b3 100644 --- a/d2core/d2components/position.go +++ b/d2core/d2components/position.go @@ -7,62 +7,41 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that PositionComponent implements Component -var _ akara.Component = &PositionComponent{} +// static check that Position implements Component +var _ akara.Component = &Position{} -// static check that PositionMap implements ComponentMap -var _ akara.ComponentMap = &PositionMap{} - -// PositionComponent contains an embedded d2vector.Position -type PositionComponent struct { - *akara.BaseComponent +// Position contains an embedded d2vector.Position, which is a vector with +// helper methods for translating between screen, isometric, tile, and sub-tile space. +type Position struct { *d2vector.Position } -// PositionMap is a map of entity ID's to Position -type PositionMap struct { - *akara.BaseComponentMap -} - -// AddPosition adds a new PositionComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *PositionComponent instead of an akara.Component -func (cm *PositionMap) AddPosition(id akara.EID) *PositionComponent { - pos := cm.Add(id).(*PositionComponent) - +// New creates a new Position. By default, the position is (0,0) +func (*Position) New() akara.Component { p := d2vector.NewPosition(0, 0) - pos.Position = &p - - return pos -} - -// GetPosition returns the PositionComponent associated with the given entity id -func (cm *PositionMap) GetPosition(id akara.EID) (*PositionComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*PositionComponent), found -} - -// Position is a convenient reference to be used as a component identifier -var Position = newPosition() // nolint:gochecknoglobals // global by design - -func newPosition() akara.Component { - return &PositionComponent{ - BaseComponent: akara.NewBaseComponent(PositionCID, newPosition, newPositionMap), + return &Position{ + Position: &p, } } -func newPositionMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(PositionCID, newPosition, newPositionMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// PositionFactory is a wrapper for the generic component factory that returns Position component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Position. +type PositionFactory struct { + Position *akara.ComponentFactory +} - cm := &PositionMap{ - BaseComponentMap: baseMap, +// AddPosition adds a Position component to the given entity and returns it +func (m *PositionFactory) AddPosition(id akara.EID) *Position { + return m.Position.Add(id).(*Position) +} + +// GetPosition returns the Position component for the given entity, and a bool for whether or not it exists +func (m *PositionFactory) GetPosition(id akara.EID) (*Position, bool) { + component, found := m.Position.Get(id) + if !found { + return nil, found } - return cm + return component.(*Position), found } diff --git a/d2core/d2components/priority.go b/d2core/d2components/priority.go index 782916de..a4059296 100644 --- a/d2core/d2components/priority.go +++ b/d2core/d2components/priority.go @@ -5,57 +5,37 @@ import ( "github.com/gravestench/akara" ) -// static check that PriorityComponent implements Component -var _ akara.Component = &PriorityComponent{} +// static check that Priority implements Component +var _ akara.Component = new(Priority) -// static check that PriorityMap implements ComponentMap -var _ akara.ComponentMap = &PriorityMap{} - -// PriorityComponent is a component that is used to add a priority value. +// Priority is a component that is used to add a priority value. // This can generally be used for sorting entities when order matters. -type PriorityComponent struct { - *akara.BaseComponent +type Priority struct { Priority int } -// PriorityMap is a map of entity ID's to Priority -type PriorityMap struct { - *akara.BaseComponentMap +// New returns a new Priority instance. The default is 0. +func (Priority) New() akara.Component { + return &Priority{} } -// AddPriority adds a new PriorityComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *PriorityComponent instead of an akara.Component -func (cm *PriorityMap) AddPriority(id akara.EID) *PriorityComponent { - return cm.Add(id).(*PriorityComponent) +// PriorityFactory is a wrapper for the generic component factory that returns Priority component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Priority. +type PriorityFactory struct { + Priority *akara.ComponentFactory } -// GetPriority returns the PriorityComponent associated with the given entity id -func (cm *PriorityMap) GetPriority(id akara.EID) (*PriorityComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddPriority adds a Priority component to the given entity and returns it +func (m *PriorityFactory) AddPriority(id akara.EID) *Priority { + return m.Priority.Add(id).(*Priority) +} + +// GetPriority returns the Priority component for the given entity, and a bool for whether or not it exists +func (m *PriorityFactory) GetPriority(id akara.EID) (*Priority, bool) { + component, found := m.Priority.Get(id) + if !found { + return nil, found } - return entry.(*PriorityComponent), found -} - -// Priority is a convenient reference to be used as a component identifier -var Priority = newPriority() // nolint:gochecknoglobals // global by design - -func newPriority() akara.Component { - return &PriorityComponent{ - BaseComponent: akara.NewBaseComponent(PriorityCID, newPriority, newPriorityMap), - } -} - -func newPriorityMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(PriorityCID, newPriority, newPriorityMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &PriorityMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Priority), found } diff --git a/d2core/d2components/renderable.go b/d2core/d2components/renderable.go index 1ade8d30..69f4dd00 100644 --- a/d2core/d2components/renderable.go +++ b/d2core/d2components/renderable.go @@ -7,56 +7,36 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" ) -// static check that RenderableComponent implements Component -var _ akara.Component = &RenderableComponent{} +// static check that Renderable implements Component +var _ akara.Component = &Renderable{} -// static check that RenderableMap implements ComponentMap -var _ akara.ComponentMap = &RenderableMap{} - -// RenderableComponent is a component that contains an embedded surface interface, which is used for rendering -type RenderableComponent struct { - *akara.BaseComponent +// Renderable is a component that contains an embedded surface interface, which is used for rendering +type Renderable struct { d2interface.Surface } -// RenderableMap is a map of entity ID's to Renderable -type RenderableMap struct { - *akara.BaseComponentMap +// New returns a Renderable component. By default, it contains a nil instance. +func (*Renderable) New() akara.Component { + return &Renderable{} } -// AddRenderable adds a new RenderableComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *RenderableComponent instead of an akara.Component -func (cm *RenderableMap) AddRenderable(id akara.EID) *RenderableComponent { - return cm.Add(id).(*RenderableComponent) +// RenderableFactory is a wrapper for the generic component factory that returns Renderable component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Renderable. +type RenderableFactory struct { + Renderable *akara.ComponentFactory } -// GetRenderable returns the RenderableComponent associated with the given entity id -func (cm *RenderableMap) GetRenderable(id akara.EID) (*RenderableComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// AddRenderable adds a Renderable component to the given entity and returns it +func (m *RenderableFactory) AddRenderable(id akara.EID) *Renderable { + return m.Renderable.Add(id).(*Renderable) +} + +// GetRenderable returns the Renderable component for the given entity, and a bool for whether or not it exists +func (m *RenderableFactory) GetRenderable(id akara.EID) (*Renderable, bool) { + component, found := m.Renderable.Get(id) + if !found { + return nil, found } - return entry.(*RenderableComponent), found -} - -// Renderable is a convenient reference to be used as a component identifier -var Renderable = newRenderable() // nolint:gochecknoglobals // global by design - -func newRenderable() akara.Component { - return &RenderableComponent{ - BaseComponent: akara.NewBaseComponent(RenderableCID, newRenderable, newRenderableMap), - } -} - -func newRenderableMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(RenderableCID, newRenderable, newRenderableMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &RenderableMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*Renderable), found } diff --git a/d2core/d2components/scale.go b/d2core/d2components/scale.go index 46ac3537..393f4cae 100644 --- a/d2core/d2components/scale.go +++ b/d2core/d2components/scale.go @@ -7,60 +7,38 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that ScaleComponent implements Component -var _ akara.Component = &ScaleComponent{} +// static check that Scale implements Component +var _ akara.Component = &Scale{} -// static check that ScaleMap implements ComponentMap -var _ akara.ComponentMap = &ScaleMap{} - -// ScaleComponent represents an entities x,y axis scale as a vector -type ScaleComponent struct { - *akara.BaseComponent +// Scale represents an entities x,y axis scale as a vector +type Scale struct { *d2vector.Vector } -// ScaleMap is a map of entity ID's to Scale -type ScaleMap struct { - *akara.BaseComponentMap -} - -// AddScale adds a new ScaleComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *ScaleComponent instead of an akara.Component -func (cm *ScaleMap) AddScale(id akara.EID) *ScaleComponent { - c := cm.Add(id).(*ScaleComponent) - - c.Vector = d2vector.NewVector(1, 1) - - return c -} - -// GetScale returns the ScaleComponent associated with the given entity id -func (cm *ScaleMap) GetScale(id akara.EID) (*ScaleComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*ScaleComponent), found -} - -// Scale is a convenient reference to be used as a component identifier -var Scale = newScale() // nolint:gochecknoglobals // global by design - -func newScale() akara.Component { - return &ScaleComponent{ - BaseComponent: akara.NewBaseComponent(ScaleCID, newScale, newScaleMap), +// New creates a new Scale instance. By default, the scale is (1,1) +func (*Scale) New() akara.Component { + return &Scale{ + Vector: d2vector.NewVector(1, 1), } } -func newScaleMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(ScaleCID, newScale, newScaleMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// ScaleFactory is a wrapper for the generic component factory that returns Scale component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Scale. +type ScaleFactory struct { + Scale *akara.ComponentFactory +} - cm := &ScaleMap{ - BaseComponentMap: baseMap, +// AddScale adds a Scale component to the given entity and returns it +func (m *ScaleFactory) AddScale(id akara.EID) *Scale { + return m.Scale.Add(id).(*Scale) +} + +// GetScale returns the Scale component for the given entity, and a bool for whether or not it exists +func (m *ScaleFactory) GetScale(id akara.EID) (*Scale, bool) { + component, found := m.Scale.Get(id) + if !found { + return nil, found } - return cm + return component.(*Scale), found } diff --git a/d2core/d2components/segmented_sprite.go b/d2core/d2components/segmented_sprite.go index 7262b6dd..0f66d659 100644 --- a/d2core/d2components/segmented_sprite.go +++ b/d2core/d2components/segmented_sprite.go @@ -5,63 +5,43 @@ import ( "github.com/gravestench/akara" ) -// static check that SegmentedSpriteComponent implements Component -var _ akara.Component = &SegmentedSpriteComponent{} +// static check that SegmentedSprite implements Component +var _ akara.Component = &SegmentedSprite{} -// static check that SegmentedSpriteMap implements ComponentMap -var _ akara.ComponentMap = &SegmentedSpriteMap{} - -// SegmentedSpriteComponent represents an entities x,y axis scale as a vector -type SegmentedSpriteComponent struct { - *akara.BaseComponent +// SegmentedSprite represents the segmentation of a dcc or dc6 sprite. +// For example, the title screen background is a single image with 12 frames. +// The segmentation can be described as 4 x segments, 3 y segments, with a frame offset of 0. +type SegmentedSprite struct { Xsegments int Ysegments int FrameOffset int } -// SegmentedSpriteMap is a map of entity ID's to SegmentedSprite -type SegmentedSpriteMap struct { - *akara.BaseComponentMap -} - -// AddSegmentedSprite adds a new SegmentedSpriteComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *SegmentedSpriteComponent instead of an akara.Component -func (cm *SegmentedSpriteMap) AddSegmentedSprite(id akara.EID) *SegmentedSpriteComponent { - c := cm.Add(id).(*SegmentedSpriteComponent) - - c.Xsegments = 1 - c.Ysegments = 1 - - return c -} - -// GetSegmentedSprite returns the SegmentedSpriteComponent associated with the given entity id -func (cm *SegmentedSpriteMap) GetSegmentedSprite(id akara.EID) (*SegmentedSpriteComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*SegmentedSpriteComponent), found -} - -// SegmentedSprite is a convenient reference to be used as a component identifier -var SegmentedSprite = newSegmentedSprite() // nolint:gochecknoglobals // global by design - -func newSegmentedSprite() akara.Component { - return &SegmentedSpriteComponent{ - BaseComponent: akara.NewBaseComponent(SegmentedSpriteCID, newSegmentedSprite, newSegmentedSpriteMap), +// New creates a new SegmentedSprite component. By default, x and y segments are both set to 1. +func (*SegmentedSprite) New() akara.Component { + return &SegmentedSprite{ + Xsegments: 1, + Ysegments: 1, } } -func newSegmentedSpriteMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(SegmentedSpriteCID, newSegmentedSprite, newSegmentedSpriteMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// SegmentedSpriteFactory is a wrapper for the generic component factory that returns SegmentedSprite component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a SegmentedSprite. +type SegmentedSpriteFactory struct { + SegmentedSprite *akara.ComponentFactory +} - cm := &SegmentedSpriteMap{ - BaseComponentMap: baseMap, +// AddSegmentedSprite adds a SegmentedSprite component to the given entity and returns it +func (m *SegmentedSpriteFactory) AddSegmentedSprite(id akara.EID) *SegmentedSprite { + return m.SegmentedSprite.Add(id).(*SegmentedSprite) +} + +// GetSegmentedSprite returns the SegmentedSprite component for the given entity, and a bool for whether or not it exists +func (m *SegmentedSpriteFactory) GetSegmentedSprite(id akara.EID) (*SegmentedSprite, bool) { + component, found := m.SegmentedSprite.Get(id) + if !found { + return nil, found } - return cm + return component.(*SegmentedSprite), found } diff --git a/d2core/d2components/size.go b/d2core/d2components/size.go index cd78ddc1..18ed5e41 100644 --- a/d2core/d2components/size.go +++ b/d2core/d2components/size.go @@ -7,60 +7,38 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that SizeComponent implements Component -var _ akara.Component = &SizeComponent{} +// static check that Size implements Component +var _ akara.Component = &Size{} -// static check that SizeMap implements ComponentMap -var _ akara.ComponentMap = &SizeMap{} - -// SizeComponent represents an entities width and height as a vector -type SizeComponent struct { - *akara.BaseComponent +// Size represents an entities width and height as a vector +type Size struct { *d2vector.Vector } -// SizeMap is a map of entity ID's to Size -type SizeMap struct { - *akara.BaseComponentMap -} - -// AddSize adds a new SizeComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *SizeComponent instead of an akara.Component -func (cm *SizeMap) AddSize(id akara.EID) *SizeComponent { - c := cm.Add(id).(*SizeComponent) - - c.Vector = d2vector.NewVector(1, 1) - - return c -} - -// GetSize returns the SizeComponent associated with the given entity id -func (cm *SizeMap) GetSize(id akara.EID) (*SizeComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*SizeComponent), found -} - -// Size is a convenient reference to be used as a component identifier -var Size = newSize() // nolint:gochecknoglobals // global by design - -func newSize() akara.Component { - return &SizeComponent{ - BaseComponent: akara.NewBaseComponent(SizeCID, newSize, newSizeMap), +// New creates a new Size. By default, size is (0,0). +func (*Size) New() akara.Component { + return &Size{ + Vector: d2vector.NewVector(0, 0), } } -func newSizeMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(SizeCID, newSize, newSizeMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// SizeFactory is a wrapper for the generic component factory that returns Size component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Size. +type SizeFactory struct { + Size *akara.ComponentFactory +} - cm := &SizeMap{ - BaseComponentMap: baseMap, +// AddSize adds a Size component to the given entity and returns it +func (m *SizeFactory) AddSize(id akara.EID) *Size { + return m.Size.Add(id).(*Size) +} + +// GetSize returns the Size component for the given entity, and a bool for whether or not it exists +func (m *SizeFactory) GetSize(id akara.EID) (*Size, bool) { + component, found := m.Size.Get(id) + if !found { + return nil, found } - return cm + return component.(*Size), found } diff --git a/d2core/d2components/velocity.go b/d2core/d2components/velocity.go index 16046adf..293908ec 100644 --- a/d2core/d2components/velocity.go +++ b/d2core/d2components/velocity.go @@ -7,60 +7,38 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" ) -// static check that VelocityComponent implements Component -var _ akara.Component = &VelocityComponent{} +// static check that Velocity implements Component +var _ akara.Component = &Velocity{} -// static check that VelocityMap implements ComponentMap -var _ akara.ComponentMap = &VelocityMap{} - -// VelocityComponent contains an embedded velocity as a vector -type VelocityComponent struct { - *akara.BaseComponent +// Velocity contains an embedded velocity as a vector +type Velocity struct { *d2vector.Vector } -// VelocityMap is a map of entity ID's to Velocity -type VelocityMap struct { - *akara.BaseComponentMap -} - -// AddVelocity adds a new VelocityComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *VelocityComponent instead of an akara.Component -func (cm *VelocityMap) AddVelocity(id akara.EID) *VelocityComponent { - c := cm.Add(id).(*VelocityComponent) - - c.Vector = d2vector.NewVector(0, 0) - - return c -} - -// GetVelocity returns the VelocityComponent associated with the given entity id -func (cm *VelocityMap) GetVelocity(id akara.EID) (*VelocityComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*VelocityComponent), found -} - -// Velocity is a convenient reference to be used as a component identifier -var Velocity = newVelocity() // nolint:gochecknoglobals // global by design - -func newVelocity() akara.Component { - return &VelocityComponent{ - BaseComponent: akara.NewBaseComponent(VelocityCID, newVelocity, newVelocityMap), +// New creates a new Velocity. By default, the velocity is (0,0). +func (*Velocity) New() akara.Component { + return &Velocity{ + Vector: d2vector.NewVector(0, 0), } } -func newVelocityMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(VelocityCID, newVelocity, newVelocityMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// VelocityFactory is a wrapper for the generic component factory that returns Velocity component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Velocity. +type VelocityFactory struct { + Velocity *akara.ComponentFactory +} - cm := &VelocityMap{ - BaseComponentMap: baseMap, +// AddVelocity adds a Velocity component to the given entity and returns it +func (m *VelocityFactory) AddVelocity(id akara.EID) *Velocity { + return m.Velocity.Add(id).(*Velocity) +} + +// GetVelocity returns the Velocity component for the given entity, and a bool for whether or not it exists +func (m *VelocityFactory) GetVelocity(id akara.EID) (*Velocity, bool) { + component, found := m.Velocity.Get(id) + if !found { + return nil, found } - return cm + return component.(*Velocity), found } diff --git a/d2core/d2components/viewport.go b/d2core/d2components/viewport.go index 7061c930..d782089e 100644 --- a/d2core/d2components/viewport.go +++ b/d2core/d2components/viewport.go @@ -7,29 +7,19 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom" ) -// static check that ViewportComponent implements Component -var _ akara.Component = &ViewportComponent{} +// static check that Viewport implements Component +var _ akara.Component = &Viewport{} -// static check that ViewportMap implements ComponentMap -var _ akara.ComponentMap = &ViewportMap{} - -// ViewportComponent represents the size and position of a scene viewport. This is used +// Viewport represents the size and position of a scene viewport. This is used // to control where on screen a viewport is rendered. -type ViewportComponent struct { - *akara.BaseComponent +type Viewport struct { *d2geom.Rectangle } -// ViewportMap is a map of entity ID's to Viewport -type ViewportMap struct { - *akara.BaseComponentMap -} - -// AddViewport adds a new ViewportComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *ViewportComponent instead of an akara.Component -func (cm *ViewportMap) AddViewport(id akara.EID) *ViewportComponent { - c := cm.Add(id).(*ViewportComponent) +// New creates a new Viewport. By default, the viewport size is 800x600, +// and is positioned at the top-left of the screen. +func (*Viewport) New() akara.Component { + c := &Viewport{} const defaultWidth, defaultHeight = 800, 600 @@ -43,32 +33,23 @@ func (cm *ViewportMap) AddViewport(id akara.EID) *ViewportComponent { return c } -// GetViewport returns the ViewportComponent associated with the given entity id -func (cm *ViewportMap) GetViewport(id akara.EID) (*ViewportComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*ViewportComponent), found +// ViewportFactory is a wrapper for the generic component factory that returns Viewport component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Viewport. +type ViewportFactory struct { + Viewport *akara.ComponentFactory } -// Viewport is a convenient reference to be used as a component identifier -var Viewport = newViewport() // nolint:gochecknoglobals // global by design - -func newViewport() akara.Component { - return &ViewportComponent{ - BaseComponent: akara.NewBaseComponent(ViewportCID, newViewport, newViewportMap), - } +// AddViewport adds a Viewport component to the given entity and returns it +func (m *ViewportFactory) AddViewport(id akara.EID) *Viewport { + return m.Viewport.Add(id).(*Viewport) } -func newViewportMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(ViewportCID, newViewport, newViewportMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &ViewportMap{ - BaseComponentMap: baseMap, +// GetViewport returns the Viewport component for the given entity, and a bool for whether or not it exists +func (m *ViewportFactory) GetViewport(id akara.EID) (*Viewport, bool) { + component, found := m.Viewport.Get(id) + if !found { + return nil, found } - return cm + return component.(*Viewport), found } diff --git a/d2core/d2components/viewport_filter.go b/d2core/d2components/viewport_filter.go index 2f602546..efb9d0cd 100644 --- a/d2core/d2components/viewport_filter.go +++ b/d2core/d2components/viewport_filter.go @@ -5,61 +5,42 @@ import ( "github.com/gravestench/akara" ) -// static check that ViewportFilterComponent implements Component -var _ akara.Component = &ViewportFilterComponent{} +// static check that ViewportFilter implements Component +var _ akara.Component = &ViewportFilter{} -// static check that ViewportFilterMap implements ComponentMap -var _ akara.ComponentMap = &ViewportFilterMap{} - -// ViewportFilterComponent is a component that contains a bitset that denotes which viewport +// ViewportFilter is a component that contains a bitset that denotes which viewport // the entity will be rendered. -type ViewportFilterComponent struct { - *akara.BaseComponent +type ViewportFilter struct { *akara.BitSet } -// ViewportFilterMap is a map of entity ID's to ViewportFilter -type ViewportFilterMap struct { - *akara.BaseComponentMap -} +// New creates a new ViewportFilter. +// By default, the filter is set to only allow the main scene viewport. +func (*ViewportFilter) New() akara.Component { + const mainViewport = 0 -// AddViewportFilter adds a new ViewportFilterComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *ViewportFilterComponent instead of an akara.Component -func (cm *ViewportFilterMap) AddViewportFilter(id akara.EID) *ViewportFilterComponent { - c := cm.Add(id).(*ViewportFilterComponent) - - c.BitSet = akara.NewBitSet(0) - - return c -} - -// GetViewportFilter returns the ViewportFilterComponent associated with the given entity id -func (cm *ViewportFilterMap) GetViewportFilter(id akara.EID) (*ViewportFilterComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false - } - - return entry.(*ViewportFilterComponent), found -} - -// ViewportFilter is a convenient reference to be used as a component identifier -var ViewportFilter = newViewportFilter() // nolint:gochecknoglobals // global by design - -func newViewportFilter() akara.Component { - return &ViewportFilterComponent{ - BaseComponent: akara.NewBaseComponent(ViewportFilterCID, newViewportFilter, newViewportFilterMap), + return &ViewportFilter{ + BitSet: akara.NewBitSet(mainViewport), } } -func newViewportFilterMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(ViewportFilterCID, newViewportFilter, newViewportFilterMap) - baseMap := akara.NewBaseComponentMap(baseComponent) +// ViewportFilterFactory is a wrapper for the generic component factory that returns ViewportFilter component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a ViewportFilter. +type ViewportFilterFactory struct { + ViewportFilter *akara.ComponentFactory +} - cm := &ViewportFilterMap{ - BaseComponentMap: baseMap, +// AddViewportFilter adds a ViewportFilter component to the given entity and returns it +func (m *ViewportFilterFactory) AddViewportFilter(id akara.EID) *ViewportFilter { + return m.ViewportFilter.Add(id).(*ViewportFilter) +} + +// GetViewportFilter returns the ViewportFilter component for the given entity, and a bool for whether or not it exists +func (m *ViewportFilterFactory) GetViewportFilter(id akara.EID) (*ViewportFilter, bool) { + component, found := m.ViewportFilter.Get(id) + if !found { + return nil, found } - return cm + return component.(*ViewportFilter), found } diff --git a/d2core/d2components/viewport_main.go b/d2core/d2components/viewport_main.go index 198378ca..83024a93 100644 --- a/d2core/d2components/viewport_main.go +++ b/d2core/d2components/viewport_main.go @@ -4,55 +4,34 @@ import ( "github.com/gravestench/akara" ) -// static check that MainViewportComponent implements Component -var _ akara.Component = &MainViewportComponent{} +// static check that MainViewport implements Component +var _ akara.Component = &MainViewport{} -// static check that MainViewportMap implements ComponentMap -var _ akara.ComponentMap = &MainViewportMap{} +// MainViewport is used to flag viewports as the main viewport of a scene +type MainViewport struct{} -// MainViewportComponent is used to flag viewports as the main viewport of a scene -type MainViewportComponent struct { - *akara.BaseComponent +// New returns a new MainViewport instance. It is always a nil instance. +func (*MainViewport) New() akara.Component { + return (*MainViewport)(nil) } -// MainViewportMap is a map of entity ID's to MainViewport -type MainViewportMap struct { - *akara.BaseComponentMap +// MainViewportFactory is a wrapper for the generic component factory that returns MainViewport component instances. +// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a MainViewport. +type MainViewportFactory struct { + MainViewport *akara.ComponentFactory } -// AddMainViewport adds a new MainViewportComponent for the given entity id and returns it. -// this is a convenience method for the generic Add method, as it returns a -// *MainViewportComponent instead of an akara.Component -func (cm *MainViewportMap) AddMainViewport(id akara.EID) *MainViewportComponent { - return cm.Add(id).(*MainViewportComponent) +// AddMainViewport adds a MainViewport component to the given entity and returns it +func (m *MainViewportFactory) AddMainViewport(id akara.EID) *MainViewport { + return m.MainViewport.Add(id).(*MainViewport) } -// GetMainViewport returns the MainViewportComponent associated with the given entity id -func (cm *MainViewportMap) GetMainViewport(id akara.EID) (*MainViewportComponent, bool) { - entry, found := cm.Get(id) - if entry == nil { - return nil, false +// GetMainViewport returns the MainViewport component for the given entity, and a bool for whether or not it exists +func (m *MainViewportFactory) GetMainViewport(id akara.EID) (*MainViewport, bool) { + component, found := m.MainViewport.Get(id) + if !found { + return nil, found } - return entry.(*MainViewportComponent), found -} - -// MainViewport is a convenient reference to be used as a component identifier -var MainViewport = newMainViewport() // nolint:gochecknoglobals // global by design - -func newMainViewport() akara.Component { - return &MainViewportComponent{ - BaseComponent: akara.NewBaseComponent(MainViewportCID, newMainViewport, newMainViewportMap), - } -} - -func newMainViewportMap() akara.ComponentMap { - baseComponent := akara.NewBaseComponent(MainViewportCID, newMainViewport, newMainViewportMap) - baseMap := akara.NewBaseComponentMap(baseComponent) - - cm := &MainViewportMap{ - BaseComponentMap: baseMap, - } - - return cm + return component.(*MainViewport), found } diff --git a/d2core/d2systems/app_bootstrap.go b/d2core/d2systems/app_bootstrap.go index c1e65524..55142cef 100644 --- a/d2core/d2systems/app_bootstrap.go +++ b/d2core/d2systems/app_bootstrap.go @@ -22,87 +22,109 @@ const ( // static check that the game config system implements the system interface var _ akara.System = &AppBootstrapSystem{} -// NewAppBootstrapSystem creates a system that initializes the common application facilities, namely -// config file source directories and loading/creating the OpenDiablo2 config file. -func NewAppBootstrapSystem() *AppBootstrapSystem { - // we are going to check entities that dont yet have loaded asset types - filesToCheck := akara.NewFilter(). - Require( // files that need to be loaded - d2components.FileType, - d2components.FileHandle, - d2components.FilePath, - ). - Forbid( // files which have been loaded - d2components.GameConfig, - d2components.StringTable, - d2components.DataDictionary, - d2components.Palette, - d2components.PaletteTransform, - d2components.Cof, - d2components.Dc6, - d2components.Dcc, - d2components.Ds1, - d2components.Dt1, - d2components.Wav, - d2components.AnimData, - ). - Build() - - // we are interested in actual game config instances, too - gameConfigs := akara.NewFilter().Require(d2components.GameConfig).Build() - - sys := &AppBootstrapSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToCheck, gameConfigs), - Logger: d2util.NewLogger(), - } - - sys.SetPrefix(logPrefixAppBootstrap) - sys.Debug("Created") - - return sys -} - // AppBootstrapSystem is responsible for the common initialization process between // the app modes (eg common to the game client as well as the headless server) type AppBootstrapSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger subscribedFiles *akara.Subscription subscribedConfigs *akara.Subscription - *d2components.GameConfigMap - *d2components.FilePathMap - *d2components.FileTypeMap - *d2components.FileHandleMap - *d2components.FileSourceMap + d2components.GameConfigFactory + d2components.FilePathFactory + d2components.FileTypeFactory + d2components.FileHandleFactory + d2components.FileSourceFactory } // Init will inject (or use existing) components related to setting up the config sources func (m *AppBootstrapSystem) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") - m.subscribedFiles = m.Subscriptions[0] - m.subscribedConfigs = m.Subscriptions[1] - - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.GameConfigMap = world.InjectMap(d2components.GameConfig).(*d2components.GameConfigMap) - m.FilePathMap = world.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.FileTypeMap = world.InjectMap(d2components.FileType).(*d2components.FileTypeMap) - m.FileHandleMap = world.InjectMap(d2components.FileHandle).(*d2components.FileHandleMap) - m.FileSourceMap = world.InjectMap(d2components.FileSource).(*d2components.FileSourceMap) - + m.setupSubscriptions() + m.setupFactories() m.injectSystems() m.setupConfigSources() m.setupConfigFile() + + m.Info("... initialization complete!") +} + +func (m *AppBootstrapSystem) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixAppBootstrap) +} + +func (m *AppBootstrapSystem) setupSubscriptions() { + m.Info("setting up component subscriptions") + + // we are going to check entities that dont yet have loaded asset types + filesToCheck := m.NewComponentFilter(). + Require( // files that need to be loaded + &d2components.FileType{}, + &d2components.FileHandle{}, + &d2components.FilePath{}, + ). + Forbid( // files which have been loaded + &d2components.GameConfig{}, + &d2components.StringTable{}, + &d2components.DataDictionary{}, + &d2components.Palette{}, + &d2components.PaletteTransform{}, + &d2components.Cof{}, + &d2components.Dc6{}, + &d2components.Dcc{}, + &d2components.Ds1{}, + &d2components.Dt1{}, + &d2components.Wav{}, + &d2components.AnimationData{}, + ). + Build() + + // we are interested in actual game config instances, too + gameConfigs := m.NewComponentFilter().Require(&d2components.GameConfig{}).Build() + + m.subscribedFiles = m.World.AddSubscription(filesToCheck) + m.subscribedConfigs = m.World.AddSubscription(gameConfigs) +} + +func (m *AppBootstrapSystem) setupFactories() { + m.Info("setting up component factories") + + gameConfigID := m.RegisterComponent(&d2components.GameConfig{}) + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + fileHandleID := m.RegisterComponent(&d2components.FileHandle{}) + fileSourceID := m.RegisterComponent(&d2components.FileSource{}) + + m.GameConfig = m.GetComponentFactory(gameConfigID) + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) + m.FileHandle = m.GetComponentFactory(fileHandleID) + m.FileSource = m.GetComponentFactory(fileSourceID) } func (m *AppBootstrapSystem) injectSystems() { - m.World.AddSystem(NewFileTypeResolver()) - m.World.AddSystem(NewFileSourceResolver()) - m.World.AddSystem(NewFileHandleResolver()) - m.World.AddSystem(NewGameConfigSystem()) - m.World.AddSystem(NewAssetLoader()) - m.World.AddSystem(NewGameObjectFactory()) + m.Info("injecting file type resolution system") + m.AddSystem(&FileTypeResolver{}) + + m.Info("injecting file source resolution system") + m.AddSystem(&FileSourceResolver{}) + + m.Info("injecting file handle resolution system") + m.AddSystem(&FileHandleResolver{}) + + m.Info("injecting game configuration system") + m.AddSystem(&GameConfigSystem{}) + + m.Info("injecting asset loader system") + m.AddSystem(&AssetLoaderSystem{}) + + m.Info("injecting game object factory system") + m.AddSystem(&GameObjectFactory{}) } // we make two entities and assign file paths for the two directories that @@ -159,13 +181,14 @@ func (m *AppBootstrapSystem) Update() { return } + m.Info("adding mpq's from config file") m.initMpqSources(cfg) m.Info("app bootstrap complete, deactivating system") - m.SetActive(false) // bootstrap is complete! + m.SetActive(false) } -func (m *AppBootstrapSystem) initMpqSources(cfg *d2components.GameConfigComponent) { +func (m *AppBootstrapSystem) initMpqSources(cfg *d2components.GameConfig) { for _, mpqFileName := range cfg.MpqLoadOrder { fullMpqFilePath := path.Join(cfg.MpqPath, mpqFileName) diff --git a/d2core/d2systems/asset_loader.go b/d2core/d2systems/asset_loader.go index fd9788fe..58a62fbc 100644 --- a/d2core/d2systems/asset_loader.go +++ b/d2core/d2systems/asset_loader.go @@ -31,95 +31,123 @@ const ( logPrefixAssetLoader = "Asset Loader System" ) -// NewAssetLoader creates a new asset loader instance -func NewAssetLoader() *AssetLoaderSystem { - // we are going to check entities that dont yet have loaded asset types - filesToLoad := akara.NewFilter(). - Require(d2components.FilePath). // we want to process entities with these file components - Require(d2components.FileType). - Require(d2components.FileHandle). - Forbid(d2components.FileSource). // but we forbid files that are already loaded - Forbid(d2components.GameConfig). - Forbid(d2components.StringTable). - Forbid(d2components.DataDictionary). - Forbid(d2components.Palette). - Forbid(d2components.PaletteTransform). - Forbid(d2components.Cof). - Forbid(d2components.Dc6). - Forbid(d2components.Dcc). - Forbid(d2components.Ds1). - Forbid(d2components.Dt1). - Forbid(d2components.Wav). - Forbid(d2components.AnimData). - Build() - - fileSources := akara.NewFilter(). - Require(d2components.FileSource). - Build() - - assetLoader := &AssetLoaderSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToLoad, fileSources), - cache: d2cache.CreateCache(assetCacheBudget).(*d2cache.Cache), - Logger: d2util.NewLogger(), - } - - assetLoader.SetPrefix(logPrefixAssetLoader) - - return assetLoader -} - var _ akara.System = &AssetLoaderSystem{} // AssetLoaderSystem is responsible for parsing data from file handles into various structs, like COF or DC6 type AssetLoaderSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger fileSub *akara.Subscription sourceSub *akara.Subscription cache *d2cache.Cache - *d2components.FilePathMap - *d2components.FileTypeMap - *d2components.FileHandleMap - *d2components.FileSourceMap - *d2components.StringTableMap - *d2components.FontTableMap - *d2components.DataDictionaryMap - *d2components.PaletteMap - *d2components.PaletteTransformMap - *d2components.CofMap - *d2components.Dc6Map - *d2components.DccMap - *d2components.Ds1Map - *d2components.Dt1Map - *d2components.WavMap - *d2components.AnimDataMap + d2components.FilePathFactory + d2components.FileTypeFactory + d2components.FileHandleFactory + d2components.FileSourceFactory + d2components.StringTableFactory + d2components.FontTableFactory + d2components.DataDictionaryFactory + d2components.PaletteFactory + d2components.PaletteTransformFactory + d2components.CofFactory + d2components.Dc6Factory + d2components.DccFactory + d2components.Ds1Factory + d2components.Dt1Factory + d2components.WavFactory + d2components.AnimationDataFactory } // Init injects component maps related to various asset types -func (m *AssetLoaderSystem) Init(_ *akara.World) { +func (m *AssetLoaderSystem) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") - m.fileSub = m.Subscriptions[0] - m.sourceSub = m.Subscriptions[1] + m.setupSubscriptions() + m.setupFactories() - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.FilePathMap = m.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.FileTypeMap = m.InjectMap(d2components.FileType).(*d2components.FileTypeMap) - m.FileHandleMap = m.InjectMap(d2components.FileHandle).(*d2components.FileHandleMap) - m.FileSourceMap = m.InjectMap(d2components.FileSource).(*d2components.FileSourceMap) - m.StringTableMap = m.InjectMap(d2components.StringTable).(*d2components.StringTableMap) - m.DataDictionaryMap = m.InjectMap(d2components.DataDictionary).(*d2components.DataDictionaryMap) - m.PaletteMap = m.InjectMap(d2components.Palette).(*d2components.PaletteMap) - m.PaletteTransformMap = m.InjectMap(d2components.PaletteTransform).(*d2components.PaletteTransformMap) - m.FontTableMap = m.InjectMap(d2components.FontTable).(*d2components.FontTableMap) - m.CofMap = m.InjectMap(d2components.Cof).(*d2components.CofMap) - m.Dc6Map = m.InjectMap(d2components.Dc6).(*d2components.Dc6Map) - m.DccMap = m.InjectMap(d2components.Dcc).(*d2components.DccMap) - m.Ds1Map = m.InjectMap(d2components.Ds1).(*d2components.Ds1Map) - m.Dt1Map = m.InjectMap(d2components.Dt1).(*d2components.Dt1Map) - m.WavMap = m.InjectMap(d2components.Wav).(*d2components.WavMap) - m.AnimDataMap = m.InjectMap(d2components.AnimData).(*d2components.AnimDataMap) + m.cache = d2cache.CreateCache(assetCacheBudget).(*d2cache.Cache) +} + +func (m *AssetLoaderSystem) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixAssetLoader) +} + +func (m *AssetLoaderSystem) setupSubscriptions() { + m.Info("setting up component subscriptions") + + // we are going to check entities that dont yet have loaded asset types + filesToLoad := m.NewComponentFilter(). + Require( + &d2components.FilePath{}, // we want to process entities with these file components + &d2components.FileType{}, + &d2components.FileHandle{}, + ). + Forbid( + &d2components.FileSource{}, // but we forbid files that are already loaded + &d2components.GameConfig{}, + &d2components.StringTable{}, + &d2components.DataDictionary{}, + &d2components.Palette{}, + &d2components.PaletteTransform{}, + &d2components.Cof{}, + &d2components.Dc6{}, + &d2components.Dcc{}, + &d2components.Ds1{}, + &d2components.Dt1{}, + &d2components.Wav{}, + &d2components.AnimationData{}, + ). + Build() + + fileSources := m.NewComponentFilter(). + Require(&d2components.FileSource{}). + Build() + + m.fileSub = m.AddSubscription(filesToLoad) + m.sourceSub = m.AddSubscription(fileSources) +} + +func (m *AssetLoaderSystem) setupFactories() { + m.Info("setting up component factories") + + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + fileHandleID := m.RegisterComponent(&d2components.FileHandle{}) + fileSourceID := m.RegisterComponent(&d2components.FileSource{}) + stringTableID := m.RegisterComponent(&d2components.StringTable{}) + fontTableID := m.RegisterComponent(&d2components.FontTable{}) + dataDictionaryID := m.RegisterComponent(&d2components.DataDictionary{}) + paletteID := m.RegisterComponent(&d2components.Palette{}) + paletteTransformID := m.RegisterComponent(&d2components.PaletteTransform{}) + cofID := m.RegisterComponent(&d2components.Cof{}) + dc6ID := m.RegisterComponent(&d2components.Dc6{}) + dccID := m.RegisterComponent(&d2components.Dcc{}) + ds1ID := m.RegisterComponent(&d2components.Ds1{}) + dt1ID := m.RegisterComponent(&d2components.Dt1{}) + wavID := m.RegisterComponent(&d2components.Wav{}) + animationDataID := m.RegisterComponent(&d2components.AnimationData{}) + + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) + m.FileHandle = m.GetComponentFactory(fileHandleID) + m.FileSource = m.GetComponentFactory(fileSourceID) + m.StringTable = m.GetComponentFactory(stringTableID) + m.DataDictionary = m.GetComponentFactory(dataDictionaryID) + m.Palette = m.GetComponentFactory(paletteID) + m.PaletteTransform = m.GetComponentFactory(paletteTransformID) + m.FontTable = m.GetComponentFactory(fontTableID) + m.Cof = m.GetComponentFactory(cofID) + m.Dc6 = m.GetComponentFactory(dc6ID) + m.Dcc = m.GetComponentFactory(dccID) + m.Ds1 = m.GetComponentFactory(ds1ID) + m.Dt1 = m.GetComponentFactory(dt1ID) + m.Wav = m.GetComponentFactory(wavID) + m.AnimationData = m.GetComponentFactory(animationDataID) } // Update processes all of the Entities in the subscription of file entities that need to be processed @@ -190,7 +218,7 @@ func (m *AssetLoaderSystem) assignFromCache(id akara.EID, path string, t d2enum. case d2enum.FileTypePalette: m.AddPalette(id).Palette = entry.(d2interface.Palette) case d2enum.FileTypePaletteTransform: - m.AddPaletteTransform(id).Transform = entry.(*d2pl2.PL2) + m.AddPaletteTransform(id).PL2 = entry.(*d2pl2.PL2) case d2enum.FileTypeCOF: m.AddCof(id).COF = entry.(*d2cof.COF) case d2enum.FileTypeDC6: @@ -204,7 +232,7 @@ func (m *AssetLoaderSystem) assignFromCache(id akara.EID, path string, t d2enum. case d2enum.FileTypeWAV: m.AddWav(id).Data = entry.(d2interface.DataStream) case d2enum.FileTypeD2: - m.AddAnimData(id).AnimationData = entry.(*d2animdata.AnimationData) + m.AddAnimationData(id).AnimationData = entry.(*d2animdata.AnimationData) } return found @@ -277,7 +305,7 @@ func (m *AssetLoaderSystem) parseAndCache(id akara.EID, path string, t d2enum.Fi case d2enum.FileTypeD2: m.Infof("Loading animation data: %s", path) - if err := m.loadAnimData(id, path, data); err != nil { + if err := m.loadAnimationData(id, path, data); err != nil { m.Error(err.Error()) } } @@ -327,7 +355,7 @@ func (m *AssetLoaderSystem) loadPalette(id akara.EID, path string, data []byte) func (m *AssetLoaderSystem) loadPaletteTransform(id akara.EID, path string, data []byte) error { loaded, err := d2pl2.Load(data) if err == nil { - m.AddPaletteTransform(id).Transform = loaded + m.AddPaletteTransform(id).PL2 = loaded if cacheErr := m.cache.Insert(path, loaded, assetCacheEntryWeight); cacheErr != nil { m.Error(cacheErr.Error()) @@ -411,10 +439,10 @@ func (m *AssetLoaderSystem) loadWAV(id akara.EID, path string, seeker io.ReadSee } } -func (m *AssetLoaderSystem) loadAnimData(id akara.EID, path string, data []byte) error { +func (m *AssetLoaderSystem) loadAnimationData(id akara.EID, path string, data []byte) error { loaded, err := d2animdata.Load(data) if err == nil { - m.AddAnimData(id).AnimationData = loaded + m.AddAnimationData(id).AnimationData = loaded if cacheErr := m.cache.Insert(path, loaded, assetCacheEntryWeight); cacheErr != nil { m.Error(cacheErr.Error()) diff --git a/d2core/d2systems/file_handle_resolver.go b/d2core/d2systems/file_handle_resolver.go index b440ed58..3c33d6db 100644 --- a/d2core/d2systems/file_handle_resolver.go +++ b/d2core/d2systems/file_handle_resolver.go @@ -30,69 +30,86 @@ const ( logPrefixFileHandleResolver = "File Handle Resolver" ) -// NewFileHandleResolver creates a new file handle resolver system -func NewFileHandleResolver() *FileHandleResolutionSystem { - // this filter is for entities that have a file path and file type but no file handle. - filesToSource := akara.NewFilter(). - Require(d2components.FilePath). - Require(d2components.FileType). - Forbid(d2components.FileHandle). - Forbid(d2components.FileSource). - Build() - - sourcesToUse := akara.NewFilter(). - RequireOne(d2components.FileSource). - Build() - - fhr := &FileHandleResolutionSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToSource, sourcesToUse), - cache: d2cache.CreateCache(fileHandleCacheBudget).(*d2cache.Cache), - Logger: d2util.NewLogger(), - } - - fhr.SetPrefix(logPrefixFileHandleResolver) - - return fhr -} - -// FileHandleResolutionSystem is responsible for using file sources to resolve files. +// FileHandleResolver is responsible for using file sources to resolve files. // File sources are checked in the order that the sources were added. // // A file source can be something like an MPQ archive or a file system directory on the host machine. // // A file handle is a primitive representation of a loaded file; something that has data // in the form of a byte slice, but has not been parsed into a more meaningful struct, like a DC6 animation. -type FileHandleResolutionSystem struct { - *akara.BaseSubscriberSystem +type FileHandleResolver struct { + akara.BaseSubscriberSystem *d2util.Logger cache *d2cache.Cache filesToLoad *akara.Subscription sourcesToUse *akara.Subscription - filePaths *d2components.FilePathMap - fileTypes *d2components.FileTypeMap - fileSources *d2components.FileSourceMap - fileHandles *d2components.FileHandleMap + d2components.FilePathFactory + d2components.FileTypeFactory + d2components.FileSourceFactory + d2components.FileHandleFactory } // Init initializes the system with the given world -func (m *FileHandleResolutionSystem) Init(_ *akara.World) { +func (m *FileHandleResolver) Init(world *akara.World) { + m.World = world + + m.cache = d2cache.CreateCache(fileHandleCacheBudget).(*d2cache.Cache) + + m.setupLogger() + m.Info("initializing ...") - m.filesToLoad = m.Subscriptions[0] - m.sourcesToUse = m.Subscriptions[1] + m.setupSubscriptions() + m.setupFactories() - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.filePaths = m.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.fileTypes = m.InjectMap(d2components.FileType).(*d2components.FileTypeMap) - m.fileHandles = m.InjectMap(d2components.FileHandle).(*d2components.FileHandleMap) - m.fileSources = m.InjectMap(d2components.FileSource).(*d2components.FileSourceMap) + m.Info("... initialization complete!") +} + +func (m *FileHandleResolver) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixFileHandleResolver) +} + +func (m *FileHandleResolver) setupSubscriptions() { + m.Info("setting up component subscriptions") + // this filter is for entities that have a file path and file type but no file handle. + filesToLoad := m.NewComponentFilter(). + Require( + &d2components.FilePath{}, + &d2components.FileType{}, + ). + Forbid( + &d2components.FileHandle{}, + &d2components.FileSource{}, + ). + Build() + + sourcesToUse := m.NewComponentFilter(). + Require(&d2components.FileSource{}). + Build() + + m.filesToLoad = m.AddSubscription(filesToLoad) + m.sourcesToUse = m.AddSubscription(sourcesToUse) +} + +func (m *FileHandleResolver) setupFactories() { + m.Info("setting up component factories") + + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + fileHandleID := m.RegisterComponent(&d2components.FileHandle{}) + fileSourceID := m.RegisterComponent(&d2components.FileSource{}) + + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) + m.FileHandle = m.GetComponentFactory(fileHandleID) + m.FileSource = m.GetComponentFactory(fileSourceID) } // Update iterates over entities which have not had a file handle resolved. // For each source, it attempts to load this file with the given source. // If the file can be opened by the source, we create the file handle using that source. -func (m *FileHandleResolutionSystem) Update() { +func (m *FileHandleResolver) Update() { filesToLoad := m.filesToLoad.GetEntities() sourcesToUse := m.sourcesToUse.GetEntities() @@ -106,23 +123,23 @@ func (m *FileHandleResolutionSystem) Update() { } // try to load a file with a source, returns true if loaded -func (m *FileHandleResolutionSystem) loadFileWithSource(fileID, sourceID akara.EID) bool { - fp, found := m.filePaths.GetFilePath(fileID) +func (m *FileHandleResolver) loadFileWithSource(fileID, sourceID akara.EID) bool { + fp, found := m.GetFilePath(fileID) if !found { return false } - ft, found := m.fileTypes.GetFileType(fileID) + ft, found := m.GetFileType(fileID) if !found { return false } - source, found := m.fileSources.GetFileSource(sourceID) + source, found := m.GetFileSource(sourceID) if !found { return false } - sourceFp, found := m.filePaths.GetFilePath(sourceID) + sourceFp, found := m.GetFilePath(sourceID) if !found { return false } @@ -136,7 +153,7 @@ func (m *FileHandleResolutionSystem) loadFileWithSource(fileID, sourceID akara.E cacheKey := m.makeCacheKey(fp.Path, sourceFp.Path) if entry, found := m.cache.Retrieve(cacheKey); found { - component := m.fileHandles.AddFileHandle(fileID) + component := m.AddFileHandle(fileID) component.Data = entry.(d2interface.DataStream) return true @@ -155,11 +172,11 @@ func (m *FileHandleResolutionSystem) loadFileWithSource(fileID, sourceID akara.E } tryPath := strings.ReplaceAll(fp.Path, "sfx", "music") - tmpComponent := &d2components.FilePathComponent{Path: tryPath} + tmpComponent := &d2components.FilePath{Path: tryPath} cacheKey = m.makeCacheKey(tryPath, sourceFp.Path) if entry, found := m.cache.Retrieve(cacheKey); found { - component := m.fileHandles.AddFileHandle(fileID) + component := m.AddFileHandle(fileID) component.Data = entry.(d2interface.DataStream) fp.Path = tryPath @@ -176,7 +193,7 @@ func (m *FileHandleResolutionSystem) loadFileWithSource(fileID, sourceID akara.E m.Infof("resolved `%s` with source `%s`", fp.Path, sourceFp.Path) - component := m.fileHandles.AddFileHandle(fileID) + component := m.AddFileHandle(fileID) component.Data = data if err := m.cache.Insert(cacheKey, data, fileHandleCacheEntryWeight); err != nil { @@ -186,7 +203,7 @@ func (m *FileHandleResolutionSystem) loadFileWithSource(fileID, sourceID akara.E return true } -func (m *FileHandleResolutionSystem) makeCacheKey(path, source string) string { +func (m *FileHandleResolver) makeCacheKey(path, source string) string { const sep = "->" return strings.Join([]string{source, path}, sep) } diff --git a/d2core/d2systems/file_handle_resolver_test.go b/d2core/d2systems/file_handle_resolver_test.go index 736bc3ce..faf1ee1e 100644 --- a/d2core/d2systems/file_handle_resolver_test.go +++ b/d2core/d2systems/file_handle_resolver_test.go @@ -7,7 +7,6 @@ import ( "github.com/gravestench/akara" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2components" ) func Test_FileHandleResolver_Process(t *testing.T) { @@ -15,34 +14,30 @@ func Test_FileHandleResolver_Process(t *testing.T) { cfg := akara.NewWorldConfig() - fileTypeResolver := NewFileTypeResolver() - fileHandleResolver := NewFileHandleResolver() - fileSourceResolver := NewFileSourceResolver() + typeSys := &FileTypeResolver{} + handleSys := &FileHandleResolver{} + sourceSys := &FileSourceResolver{} - cfg.With(fileTypeResolver). - With(fileSourceResolver). - With(fileHandleResolver) + cfg.With(typeSys). + With(sourceSys). + With(handleSys) world := akara.NewWorld(cfg) - filepathMap, err := world.GetMap(d2components.FilePath) - if err != nil { - t.Error("file path component map not found") - } - - filePaths := filepathMap.(*d2components.FilePathMap) + filePaths := typeSys.FilePathFactory + fileHandles := handleSys.FileHandleFactory sourceEntity := world.NewEntity() - sourceFp := filePaths.AddFilePath(sourceEntity) - sourceFp.Path = testDataPath + source := filePaths.AddFilePath(sourceEntity) + source.Path = testDataPath fileEntity := world.NewEntity() - fileFp := filePaths.AddFilePath(fileEntity) - fileFp.Path = "testfile_a.txt" + file := filePaths.AddFilePath(fileEntity) + file.Path = "testfile_a.txt" _ = world.Update(0) - ft, found := fileTypeResolver.GetFileType(sourceEntity) + ft, found := typeSys.GetFileType(sourceEntity) if !found { t.Error("file source type not created for entity") return @@ -53,14 +48,6 @@ func Test_FileHandleResolver_Process(t *testing.T) { return } - handleMap, err := world.GetMap(d2components.FileHandle) - if err != nil { - t.Error("file handle component map is nil") - return - } - - fileHandles := handleMap.(*d2components.FileHandleMap) - handle, found := fileHandles.GetFileHandle(fileEntity) if !found { t.Error("file handle for entity was not found") diff --git a/d2core/d2systems/file_source_resolver.go b/d2core/d2systems/file_source_resolver.go index ed544b3d..ee2358c0 100644 --- a/d2core/d2systems/file_source_resolver.go +++ b/d2core/d2systems/file_source_resolver.go @@ -19,48 +19,64 @@ const ( logPrefixFileSourceResolver = "File Source Resolver" ) -// NewFileSourceResolver creates a new file source resolver system -func NewFileSourceResolver() *FileSourceResolver { - // subscribe to entities with a file type and file path, but no file source type - filesToCheck := akara.NewFilter(). - Require(d2components.FilePath). - Require(d2components.FileType). - Forbid(d2components.FileSource). - Build() - - fsr := &FileSourceResolver{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToCheck), - Logger: d2util.NewLogger(), - } - - fsr.SetPrefix(logPrefixFileSourceResolver) - - return fsr -} - // FileSourceResolver is responsible for determining if files can be used as a file source. // If it can, it sets the file up as a source, and the file handle resolver system can // then use the source to open files. type FileSourceResolver struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger - fileSub *akara.Subscription - filePaths *d2components.FilePathMap - fileTypes *d2components.FileTypeMap - fileSources *d2components.FileSourceMap + filesToCheck *akara.Subscription + d2components.FilePathFactory + d2components.FileTypeFactory + d2components.FileSourceFactory } // Init initializes the file source resolver, injecting the necessary components into the world -func (m *FileSourceResolver) Init(_ *akara.World) { +func (m *FileSourceResolver) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") - m.fileSub = m.Subscriptions[0] + m.setupSubscriptions() + m.setupFactories() - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.filePaths = m.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.fileTypes = m.InjectMap(d2components.FileType).(*d2components.FileTypeMap) - m.fileSources = m.InjectMap(d2components.FileSource).(*d2components.FileSourceMap) + m.Info("... initialization complete!") +} + +func (m *FileSourceResolver) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixFileSourceResolver) +} + +func (m *FileSourceResolver) setupSubscriptions() { + m.Info("setting up component subscriptions") + + // subscribe to entities with a file type and file path, but no file source type + filesToCheck := m.NewComponentFilter(). + Require( + &d2components.FilePath{}, + &d2components.FileType{}, + ). + Forbid( + &d2components.FileSource{}, + ). + Build() + + m.filesToCheck = m.AddSubscription(filesToCheck) +} + +func (m *FileSourceResolver) setupFactories() { + m.Info("setting up component factories") + + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + fileSourceID := m.RegisterComponent(&d2components.FileSource{}) + + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) + m.FileSource = m.GetComponentFactory(fileSourceID) } // Update iterates over entities from its subscription, and checks if it can be used as a file source @@ -73,12 +89,12 @@ func (m *FileSourceResolver) Update() { } func (m *FileSourceResolver) processSourceEntity(id akara.EID) { - fp, found := m.filePaths.GetFilePath(id) + fp, found := m.GetFilePath(id) if !found { return } - ft, found := m.fileTypes.GetFileType(id) + ft, found := m.GetFileType(id) if !found { return } @@ -95,16 +111,11 @@ func (m *FileSourceResolver) processSourceEntity(id akara.EID) { break } - source := m.fileSources.AddFileSource(id) - source.AbstractSource = instance + m.AddFileSource(id).AbstractSource = instance m.Infof("using MPQ source for `%s`", fp.Path) case d2enum.FileTypeDirectory: - instance := m.makeFileSystemSource(fp.Path) - - source := m.fileSources.AddFileSource(id) - source.AbstractSource = instance - + m.AddFileSource(id).AbstractSource = m.makeFileSystemSource(fp.Path) m.Infof("using FILESYSTEM source for `%s`", fp.Path) } } @@ -118,7 +129,7 @@ type fsSource struct { rootDir string } -func (s *fsSource) Open(path *d2components.FilePathComponent) (d2interface.DataStream, error) { +func (s *fsSource) Open(path *d2components.FilePath) (d2interface.DataStream, error) { fileData, err := os.Open(s.fullPath(path.Path)) if err != nil { return nil, err @@ -149,7 +160,7 @@ type mpqSource struct { mpq d2interface.Archive } -func (s *mpqSource) Open(path *d2components.FilePathComponent) (d2interface.DataStream, error) { +func (s *mpqSource) Open(path *d2components.FilePath) (d2interface.DataStream, error) { fileData, err := s.mpq.ReadFileStream(s.cleanMpqPath(path.Path)) if err != nil { return nil, err diff --git a/d2core/d2systems/file_source_resolver_test.go b/d2core/d2systems/file_source_resolver_test.go index a3acdf10..71e0461d 100644 --- a/d2core/d2systems/file_source_resolver_test.go +++ b/d2core/d2systems/file_source_resolver_test.go @@ -6,7 +6,6 @@ import ( "github.com/gravestench/akara" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2components" ) func Test_FileSourceResolution(t *testing.T) { @@ -14,20 +13,16 @@ func Test_FileSourceResolution(t *testing.T) { cfg := akara.NewWorldConfig() - srcResolver := NewFileSourceResolver() - fileTypeResolver := NewFileTypeResolver() + sourceSys := &FileSourceResolver{} + typeSys := &FileTypeResolver{} - cfg.With(fileTypeResolver). - With(srcResolver) + cfg.With(typeSys). + With(sourceSys) world := akara.NewWorld(cfg) - filepathMap, err := world.GetMap(d2components.FilePath) - if err != nil { - t.Error("file path component map not found") - } - - filePaths := filepathMap.(*d2components.FilePathMap) + filePaths := typeSys.FilePathFactory + fileSources := sourceSys.FileSourceFactory sourceEntity := world.NewEntity() sourceFp := filePaths.AddFilePath(sourceEntity) @@ -35,7 +30,7 @@ func Test_FileSourceResolution(t *testing.T) { _ = world.Update(0) - ft, found := fileTypeResolver.GetFileType(sourceEntity) + ft, found := typeSys.GetFileType(sourceEntity) if !found { t.Error("file source type not created for entity") } @@ -44,7 +39,7 @@ func Test_FileSourceResolution(t *testing.T) { t.Error("expected file system source type for entity") } - fs, found := srcResolver.fileSources.GetFileSource(sourceEntity) + fs, found := fileSources.GetFileSource(sourceEntity) if !found { t.Error("file source not created for entity") } diff --git a/d2core/d2systems/file_type_resolver.go b/d2core/d2systems/file_type_resolver.go index 11f9af77..98d6b950 100644 --- a/d2core/d2systems/file_type_resolver.go +++ b/d2core/d2systems/file_type_resolver.go @@ -18,25 +18,6 @@ const ( logPrefixFileTypeResolver = "File Type Resolver" ) -// NewFileTypeResolver creates a new file type resolution system. -func NewFileTypeResolver() *FileTypeResolver { - // we subscribe only to entities that have a filepath - // and have not yet been given a file type - filesToCheck := akara.NewFilter(). - Require(d2components.FilePath). - Forbid(d2components.FileType). - Build() - - ftr := &FileTypeResolver{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToCheck), - Logger: d2util.NewLogger(), - } - - ftr.SetPrefix(logPrefixFileTypeResolver) - - return ftr -} - // static check that FileTypeResolver implements the System interface var _ akara.System = &FileTypeResolver{} @@ -46,23 +27,47 @@ var _ akara.System = &FileTypeResolver{} // and it will then create the file type component for the entity, thus removing the entity // from its subscription. type FileTypeResolver struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger filesToCheck *akara.Subscription - *d2components.FilePathMap - *d2components.FileTypeMap + d2components.FilePathFactory + d2components.FileTypeFactory } // Init initializes the system with the given world -func (m *FileTypeResolver) Init(_ *akara.World) { +func (m *FileTypeResolver) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") - m.filesToCheck = m.Subscriptions[0] + m.setupFactories() + m.setupSubscriptions() +} - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.FilePathMap = m.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.FileTypeMap = m.InjectMap(d2components.FileType).(*d2components.FileTypeMap) +func (m *FileTypeResolver) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixFileTypeResolver) +} + +func (m *FileTypeResolver) setupFactories() { + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) +} + +func (m *FileTypeResolver) setupSubscriptions() { + // we subscribe only to entities that have a filepath + // and have not yet been given a file type + filesToCheck := m.NewComponentFilter(). + Require(&d2components.FilePath{}). + Forbid(&d2components.FileType{}). + Build() + + m.filesToCheck = m.AddSubscription(filesToCheck) } // Update processes all of the Entities diff --git a/d2core/d2systems/file_type_resolver_test.go b/d2core/d2systems/file_type_resolver_test.go index e18a0500..a617104d 100644 --- a/d2core/d2systems/file_type_resolver_test.go +++ b/d2core/d2systems/file_type_resolver_test.go @@ -9,30 +9,23 @@ import ( ) func TestNewFileTypeResolver_KnownType(t *testing.T) { - cfg := akara.NewWorldConfig() - - resolver := NewFileTypeResolver() - - cfg.With(resolver) - - world := akara.NewWorld(cfg) + typeSys := &FileTypeResolver{} + world := akara.NewWorld(akara.NewWorldConfig().With(typeSys)) e := world.NewEntity() + typeSys.AddFilePath(e).Path = "/some/path/to/a/file.dcc" - fp := resolver.AddFilePath(e) - fp.Path = "/some/path/to/a/file.dcc" - - if len(resolver.Subscriptions[0].GetEntities()) != 1 { - t.Error("entity with file path not added to file type resolver subscription") + if len(typeSys.filesToCheck.GetEntities()) != 1 { + t.Error("entity with file path not added to file type typeSys subscription") } _ = world.Update(0) - if len(resolver.Subscriptions[0].GetEntities()) != 0 { - t.Error("entity with existing file type not removed from file type resolver subscription") + if len(typeSys.filesToCheck.GetEntities()) != 0 { + t.Error("entity with existing file type not removed from file type typeSys subscription") } - ft, found := resolver.GetFileType(e) + ft, found := typeSys.GetFileType(e) if !found { t.Error("file type component not added to entity with file path component") } @@ -43,22 +36,17 @@ func TestNewFileTypeResolver_KnownType(t *testing.T) { } func TestNewFileTypeResolver_UnknownType(t *testing.T) { - cfg := akara.NewWorldConfig() - - resolver := NewFileTypeResolver() - - cfg.With(resolver) - - world := akara.NewWorld(cfg) + typeSys := &FileTypeResolver{} + world := akara.NewWorld(akara.NewWorldConfig().With(typeSys)) e := world.NewEntity() - fp := resolver.AddFilePath(e) + fp := typeSys.AddFilePath(e) fp.Path = "/some/path/to/a/file.XYZ" _ = world.Update(0) - ft, _ := resolver.GetFileType(e) + ft, _ := typeSys.GetFileType(e) if ft.Type != d2enum.FileTypeUnknown { t.Error("unexpected file type") diff --git a/d2core/d2systems/game_client_bootstrap.go b/d2core/d2systems/game_client_bootstrap.go index 11b22e61..e9d9c27b 100644 --- a/d2core/d2systems/game_client_bootstrap.go +++ b/d2core/d2systems/game_client_bootstrap.go @@ -4,7 +4,6 @@ import ( "github.com/gravestench/akara" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2components" ) const ( @@ -14,53 +13,51 @@ const ( // static check that the game config system implements the system interface var _ akara.System = &GameClientBootstrapSystem{} -// NewGameClientBootstrapSystem makes a new client bootstrap system -func NewGameClientBootstrapSystem() *GameClientBootstrapSystem { - // we are interested in actual game config instances, too - gameConfigs := akara.NewFilter().Require(d2components.GameConfig).Build() - - sys := &GameClientBootstrapSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(gameConfigs), - Logger: d2util.NewLogger(), - } - - sys.SetPrefix(logPrefixGameClientBootstrap) - - return sys -} - // GameClientBootstrapSystem is responsible for setting up other // systems that are common to both the game client and the headless game server type GameClientBootstrapSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger - *RenderSystem } // Init injects the common systems required by both the game client and headless server -func (m *GameClientBootstrapSystem) Init(_ *akara.World) { +func (m *GameClientBootstrapSystem) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") m.injectSystems() - m.Info("game client bootstrap complete, deactivating") - m.SetActive(false) + m.Info("initialization complete") if err := m.World.Update(0); err != nil { m.Error(err.Error()) } } -func (m *GameClientBootstrapSystem) injectSystems() { - m.RenderSystem = NewRenderSystem() +func (m *GameClientBootstrapSystem) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixGameClientBootstrap) +} - m.World.AddSystem(m.RenderSystem) - m.World.AddSystem(NewUpdateCounterSystem()) - m.World.AddSystem(NewLoadingScene()) - m.World.AddSystem(NewMainMenuScene()) +func (m *GameClientBootstrapSystem) injectSystems() { + m.Info("injecting render system") + m.AddSystem(&RenderSystem{}) + + m.Info("injecting update counter system") + m.AddSystem(&UpdateCounter{}) + + m.Info("injecting loading scene") + m.AddSystem(NewLoadingScene()) + + m.Info("injecting main menu scene") + m.AddSystem(NewMainMenuScene()) } // Update does nothing, but exists to satisfy the `akara.System` interface func (m *GameClientBootstrapSystem) Update() { - // nothing to do after init ... + m.Info("game client bootstrap complete, deactivating") + m.RemoveSystem(m) } diff --git a/d2core/d2systems/game_config.go b/d2core/d2systems/game_config.go index 38fdd37c..f4ed1b4f 100644 --- a/d2core/d2systems/game_config.go +++ b/d2core/d2systems/game_config.go @@ -18,42 +18,6 @@ const ( loggerPrefixGameConfig = "Game Config" ) -// NewGameConfigSystem creates a new game config system -func NewGameConfigSystem() *GameConfigSystem { - // we are going to check entities that dont yet have loaded asset types - filesToCheck := akara.NewFilter(). - Require(d2components.FilePath). - Require(d2components.FileType). - Require(d2components.FileHandle). - Forbid(d2components.GameConfig). - Forbid(d2components.StringTable). - Forbid(d2components.DataDictionary). - Forbid(d2components.Palette). - Forbid(d2components.PaletteTransform). - Forbid(d2components.Cof). - Forbid(d2components.Dc6). - Forbid(d2components.Dcc). - Forbid(d2components.Ds1). - Forbid(d2components.Dt1). - Forbid(d2components.Wav). - Forbid(d2components.AnimData). - Build() - - // we are interested in actual game config instances, too - gameConfigs := akara.NewFilter(). - Require(d2components.GameConfig). - Build() - - gcs := &GameConfigSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filesToCheck, gameConfigs), - Logger: d2util.NewLogger(), - } - - gcs.SetPrefix(loggerPrefixGameConfig) - - return gcs -} - // GameConfigSystem is responsible for game config configFileBootstrap procedure, as well as // clearing the `Dirty` component of game configs. In the `configFileBootstrap` method of this system // you can see that this system will add entities for the directories it expects config files @@ -65,34 +29,87 @@ func NewGameConfigSystem() *GameConfigSystem { // other systems are not present in the world, but no config files will be loaded by // this system either... type GameConfigSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger filesToCheck *akara.Subscription gameConfigs *akara.Subscription - *d2components.GameConfigMap - *d2components.FilePathMap - *d2components.FileTypeMap - *d2components.FileHandleMap - *d2components.FileSourceMap - *d2components.DirtyMap - ActiveConfig *d2components.GameConfigComponent + d2components.GameConfigFactory + d2components.FilePathFactory + d2components.FileTypeFactory + d2components.FileHandleFactory + d2components.FileSourceFactory + d2components.DirtyFactory + activeConfig *d2components.GameConfig } // Init the world with the necessary components related to game config files func (m *GameConfigSystem) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") - m.filesToCheck = m.Subscriptions[0] - m.gameConfigs = m.Subscriptions[1] + m.setupFactories() + m.setupSubscriptions() +} - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.FilePathMap = world.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - m.FileTypeMap = world.InjectMap(d2components.FileType).(*d2components.FileTypeMap) - m.FileHandleMap = world.InjectMap(d2components.FileHandle).(*d2components.FileHandleMap) - m.FileSourceMap = world.InjectMap(d2components.FileSource).(*d2components.FileSourceMap) - m.GameConfigMap = world.InjectMap(d2components.GameConfig).(*d2components.GameConfigMap) - m.DirtyMap = world.InjectMap(d2components.Dirty).(*d2components.DirtyMap) +func (m *GameConfigSystem) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(loggerPrefixGameConfig) +} + +func (m *GameConfigSystem) setupFactories() { + m.Info("setting up component factories") + + filePathID := m.RegisterComponent(&d2components.FilePath{}) + fileTypeID := m.RegisterComponent(&d2components.FileType{}) + fileHandleID := m.RegisterComponent(&d2components.FileHandle{}) + fileSourceID := m.RegisterComponent(&d2components.FileSource{}) + gameConfigID := m.RegisterComponent(&d2components.GameConfig{}) + dirtyID := m.RegisterComponent(&d2components.Dirty{}) + + m.FilePath = m.GetComponentFactory(filePathID) + m.FileType = m.GetComponentFactory(fileTypeID) + m.FileHandle = m.GetComponentFactory(fileHandleID) + m.FileSource = m.GetComponentFactory(fileSourceID) + m.GameConfig = m.GetComponentFactory(gameConfigID) + m.Dirty = m.GetComponentFactory(dirtyID) +} + +func (m *GameConfigSystem) setupSubscriptions() { + m.Info("setting up component subscriptions") + + // we are going to check entities that dont yet have loaded asset types + filesToCheck := m.NewComponentFilter(). + Require( + &d2components.FilePath{}, + &d2components.FileType{}, + &d2components.FileHandle{}, + ). + Forbid( + &d2components.GameConfig{}, + &d2components.StringTable{}, + &d2components.DataDictionary{}, + &d2components.Palette{}, + &d2components.PaletteTransform{}, + &d2components.Cof{}, + &d2components.Dc6{}, + &d2components.Dcc{}, + &d2components.Ds1{}, + &d2components.Dt1{}, + &d2components.Wav{}, + &d2components.AnimationData{}, + ). + Build() + + // we are interested in actual game config instances, too + gameConfigs := m.NewComponentFilter(). + Require(&d2components.GameConfig{}). + Build() + + m.filesToCheck = m.AddSubscription(filesToCheck) + m.gameConfigs = m.AddSubscription(gameConfigs) } // Update checks for new config files @@ -130,8 +147,8 @@ func (m *GameConfigSystem) loadConfig(eid akara.EID) { gameConfig := m.AddGameConfig(eid) if err := json.NewDecoder(fh.Data).Decode(gameConfig); err != nil { - m.GameConfigMap.Remove(eid) + m.RemoveEntity(eid) } - m.ActiveConfig = gameConfig + m.activeConfig = gameConfig } diff --git a/d2core/d2systems/game_config_test.go b/d2core/d2systems/game_config_test.go index c2ffcac6..82466e02 100644 --- a/d2core/d2systems/game_config_test.go +++ b/d2core/d2systems/game_config_test.go @@ -3,8 +3,6 @@ package d2systems import ( "testing" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2components" - "github.com/gravestench/akara" ) @@ -13,10 +11,10 @@ func Test_GameConfigSystem_Bootstrap(t *testing.T) { cfg := akara.NewWorldConfig() - typeSys := NewFileTypeResolver() - handleSys := NewFileHandleResolver() - srcSys := NewFileSourceResolver() - cfgSys := NewGameConfigSystem() + typeSys := &FileTypeResolver{} + handleSys := &FileHandleResolver{} + srcSys := &FileSourceResolver{} + cfgSys := &GameConfigSystem{} cfg.With(typeSys). With(srcSys). @@ -25,21 +23,8 @@ func Test_GameConfigSystem_Bootstrap(t *testing.T) { world := akara.NewWorld(cfg) - // for the purpose of this test, we want to add the testdata directory, so that - // when the game looks for the config file it gets pulled from there - filePathsAbstract, err := world.GetMap(d2components.FilePath) - if err != nil { - t.Error("file path component map not found") - return - } - - filePaths := filePathsAbstract.(*d2components.FilePathMap) - - cfgDir := filePaths.AddFilePath(world.NewEntity()) - cfgDir.Path = testDataPath - - cfgFile := filePaths.AddFilePath(world.NewEntity()) - cfgFile.Path = "config.json" + cfgSys.AddFilePath(world.NewEntity()).Path = testDataPath + cfgSys.AddFilePath(world.NewEntity()).Path = "config.json" // at this point the world has initialized the systems. when the world // updates it should process the config dir to a source and then diff --git a/d2core/d2systems/game_object_factory.go b/d2core/d2systems/game_object_factory.go index 1298a130..1f5c5294 100644 --- a/d2core/d2systems/game_object_factory.go +++ b/d2core/d2systems/game_object_factory.go @@ -10,36 +10,35 @@ const ( logPrefixGameObjectFactory = "Object Factory" ) -// NewGameObjectFactory creates a game object factory -func NewGameObjectFactory() *GameObjectFactory { - m := &GameObjectFactory{ - BaseSystem: &akara.BaseSystem{}, - Logger: d2util.NewLogger(), - } - - m.SetPrefix(logPrefixGameObjectFactory) - - return m -} - // static check that GameObjectFactory implements the System interface var _ akara.System = &GameObjectFactory{} // GameObjectFactory is a wrapper system for subordinate systems that // do the actual object creation work. type GameObjectFactory struct { - *akara.BaseSystem + akara.BaseSystem *d2util.Logger - SpriteFactory *SpriteFactory + *SpriteFactory } // Init will initialize the Game Object Factory by injecting all of the factory subsystems into the world func (t *GameObjectFactory) Init(world *akara.World) { + t.World = world + + t.setupLogger() + t.Info("initializing ...") + t.injectSubSystems() } +func (t *GameObjectFactory) setupLogger() { + t.Logger = d2util.NewLogger() + t.SetPrefix(logPrefixGameObjectFactory) +} + func (t *GameObjectFactory) injectSubSystems() { + t.Info("creating sprite factory") t.SpriteFactory = NewSpriteFactorySubsystem(t.BaseSystem, t.Logger) } diff --git a/d2core/d2systems/movement.go b/d2core/d2systems/movement.go index c4042b4c..7554c359 100644 --- a/d2core/d2systems/movement.go +++ b/d2core/d2systems/movement.go @@ -14,58 +14,51 @@ const ( logPrefixMovementSystem = "Movement System" ) -// NewMovementSystem creates a movement system -func NewMovementSystem() *MovementSystem { - cfg := akara.NewFilter().Require(d2components.Position, d2components.Velocity) - - filter := cfg.Build() - - sys := &MovementSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(filter), - Logger: d2util.NewLogger(), - } - - sys.SetPrefix(logPrefixMovementSystem) - - return sys -} - // static check that MovementSystem implements the System interface var _ akara.System = &MovementSystem{} // MovementSystem handles entity movement based on velocity and position components type MovementSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger - *d2components.PositionMap - *d2components.VelocityMap + d2components.PositionFactory + d2components.VelocityFactory + movableEntities *akara.Subscription } // Init initializes the system with the given world -func (m *MovementSystem) Init(_ *akara.World) { +func (m *MovementSystem) Init(world *akara.World) { + m.World = world + + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixMovementSystem) + m.Info("initializing ...") - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.PositionMap = m.InjectMap(d2components.Position).(*d2components.PositionMap) - m.VelocityMap = m.InjectMap(d2components.Velocity).(*d2components.VelocityMap) + positionID := m.RegisterComponent(&d2components.Position{}) + velocityID := m.RegisterComponent(&d2components.Velocity{}) + + m.Position = m.GetComponentFactory(positionID) + m.Velocity = m.GetComponentFactory(velocityID) + + movable := m.NewComponentFilter().Require( + &d2components.Position{}, + &d2components.Velocity{}, + ).Build() + + m.movableEntities = m.AddSubscription(movable) } // Update positions of all entities with their velocities func (m *MovementSystem) Update() { - for subIdx := range m.Subscriptions { - entities := m.Subscriptions[subIdx].GetEntities() + entities := m.movableEntities.GetEntities() - m.Infof("Processing movement for %d entities ...", len(entities)) - - for entIdx := range entities { - m.ProcessEntity(entities[entIdx]) - } + for entIdx := range entities { + m.move(entities[entIdx]) } } -// ProcessEntity updates an individual entity in the movement system -func (m *MovementSystem) ProcessEntity(id akara.EID) { +func (m *MovementSystem) move(id akara.EID) { position, found := m.GetPosition(id) if !found { return @@ -77,5 +70,5 @@ func (m *MovementSystem) ProcessEntity(id akara.EID) { } s := float64(m.World.TimeDelta) / float64(time.Second) - position.Vector = *position.Vector.Add(velocity.Vector.Clone().Scale(s)) + position.Vector.Add(velocity.Vector.Clone().Scale(s)) } diff --git a/d2core/d2systems/movement_test.go b/d2core/d2systems/movement_test.go index 88989743..d5f55cd3 100644 --- a/d2core/d2systems/movement_test.go +++ b/d2core/d2systems/movement_test.go @@ -7,14 +7,12 @@ import ( "time" "github.com/gravestench/akara" - - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2components" ) func TestMovementSystem_Init(t *testing.T) { cfg := akara.NewWorldConfig() - cfg.With(NewMovementSystem()) + cfg.With(&MovementSystem{}) world := akara.NewWorld(cfg) @@ -24,7 +22,7 @@ func TestMovementSystem_Init(t *testing.T) { } func TestMovementSystem_Active(t *testing.T) { - sys := NewMovementSystem() + sys := &MovementSystem{} if sys.Active() { t.Error("system should not be active at creation") @@ -32,7 +30,7 @@ func TestMovementSystem_Active(t *testing.T) { } func TestMovementSystem_SetActive(t *testing.T) { - sys := NewMovementSystem() + sys := &MovementSystem{} sys.SetActive(false) @@ -42,20 +40,13 @@ func TestMovementSystem_SetActive(t *testing.T) { } func TestMovementSystem_EntityAdded(t *testing.T) { - cfg := akara.NewWorldConfig() - - sys := NewMovementSystem() - - cfg.With(sys). - With(d2components.Position). - With(d2components.Velocity) - + moveSys := &MovementSystem{} + cfg := akara.NewWorldConfig().With(moveSys) world := akara.NewWorld(cfg) e := world.NewEntity() - - position := sys.AddPosition(e) - velocity := sys.AddVelocity(e) + position := moveSys.AddPosition(e) + velocity := moveSys.AddVelocity(e) px, py := 10., 10. vx, vy := 1., 0. @@ -63,18 +54,18 @@ func TestMovementSystem_EntityAdded(t *testing.T) { position.Set(px, py) velocity.Set(vx, vy) - if len(sys.Subscriptions[0].GetEntities()) != 1 { + if len(moveSys.movableEntities.GetEntities()) != 1 { t.Error("entity not added to the system") } - if p, found := sys.GetPosition(e); !found { + if p, found := moveSys.GetPosition(e); !found { t.Error("position component not found") } else if p.X() != px || p.Y() != py { fmtError := "position component values incorrect:\n\t expected %v, %v but got %v, %v" t.Errorf(fmtError, px, py, p.X(), p.Y()) } - if v, found := sys.GetVelocity(e); !found { + if v, found := moveSys.GetVelocity(e); !found { t.Error("position component not found") } else if v.X() != vx || v.Y() != vy { fmtError := "velocity component values incorrect:\n\t expected %v, %v but got %v, %v" @@ -86,12 +77,9 @@ func TestMovementSystem_Update(t *testing.T) { // world configFileBootstrap cfg := akara.NewWorldConfig() - movementSystem := NewMovementSystem() - positions := d2components.Position.NewMap() - velocities := d2components.Velocity.NewMap() - - cfg.With(movementSystem).With(positions).With(velocities) + movementSystem := &MovementSystem{} + cfg.With(movementSystem) world := akara.NewWorld(cfg) // lets make an entity and add some components to it @@ -118,7 +106,7 @@ func TestMovementSystem_Update(t *testing.T) { func benchN(n int, b *testing.B) { cfg := akara.NewWorldConfig() - movementSystem := NewMovementSystem() + movementSystem := &MovementSystem{} cfg.With(movementSystem) diff --git a/d2core/d2systems/render.go b/d2core/d2systems/render.go index 3a2cd97c..34dacf69 100644 --- a/d2core/d2systems/render.go +++ b/d2core/d2systems/render.go @@ -21,60 +21,71 @@ const ( logPrefixRenderSystem = "Render System" ) -// NewRenderSystem creates a new render system -func NewRenderSystem() *RenderSystem { - viewports := akara.NewFilter(). - Require(d2components.Viewport). - Require(d2components.MainViewport). - Require(d2components.Renderable). - Build() - - gameConfigs := akara.NewFilter().Require(d2components.GameConfig).Build() - - r := &RenderSystem{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(viewports, gameConfigs), - Logger: d2util.NewLogger(), - } - - r.SetPrefix(logPrefixRenderSystem) - - return r -} - // static check that RenderSystem implements the System interface var _ akara.System = &RenderSystem{} // RenderSystem is responsible for rendering the main viewports of scenes // to the game screen. type RenderSystem struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger renderer d2interface.Renderer viewports *akara.Subscription configs *akara.Subscription - *d2components.GameConfigMap - *d2components.ViewportMap - *d2components.MainViewportMap - *d2components.RenderableMap + d2components.GameConfigFactory + d2components.ViewportFactory + d2components.MainViewportFactory + d2components.RenderableFactory lastUpdate time.Time gameLoopInitDelay time.Duration // there is a race condition, this is a hack } // Init initializes the system with the given world, injecting the necessary components -func (m *RenderSystem) Init(_ *akara.World) { +func (m *RenderSystem) Init(world *akara.World) { + m.World = world + + m.setupLogger() + m.Info("initializing ...") + m.setupFactories() + m.setupSubscriptions() + m.gameLoopInitDelay = time.Millisecond +} - m.viewports = m.Subscriptions[0] - m.configs = m.Subscriptions[1] +func (m *RenderSystem) setupLogger() { + m.Logger = d2util.NewLogger() + m.SetPrefix(logPrefixRenderSystem) +} - // try to inject the components we require, then cast the returned - // abstract ComponentMap back to the concrete implementation - m.GameConfigMap = m.InjectMap(d2components.GameConfig).(*d2components.GameConfigMap) - m.ViewportMap = m.InjectMap(d2components.Viewport).(*d2components.ViewportMap) - m.MainViewportMap = m.InjectMap(d2components.MainViewport).(*d2components.MainViewportMap) - m.RenderableMap = m.InjectMap(d2components.Renderable).(*d2components.RenderableMap) +func (m *RenderSystem) setupFactories() { + gameConfigID := m.RegisterComponent(&d2components.GameConfig{}) + viewportID := m.RegisterComponent(&d2components.Viewport{}) + mainViewportID := m.RegisterComponent(&d2components.MainViewport{}) + renderableID := m.RegisterComponent(&d2components.Renderable{}) + + m.GameConfig = m.GetComponentFactory(gameConfigID) + m.Viewport = m.GetComponentFactory(viewportID) + m.MainViewport = m.GetComponentFactory(mainViewportID) + m.Renderable = m.GetComponentFactory(renderableID) +} + +func (m *RenderSystem) setupSubscriptions() { + viewports := m.NewComponentFilter(). + Require( + &d2components.Viewport{}, + &d2components.MainViewport{}, + &d2components.Renderable{}, + ). + Build() + + gameConfigs := m.NewComponentFilter(). + Require(&d2components.GameConfig{}). + Build() + + m.viewports = m.AddSubscription(viewports) + m.configs = m.AddSubscription(gameConfigs) } // Update will initialize the renderer, start the game loop, and diff --git a/d2core/d2systems/scene_base.go b/d2core/d2systems/scene_base.go index 537be8ca..4c27c932 100644 --- a/d2core/d2systems/scene_base.go +++ b/d2core/d2systems/scene_base.go @@ -55,16 +55,16 @@ type BaseScene struct { Add *sceneObjectFactory Viewports []akara.EID GameObjects []akara.EID - *d2components.ViewportMap - *d2components.MainViewportMap - *d2components.ViewportFilterMap - *d2components.CameraMap - *d2components.RenderableMap - *d2components.PositionMap - *d2components.ScaleMap - *d2components.AnimationMap - *d2components.OriginMap - *d2components.AlphaMap + d2components.ViewportFactory + d2components.MainViewportFactory + d2components.ViewportFilterFactory + d2components.CameraFactory + d2components.RenderableFactory + d2components.PositionFactory + d2components.ScaleFactory + d2components.AnimationFactory + d2components.OriginFactory + d2components.AlphaFactory } // Booted returns whether or not the scene has booted @@ -87,9 +87,9 @@ func (s *BaseScene) Init(world *akara.World) { } func (s *BaseScene) boot() { - s.Info("booting ...") + s.Info("base scene booting ...") - s.injectComponentMaps() + s.setupFactories() s.Add = &sceneObjectFactory{ BaseScene: s, @@ -129,21 +129,34 @@ func (s *BaseScene) boot() { s.createDefaultViewport() - s.Info("booted!") + s.Info("base scene booted!") s.booted = true } -func (s *BaseScene) injectComponentMaps() { - s.MainViewportMap = s.World.InjectMap(d2components.MainViewport).(*d2components.MainViewportMap) - s.ViewportMap = s.World.InjectMap(d2components.Viewport).(*d2components.ViewportMap) - s.ViewportFilterMap = s.World.InjectMap(d2components.ViewportFilter).(*d2components.ViewportFilterMap) - s.CameraMap = s.World.InjectMap(d2components.Camera).(*d2components.CameraMap) - s.RenderableMap = s.World.InjectMap(d2components.Renderable).(*d2components.RenderableMap) - s.PositionMap = s.World.InjectMap(d2components.Position).(*d2components.PositionMap) - s.ScaleMap = s.World.InjectMap(d2components.Scale).(*d2components.ScaleMap) - s.AnimationMap = s.World.InjectMap(d2components.Animation).(*d2components.AnimationMap) - s.OriginMap = s.World.InjectMap(d2components.Origin).(*d2components.OriginMap) - s.AlphaMap = s.World.InjectMap(d2components.Alpha).(*d2components.AlphaMap) +func (s *BaseScene) setupFactories() { + s.Info("setting up component factories") + + mainViewportID := s.RegisterComponent(&d2components.MainViewport{}) + viewportID := s.RegisterComponent(&d2components.Viewport{}) + viewportFilterID := s.RegisterComponent(&d2components.ViewportFilter{}) + cameraID := s.RegisterComponent(&d2components.Camera{}) + renderableID := s.RegisterComponent(&d2components.Renderable{}) + positionID := s.RegisterComponent(&d2components.Position{}) + scaleID := s.RegisterComponent(&d2components.Scale{}) + animationID := s.RegisterComponent(&d2components.Animation{}) + originID := s.RegisterComponent(&d2components.Origin{}) + alphaID := s.RegisterComponent(&d2components.Alpha{}) + + s.MainViewport = s.GetComponentFactory(mainViewportID) + s.Viewport = s.GetComponentFactory(viewportID) + s.ViewportFilter = s.GetComponentFactory(viewportFilterID) + s.Camera = s.GetComponentFactory(cameraID) + s.Renderable = s.GetComponentFactory(renderableID) + s.Position = s.GetComponentFactory(positionID) + s.Scale = s.GetComponentFactory(scaleID) + s.Animation = s.GetComponentFactory(animationID) + s.Origin = s.GetComponentFactory(originID) + s.Alpha = s.GetComponentFactory(alphaID) } func (s *BaseScene) createDefaultViewport() { @@ -239,7 +252,7 @@ func (s *BaseScene) renderViewport(idx int, objects []akara.EID) { if idx == mainViewport { s.AddMainViewport(id) } else { - s.MainViewportMap.Remove(id) + s.MainViewport.Remove(id) } camera, found := s.GetCamera(id) diff --git a/d2core/d2systems/scene_loading_screen.go b/d2core/d2systems/scene_loading_screen.go index a90483aa..149c315f 100644 --- a/d2core/d2systems/scene_loading_screen.go +++ b/d2core/d2systems/scene_loading_screen.go @@ -12,6 +12,9 @@ const ( sceneKeyLoading = "Loading" ) +// static check that LoadingScene implements the scene interface +var _ d2interface.Scene = &LoadingScene{} + // NewLoadingScene creates a new main menu scene. This is the first screen that the user // will see when launching the game. func NewLoadingScene() *LoadingScene { @@ -22,9 +25,6 @@ func NewLoadingScene() *LoadingScene { return scene } -// static check that LoadingScene implements the scene interface -var _ d2interface.Scene = &LoadingScene{} - // LoadingScene represents the game's main menu, where users can select single or multi player, // or start the map engine test. type LoadingScene struct { @@ -34,34 +34,42 @@ type LoadingScene struct { booted bool } -// Init the main menu scene -func (s *LoadingScene) Init(_ *akara.World) { - s.Info("initializing ...") +func (s *LoadingScene) setupSubscriptions() { + s.Info("setting up component subscriptions") - s.setupSubscription() -} - -func (s *LoadingScene) setupSubscription() { - filesToLoad := akara.NewFilter(). - Require(d2components.FileHandle). - Forbid(d2components.FileSource). // but we forbid files that are already loaded - Forbid(d2components.GameConfig). - Forbid(d2components.StringTable). - Forbid(d2components.DataDictionary). - Forbid(d2components.Palette). - Forbid(d2components.PaletteTransform). - Forbid(d2components.Cof). - Forbid(d2components.Dc6). - Forbid(d2components.Dcc). - Forbid(d2components.Ds1). - Forbid(d2components.Dt1). - Forbid(d2components.Wav). - Forbid(d2components.AnimData). + filesToLoad := s.NewComponentFilter(). + Require( + &d2components.FileHandle{}, + ). + Forbid( // but we forbid files that are already loaded + &d2components.FileSource{}, + &d2components.GameConfig{}, + &d2components.StringTable{}, + &d2components.DataDictionary{}, + &d2components.Palette{}, + &d2components.PaletteTransform{}, + &d2components.Cof{}, + &d2components.Dc6{}, + &d2components.Dcc{}, + &d2components.Ds1{}, + &d2components.Dt1{}, + &d2components.Wav{}, + &d2components.AnimationData{}, + ). Build() s.filesToLoad = s.World.AddSubscription(filesToLoad) } +// Init the main menu scene +func (s *LoadingScene) Init(world *akara.World) { + s.World = world + + s.Info("initializing ...") + + s.setupSubscriptions() +} + func (s *LoadingScene) boot() { if !s.BaseScene.booted { return diff --git a/d2core/d2systems/scene_main_menu.go b/d2core/d2systems/scene_main_menu.go index f2c93073..6db69140 100644 --- a/d2core/d2systems/scene_main_menu.go +++ b/d2core/d2systems/scene_main_menu.go @@ -32,7 +32,9 @@ type MainMenuScene struct { } // Init the main menu scene -func (s *MainMenuScene) Init(_ *akara.World) { +func (s *MainMenuScene) Init(world *akara.World) { + s.World = world + s.Info("initializing ...") } diff --git a/d2core/d2systems/sprite_factory.go b/d2core/d2systems/sprite_factory.go index fed8242c..88b98f5c 100644 --- a/d2core/d2systems/sprite_factory.go +++ b/d2core/d2systems/sprite_factory.go @@ -15,20 +15,9 @@ const ( // NewSpriteFactorySubsystem creates a new sprite factory which is intended // to be embedded in the game object factory system. -func NewSpriteFactorySubsystem(b *akara.BaseSystem, l *d2util.Logger) *SpriteFactory { - spritesToRender := akara.NewFilter(). - Require(d2components.Animation). // we want to process entities that have an animation ... - Forbid(d2components.Renderable). // ... but are missing a surface - Build() - - spritesToUpdate := akara.NewFilter(). - Require(d2components.Animation). // we want to process entities that have an animation ... - Require(d2components.Renderable). // ... but are missing a surface - Build() - +func NewSpriteFactorySubsystem(b akara.BaseSystem, l *d2util.Logger) *SpriteFactory { sys := &SpriteFactory{ - BaseSubscriberSystem: akara.NewBaseSubscriberSystem(spritesToRender, spritesToUpdate), - Logger: l, + Logger: l, } sys.BaseSystem = b @@ -47,39 +36,67 @@ type spriteLoadQueue = map[akara.EID]spriteLoadQueueEntry // SpriteFactory is responsible for queueing sprites to be loaded (as animations), // as well as binding the animation to a renderer if one is present (which generates the sprite surfaces). type SpriteFactory struct { - *akara.BaseSubscriberSystem + akara.BaseSubscriberSystem *d2util.Logger - *RenderSystem - *d2components.FilePathMap - *d2components.PositionMap - *d2components.Dc6Map - *d2components.DccMap - *d2components.PaletteMap - *d2components.AnimationMap - *d2components.RenderableMap - *d2components.SegmentedSpriteMap + RenderSystem *RenderSystem + d2components.FilePathFactory + d2components.PositionFactory + d2components.Dc6Factory + d2components.DccFactory + d2components.PaletteFactory + d2components.AnimationFactory + d2components.RenderableFactory + d2components.SegmentedSpriteFactory loadQueue spriteLoadQueue spritesToRender *akara.Subscription spritesToUpdate *akara.Subscription } // Init the sprite factory, injecting the necessary components -func (t *SpriteFactory) Init(_ *akara.World) { +func (t *SpriteFactory) Init(world *akara.World) { + t.World = world + t.Info("initializing sprite factory ...") + t.setupFactories() + t.setupSubscriptions() + t.loadQueue = make(spriteLoadQueue) +} - t.spritesToRender = t.Subscriptions[0] - t.spritesToUpdate = t.Subscriptions[1] +func (t *SpriteFactory) setupFactories() { + filePathID := t.RegisterComponent(&d2components.FilePath{}) + positionID := t.RegisterComponent(&d2components.Position{}) + dc6ID := t.RegisterComponent(&d2components.Dc6{}) + dccID := t.RegisterComponent(&d2components.Dcc{}) + paletteID := t.RegisterComponent(&d2components.Palette{}) + animationID := t.RegisterComponent(&d2components.Animation{}) + renderableID := t.RegisterComponent(&d2components.Renderable{}) + segmentedSpriteID := t.RegisterComponent(&d2components.SegmentedSprite{}) - t.FilePathMap = t.InjectMap(d2components.FilePath).(*d2components.FilePathMap) - t.PositionMap = t.InjectMap(d2components.Position).(*d2components.PositionMap) - t.Dc6Map = t.InjectMap(d2components.Dc6).(*d2components.Dc6Map) - t.DccMap = t.InjectMap(d2components.Dcc).(*d2components.DccMap) - t.PaletteMap = t.InjectMap(d2components.Palette).(*d2components.PaletteMap) - t.AnimationMap = t.InjectMap(d2components.Animation).(*d2components.AnimationMap) - t.RenderableMap = t.InjectMap(d2components.Renderable).(*d2components.RenderableMap) - t.SegmentedSpriteMap = t.InjectMap(d2components.SegmentedSprite).(*d2components.SegmentedSpriteMap) + t.FilePath = t.GetComponentFactory(filePathID) + t.Position = t.GetComponentFactory(positionID) + t.Dc6 = t.GetComponentFactory(dc6ID) + t.Dcc = t.GetComponentFactory(dccID) + t.Palette = t.GetComponentFactory(paletteID) + t.Animation = t.GetComponentFactory(animationID) + t.Renderable = t.GetComponentFactory(renderableID) + t.SegmentedSpriteFactory.SegmentedSprite = t.GetComponentFactory(segmentedSpriteID) +} + +func (t *SpriteFactory) setupSubscriptions() { + spritesToRender := t.NewComponentFilter(). + Require(&d2components.Animation{}). // we want to process entities that have an animation ... + Forbid(&d2components.Renderable{}). // ... but are missing a surface + Build() + + spritesToUpdate := t.NewComponentFilter(). + Require(&d2components.Animation{}). // we want to process entities that have an animation ... + Require(&d2components.Renderable{}). // ... but are missing a surface + Build() + + t.spritesToRender = t.AddSubscription(spritesToRender) + t.spritesToUpdate = t.AddSubscription(spritesToUpdate) } // Update processes the load queue which attempting to create animations, as well as @@ -191,7 +208,7 @@ func (t *SpriteFactory) tryRenderingSprite(eid akara.EID) { return } - anim.BindRenderer(t.renderer) + anim.BindRenderer(t.RenderSystem.renderer) sfc := anim.GetCurrentFrameSurface() @@ -225,15 +242,15 @@ func (t *SpriteFactory) updateSprite(eid akara.EID) { } func (t *SpriteFactory) createDc6Animation( - dc6 *d2components.Dc6Component, - pal *d2components.PaletteComponent, + dc6 *d2components.Dc6, + pal *d2components.Palette, ) (d2interface.Animation, error) { return d2animation.NewDC6Animation(dc6.DC6, pal.Palette, 0) } func (t *SpriteFactory) createDccAnimation( - dcc *d2components.DccComponent, - pal *d2components.PaletteComponent, + dcc *d2components.Dcc, + pal *d2components.Palette, ) (d2interface.Animation, error) { return d2animation.NewDCCAnimation(dcc.DCC, pal.Palette, 0) } diff --git a/d2core/d2systems/update_counter.go b/d2core/d2systems/update_counter.go index 212c1da9..f98de7b7 100644 --- a/d2core/d2systems/update_counter.go +++ b/d2core/d2systems/update_counter.go @@ -10,23 +10,11 @@ const ( logPrefixUpdateCounter = "Update Counter" ) -// NewUpdateCounterSystem creates a new update counter system -func NewUpdateCounterSystem() *UpdateCounter { - uc := &UpdateCounter{ - BaseSystem: &akara.BaseSystem{}, - Logger: d2util.NewLogger(), - } - - uc.SetPrefix(logPrefixUpdateCounter) - - return uc -} - var _ akara.System = &UpdateCounter{} // UpdateCounter is a utility system that logs the number of updates per second type UpdateCounter struct { - *akara.BaseSystem + akara.BaseSystem *d2util.Logger secondsElapsed float64 count int @@ -36,6 +24,8 @@ type UpdateCounter struct { func (u *UpdateCounter) Init(world *akara.World) { u.World = world + u.setupLogger() + if u.World == nil { u.SetActive(false) } @@ -43,6 +33,11 @@ func (u *UpdateCounter) Init(world *akara.World) { u.Info("initializing") } +func (u *UpdateCounter) setupLogger() { + u.Logger = d2util.NewLogger() + u.SetPrefix(logPrefixUpdateCounter) +} + // Update the world update count in 1 second intervals func (u *UpdateCounter) Update() { u.count++ diff --git a/go.mod b/go.mod index b888e3c8..78e54f9d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/go-gl/glfw/v3.3/glfw v0.0.0-20201108214237-06ea97f0c265 // indirect github.com/go-restruct/restruct v1.2.0-alpha github.com/google/uuid v1.1.2 - github.com/gravestench/akara v0.0.0-20201122210148-a1ee8ea83994 + github.com/gravestench/akara v0.0.0-20201128054238-892de9d70d6b github.com/hajimehoshi/ebiten/v2 v2.0.0 github.com/pkg/errors v0.9.1 // indirect github.com/pkg/profile v1.5.0 diff --git a/go.sum b/go.sum index ec71cf16..c738e101 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,8 @@ github.com/gravestench/akara v0.0.0-20201119221449-924b47999403 h1:hoCEhoSD+4Hvg github.com/gravestench/akara v0.0.0-20201119221449-924b47999403/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ= github.com/gravestench/akara v0.0.0-20201122210148-a1ee8ea83994 h1:Wp+4kZ0Pkap2ueAkTrE22rk++3VZE8TsU1bewpnzmsM= github.com/gravestench/akara v0.0.0-20201122210148-a1ee8ea83994/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ= +github.com/gravestench/akara v0.0.0-20201128054238-892de9d70d6b h1:Ngfdn7O3wXQBzbOLsL6vQ9G4F7utUiKjQqKnwHbY5uI= +github.com/gravestench/akara v0.0.0-20201128054238-892de9d70d6b/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ= github.com/hajimehoshi/bitmapfont/v2 v2.1.0/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs= github.com/hajimehoshi/ebiten/v2 v2.0.0 h1:G8mhkKFtnDPPZ/ChaGWx4Bm0NusYEcafGCJ8QLxEaYs= github.com/hajimehoshi/ebiten/v2 v2.0.0/go.mod h1:hpZZQ/kk8DZqft7QsQ5hZLRQXHSZPdKnaa0tcJ3CZFE= diff --git a/main.go b/main.go index 26f33c39..fa508a63 100644 --- a/main.go +++ b/main.go @@ -26,8 +26,8 @@ func main() { cfg := akara.NewWorldConfig() cfg. - With(d2systems.NewAppBootstrapSystem()). - With(d2systems.NewGameClientBootstrapSystem()) + With(&d2systems.AppBootstrapSystem{}). + With(&d2systems.GameClientBootstrapSystem{}) akara.NewWorld(cfg)