mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-20 07:27:19 -05:00
remove d2asset singleton (#726)
* export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
This commit is contained in:
parent
f4a71c72e4
commit
854fce3b14
38
d2app/app.go
38
d2app/app.go
@ -60,6 +60,7 @@ type App struct {
|
||||
captureFrames []*image.RGBA
|
||||
gitBranch string
|
||||
gitCommit string
|
||||
asset *d2asset.AssetManager
|
||||
inputManager d2interface.InputManager
|
||||
terminal d2interface.Terminal
|
||||
scriptEngine *d2script.ScriptEngine
|
||||
@ -89,8 +90,9 @@ func Create(gitBranch, gitCommit string,
|
||||
scriptEngine *d2script.ScriptEngine,
|
||||
audio d2interface.AudioProvider,
|
||||
renderer d2interface.Renderer,
|
||||
asset *d2asset.AssetManager,
|
||||
) *App {
|
||||
uiManager := d2ui.NewUIManager(renderer, inputManager, audio)
|
||||
uiManager := d2ui.NewUIManager(asset, renderer, inputManager, audio)
|
||||
screenManager := d2screen.NewScreenManager(uiManager)
|
||||
|
||||
result := &App{
|
||||
@ -103,6 +105,7 @@ func Create(gitBranch, gitCommit string,
|
||||
renderer: renderer,
|
||||
ui: uiManager,
|
||||
screen: screenManager,
|
||||
asset: asset,
|
||||
tAllocSamples: createZeroedRing(nSamplesTAlloc),
|
||||
}
|
||||
|
||||
@ -174,11 +177,7 @@ func (a *App) initialize() error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := d2asset.Initialize(a.renderer, a.terminal); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d2gui.Initialize(a.inputManager); err != nil {
|
||||
if err := d2gui.Initialize(a.asset, a.inputManager); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -208,7 +207,7 @@ func (a *App) loadStrings() error {
|
||||
}
|
||||
|
||||
for _, tablePath := range tablePaths {
|
||||
data, err := d2asset.LoadFile(tablePath)
|
||||
data, err := a.asset.LoadFile(tablePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -298,7 +297,7 @@ func (a *App) loadDataDict() error {
|
||||
d2datadict.InitObjectRecords()
|
||||
|
||||
for _, entry := range entries {
|
||||
data, err := d2asset.LoadFile(entry.path)
|
||||
data, err := a.asset.LoadFile(entry.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -678,42 +677,51 @@ func updateInitError(target d2interface.Surface) error {
|
||||
// ToMainMenu forces the game to transition to the Main Menu
|
||||
func (a *App) ToMainMenu() {
|
||||
buildInfo := d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit}
|
||||
mainMenu := d2gamescreen.CreateMainMenu(a, a.renderer, a.inputManager, a.audio, a.ui, buildInfo)
|
||||
|
||||
mainMenu := d2gamescreen.CreateMainMenu(a, a.asset, a.renderer, a.inputManager, a.audio, a.ui,
|
||||
buildInfo)
|
||||
|
||||
a.screen.SetNextScreen(mainMenu)
|
||||
}
|
||||
|
||||
// ToSelectHero forces the game to transition to the Select Hero (create character) screen
|
||||
func (a *App) ToSelectHero(connType d2clientconnectiontype.ClientConnectionType, host string) {
|
||||
selectHero := d2gamescreen.CreateSelectHeroClass(a, a.renderer, a.audio, a.ui, connType, host)
|
||||
selectHero := d2gamescreen.CreateSelectHeroClass(a, a.asset, a.renderer, a.audio, a.ui,
|
||||
connType, host)
|
||||
a.screen.SetNextScreen(selectHero)
|
||||
}
|
||||
|
||||
// ToCreateGame forces the game to transition to the Create Game screen
|
||||
func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.ClientConnectionType, host string) {
|
||||
gameClient, _ := d2client.Create(connType, a.scriptEngine)
|
||||
gameClient, _ := d2client.Create(connType, a.asset, a.scriptEngine)
|
||||
|
||||
if err := gameClient.Open(host, filePath); err != nil {
|
||||
// TODO an error screen should be shown in this case
|
||||
fmt.Printf("can not connect to the host: %s", host)
|
||||
}
|
||||
|
||||
a.screen.SetNextScreen(d2gamescreen.CreateGame(a, a.renderer, a.inputManager, a.audio, gameClient, a.terminal))
|
||||
a.screen.SetNextScreen(d2gamescreen.CreateGame(a, a.asset, a.ui, a.renderer, a.inputManager,
|
||||
a.audio, gameClient, a.terminal))
|
||||
}
|
||||
|
||||
// ToCharacterSelect forces the game to transition to the Character Select (load character) screen
|
||||
func (a *App) ToCharacterSelect(connType d2clientconnectiontype.ClientConnectionType, connHost string) {
|
||||
characterSelect := d2gamescreen.CreateCharacterSelect(a, a.renderer, a.inputManager, a.audio, a.ui, connType, connHost)
|
||||
|
||||
characterSelect := d2gamescreen.CreateCharacterSelect(a, a.asset, a.renderer, a.inputManager,
|
||||
a.audio, a.ui, connType, connHost)
|
||||
|
||||
a.screen.SetNextScreen(characterSelect)
|
||||
}
|
||||
|
||||
// ToMapEngineTest forces the game to transition to the map engine test screen
|
||||
func (a *App) ToMapEngineTest(region, level int) {
|
||||
met := d2gamescreen.CreateMapEngineTest(region, level, a.terminal, a.renderer, a.inputManager,
|
||||
met := d2gamescreen.CreateMapEngineTest(region, level, a.asset, a.terminal, a.renderer,
|
||||
a.inputManager,
|
||||
a.audio, a.screen)
|
||||
a.screen.SetNextScreen(met)
|
||||
}
|
||||
|
||||
// ToCredits forces the game to transition to the credits screen
|
||||
func (a *App) ToCredits() {
|
||||
a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.renderer, a.ui))
|
||||
a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.asset, a.renderer, a.ui))
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
@ -19,6 +20,7 @@ var _ d2interface.AnimationManager = &animationManager{}
|
||||
var _ d2interface.Cacher = &animationManager{}
|
||||
|
||||
type animationManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
renderer d2interface.Renderer
|
||||
}
|
||||
@ -31,13 +33,6 @@ func (am *animationManager) GetCache() d2interface.Cache {
|
||||
return am.cache
|
||||
}
|
||||
|
||||
func createAnimationManager(renderer d2interface.Renderer) *animationManager {
|
||||
return &animationManager{
|
||||
renderer: renderer,
|
||||
cache: d2cache.CreateCache(animationBudget),
|
||||
}
|
||||
}
|
||||
|
||||
func (am *animationManager) LoadAnimation(
|
||||
animationPath, palettePath string,
|
||||
effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
@ -51,22 +46,22 @@ func (am *animationManager) LoadAnimation(
|
||||
ext := strings.ToLower(filepath.Ext(animationPath))
|
||||
switch ext {
|
||||
case ".dc6":
|
||||
palette, err := LoadPalette(palettePath)
|
||||
palette, err := am.LoadPalette(palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
animation, err = CreateDC6Animation(am.renderer, animationPath, palette, d2enum.DrawEffectNone)
|
||||
animation, err = am.CreateDC6Animation(animationPath, palette, d2enum.DrawEffectNone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ".dcc":
|
||||
palette, err := LoadPalette(palettePath)
|
||||
palette, err := am.LoadPalette(palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
animation, err = CreateDCCAnimation(am.renderer, animationPath, palette, effect)
|
||||
animation, err = am.CreateDCCAnimation(animationPath, palette, effect)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -80,3 +75,85 @@ func (am *animationManager) LoadAnimation(
|
||||
|
||||
return animation, nil
|
||||
}
|
||||
|
||||
// CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
||||
func (am *animationManager) CreateDC6Animation(dc6Path string,
|
||||
palette d2interface.Palette, effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
dc6, err := am.loadDC6(dc6Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
anim := DC6Animation{
|
||||
animation: animation{
|
||||
directions: make([]animationDirection, dc6.Directions),
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
originAtBottom: true,
|
||||
effect: effect,
|
||||
},
|
||||
dc6Path: dc6Path,
|
||||
dc6: dc6,
|
||||
palette: palette,
|
||||
renderer: am.renderer,
|
||||
}
|
||||
|
||||
err = anim.SetDirection(0)
|
||||
|
||||
return &anim, err
|
||||
}
|
||||
|
||||
// CreateDCCAnimation creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||
func (am *animationManager) CreateDCCAnimation(dccPath string,
|
||||
palette d2interface.Palette,
|
||||
effect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
dcc, err := am.loadDCC(dccPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
anim := animation{
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
directions: make([]animationDirection, dcc.NumberOfDirections),
|
||||
effect: effect,
|
||||
}
|
||||
|
||||
DCC := DCCAnimation{
|
||||
animation: anim,
|
||||
animationManager: am,
|
||||
dccPath: dccPath,
|
||||
palette: palette,
|
||||
renderer: am.renderer,
|
||||
}
|
||||
|
||||
err = DCC.SetDirection(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DCC, nil
|
||||
}
|
||||
|
||||
func (am *animationManager) loadDC6(path string) (*d2dc6.DC6, error) {
|
||||
dc6Data, err := am.LoadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dc6, err := d2dc6.Load(dc6Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dc6, nil
|
||||
}
|
||||
|
||||
func (am *animationManager) loadDCC(path string) (*d2dcc.DCC, error) {
|
||||
dccData, err := am.LoadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return d2dcc.Load(dccData)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||
@ -16,6 +15,7 @@ var _ d2interface.ArchiveManager = &archiveManager{}
|
||||
var _ d2interface.Cacher = &archiveManager{}
|
||||
|
||||
type archiveManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
config *d2config.Configuration
|
||||
archives []d2interface.Archive
|
||||
@ -26,10 +26,6 @@ const (
|
||||
archiveBudget = 1024 * 1024 * 512
|
||||
)
|
||||
|
||||
func createArchiveManager(config *d2config.Configuration) d2interface.ArchiveManager {
|
||||
return &archiveManager{cache: d2cache.CreateCache(archiveBudget), config: config}
|
||||
}
|
||||
|
||||
// LoadArchiveForFile loads the archive for the given (in-archive) file path
|
||||
func (am *archiveManager) LoadArchiveForFile(filePath string) (d2interface.Archive, error) {
|
||||
am.mutex.Lock()
|
||||
|
@ -3,7 +3,6 @@ package d2asset
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||
@ -18,20 +17,12 @@ var _ d2interface.FileManager = &fileManager{}
|
||||
var _ d2interface.Cacher = &fileManager{}
|
||||
|
||||
type fileManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
archiveManager d2interface.ArchiveManager
|
||||
config *d2config.Configuration
|
||||
}
|
||||
|
||||
func createFileManager(config *d2config.Configuration,
|
||||
archiveManager d2interface.ArchiveManager) d2interface.FileManager {
|
||||
return &fileManager{
|
||||
d2cache.CreateCache(fileBudget),
|
||||
archiveManager,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadFileStream loads a file as a stream automatically from an archive
|
||||
func (fm *fileManager) LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
||||
filePath = fm.fixupFilePath(filePath)
|
||||
|
@ -1,13 +1,14 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
type assetManager struct {
|
||||
// AssetManager loads files and game objects
|
||||
type AssetManager struct {
|
||||
archiveManager d2interface.ArchiveManager
|
||||
archivedFileManager d2interface.FileManager
|
||||
paletteManager d2interface.PaletteManager
|
||||
@ -16,39 +17,66 @@ type assetManager struct {
|
||||
fontManager d2interface.FontManager
|
||||
}
|
||||
|
||||
func loadDC6(dc6Path string) (*d2dc6.DC6, error) {
|
||||
dc6Data, err := LoadFile(dc6Path)
|
||||
// LoadFileStream streams an MPQ file from a source file path
|
||||
func (am *AssetManager) LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
||||
data, err := am.archivedFileManager.LoadFileStream(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
||||
}
|
||||
|
||||
dc6, err := d2dc6.Load(dc6Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dc6, nil
|
||||
return data, err
|
||||
}
|
||||
|
||||
func loadDCC(dccPath string) (*d2dcc.DCC, error) {
|
||||
dccData, err := LoadFile(dccPath)
|
||||
// LoadFile loads an entire file from a source file path as a []byte
|
||||
func (am *AssetManager) LoadFile(filePath string) ([]byte, error) {
|
||||
data, err := am.archivedFileManager.LoadFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
||||
}
|
||||
|
||||
return d2dcc.Load(dccData)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func loadCOF(cofPath string) (*d2cof.COF, error) {
|
||||
cofData, err := LoadFile(cofPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// FileExists checks if a file exists on the underlying file system at the given file path.
|
||||
func (am *AssetManager) FileExists(filePath string) (bool, error) {
|
||||
return am.archivedFileManager.FileExists(filePath)
|
||||
}
|
||||
|
||||
// LoadAnimation loads an animation by its resource path and its palette path
|
||||
func (am *AssetManager) LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
||||
return am.LoadAnimationWithEffect(animationPath, palettePath, d2enum.DrawEffectNone)
|
||||
}
|
||||
|
||||
// LoadAnimationWithEffect loads an animation by its resource path and its palette path with a given transparency value
|
||||
func (am *AssetManager) LoadAnimationWithEffect(animationPath, palettePath string,
|
||||
drawEffect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
return am.animationManager.LoadAnimation(animationPath, palettePath, drawEffect)
|
||||
}
|
||||
|
||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||
func (am *AssetManager) LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
||||
c := &Composite{
|
||||
AssetManager: am,
|
||||
baseType: baseType,
|
||||
basePath: baseString(baseType),
|
||||
token: token,
|
||||
palettePath: palettePath,
|
||||
}
|
||||
|
||||
return d2cof.Load(cofData)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (am *assetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
||||
// LoadFont loads a font the resource files
|
||||
func (am *AssetManager) LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
||||
return am.fontManager.LoadFont(tablePath, spritePath, palettePath)
|
||||
}
|
||||
|
||||
// LoadPalette loads a palette from a given palette path
|
||||
func (am *AssetManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||
return am.paletteManager.LoadPalette(palettePath)
|
||||
}
|
||||
|
||||
func (am *AssetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
||||
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
||||
if verbose {
|
||||
term.OutputInfof("asset manager verbose logging enabled")
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
// Composite is a composite entity animation
|
||||
type Composite struct {
|
||||
*AssetManager
|
||||
baseType d2enum.ObjectType
|
||||
basePath string
|
||||
token string
|
||||
@ -28,12 +29,6 @@ type size struct {
|
||||
Height int
|
||||
}
|
||||
|
||||
// CreateComposite creates a Composite from a given ObjectLookupRecord and palettePath.
|
||||
func CreateComposite(baseType d2enum.ObjectType, token, palettePath string) *Composite {
|
||||
return &Composite{baseType: baseType, basePath: baseString(baseType),
|
||||
token: token, palettePath: palettePath}
|
||||
}
|
||||
|
||||
// Advance moves the composite animation forward for a given elapsed time in nanoseconds.
|
||||
func (c *Composite) Advance(elapsed float64) error {
|
||||
if c.mode == nil {
|
||||
@ -233,11 +228,11 @@ type compositeMode struct {
|
||||
|
||||
func (c *Composite) createMode(animationMode animationMode, weaponClass string) (*compositeMode, error) {
|
||||
cofPath := fmt.Sprintf("%s/%s/COF/%s%s%s.COF", c.basePath, c.token, c.token, animationMode, weaponClass)
|
||||
if exists, _ := FileExists(cofPath); !exists {
|
||||
if exists, _ := c.FileExists(cofPath); !exists {
|
||||
return nil, errors.New("composite not found")
|
||||
}
|
||||
|
||||
cof, err := loadCOF(cofPath)
|
||||
cof, err := c.loadCOF(cofPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -296,8 +291,9 @@ func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weap
|
||||
}
|
||||
|
||||
for _, animationPath := range animationPaths {
|
||||
if exists, _ := FileExists(animationPath); exists {
|
||||
animation, err := LoadAnimationWithEffect(animationPath, palettePath, drawEffect)
|
||||
if exists, _ := c.FileExists(animationPath); exists {
|
||||
animation, err := c.LoadAnimationWithEffect(animationPath, palettePath,
|
||||
drawEffect)
|
||||
if err == nil {
|
||||
return animation, nil
|
||||
}
|
||||
@ -345,6 +341,15 @@ func (c *Composite) updateSize() {
|
||||
c.size.Height = biggestH
|
||||
}
|
||||
|
||||
func (c *Composite) loadCOF(cofPath string) (*d2cof.COF, error) {
|
||||
cofData, err := c.LoadFile(cofPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return d2cof.Load(cofData)
|
||||
}
|
||||
|
||||
func baseString(baseType d2enum.ObjectType) string {
|
||||
switch baseType {
|
||||
case d2enum.ObjectTypePlayer:
|
||||
|
@ -1,90 +1,51 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||
)
|
||||
|
||||
var singleton *assetManager //nolint:gochecknoglobals // Currently global by design
|
||||
// NewAssetManager creates and assigns all necessary dependencies for the AssetManager top-level functions to work correctly
|
||||
func NewAssetManager(renderer d2interface.Renderer,
|
||||
term d2interface.Terminal) (*AssetManager, error) {
|
||||
|
||||
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
|
||||
func Initialize(renderer d2interface.Renderer,
|
||||
term d2interface.Terminal) error {
|
||||
var (
|
||||
archiveManager = createArchiveManager(d2config.Config)
|
||||
archivedFileManager = createFileManager(d2config.Config, archiveManager)
|
||||
paletteManager = createPaletteManager()
|
||||
paletteTransformManager = createPaletteTransformManager()
|
||||
animationManager = createAnimationManager(renderer)
|
||||
fontManager = createFontManager()
|
||||
)
|
||||
manager := &AssetManager{}
|
||||
|
||||
singleton = &assetManager{
|
||||
archiveManager,
|
||||
archivedFileManager,
|
||||
paletteManager,
|
||||
paletteTransformManager,
|
||||
animationManager,
|
||||
fontManager,
|
||||
manager.archiveManager = &archiveManager{
|
||||
AssetManager: manager,
|
||||
cache: d2cache.CreateCache(archiveBudget),
|
||||
config: d2config.Config,
|
||||
}
|
||||
|
||||
manager.archivedFileManager = &fileManager{
|
||||
manager,
|
||||
d2cache.CreateCache(fileBudget),
|
||||
manager.archiveManager,
|
||||
d2config.Config,
|
||||
}
|
||||
|
||||
manager.paletteManager = &paletteManager{
|
||||
manager,
|
||||
d2cache.CreateCache(paletteBudget),
|
||||
}
|
||||
|
||||
manager.paletteTransformManager = &paletteTransformManager{
|
||||
manager,
|
||||
d2cache.CreateCache(paletteTransformBudget),
|
||||
}
|
||||
|
||||
manager.animationManager = &animationManager{
|
||||
AssetManager: manager,
|
||||
renderer: renderer,
|
||||
cache: d2cache.CreateCache(animationBudget),
|
||||
}
|
||||
|
||||
manager.fontManager = &fontManager{manager, d2cache.CreateCache(fontBudget)}
|
||||
|
||||
if term != nil {
|
||||
return singleton.BindTerminalCommands(term)
|
||||
return manager, manager.BindTerminalCommands(term)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFileStream streams an MPQ file from a source file path
|
||||
func LoadFileStream(filePath string) (d2interface.ArchiveDataStream, error) {
|
||||
data, err := singleton.archivedFileManager.LoadFileStream(filePath)
|
||||
if err != nil {
|
||||
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
||||
}
|
||||
|
||||
return data, err
|
||||
}
|
||||
|
||||
// LoadFile loads an entire file from a source file path as a []byte
|
||||
func LoadFile(filePath string) ([]byte, error) {
|
||||
data, err := singleton.archivedFileManager.LoadFile(filePath)
|
||||
if err != nil {
|
||||
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
||||
}
|
||||
|
||||
return data, err
|
||||
}
|
||||
|
||||
// FileExists checks if a file exists on the underlying file system at the given file path.
|
||||
func FileExists(filePath string) (bool, error) {
|
||||
return singleton.archivedFileManager.FileExists(filePath)
|
||||
}
|
||||
|
||||
// LoadAnimation loads an animation by its resource path and its palette path
|
||||
func LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
||||
return LoadAnimationWithEffect(animationPath, palettePath, d2enum.DrawEffectNone)
|
||||
}
|
||||
|
||||
// LoadAnimationWithEffect loads an animation by its resource path and its palette path with a given transparency value
|
||||
func LoadAnimationWithEffect(animationPath, palettePath string,
|
||||
drawEffect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
return singleton.animationManager.LoadAnimation(animationPath, palettePath, drawEffect)
|
||||
}
|
||||
|
||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||
func LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
||||
return CreateComposite(baseType, token, palettePath), nil
|
||||
}
|
||||
|
||||
// LoadFont loads a font the resource files
|
||||
func LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
||||
return singleton.fontManager.LoadFont(tablePath, spritePath, palettePath)
|
||||
}
|
||||
|
||||
// LoadPalette loads a palette from a given palette path
|
||||
func LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||
return singleton.paletteManager.LoadPalette(palettePath)
|
||||
return manager, nil
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package d2asset
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||
d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
@ -14,36 +16,11 @@ var _ d2iface.Animation = &DC6Animation{} // Static check to confirm struct conf
|
||||
type DC6Animation struct {
|
||||
animation
|
||||
dc6Path string
|
||||
dc6 *d2dc6.DC6
|
||||
palette d2iface.Palette
|
||||
renderer d2iface.Renderer
|
||||
}
|
||||
|
||||
// CreateDC6Animation creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
||||
func CreateDC6Animation(renderer d2iface.Renderer, dc6Path string,
|
||||
palette d2iface.Palette, effect d2enum.DrawEffect) (d2iface.Animation, error) {
|
||||
dc6, err := loadDC6(dc6Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
anim := DC6Animation{
|
||||
animation: animation{
|
||||
directions: make([]animationDirection, dc6.Directions),
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
originAtBottom: true,
|
||||
effect: effect,
|
||||
},
|
||||
dc6Path: dc6Path,
|
||||
palette: palette,
|
||||
renderer: renderer,
|
||||
}
|
||||
|
||||
err = anim.SetDirection(0)
|
||||
|
||||
return &anim, err
|
||||
}
|
||||
|
||||
// SetDirection decodes and sets the direction
|
||||
func (a *DC6Animation) SetDirection(directionIndex int) error {
|
||||
const smallestInvalidDirectionIndex = 64
|
||||
@ -66,11 +43,7 @@ func (a *DC6Animation) SetDirection(directionIndex int) error {
|
||||
}
|
||||
|
||||
func (a *DC6Animation) decodeDirection(directionIndex int) error {
|
||||
dc6, err := loadDC6(a.dc6Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dc6 := a.dc6
|
||||
startFrame := directionIndex * int(dc6.FramesPerDirection)
|
||||
|
||||
for i := 0; i < int(dc6.FramesPerDirection); i++ {
|
||||
|
@ -16,41 +16,12 @@ var _ d2iface.Animation = &DCCAnimation{} // Static check to confirm struct conf
|
||||
// DCCAnimation represents an animation decoded from DCC
|
||||
type DCCAnimation struct {
|
||||
animation
|
||||
*animationManager
|
||||
dccPath string
|
||||
palette d2iface.Palette
|
||||
renderer d2iface.Renderer
|
||||
}
|
||||
|
||||
// CreateDCCAnimation creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||
func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2iface.Palette,
|
||||
effect d2enum.DrawEffect) (d2iface.Animation, error) {
|
||||
dcc, err := loadDCC(dccPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
anim := animation{
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
directions: make([]animationDirection, dcc.NumberOfDirections),
|
||||
effect: effect,
|
||||
}
|
||||
|
||||
DCC := DCCAnimation{
|
||||
animation: anim,
|
||||
dccPath: dccPath,
|
||||
palette: palette,
|
||||
renderer: renderer,
|
||||
}
|
||||
|
||||
err = DCC.SetDirection(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &DCC, nil
|
||||
}
|
||||
|
||||
// Clone creates a copy of the animation
|
||||
func (a *DCCAnimation) Clone() d2iface.Animation {
|
||||
animation := *a
|
||||
@ -79,7 +50,7 @@ func (a *DCCAnimation) SetDirection(directionIndex int) error {
|
||||
}
|
||||
|
||||
func (a *DCCAnimation) decodeDirection(directionIndex int) error {
|
||||
dcc, err := loadDCC(a.dccPath)
|
||||
dcc, err := a.loadDCC(a.dccPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"image/color"
|
||||
"strings"
|
||||
|
||||
@ -25,45 +23,6 @@ type Font struct {
|
||||
color color.Color
|
||||
}
|
||||
|
||||
func loadFont(tablePath, spritePath, palettePath string) (d2interface.Font, error) {
|
||||
sheet, err := LoadAnimation(spritePath, palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := LoadFile(tablePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if string(data[:5]) != "Woo!\x01" {
|
||||
return nil, errors.New("invalid font table format")
|
||||
}
|
||||
|
||||
_, maxCharHeight := sheet.GetFrameBounds()
|
||||
|
||||
glyphs := make(map[rune]fontGlyph)
|
||||
|
||||
for i := 12; i < len(data); i += 14 {
|
||||
code := rune(binary.LittleEndian.Uint16(data[i : i+2]))
|
||||
|
||||
var glyph fontGlyph
|
||||
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
||||
glyph.width = int(data[i+3])
|
||||
glyph.height = maxCharHeight
|
||||
|
||||
glyphs[code] = glyph
|
||||
}
|
||||
|
||||
font := &Font{
|
||||
sheet: sheet,
|
||||
glyphs: glyphs,
|
||||
color: color.White,
|
||||
}
|
||||
|
||||
return font, nil
|
||||
}
|
||||
|
||||
// SetColor sets the fonts color
|
||||
func (f *Font) SetColor(c color.Color) {
|
||||
f.color = c
|
||||
|
@ -1,9 +1,11 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
@ -16,13 +18,10 @@ var _ d2interface.FontManager = &fontManager{}
|
||||
var _ d2interface.Cacher = &fontManager{}
|
||||
|
||||
type fontManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
}
|
||||
|
||||
func createFontManager() d2interface.FontManager {
|
||||
return &fontManager{d2cache.CreateCache(fontBudget)}
|
||||
}
|
||||
|
||||
// LoadFont loads a font from the archives managed by the ArchiveManager
|
||||
func (fm *fontManager) LoadFont(tablePath, spritePath, palettePath string) (d2interface.Font,
|
||||
error) {
|
||||
@ -31,7 +30,41 @@ func (fm *fontManager) LoadFont(tablePath, spritePath, palettePath string) (d2in
|
||||
return font.(d2interface.Font), nil
|
||||
}
|
||||
|
||||
font, err := loadFont(tablePath, spritePath, palettePath)
|
||||
sheet, err := fm.LoadAnimation(spritePath, palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := fm.LoadFile(tablePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if string(data[:5]) != "Woo!\x01" {
|
||||
return nil, errors.New("invalid font table format")
|
||||
}
|
||||
|
||||
_, maxCharHeight := sheet.GetFrameBounds()
|
||||
|
||||
glyphs := make(map[rune]fontGlyph)
|
||||
|
||||
for i := 12; i < len(data); i += 14 {
|
||||
code := rune(binary.LittleEndian.Uint16(data[i : i+2]))
|
||||
|
||||
var glyph fontGlyph
|
||||
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
||||
glyph.width = int(data[i+3])
|
||||
glyph.height = maxCharHeight
|
||||
|
||||
glyphs[code] = glyph
|
||||
}
|
||||
|
||||
font := &Font{
|
||||
sheet: sheet,
|
||||
glyphs: glyphs,
|
||||
color: color.White,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
@ -11,6 +10,7 @@ var _ d2interface.PaletteManager = &paletteManager{}
|
||||
var _ d2interface.Cacher = &paletteManager{}
|
||||
|
||||
type paletteManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
}
|
||||
|
||||
@ -18,17 +18,13 @@ const (
|
||||
paletteBudget = 64
|
||||
)
|
||||
|
||||
func createPaletteManager() d2interface.PaletteManager {
|
||||
return &paletteManager{d2cache.CreateCache(paletteBudget)}
|
||||
}
|
||||
|
||||
// LoadPalette loads a palette from archives managed by the ArchiveManager
|
||||
func (pm *paletteManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||
if palette, found := pm.cache.Retrieve(palettePath); found {
|
||||
return palette.(d2interface.Palette), nil
|
||||
}
|
||||
|
||||
paletteData, err := LoadFile(palettePath)
|
||||
paletteData, err := pm.LoadFile(palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package d2asset
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
type paletteTransformManager struct {
|
||||
*AssetManager
|
||||
cache d2interface.Cache
|
||||
}
|
||||
|
||||
@ -14,16 +14,12 @@ const (
|
||||
paletteTransformBudget = 64
|
||||
)
|
||||
|
||||
func createPaletteTransformManager() *paletteTransformManager {
|
||||
return &paletteTransformManager{d2cache.CreateCache(paletteTransformBudget)}
|
||||
}
|
||||
|
||||
func (pm *paletteTransformManager) loadPaletteTransform(path string) (*d2pl2.PL2, error) {
|
||||
if pl2, found := pm.cache.Retrieve(path); found {
|
||||
return pl2.(*d2pl2.PL2), nil
|
||||
}
|
||||
|
||||
data, err := LoadFile(path)
|
||||
data, err := pm.LoadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package ebiten
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
@ -15,18 +16,11 @@ const sampleRate = 44100
|
||||
|
||||
var _ d2interface.AudioProvider = &AudioProvider{} // Static check to confirm struct conforms to interface
|
||||
|
||||
// AudioProvider represents a provider capable of playing audio
|
||||
type AudioProvider struct {
|
||||
audioContext *audio.Context // The Audio context
|
||||
bgmAudio *audio.Player // The audio player
|
||||
lastBgm string
|
||||
sfxVolume float64
|
||||
bgmVolume float64
|
||||
}
|
||||
|
||||
// CreateAudio creates an instance of ebiten's audio provider
|
||||
func CreateAudio() (*AudioProvider, error) {
|
||||
result := &AudioProvider{}
|
||||
func CreateAudio(am *d2asset.AssetManager) (*AudioProvider, error) {
|
||||
result := &AudioProvider{
|
||||
assetManager: am,
|
||||
}
|
||||
|
||||
var err error
|
||||
result.audioContext, err = audio.NewContext(sampleRate)
|
||||
@ -39,6 +33,16 @@ func CreateAudio() (*AudioProvider, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AudioProvider represents a provider capable of playing audio
|
||||
type AudioProvider struct {
|
||||
assetManager *d2asset.AssetManager
|
||||
audioContext *audio.Context // The Audio context
|
||||
bgmAudio *audio.Player // The audio player
|
||||
lastBgm string
|
||||
sfxVolume float64
|
||||
bgmVolume float64
|
||||
}
|
||||
|
||||
// PlayBGM loads an audio stream and plays it in the background
|
||||
func (eap *AudioProvider) PlayBGM(song string) {
|
||||
if eap.lastBgm == song {
|
||||
@ -61,7 +65,7 @@ func (eap *AudioProvider) PlayBGM(song string) {
|
||||
}
|
||||
}
|
||||
|
||||
audioStream, err := d2asset.LoadFileStream(song)
|
||||
audioStream, err := eap.assetManager.LoadFileStream(song)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -103,7 +107,7 @@ func (eap *AudioProvider) LoadSound(sfx string, loop, bgm bool) (d2interface.Sou
|
||||
volume = eap.bgmVolume
|
||||
}
|
||||
|
||||
result := CreateSoundEffect(sfx, eap.audioContext, loop)
|
||||
result := eap.createSoundEffect(sfx, eap.audioContext, loop)
|
||||
|
||||
result.volumeScale = volume
|
||||
result.SetVolume(volume)
|
||||
@ -116,3 +120,53 @@ func (eap *AudioProvider) SetVolumes(bgmVolume, sfxVolume float64) {
|
||||
eap.sfxVolume = sfxVolume
|
||||
eap.bgmVolume = bgmVolume
|
||||
}
|
||||
|
||||
// createSoundEffect creates a new instance of ebiten's sound effect implementation.
|
||||
func (eap *AudioProvider) createSoundEffect(sfx string, context *audio.Context,
|
||||
loop bool) *SoundEffect {
|
||||
result := &SoundEffect{}
|
||||
|
||||
soundFile := "/data/global/sfx/"
|
||||
|
||||
if _, exists := d2datadict.Sounds[sfx]; exists {
|
||||
soundEntry := d2datadict.Sounds[sfx]
|
||||
soundFile += soundEntry.FileName
|
||||
} else {
|
||||
soundFile += sfx
|
||||
}
|
||||
|
||||
audioData, err := eap.assetManager.LoadFileStream(soundFile)
|
||||
|
||||
if err != nil {
|
||||
audioData, err = eap.assetManager.LoadFileStream("/data/global/music/" + sfx)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
d, err := wav.Decode(context, audioData)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var player *audio.Player
|
||||
|
||||
if loop {
|
||||
s := audio.NewInfiniteLoop(d, d.Length())
|
||||
result.panStream = newPanStreamFromReader(s)
|
||||
player, err = audio.NewPlayer(context, result.panStream)
|
||||
} else {
|
||||
result.panStream = newPanStreamFromReader(d)
|
||||
player, err = audio.NewPlayer(context, result.panStream)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
result.player = player
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
package ebiten
|
||||
|
||||
import (
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/audio"
|
||||
"github.com/hajimehoshi/ebiten/audio/wav"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
type panStream struct {
|
||||
@ -56,55 +51,6 @@ type SoundEffect struct {
|
||||
panStream *panStream
|
||||
}
|
||||
|
||||
// CreateSoundEffect creates a new instance of ebiten's sound effect implementation.
|
||||
func CreateSoundEffect(sfx string, context *audio.Context, loop bool) *SoundEffect {
|
||||
result := &SoundEffect{}
|
||||
|
||||
soundFile := "/data/global/sfx/"
|
||||
|
||||
if _, exists := d2datadict.Sounds[sfx]; exists {
|
||||
soundEntry := d2datadict.Sounds[sfx]
|
||||
soundFile += soundEntry.FileName
|
||||
} else {
|
||||
soundFile += sfx
|
||||
}
|
||||
|
||||
audioData, err := d2asset.LoadFileStream(soundFile)
|
||||
|
||||
if err != nil {
|
||||
audioData, err = d2asset.LoadFileStream("/data/global/music/" + sfx)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
d, err := wav.Decode(context, audioData)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var player *audio.Player
|
||||
|
||||
if loop {
|
||||
s := audio.NewInfiniteLoop(d, d.Length())
|
||||
result.panStream = newPanStreamFromReader(s)
|
||||
player, err = audio.NewPlayer(context, result.panStream)
|
||||
} else {
|
||||
result.panStream = newPanStreamFromReader(d)
|
||||
player, err = audio.NewPlayer(context, result.panStream)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
result.player = player
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SetPan sets the audio pan, left is -1.0, center is 0.0, right is 1.0
|
||||
func (v *SoundEffect) SetPan(pan float64) {
|
||||
v.panStream.pan = pan
|
||||
|
@ -1,11 +1,7 @@
|
||||
package d2gui
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
type buttonState int
|
||||
@ -30,90 +26,6 @@ type Button struct {
|
||||
surfaces []d2interface.Surface
|
||||
}
|
||||
|
||||
func createButton(renderer d2interface.Renderer, text string, buttonStyle ButtonStyle) (*Button, error) {
|
||||
config := getButtonStyleConfig(buttonStyle)
|
||||
if config == nil {
|
||||
return nil, errors.New("invalid button style")
|
||||
}
|
||||
|
||||
animation, loadErr := d2asset.LoadAnimation(config.animationPath, config.palettePath)
|
||||
if loadErr != nil {
|
||||
return nil, loadErr
|
||||
}
|
||||
|
||||
var buttonWidth int
|
||||
|
||||
for i := 0; i < config.segmentsX; i++ {
|
||||
w, _, err := animation.GetFrameSize(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buttonWidth += w
|
||||
}
|
||||
|
||||
var buttonHeight int
|
||||
|
||||
for i := 0; i < config.segmentsY; i++ {
|
||||
_, h, err := animation.GetFrameSize(i * config.segmentsY)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buttonHeight += h
|
||||
}
|
||||
|
||||
font, loadErr := loadFont(config.fontStyle)
|
||||
if loadErr != nil {
|
||||
return nil, loadErr
|
||||
}
|
||||
|
||||
textColor := rgbaColor(grey)
|
||||
textWidth, textHeight := font.GetTextMetrics(text)
|
||||
textX := half(buttonWidth) - half(textWidth)
|
||||
textY := half(buttonHeight) - half(textHeight) + config.textOffset
|
||||
|
||||
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
|
||||
surfaces := make([]d2interface.Surface, surfaceCount)
|
||||
|
||||
for i := 0; i < surfaceCount; i++ {
|
||||
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
|
||||
if surfaceErr != nil {
|
||||
return nil, surfaceErr
|
||||
}
|
||||
|
||||
segX, segY, frame := config.segmentsX, config.segmentsY, i
|
||||
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
|
||||
return nil, segErr
|
||||
}
|
||||
|
||||
font.SetColor(textColor)
|
||||
|
||||
var textOffsetX, textOffsetY int
|
||||
|
||||
switch buttonState(i) {
|
||||
case buttonStatePressed, buttonStatePressedToggled:
|
||||
textOffsetX = -2
|
||||
textOffsetY = 2
|
||||
}
|
||||
|
||||
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
|
||||
surfaceErr = font.RenderText(text, surface)
|
||||
surface.Pop()
|
||||
|
||||
if surfaceErr != nil {
|
||||
return nil, surfaceErr
|
||||
}
|
||||
|
||||
surfaces[i] = surface
|
||||
}
|
||||
|
||||
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
|
||||
button.SetVisible(true)
|
||||
|
||||
return button, nil
|
||||
}
|
||||
|
||||
func (b *Button) onMouseButtonDown(_ d2interface.MouseEvent) bool {
|
||||
b.state = buttonStatePressed
|
||||
return false
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
func loadFont(fontStyle FontStyle) (d2interface.Font, error) {
|
||||
@ -15,7 +14,8 @@ func loadFont(fontStyle FontStyle) (d2interface.Font, error) {
|
||||
return nil, errors.New("invalid font style")
|
||||
}
|
||||
|
||||
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
|
||||
return singleton.asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6",
|
||||
config.palettePath)
|
||||
}
|
||||
|
||||
func renderSegmented(animation d2interface.Animation, segmentsX, segmentsY, frameOffset int,
|
||||
|
@ -3,6 +3,8 @@ package d2gui
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
@ -14,11 +16,11 @@ var (
|
||||
var singleton *manager // nolint:gochecknoglobals // currently global by design
|
||||
|
||||
// Initialize creates a singleton gui manager
|
||||
func Initialize(inputManager d2interface.InputManager) error {
|
||||
func Initialize(asset *d2asset.AssetManager, inputManager d2interface.InputManager) error {
|
||||
verifyNotInit()
|
||||
|
||||
var err error
|
||||
if singleton, err = createGuiManager(inputManager); err != nil {
|
||||
if singleton, err = createGuiManager(asset, inputManager); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,13 @@
|
||||
package d2gui
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
||||
"errors"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||
)
|
||||
|
||||
type layoutEntry struct {
|
||||
widget widget
|
||||
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
|
||||
mouseOver bool
|
||||
mouseDown [3]bool
|
||||
}
|
||||
|
||||
const layoutDebug = false // turns on debug rendering stuff for layouts
|
||||
|
||||
const (
|
||||
@ -168,7 +158,7 @@ func (l *Layout) AddLabel(text string, fontStyle FontStyle) (*Label, error) {
|
||||
|
||||
// AddButton given a string and ButtonStyle, adds a button as a layout entry
|
||||
func (l *Layout) AddButton(text string, buttonStyle ButtonStyle) (*Button, error) {
|
||||
button, err := createButton(l.renderer, text, buttonStyle)
|
||||
button, err := l.createButton(l.renderer, text, buttonStyle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -421,10 +411,88 @@ func (l *Layout) handleEntryVerticalAlign(width int, entry *layoutEntry) {
|
||||
}
|
||||
}
|
||||
|
||||
// IsIn layout entry, spc. of an event.
|
||||
func (l *layoutEntry) IsIn(event d2interface.HandlerEvent) bool {
|
||||
sx, sy := l.widget.ScreenPos()
|
||||
rect := d2geom.Rectangle{Left: sx, Top: sy, Width: l.width, Height: l.height}
|
||||
func (l *Layout) createButton(renderer d2interface.Renderer, text string,
|
||||
buttonStyle ButtonStyle) (*Button,
|
||||
error) {
|
||||
config := getButtonStyleConfig(buttonStyle)
|
||||
if config == nil {
|
||||
return nil, errors.New("invalid button style")
|
||||
}
|
||||
|
||||
return rect.IsInRect(event.X(), event.Y())
|
||||
animation, loadErr := singleton.asset.LoadAnimation(config.animationPath, config.palettePath)
|
||||
if loadErr != nil {
|
||||
return nil, loadErr
|
||||
}
|
||||
|
||||
var buttonWidth int
|
||||
|
||||
for i := 0; i < config.segmentsX; i++ {
|
||||
w, _, err := animation.GetFrameSize(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buttonWidth += w
|
||||
}
|
||||
|
||||
var buttonHeight int
|
||||
|
||||
for i := 0; i < config.segmentsY; i++ {
|
||||
_, h, err := animation.GetFrameSize(i * config.segmentsY)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buttonHeight += h
|
||||
}
|
||||
|
||||
font, loadErr := loadFont(config.fontStyle)
|
||||
if loadErr != nil {
|
||||
return nil, loadErr
|
||||
}
|
||||
|
||||
textColor := rgbaColor(grey)
|
||||
textWidth, textHeight := font.GetTextMetrics(text)
|
||||
textX := half(buttonWidth) - half(textWidth)
|
||||
textY := half(buttonHeight) - half(textHeight) + config.textOffset
|
||||
|
||||
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
|
||||
surfaces := make([]d2interface.Surface, surfaceCount)
|
||||
|
||||
for i := 0; i < surfaceCount; i++ {
|
||||
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
|
||||
if surfaceErr != nil {
|
||||
return nil, surfaceErr
|
||||
}
|
||||
|
||||
segX, segY, frame := config.segmentsX, config.segmentsY, i
|
||||
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
|
||||
return nil, segErr
|
||||
}
|
||||
|
||||
font.SetColor(textColor)
|
||||
|
||||
var textOffsetX, textOffsetY int
|
||||
|
||||
switch buttonState(i) {
|
||||
case buttonStatePressed, buttonStatePressedToggled:
|
||||
textOffsetX = -2
|
||||
textOffsetY = 2
|
||||
}
|
||||
|
||||
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
|
||||
surfaceErr = font.RenderText(text, surface)
|
||||
surface.Pop()
|
||||
|
||||
if surfaceErr != nil {
|
||||
return nil, surfaceErr
|
||||
}
|
||||
|
||||
surfaces[i] = surface
|
||||
}
|
||||
|
||||
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
|
||||
button.SetVisible(true)
|
||||
|
||||
return button, nil
|
||||
}
|
||||
|
26
d2core/d2gui/layout_entry.go
Normal file
26
d2core/d2gui/layout_entry.go
Normal file
@ -0,0 +1,26 @@
|
||||
package d2gui
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
type layoutEntry struct {
|
||||
widget widget
|
||||
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
|
||||
mouseOver bool
|
||||
mouseDown [3]bool
|
||||
}
|
||||
|
||||
// IsIn layout entry, spc. of an event.
|
||||
func (l *layoutEntry) IsIn(event d2interface.HandlerEvent) bool {
|
||||
sx, sy := l.widget.ScreenPos()
|
||||
rect := d2geom.Rectangle{Left: sx, Top: sy, Width: l.width, Height: l.height}
|
||||
|
||||
return rect.IsInRect(event.X(), event.Y())
|
||||
}
|
@ -5,12 +5,12 @@ import (
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
type manager struct {
|
||||
asset *d2asset.AssetManager
|
||||
layout *Layout
|
||||
cursorAnim d2interface.Animation
|
||||
cursorX int
|
||||
@ -20,18 +20,19 @@ type manager struct {
|
||||
loading bool
|
||||
}
|
||||
|
||||
func createGuiManager(inputManager d2interface.InputManager) (*manager, error) {
|
||||
cursorAnim, err := d2asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
|
||||
func createGuiManager(asset *d2asset.AssetManager, inputManager d2interface.InputManager) (*manager, error) {
|
||||
cursorAnim, err := asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
loadingAnim, err := d2asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading)
|
||||
loadingAnim, err := asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
manager := &manager{
|
||||
asset: asset,
|
||||
cursorAnim: cursorAnim,
|
||||
loadingAnim: loadingAnim,
|
||||
cursorVisible: true,
|
||||
|
@ -3,7 +3,6 @@ package d2gui
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// AnimationDirection is a the animation play direction
|
||||
@ -32,7 +31,7 @@ type AnimatedSprite struct {
|
||||
}
|
||||
|
||||
func createSprite(imagePath, palettePath string) (*Sprite, error) {
|
||||
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
|
||||
animation, err := singleton.asset.LoadAnimation(imagePath, palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -45,7 +44,7 @@ func createSprite(imagePath, palettePath string) (*Sprite, error) {
|
||||
}
|
||||
|
||||
func createAnimatedSprite(imagePath, palettePath string, direction AnimationDirection) (*AnimatedSprite, error) {
|
||||
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
|
||||
animation, err := singleton.asset.LoadAnimation(imagePath, palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||
@ -16,6 +18,9 @@ import (
|
||||
|
||||
// MapEngine loads the tiles which make up the isometric map and the entities
|
||||
type MapEngine struct {
|
||||
asset *d2asset.AssetManager
|
||||
*d2mapstamp.StampFactory
|
||||
*d2mapentity.MapEntityFactory
|
||||
seed int64 // The map seed
|
||||
entities map[string]d2interface.MapEntity // Entities on the map
|
||||
tiles []MapTile
|
||||
@ -28,8 +33,16 @@ type MapEngine struct {
|
||||
}
|
||||
|
||||
// CreateMapEngine creates a new instance of the map engine and returns a pointer to it.
|
||||
func CreateMapEngine() *MapEngine {
|
||||
engine := &MapEngine{}
|
||||
func CreateMapEngine(asset *d2asset.AssetManager) *MapEngine {
|
||||
entity := d2mapentity.NewMapEntityFactory(asset)
|
||||
stamp := d2mapstamp.NewStampFactory(asset, entity)
|
||||
|
||||
engine := &MapEngine{
|
||||
asset: asset,
|
||||
MapEntityFactory: entity,
|
||||
StampFactory: stamp,
|
||||
}
|
||||
|
||||
return engine
|
||||
}
|
||||
|
||||
@ -64,7 +77,7 @@ func (m *MapEngine) addDT1(fileName string) {
|
||||
}
|
||||
}
|
||||
|
||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + fileName)
|
||||
fileData, err := m.asset.LoadFile("/data/global/tiles/" + fileName)
|
||||
if err != nil {
|
||||
log.Printf("Could not load /data/global/tiles/%s", fileName)
|
||||
// panic(err)
|
||||
@ -84,7 +97,7 @@ func (m *MapEngine) AddDS1(fileName string) {
|
||||
return
|
||||
}
|
||||
|
||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + fileName)
|
||||
fileData, err := m.asset.LoadFile("/data/global/tiles/" + fileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -289,7 +302,7 @@ func (m *MapEngine) TileExists(tileX, tileY int) bool {
|
||||
|
||||
// GenerateMap clears the map and places the specified stamp.
|
||||
func (m *MapEngine) GenerateMap(regionType d2enum.RegionIdType, levelPreset, fileIndex int) {
|
||||
region := d2mapstamp.LoadStamp(regionType, levelPreset, fileIndex)
|
||||
region := m.LoadStamp(regionType, levelPreset, fileIndex)
|
||||
regionSize := region.Size()
|
||||
m.ResetMap(regionType, regionSize.Width, regionSize.Height)
|
||||
m.PlaceStamp(region, 0, 0)
|
||||
|
@ -4,6 +4,9 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||
@ -15,6 +18,16 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2item/diablo2item"
|
||||
)
|
||||
|
||||
// NewMapEntityFactory creates a MapEntityFactory instance with the given asset manager
|
||||
func NewMapEntityFactory(asset *d2asset.AssetManager) *MapEntityFactory {
|
||||
return &MapEntityFactory{asset}
|
||||
}
|
||||
|
||||
// MapEntityFactory creates map entities for the MapEngine
|
||||
type MapEntityFactory struct {
|
||||
asset *d2asset.AssetManager
|
||||
}
|
||||
|
||||
// NewAnimatedEntity creates an instance of AnimatedEntity
|
||||
func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntity {
|
||||
entity := &AnimatedEntity{
|
||||
@ -27,7 +40,7 @@ func NewAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntit
|
||||
}
|
||||
|
||||
// NewPlayer creates a new player entity and returns a pointer to it.
|
||||
func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||
func (f *MapEntityFactory) NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||
stats *d2hero.HeroStatsState, equipment *d2inventory.CharacterEquipment) *Player {
|
||||
layerEquipment := &[d2enum.CompositeTypeMax]string{
|
||||
d2enum.CompositeTypeHead: equipment.Head.GetArmorClass(),
|
||||
@ -40,7 +53,7 @@ func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||
d2enum.CompositeTypeShield: equipment.Shield.GetItemCode(),
|
||||
}
|
||||
|
||||
composite, err := d2asset.LoadComposite(d2enum.ObjectTypePlayer, heroType.GetToken(),
|
||||
composite, err := f.asset.LoadComposite(d2enum.ObjectTypePlayer, heroType.GetToken(),
|
||||
d2resource.PaletteUnits)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -81,8 +94,8 @@ func NewPlayer(id, name string, x, y, direction int, heroType d2enum.Hero,
|
||||
}
|
||||
|
||||
// NewMissile creates a new Missile and initializes it's animation.
|
||||
func NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
||||
animation, err := d2asset.LoadAnimation(
|
||||
func (f *MapEntityFactory) NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
||||
animation, err := f.asset.LoadAnimation(
|
||||
fmt.Sprintf("%s/%s.dcc", d2resource.MissileData, record.Animation.CelFileName),
|
||||
d2resource.PaletteUnits,
|
||||
)
|
||||
@ -109,7 +122,7 @@ func NewMissile(x, y int, record *d2datadict.MissileRecord) (*Missile, error) {
|
||||
}
|
||||
|
||||
// NewItem creates an item map entity
|
||||
func NewItem(x, y int, codes ...string) (*Item, error) {
|
||||
func (f *MapEntityFactory) NewItem(x, y int, codes ...string) (*Item, error) {
|
||||
item := diablo2item.NewItem(codes...)
|
||||
|
||||
if item == nil {
|
||||
@ -118,7 +131,7 @@ func NewItem(x, y int, codes ...string) (*Item, error) {
|
||||
|
||||
filename := item.CommonRecord().FlippyFile
|
||||
filepath := fmt.Sprintf("%s/%s.DC6", d2resource.ItemGraphics, filename)
|
||||
animation, err := d2asset.LoadAnimation(filepath, d2resource.PaletteUnits)
|
||||
animation, err := f.asset.LoadAnimation(filepath, d2resource.PaletteUnits)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -137,7 +150,7 @@ func NewItem(x, y int, codes ...string) (*Item, error) {
|
||||
}
|
||||
|
||||
// NewNPC creates a new NPC and returns a pointer to it.
|
||||
func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC, error) {
|
||||
func (f *MapEntityFactory) NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC, error) {
|
||||
result := &NPC{
|
||||
mapEntity: newMapEntity(x, y),
|
||||
HasPaths: false,
|
||||
@ -151,7 +164,7 @@ func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC,
|
||||
equipment[compType] = selectEquip(opts)
|
||||
}
|
||||
|
||||
composite, _ := d2asset.LoadComposite(d2enum.ObjectTypeCharacter, monstat.AnimationDirectoryToken,
|
||||
composite, _ := f.asset.LoadComposite(d2enum.ObjectTypeCharacter, monstat.AnimationDirectoryToken,
|
||||
d2resource.PaletteUnits)
|
||||
result.composite = composite
|
||||
|
||||
@ -175,3 +188,30 @@ func NewNPC(x, y int, monstat *d2datadict.MonStatsRecord, direction int) (*NPC,
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// NewObject creates an instance of AnimatedComposite
|
||||
func (f *MapEntityFactory) NewObject(x, y int, objectRec *d2datadict.ObjectRecord,
|
||||
palettePath string) (*Object, error) {
|
||||
locX, locY := float64(x), float64(y)
|
||||
entity := &Object{
|
||||
uuid: uuid.NewV4().String(),
|
||||
objectRecord: objectRec,
|
||||
Position: d2vector.NewPosition(locX, locY),
|
||||
name: d2tbl.TranslateString(objectRec.Name),
|
||||
}
|
||||
objectType := &d2datadict.ObjectTypes[objectRec.Index]
|
||||
|
||||
composite, err := f.asset.LoadComposite(d2enum.ObjectTypeItem, objectType.Token,
|
||||
palettePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entity.composite = composite
|
||||
|
||||
entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false)
|
||||
|
||||
initObject(entity)
|
||||
|
||||
return entity, nil
|
||||
}
|
@ -1,18 +1,14 @@
|
||||
// Package d2object implements objects placed on the map and their functionality
|
||||
package d2object
|
||||
package d2mapentity
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
@ -28,36 +24,6 @@ type Object struct {
|
||||
name string
|
||||
}
|
||||
|
||||
// CreateObject creates an instance of AnimatedComposite
|
||||
func CreateObject(x, y int, objectRec *d2datadict.ObjectRecord, palettePath string) (*Object, error) {
|
||||
locX, locY := float64(x), float64(y)
|
||||
entity := &Object{
|
||||
uuid: uuid.NewV4().String(),
|
||||
objectRecord: objectRec,
|
||||
Position: d2vector.NewPosition(locX, locY),
|
||||
name: d2tbl.TranslateString(objectRec.Name),
|
||||
}
|
||||
objectType := &d2datadict.ObjectTypes[objectRec.Index]
|
||||
|
||||
composite, err := d2asset.LoadComposite(d2enum.ObjectTypeItem, objectType.Token,
|
||||
d2resource.PaletteUnits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entity.composite = composite
|
||||
|
||||
if err := entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := initObject(entity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
// setMode changes the graphical mode of this animated entity
|
||||
func (ob *Object) setMode(animationMode d2enum.ObjectAnimationMode, direction int, randomFrame bool) error {
|
||||
err := ob.composite.SetMode(animationMode, "HTH")
|
@ -1,4 +1,4 @@
|
||||
package d2object
|
||||
package d2mapentity
|
||||
|
||||
import (
|
||||
"math/rand"
|
@ -1,4 +1,3 @@
|
||||
//nolint:gomnd
|
||||
package d2mapgen
|
||||
|
||||
import (
|
||||
@ -20,7 +19,7 @@ func loadPreset(mapEngine *d2mapengine.MapEngine, id, index int) *d2mapstamp.Sta
|
||||
mapEngine.AddDS1(file)
|
||||
}
|
||||
|
||||
return d2mapstamp.LoadStamp(d2enum.RegionAct1Wilderness, id, index)
|
||||
return mapEngine.LoadStamp(d2enum.RegionAct1Wilderness, id, index)
|
||||
}
|
||||
|
||||
// GenerateAct1Overworld generates the map and entities for the first town and surrounding area.
|
||||
@ -33,7 +32,7 @@ func GenerateAct1Overworld(mapEngine *d2mapengine.MapEngine) {
|
||||
mapWidth := mapEngine.Size().Width
|
||||
mapHeight := mapEngine.Size().Height
|
||||
|
||||
townStamp := d2mapstamp.LoadStamp(d2enum.RegionAct1Town, 1, -1)
|
||||
townStamp := mapEngine.LoadStamp(d2enum.RegionAct1Town, 1, -1)
|
||||
townStamp.RegionPath()
|
||||
townSize := townStamp.Size()
|
||||
|
||||
|
@ -48,6 +48,7 @@ const (
|
||||
|
||||
// MapRenderer manages the game viewport and Camera. It requests tile and entity data from MapEngine and renders it.
|
||||
type MapRenderer struct {
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer // Used for drawing operations
|
||||
mapEngine *d2mapengine.MapEngine // The map engine that is being rendered
|
||||
palette d2interface.Palette // The palette used for this map
|
||||
@ -61,9 +62,11 @@ type MapRenderer struct {
|
||||
}
|
||||
|
||||
// CreateMapRenderer creates a new MapRenderer, sets the required fields and returns a pointer to it.
|
||||
func CreateMapRenderer(renderer d2interface.Renderer, mapEngine *d2mapengine.MapEngine,
|
||||
func CreateMapRenderer(asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||
mapEngine *d2mapengine.MapEngine,
|
||||
term d2interface.Terminal, startX, startY float64) *MapRenderer {
|
||||
result := &MapRenderer{
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
mapEngine: mapEngine,
|
||||
viewport: NewViewport(0, 0, 800, 600),
|
||||
@ -563,7 +566,8 @@ func (mr *MapRenderer) Advance(elapsed float64) {
|
||||
mr.Camera.Advance(elapsed)
|
||||
}
|
||||
|
||||
func loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette, error) {
|
||||
func (mr *MapRenderer) loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette,
|
||||
error) {
|
||||
var palettePath string
|
||||
|
||||
switch levelType {
|
||||
@ -586,7 +590,7 @@ func loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette, erro
|
||||
return nil, errors.New("failed to find palette for region")
|
||||
}
|
||||
|
||||
return d2asset.LoadPalette(palettePath)
|
||||
return mr.asset.LoadPalette(palettePath)
|
||||
}
|
||||
|
||||
// ViewportToLeft moves the viewport to the left.
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func (mr *MapRenderer) generateTileCache() {
|
||||
mr.palette, _ = loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
|
||||
mr.palette, _ = mr.loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
|
||||
|
||||
tiles := *mr.mapEngine.Tiles()
|
||||
for idx := range tiles {
|
||||
|
74
d2core/d2map/d2mapstamp/factory.go
Normal file
74
d2core/d2map/d2mapstamp/factory.go
Normal file
@ -0,0 +1,74 @@
|
||||
package d2mapstamp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
func NewStampFactory(asset *d2asset.AssetManager, entity *d2mapentity.MapEntityFactory) *StampFactory {
|
||||
return &StampFactory{asset, entity}
|
||||
}
|
||||
|
||||
type StampFactory struct {
|
||||
asset *d2asset.AssetManager
|
||||
entity *d2mapentity.MapEntityFactory
|
||||
}
|
||||
|
||||
// LoadStamp loads the Stamp data from file.
|
||||
func (f *StampFactory) LoadStamp(levelType d2enum.RegionIdType, levelPreset, fileIndex int) *Stamp {
|
||||
stamp := &Stamp{
|
||||
entity: f.entity,
|
||||
regionID: levelType,
|
||||
levelType: d2datadict.LevelTypes[levelType],
|
||||
levelPreset: d2datadict.LevelPresets[levelPreset],
|
||||
}
|
||||
|
||||
for _, levelTypeDt1 := range &stamp.levelType.Files {
|
||||
if levelTypeDt1 != "" && levelTypeDt1 != "0" {
|
||||
fileData, err := f.asset.LoadFile("/data/global/tiles/" + levelTypeDt1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dt1, _ := d2dt1.LoadDT1(fileData)
|
||||
|
||||
stamp.tiles = append(stamp.tiles, dt1.Tiles...)
|
||||
}
|
||||
}
|
||||
|
||||
var levelFilesToPick []string
|
||||
|
||||
for _, fileRecord := range stamp.levelPreset.Files {
|
||||
if fileRecord != "" && fileRecord != "0" {
|
||||
levelFilesToPick = append(levelFilesToPick, fileRecord)
|
||||
}
|
||||
}
|
||||
|
||||
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * rand.Float64()))
|
||||
if fileIndex >= 0 && fileIndex < len(levelFilesToPick) {
|
||||
levelIndex = fileIndex
|
||||
}
|
||||
|
||||
if levelFilesToPick == nil {
|
||||
panic("no level files to pick from")
|
||||
}
|
||||
|
||||
stamp.regionPath = levelFilesToPick[levelIndex]
|
||||
fileData, err := f.asset.LoadFile("/data/global/tiles/" + stamp.regionPath)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stamp.ds1, _ = d2ds1.LoadDS1(fileData)
|
||||
|
||||
return stamp
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package d2mapstamp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||
@ -13,13 +10,16 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2object"
|
||||
)
|
||||
|
||||
const (
|
||||
subtilesPerTile = 5
|
||||
)
|
||||
|
||||
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
|
||||
type Stamp struct {
|
||||
entity *d2mapentity.MapEntityFactory
|
||||
regionPath string // The file path of the region
|
||||
regionID d2enum.RegionIdType
|
||||
levelType d2datadict.LevelTypeRecord // The level type id for this stamp
|
||||
@ -28,56 +28,6 @@ type Stamp struct {
|
||||
ds1 *d2ds1.DS1 // The backing DS1 file for this stamp
|
||||
}
|
||||
|
||||
// LoadStamp loads the Stamp data from file.
|
||||
func LoadStamp(levelType d2enum.RegionIdType, levelPreset, fileIndex int) *Stamp {
|
||||
stamp := &Stamp{
|
||||
regionID: levelType,
|
||||
levelType: d2datadict.LevelTypes[levelType],
|
||||
levelPreset: d2datadict.LevelPresets[levelPreset],
|
||||
}
|
||||
|
||||
for _, levelTypeDt1 := range &stamp.levelType.Files {
|
||||
if levelTypeDt1 != "" && levelTypeDt1 != "0" {
|
||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + levelTypeDt1)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dt1, _ := d2dt1.LoadDT1(fileData)
|
||||
|
||||
stamp.tiles = append(stamp.tiles, dt1.Tiles...)
|
||||
}
|
||||
}
|
||||
|
||||
var levelFilesToPick []string
|
||||
|
||||
for _, fileRecord := range stamp.levelPreset.Files {
|
||||
if fileRecord != "" && fileRecord != "0" {
|
||||
levelFilesToPick = append(levelFilesToPick, fileRecord)
|
||||
}
|
||||
}
|
||||
|
||||
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * rand.Float64()))
|
||||
if fileIndex >= 0 && fileIndex < len(levelFilesToPick) {
|
||||
levelIndex = fileIndex
|
||||
}
|
||||
|
||||
if levelFilesToPick == nil {
|
||||
panic("no level files to pick from")
|
||||
}
|
||||
|
||||
stamp.regionPath = levelFilesToPick[levelIndex]
|
||||
fileData, err := d2asset.LoadFile("/data/global/tiles/" + stamp.regionPath)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stamp.ds1, _ = d2ds1.LoadDS1(fileData)
|
||||
|
||||
return stamp
|
||||
}
|
||||
|
||||
// Size returns the size of the stamp in tiles.
|
||||
func (mr *Stamp) Size() d2geom.Size {
|
||||
return d2geom.Size{Width: int(mr.ds1.Width), Height: int(mr.ds1.Height)}
|
||||
@ -132,7 +82,7 @@ func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity
|
||||
if monstat != nil {
|
||||
// Temorary use of Lookup.
|
||||
npcX, npcY := (tileOffsetX*5)+object.X, (tileOffsetY*5)+object.Y
|
||||
npc, err := d2mapentity.NewNPC(npcX, npcY, monstat, 0)
|
||||
npc, err := mr.entity.NewNPC(npcX, npcY, monstat, 0)
|
||||
|
||||
if err == nil {
|
||||
npc.SetPaths(convertPaths(tileOffsetX, tileOffsetY, object.Paths))
|
||||
@ -153,7 +103,7 @@ func (mr *Stamp) Entities(tileOffsetX, tileOffsetY int) []d2interface.MapEntity
|
||||
objectRecord := d2datadict.Objects[lookup.ObjectsTxtId]
|
||||
|
||||
if objectRecord != nil {
|
||||
entity, err := d2object.CreateObject((tileOffsetX*5)+object.X,
|
||||
entity, err := mr.entity.NewObject((tileOffsetX*5)+object.X,
|
||||
(tileOffsetY*5)+object.Y, objectRecord, d2resource.PaletteUnits)
|
||||
|
||||
if err != nil {
|
||||
@ -173,8 +123,8 @@ func convertPaths(tileOffsetX, tileOffsetY int, paths []d2path.Path) []d2path.Pa
|
||||
for i := 0; i < len(paths); i++ {
|
||||
result[i].Action = paths[i].Action
|
||||
result[i].Position = d2vector.NewPosition(
|
||||
paths[i].Position.X()+float64(tileOffsetX*5),
|
||||
paths[i].Position.Y()+float64(tileOffsetY*5))
|
||||
paths[i].Position.X()+float64(tileOffsetX*subtilesPerTile),
|
||||
paths[i].Position.Y()+float64(tileOffsetY*subtilesPerTile))
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
)
|
||||
|
||||
@ -192,7 +191,7 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
||||
lbl.Color[0] = d2util.Color(greyAlpha100)
|
||||
lbl.Alignment = d2gui.HorizontalAlignCenter
|
||||
|
||||
animation, _ := d2asset.LoadAnimation(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||
animation, _ := ui.asset.LoadAnimation(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||
buttonSprite, _ := ui.NewSprite(animation)
|
||||
|
||||
for i := 0; i < buttonLayout.XSegments; i++ {
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// Checkbox represents a checkbox UI element
|
||||
@ -32,7 +31,7 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
|
||||
enabled: true,
|
||||
}
|
||||
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.Checkbox, d2resource.PaletteFechar)
|
||||
animation, _ := ui.asset.LoadAnimation(d2resource.Checkbox, d2resource.PaletteFechar)
|
||||
checkboxSprite, _ := ui.NewSprite(animation)
|
||||
result.width, result.height, _ = checkboxSprite.GetFrameSize(0)
|
||||
checkboxSprite.SetPosition(0, 0)
|
||||
|
@ -2,6 +2,7 @@ package d2ui
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// CursorButton represents a mouse button
|
||||
@ -16,11 +17,13 @@ const (
|
||||
|
||||
// NewUIManager creates a UIManager instance with the given input and audio provider
|
||||
func NewUIManager(
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
input d2interface.InputManager,
|
||||
audio d2interface.AudioProvider,
|
||||
) *UIManager {
|
||||
ui := &UIManager{
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
inputManager: input,
|
||||
audio: audio,
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
)
|
||||
|
||||
@ -26,7 +25,7 @@ type Label struct {
|
||||
|
||||
// NewLabel creates a new instance of a UI label
|
||||
func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label {
|
||||
font, _ := d2asset.LoadFont(fontPath+".tbl", fontPath+".dc6", palettePath)
|
||||
font, _ := ui.asset.LoadFont(fontPath+".tbl", fontPath+".dc6", palettePath)
|
||||
result := &Label{
|
||||
Alignment: d2gui.HorizontalAlignLeft,
|
||||
Color: map[int]color.Color{0: color.White},
|
||||
|
@ -3,7 +3,6 @@ package d2ui
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,7 +28,7 @@ type Scrollbar struct {
|
||||
|
||||
// NewScrollbar creates a scrollbar instance
|
||||
func (ui *UIManager) NewScrollbar(x, y, height int) *Scrollbar {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.Scrollbar, d2resource.PaletteSky)
|
||||
animation, _ := ui.asset.LoadAnimation(d2resource.Scrollbar, d2resource.PaletteSky)
|
||||
scrollbarSprite, _ := ui.NewSprite(animation)
|
||||
result := &Scrollbar{
|
||||
visible: true,
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// TextBox represents a text input box
|
||||
@ -27,7 +26,7 @@ type TextBox struct {
|
||||
|
||||
// NewTextbox creates a new instance of a text box
|
||||
func (ui *UIManager) NewTextbox() *TextBox {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
||||
animation, _ := ui.asset.LoadAnimation(d2resource.TextBox2, d2resource.PaletteUnits)
|
||||
bgSprite, _ := ui.NewSprite(animation)
|
||||
tb := &TextBox{
|
||||
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
|
@ -3,6 +3,8 @@ package d2ui
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
@ -10,6 +12,7 @@ import (
|
||||
|
||||
// UIManager manages a collection of UI elements (buttons, textboxes, labels)
|
||||
type UIManager struct {
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
inputManager d2interface.InputManager
|
||||
audio d2interface.AudioProvider
|
||||
|
@ -8,17 +8,20 @@ import (
|
||||
|
||||
// BlizzardIntro represents the Blizzard Intro screen
|
||||
type BlizzardIntro struct {
|
||||
asset *d2asset.AssetManager
|
||||
videoDecoder *d2video.BinkDecoder
|
||||
}
|
||||
|
||||
// CreateBlizzardIntro creates a Blizzard Intro screen
|
||||
func CreateBlizzardIntro() *BlizzardIntro {
|
||||
return &BlizzardIntro{}
|
||||
func CreateBlizzardIntro(asset *d2asset.AssetManager) *BlizzardIntro {
|
||||
return &BlizzardIntro{
|
||||
asset: asset,
|
||||
}
|
||||
}
|
||||
|
||||
// OnLoad loads the resources for the Blizzard Intro screen
|
||||
func (v *BlizzardIntro) OnLoad(loading d2screen.LoadingState) {
|
||||
videoBytes, err := d2asset.LoadFile("/data/local/video/BlizNorth640x480.bik")
|
||||
videoBytes, err := v.asset.LoadFile("/data/local/video/BlizNorth640x480.bik")
|
||||
if err != nil {
|
||||
loading.Error(err)
|
||||
return
|
||||
|
@ -21,6 +21,8 @@ import (
|
||||
|
||||
// CharacterSelect represents the character select screen
|
||||
type CharacterSelect struct {
|
||||
asset *d2asset.AssetManager
|
||||
*d2mapentity.MapEntityFactory
|
||||
background *d2ui.Sprite
|
||||
newCharButton *d2ui.Button
|
||||
convertCharButton *d2ui.Button
|
||||
@ -54,6 +56,7 @@ type CharacterSelect struct {
|
||||
// CreateCharacterSelect creates the character select screen and returns a pointer to it
|
||||
func CreateCharacterSelect(
|
||||
navigator Navigator,
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
inputManager d2interface.InputManager,
|
||||
audioProvider d2interface.AudioProvider,
|
||||
@ -63,6 +66,8 @@ func CreateCharacterSelect(
|
||||
) *CharacterSelect {
|
||||
return &CharacterSelect{
|
||||
selectedCharacter: -1,
|
||||
asset: asset,
|
||||
MapEntityFactory: d2mapentity.NewMapEntityFactory(asset),
|
||||
renderer: renderer,
|
||||
connectionType: connectionType,
|
||||
connectionHost: connectionHost,
|
||||
@ -133,7 +138,8 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
|
||||
|
||||
loading.Progress(tenPercent)
|
||||
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
|
||||
animation, _ := v.asset.LoadAnimation(d2resource.CharacterSelectionBackground,
|
||||
d2resource.PaletteSky)
|
||||
bgX, bgY := 0, 0
|
||||
v.background, _ = v.uiManager.NewSprite(animation)
|
||||
v.background.SetPosition(bgX, bgY)
|
||||
@ -154,12 +160,13 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) {
|
||||
deleteConfirmX, deleteConfirmY := 400, 185
|
||||
v.deleteCharConfirmLabel.SetPosition(deleteConfirmX, deleteConfirmY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.CharacterSelectionSelectBox,
|
||||
d2resource.PaletteSky)
|
||||
v.selectionBox, _ = v.uiManager.NewSprite(animation)
|
||||
selBoxX, selBoxY := 37, 86
|
||||
v.selectionBox.SetPosition(selBoxX, selBoxY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||
v.okCancelBox, _ = v.uiManager.NewSprite(animation)
|
||||
okCancelX, okCancelY := 270, 175
|
||||
v.okCancelBox.SetPosition(okCancelX, okCancelY)
|
||||
@ -283,7 +290,7 @@ func (v *CharacterSelect) updateCharacterBoxes() {
|
||||
equipment := d2inventory.HeroObjects[heroType]
|
||||
|
||||
// TODO: Generate or load the object from the actual player data...
|
||||
v.characterImage[i] = d2mapentity.NewPlayer("", "", 0, 0, 0,
|
||||
v.characterImage[i] = v.NewPlayer("", "", 0, 0, 0,
|
||||
v.gameStates[idx].HeroType,
|
||||
v.gameStates[idx].Stats,
|
||||
&equipment,
|
||||
|
@ -39,14 +39,17 @@ type Credits struct {
|
||||
cyclesTillNextLine int
|
||||
doneWithCredits bool
|
||||
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
navigator Navigator
|
||||
uiManager *d2ui.UIManager
|
||||
}
|
||||
|
||||
// CreateCredits creates an instance of the credits screen
|
||||
func CreateCredits(navigator Navigator, renderer d2interface.Renderer, ui *d2ui.UIManager) *Credits {
|
||||
func CreateCredits(navigator Navigator, asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||
ui *d2ui.UIManager) *Credits {
|
||||
result := &Credits{
|
||||
asset: asset,
|
||||
labels: make([]*labelItem, 0),
|
||||
cycleTime: 0,
|
||||
doneWithCredits: false,
|
||||
@ -86,7 +89,7 @@ func (v *Credits) LoadContributors() []string {
|
||||
|
||||
// OnLoad is called to load the resources for the credits screen
|
||||
func (v *Credits) OnLoad(loading d2screen.LoadingState) {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky)
|
||||
animation, _ := v.asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky)
|
||||
v.creditsBackground, _ = v.uiManager.NewSprite(animation)
|
||||
v.creditsBackground.SetPosition(creditsX, creditsY)
|
||||
loading.Progress(twentyPercent)
|
||||
@ -96,7 +99,7 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
loading.Progress(fourtyPercent)
|
||||
|
||||
fileData, err := d2asset.LoadFile(d2resource.CreditsText)
|
||||
fileData, err := v.asset.LoadFile(d2resource.CreditsText)
|
||||
if err != nil {
|
||||
loading.Error(err)
|
||||
return
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||
|
||||
@ -30,6 +32,8 @@ const (
|
||||
|
||||
// Game represents the Gameplay screen
|
||||
type Game struct {
|
||||
*d2mapentity.MapEntityFactory
|
||||
asset *d2asset.AssetManager
|
||||
gameClient *d2client.GameClient
|
||||
mapRenderer *d2maprenderer.MapRenderer
|
||||
uiManager *d2ui.UIManager
|
||||
@ -50,6 +54,8 @@ type Game struct {
|
||||
// CreateGame creates the Gameplay screen and returns a pointer to it
|
||||
func CreateGame(
|
||||
navigator Navigator,
|
||||
asset *d2asset.AssetManager,
|
||||
ui *d2ui.UIManager,
|
||||
renderer d2interface.Renderer,
|
||||
inputManager d2interface.InputManager,
|
||||
audioProvider d2interface.AudioProvider,
|
||||
@ -71,19 +77,21 @@ func CreateGame(
|
||||
}
|
||||
|
||||
result := &Game{
|
||||
asset: asset,
|
||||
gameClient: gameClient,
|
||||
gameControls: nil,
|
||||
localPlayer: nil,
|
||||
lastRegionType: d2enum.RegionNone,
|
||||
ticksSinceLevelCheck: 0,
|
||||
mapRenderer: d2maprenderer.CreateMapRenderer(renderer, gameClient.MapEngine, term, startX, startY),
|
||||
escapeMenu: NewEscapeMenu(navigator, renderer, audioProvider),
|
||||
inputManager: inputManager,
|
||||
audioProvider: audioProvider,
|
||||
renderer: renderer,
|
||||
terminal: term,
|
||||
soundEngine: d2audio.NewSoundEngine(audioProvider, term),
|
||||
uiManager: d2ui.NewUIManager(renderer, inputManager, audioProvider),
|
||||
mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer,
|
||||
gameClient.MapEngine, term, startX, startY),
|
||||
escapeMenu: NewEscapeMenu(navigator, renderer, audioProvider),
|
||||
inputManager: inputManager,
|
||||
audioProvider: audioProvider,
|
||||
renderer: renderer,
|
||||
terminal: term,
|
||||
soundEngine: d2audio.NewSoundEngine(audioProvider, term),
|
||||
uiManager: ui,
|
||||
}
|
||||
result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine)
|
||||
|
||||
@ -135,12 +143,13 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
|
||||
v.terminal.OutputErrorf("no monstat entry for \"%s\"", name)
|
||||
return
|
||||
}
|
||||
var monster *d2mapentity.NPC
|
||||
monster, err = d2mapentity.NewNPC(x, y, monstat, 0)
|
||||
|
||||
monster, err := v.gameClient.MapEngine.NewNPC(x, y, monstat, 0)
|
||||
if err != nil {
|
||||
v.terminal.OutputErrorf("error generating monster \"%s\": %v", name, err)
|
||||
return
|
||||
}
|
||||
|
||||
v.gameClient.MapEngine.AddEntity(monster)
|
||||
},
|
||||
)
|
||||
@ -266,7 +275,7 @@ func (v *Game) bindGameControls() error {
|
||||
v.localPlayer = player
|
||||
|
||||
var err error
|
||||
v.gameControls, err = d2player.NewGameControls(v.renderer, player,
|
||||
v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player,
|
||||
v.gameClient.MapEngine, v.mapRenderer, v, v.terminal, v.uiManager, v.gameClient.IsSinglePlayer())
|
||||
|
||||
if err != nil {
|
||||
|
@ -111,6 +111,7 @@ type MainMenu struct {
|
||||
screenMode mainMenuScreenMode
|
||||
leftButtonHeld bool
|
||||
|
||||
asset *d2asset.AssetManager
|
||||
inputManager d2interface.InputManager
|
||||
renderer d2interface.Renderer
|
||||
audioProvider d2interface.AudioProvider
|
||||
@ -124,6 +125,7 @@ type MainMenu struct {
|
||||
// CreateMainMenu creates an instance of MainMenu
|
||||
func CreateMainMenu(
|
||||
navigator Navigator,
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
inputManager d2interface.InputManager,
|
||||
audioProvider d2interface.AudioProvider,
|
||||
@ -131,6 +133,7 @@ func CreateMainMenu(
|
||||
buildInfo BuildInfo,
|
||||
) *MainMenu {
|
||||
return &MainMenu{
|
||||
asset: asset,
|
||||
screenMode: ScreenModeUnknown,
|
||||
leftButtonHeld: true,
|
||||
renderer: renderer,
|
||||
@ -169,19 +172,19 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) {
|
||||
}
|
||||
|
||||
func (v *MainMenu) loadBackgroundSprites() {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
|
||||
animation, _ := v.asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
|
||||
v.background, _ = v.uiManager.NewSprite(animation)
|
||||
v.background.SetPosition(backgroundX, backgroundY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
|
||||
v.trademarkBackground, _ = v.uiManager.NewSprite(animation)
|
||||
v.trademarkBackground.SetPosition(backgroundX, backgroundY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky)
|
||||
v.tcpIPBackground, _ = v.uiManager.NewSprite(animation)
|
||||
v.tcpIPBackground.SetPosition(backgroundX, backgroundY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
|
||||
v.serverIPBackground, _ = v.uiManager.NewSprite(animation)
|
||||
v.serverIPBackground.SetPosition(serverIPbackgroundX, serverIPbackgroundY)
|
||||
}
|
||||
@ -233,24 +236,24 @@ func (v *MainMenu) createLabels(loading d2screen.LoadingState) {
|
||||
}
|
||||
|
||||
func (v *MainMenu) createLogos(loading d2screen.LoadingState) {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
|
||||
animation, _ := v.asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
|
||||
v.diabloLogoLeft, _ = v.uiManager.NewSprite(animation)
|
||||
v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate)
|
||||
v.diabloLogoLeft.PlayForward()
|
||||
v.diabloLogoLeft.SetPosition(diabloLogoX, diabloLogoY)
|
||||
loading.Progress(sixtyPercent)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
|
||||
v.diabloLogoRight, _ = v.uiManager.NewSprite(animation)
|
||||
v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate)
|
||||
v.diabloLogoRight.PlayForward()
|
||||
v.diabloLogoRight.SetPosition(diabloLogoX, diabloLogoY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
|
||||
v.diabloLogoLeftBack, _ = v.uiManager.NewSprite(animation)
|
||||
v.diabloLogoLeftBack.SetPosition(diabloLogoX, diabloLogoY)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
|
||||
animation, _ = v.asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
|
||||
v.diabloLogoRightBack, _ = v.uiManager.NewSprite(animation)
|
||||
v.diabloLogoRightBack.SetPosition(diabloLogoX, diabloLogoY)
|
||||
}
|
||||
|
@ -7,17 +7,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||
)
|
||||
@ -87,6 +84,7 @@ func getRegions() []regionSpec {
|
||||
|
||||
// MapEngineTest represents the MapEngineTest screen
|
||||
type MapEngineTest struct {
|
||||
asset *d2asset.AssetManager
|
||||
gameState *d2player.PlayerState
|
||||
mapEngine *d2mapengine.MapEngine
|
||||
mapRenderer *d2maprenderer.MapRenderer
|
||||
@ -112,6 +110,7 @@ type MapEngineTest struct {
|
||||
// CreateMapEngineTest creates the Map Engine Test screen and returns a pointer to it
|
||||
func CreateMapEngineTest(currentRegion,
|
||||
levelPreset int,
|
||||
asset *d2asset.AssetManager,
|
||||
term d2interface.Terminal,
|
||||
renderer d2interface.Renderer,
|
||||
inputManager d2interface.InputManager,
|
||||
@ -124,6 +123,7 @@ func CreateMapEngineTest(currentRegion,
|
||||
fileIndex: 0,
|
||||
regionSpec: regionSpec{},
|
||||
filesCount: 0,
|
||||
asset: asset,
|
||||
terminal: term,
|
||||
renderer: renderer,
|
||||
inputManager: inputManager,
|
||||
@ -171,7 +171,7 @@ func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) {
|
||||
met.mapEngine.SetSeed(time.Now().UnixNano())
|
||||
d2mapgen.GenerateAct1Overworld(met.mapEngine)
|
||||
} else {
|
||||
met.mapEngine = d2mapengine.CreateMapEngine() // necessary for map name update
|
||||
met.mapEngine = d2mapengine.CreateMapEngine(met.asset) // necessary for map name update
|
||||
met.mapEngine.SetSeed(time.Now().UnixNano())
|
||||
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
|
||||
}
|
||||
@ -193,11 +193,12 @@ func (met *MapEngineTest) OnLoad(loading d2screen.LoadingState) {
|
||||
|
||||
loading.Progress(twentyPercent)
|
||||
|
||||
met.mapEngine = d2mapengine.CreateMapEngine()
|
||||
met.mapEngine = d2mapengine.CreateMapEngine(met.asset)
|
||||
|
||||
loading.Progress(fiftyPercent)
|
||||
|
||||
met.mapRenderer = d2maprenderer.CreateMapRenderer(met.renderer, met.mapEngine, met.terminal, 0.0, 0.0)
|
||||
met.mapRenderer = d2maprenderer.CreateMapRenderer(met.asset, met.renderer, met.mapEngine,
|
||||
met.terminal, 0.0, 0.0)
|
||||
|
||||
loading.Progress(seventyPercent)
|
||||
met.loadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
|
||||
|
@ -4,13 +4,12 @@ import (
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
|
||||
@ -269,6 +268,7 @@ func (hri *HeroRenderInfo) advance(elapsed float64) {
|
||||
|
||||
// SelectHeroClass represents the Select Hero Class screen
|
||||
type SelectHeroClass struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
bgImage *d2ui.Sprite
|
||||
campfire *d2ui.Sprite
|
||||
@ -298,6 +298,7 @@ type SelectHeroClass struct {
|
||||
// CreateSelectHeroClass creates an instance of a SelectHeroClass
|
||||
func CreateSelectHeroClass(
|
||||
navigator Navigator,
|
||||
manager *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
audioProvider d2interface.AudioProvider,
|
||||
ui *d2ui.UIManager,
|
||||
@ -732,7 +733,7 @@ func (v *SelectHeroClass) loadSprite(animationPath string, position image.Point,
|
||||
return nil
|
||||
}
|
||||
|
||||
animation, err := d2asset.LoadAnimation(animationPath, d2resource.PaletteFechar)
|
||||
animation, err := v.asset.LoadAnimation(animationPath, d2resource.PaletteFechar)
|
||||
if err != nil {
|
||||
fmt.Printf("could not load animation: %s\n", animationPath)
|
||||
return nil
|
||||
|
@ -47,6 +47,7 @@ const (
|
||||
// GameControls represents the game's controls on the screen
|
||||
type GameControls struct {
|
||||
actionableRegions []ActionableRegion
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer // TODO: This shouldn't be a dependency
|
||||
inputListener InputCallbackListener
|
||||
hero *d2mapentity.Player
|
||||
@ -103,6 +104,7 @@ const (
|
||||
|
||||
// NewGameControls creates a GameControls instance and returns a pointer to it
|
||||
func NewGameControls(
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
hero *d2mapentity.Player,
|
||||
mapEngine *d2mapengine.MapEngine,
|
||||
@ -161,16 +163,17 @@ func NewGameControls(
|
||||
globeStatsLabel := hpManaStatsLabel
|
||||
|
||||
gc := &GameControls{
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
renderer: renderer,
|
||||
hero: hero,
|
||||
mapEngine: mapEngine,
|
||||
inputListener: inputListener,
|
||||
mapRenderer: mapRenderer,
|
||||
inventory: NewInventory(ui, inventoryRecord),
|
||||
heroStatsPanel: NewHeroStatsPanel(ui, hero.Name(), hero.Class, hero.Stats),
|
||||
helpOverlay: help.NewHelpOverlay(renderer),
|
||||
miniPanel: newMiniPanel(ui, isSinglePlayer),
|
||||
inventory: NewInventory(asset, ui, inventoryRecord),
|
||||
heroStatsPanel: NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats),
|
||||
helpOverlay: help.NewHelpOverlay(asset, renderer, ui),
|
||||
miniPanel: newMiniPanel(asset, ui, isSinglePlayer),
|
||||
missileID: missileID,
|
||||
nameLabel: hoverLabel,
|
||||
zoneChangeText: zoneLabel,
|
||||
@ -378,20 +381,20 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
||||
|
||||
// Load loads the resources required for the GameControls
|
||||
func (g *GameControls) Load() {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
||||
animation, _ := g.asset.LoadAnimation(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
||||
g.globeSprite, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
||||
animation, _ = g.asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
||||
g.hpManaStatusSprite, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
||||
animation, _ = g.asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
||||
g.mainPanel, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.MenuButton, d2resource.PaletteSky)
|
||||
animation, _ = g.asset.LoadAnimation(d2resource.MenuButton, d2resource.PaletteSky)
|
||||
_ = animation.SetCurrentFrame(2)
|
||||
g.menuButton, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.GenericSkills, d2resource.PaletteSky)
|
||||
animation, _ = g.asset.LoadAnimation(d2resource.GenericSkills, d2resource.PaletteSky)
|
||||
g.skillIcon, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
g.loadUIButtons()
|
||||
|
@ -2,9 +2,10 @@ package help
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"image/color"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
@ -25,6 +26,7 @@ const (
|
||||
|
||||
// HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed
|
||||
type Overlay struct {
|
||||
asset *d2asset.AssetManager
|
||||
isOpen bool
|
||||
renderer d2interface.Renderer
|
||||
frames []*d2ui.Sprite
|
||||
@ -36,9 +38,12 @@ type Overlay struct {
|
||||
layout *d2gui.Layout
|
||||
}
|
||||
|
||||
func NewHelpOverlay(renderer d2interface.Renderer) *Overlay {
|
||||
func NewHelpOverlay(asset *d2asset.AssetManager, renderer d2interface.Renderer,
|
||||
ui *d2ui.UIManager) *Overlay {
|
||||
h := &Overlay{
|
||||
renderer: renderer,
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
uiManager: ui,
|
||||
}
|
||||
|
||||
return h
|
||||
@ -89,7 +94,7 @@ func (h *Overlay) Load() {
|
||||
prevY = 0
|
||||
)
|
||||
for frameIndex := 0; frameIndex < 7; frameIndex++ {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.HelpBorder, d2resource.PaletteSky)
|
||||
animation, _ := h.asset.LoadAnimation(d2resource.HelpBorder, d2resource.PaletteSky)
|
||||
_ = animation.SetCurrentFrame(frameIndex)
|
||||
f, _ := h.uiManager.NewSprite(animation)
|
||||
|
||||
@ -139,7 +144,7 @@ func (h *Overlay) Load() {
|
||||
|
||||
// Close
|
||||
|
||||
anim, _ := d2asset.LoadAnimation(d2resource.SquareButton, d2resource.PaletteSky)
|
||||
anim, _ := h.asset.LoadAnimation(d2resource.SquareButton, d2resource.PaletteSky)
|
||||
close, _ := h.uiManager.NewSprite(anim)
|
||||
_ = close.SetCurrentFrame(0)
|
||||
close.SetPosition(685, 57)
|
||||
@ -339,7 +344,7 @@ func (h *Overlay) createBullet(c callout) {
|
||||
newLabel.SetPosition(c.LabelX, c.LabelY)
|
||||
h.text = append(h.text, newLabel)
|
||||
|
||||
anim, _ := d2asset.LoadAnimation(d2resource.HelpYellowBullet, d2resource.PaletteSky)
|
||||
anim, _ := h.asset.LoadAnimation(d2resource.HelpYellowBullet, d2resource.PaletteSky)
|
||||
newDot, _ := h.uiManager.NewSprite(anim)
|
||||
_ = newDot.SetCurrentFrame(0)
|
||||
newDot.SetPosition(c.DotX, c.DotY+14)
|
||||
@ -365,7 +370,7 @@ func (h *Overlay) createCallout(c callout) {
|
||||
}
|
||||
h.lines = append(h.lines, l)
|
||||
|
||||
anim, _ := d2asset.LoadAnimation(d2resource.HelpWhiteBullet, d2resource.PaletteSky)
|
||||
anim, _ := h.asset.LoadAnimation(d2resource.HelpWhiteBullet, d2resource.PaletteSky)
|
||||
newDot, _ := h.uiManager.NewSprite(anim)
|
||||
_ = newDot.SetCurrentFrame(0)
|
||||
newDot.SetPosition(c.DotX, c.DotY)
|
||||
|
@ -41,6 +41,7 @@ type StatsPanelLabels struct {
|
||||
|
||||
// HeroStatsPanel represents the hero status panel
|
||||
type HeroStatsPanel struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
frame *d2ui.Sprite
|
||||
panel *d2ui.Sprite
|
||||
@ -57,12 +58,13 @@ type HeroStatsPanel struct {
|
||||
}
|
||||
|
||||
// NewHeroStatsPanel creates a new hero status panel
|
||||
func NewHeroStatsPanel(ui *d2ui.UIManager, heroName string, heroClass d2enum.Hero,
|
||||
func NewHeroStatsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName string, heroClass d2enum.Hero,
|
||||
heroState *d2hero.HeroStatsState) *HeroStatsPanel {
|
||||
originX := 0
|
||||
originY := 0
|
||||
|
||||
return &HeroStatsPanel{
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
renderer: ui.Renderer(),
|
||||
originX: originX,
|
||||
@ -76,9 +78,9 @@ func NewHeroStatsPanel(ui *d2ui.UIManager, heroName string, heroClass d2enum.Her
|
||||
|
||||
// Load loads the data for the hero status panel
|
||||
func (s *HeroStatsPanel) Load() {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||
animation, _ := s.asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||
s.frame, _ = s.uiManager.NewSprite(animation)
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
animation, _ = s.asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
s.panel, _ = s.uiManager.NewSprite(animation)
|
||||
s.initStatValueLabels()
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
// Inventory represents the inventory
|
||||
type Inventory struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
frame *d2ui.Sprite
|
||||
panel *d2ui.Sprite
|
||||
@ -32,13 +33,15 @@ type Inventory struct {
|
||||
}
|
||||
|
||||
// NewInventory creates an inventory instance and returns a pointer to it
|
||||
func NewInventory(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *Inventory {
|
||||
func NewInventory(asset *d2asset.AssetManager, ui *d2ui.UIManager,
|
||||
record *d2datadict.InventoryRecord) *Inventory {
|
||||
hoverLabel := ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteStatic)
|
||||
hoverLabel.Alignment = d2gui.HorizontalAlignCenter
|
||||
|
||||
return &Inventory{
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
grid: NewItemGrid(ui, record),
|
||||
grid: NewItemGrid(asset, ui, record),
|
||||
originX: record.Panel.Left,
|
||||
hoverLabel: hoverLabel,
|
||||
// originY: record.Panel.Top,
|
||||
@ -68,10 +71,10 @@ func (g *Inventory) Close() {
|
||||
|
||||
// Load loads the resources required by the inventory
|
||||
func (g *Inventory) Load() {
|
||||
animation, _ := d2asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||
animation, _ := g.asset.LoadAnimation(d2resource.Frame, d2resource.PaletteSky)
|
||||
g.frame, _ = g.uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
animation, _ = g.asset.LoadAnimation(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||
g.panel, _ = g.uiManager.NewSprite(animation)
|
||||
items := []InventoryItem{
|
||||
diablo2item.NewItem("kit", "Crimson", "of the Bat", "of Frost").Identify(),
|
||||
|
@ -33,6 +33,7 @@ var errorInventoryFull = errors.New("inventory full")
|
||||
// ItemGrid is a reusable grid for use with player and merchant inventory.
|
||||
// Handles layout and rendering item icons based on code.
|
||||
type ItemGrid struct {
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
items []InventoryItem
|
||||
equipmentSlots map[d2enum.EquippedSlot]EquipmentSlot
|
||||
@ -44,10 +45,12 @@ type ItemGrid struct {
|
||||
slotSize int
|
||||
}
|
||||
|
||||
func NewItemGrid(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *ItemGrid {
|
||||
func NewItemGrid(asset *d2asset.AssetManager, ui *d2ui.UIManager,
|
||||
record *d2datadict.InventoryRecord) *ItemGrid {
|
||||
grid := record.Grid
|
||||
|
||||
return &ItemGrid{
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
width: grid.Box.Width,
|
||||
height: grid.Box.Height,
|
||||
@ -118,7 +121,7 @@ func (g *ItemGrid) loadItem(item InventoryItem) {
|
||||
var itemSprite *d2ui.Sprite
|
||||
|
||||
// TODO: Put the pattern into D2Shared
|
||||
animation, err := d2asset.LoadAnimation(
|
||||
animation, err := g.asset.LoadAnimation(
|
||||
fmt.Sprintf("/data/global/items/inv%s.dc6", item.GetItemCode()),
|
||||
d2resource.PaletteSky,
|
||||
)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type miniPanel struct {
|
||||
asset *d2asset.AssetManager
|
||||
container *d2ui.Sprite
|
||||
button *d2ui.Sprite
|
||||
isOpen bool
|
||||
@ -16,16 +17,16 @@ type miniPanel struct {
|
||||
rectangle d2geom.Rectangle
|
||||
}
|
||||
|
||||
func newMiniPanel(uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
||||
func newMiniPanel(asset *d2asset.AssetManager, uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
||||
miniPanelContainerPath := d2resource.Minipanel
|
||||
if isSinglePlayer {
|
||||
miniPanelContainerPath = d2resource.MinipanelSmall
|
||||
}
|
||||
|
||||
animation, _ := d2asset.LoadAnimation(miniPanelContainerPath, d2resource.PaletteSky)
|
||||
animation, _ := asset.LoadAnimation(miniPanelContainerPath, d2resource.PaletteSky)
|
||||
containerSprite, _ := uiManager.NewSprite(animation)
|
||||
|
||||
animation, _ = d2asset.LoadAnimation(d2resource.MinipanelButton, d2resource.PaletteSky)
|
||||
animation, _ = asset.LoadAnimation(d2resource.MinipanelButton, d2resource.PaletteSky)
|
||||
buttonSprite, _ := uiManager.NewSprite(animation)
|
||||
|
||||
rectangle := d2geom.Rectangle{Left: 325, Top: 526, Width: 156, Height: 26}
|
||||
@ -34,7 +35,14 @@ func newMiniPanel(uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
|
||||
rectangle.Width = 182
|
||||
}
|
||||
|
||||
return &miniPanel{container: containerSprite, button: buttonSprite, isOpen: true, isSinglePlayer: isSinglePlayer, rectangle: rectangle}
|
||||
return &miniPanel{
|
||||
asset: asset,
|
||||
container: containerSprite,
|
||||
button: buttonSprite,
|
||||
isOpen: true,
|
||||
isSinglePlayer: isSinglePlayer,
|
||||
rectangle: rectangle,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *miniPanel) IsOpen() bool {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package d2localclient
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
|
||||
@ -13,6 +14,7 @@ import (
|
||||
// LocalClientConnection is the implementation of ClientConnection
|
||||
// for a local client.
|
||||
type LocalClientConnection struct {
|
||||
asset *d2asset.AssetManager
|
||||
clientListener d2networking.ClientListener // The game client
|
||||
uniqueID string // Unique ID generated on construction
|
||||
openNetworkServer bool // True if this is a server
|
||||
@ -38,8 +40,9 @@ func (l *LocalClientConnection) SendPacketToClient(packet d2netpacket.NetPacket)
|
||||
|
||||
// Create constructs a new LocalClientConnection and returns
|
||||
// a pointer to it.
|
||||
func Create(openNetworkServer bool) *LocalClientConnection {
|
||||
func Create(asset *d2asset.AssetManager, openNetworkServer bool) *LocalClientConnection {
|
||||
result := &LocalClientConnection{
|
||||
asset: asset,
|
||||
uniqueID: uuid.NewV4().String(),
|
||||
openNetworkServer: openNetworkServer,
|
||||
}
|
||||
@ -53,7 +56,7 @@ func (l *LocalClientConnection) Open(_, saveFilePath string) error {
|
||||
|
||||
l.SetPlayerState(d2player.LoadPlayerState(saveFilePath))
|
||||
|
||||
l.gameServer, err = d2server.NewGameServer(l.openNetworkServer, 30)
|
||||
l.gameServer, err = d2server.NewGameServer(l.asset, l.openNetworkServer, 30)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
@ -31,6 +33,7 @@ const (
|
||||
type GameClient struct {
|
||||
clientConnection ServerConnection // Abstract local/remote connection
|
||||
connectionType d2clientconnectiontype.ClientConnectionType // Type of connection (local or remote)
|
||||
asset *d2asset.AssetManager
|
||||
scriptEngine *d2script.ScriptEngine
|
||||
GameState *d2player.PlayerState // local player state
|
||||
MapEngine *d2mapengine.MapEngine // Map and entities
|
||||
@ -41,9 +44,11 @@ type GameClient struct {
|
||||
}
|
||||
|
||||
// Create constructs a new GameClient and returns a pointer to it.
|
||||
func Create(connectionType d2clientconnectiontype.ClientConnectionType, scriptEngine *d2script.ScriptEngine) (*GameClient, error) {
|
||||
func Create(connectionType d2clientconnectiontype.ClientConnectionType,
|
||||
asset *d2asset.AssetManager, scriptEngine *d2script.ScriptEngine) (*GameClient, error) {
|
||||
result := &GameClient{
|
||||
MapEngine: d2mapengine.CreateMapEngine(), // TODO: Mapgen - Needs levels.txt stuff
|
||||
asset: asset,
|
||||
MapEngine: d2mapengine.CreateMapEngine(asset), // TODO: Mapgen - Needs levels.txt stuff
|
||||
Players: make(map[string]*d2mapentity.Player),
|
||||
connectionType: connectionType,
|
||||
scriptEngine: scriptEngine,
|
||||
@ -53,9 +58,9 @@ func Create(connectionType d2clientconnectiontype.ClientConnectionType, scriptEn
|
||||
case d2clientconnectiontype.LANClient:
|
||||
result.clientConnection = d2remoteclient.Create()
|
||||
case d2clientconnectiontype.LANServer:
|
||||
result.clientConnection = d2localclient.Create(true)
|
||||
result.clientConnection = d2localclient.Create(asset, true)
|
||||
case d2clientconnectiontype.Local:
|
||||
result.clientConnection = d2localclient.Create(false)
|
||||
result.clientConnection = d2localclient.Create(asset, false)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown client connection type specified: %d", connectionType)
|
||||
}
|
||||
@ -180,7 +185,7 @@ func (g *GameClient) handleAddPlayerPacket(packet d2netpacket.NetPacket) error {
|
||||
return err
|
||||
}
|
||||
|
||||
newPlayer := d2mapentity.NewPlayer(player.ID, player.Name, player.X, player.Y, 0,
|
||||
newPlayer := g.MapEngine.NewPlayer(player.ID, player.Name, player.X, player.Y, 0,
|
||||
player.HeroType, player.Stats, &player.Equipment)
|
||||
|
||||
g.Players[newPlayer.ID()] = newPlayer
|
||||
@ -195,7 +200,7 @@ func (g *GameClient) handleSpawnItemPacket(packet d2netpacket.NetPacket) error {
|
||||
return err
|
||||
}
|
||||
|
||||
itemEntity, err := d2mapentity.NewItem(item.X, item.Y, item.Codes...)
|
||||
itemEntity, err := g.MapEngine.NewItem(item.X, item.Y, item.Codes...)
|
||||
|
||||
if err == nil {
|
||||
g.MapEngine.AddEntity(itemEntity)
|
||||
@ -255,7 +260,7 @@ func (g *GameClient) handleCastSkillPacket(packet d2netpacket.NetPacket) error {
|
||||
player.ClearPath()
|
||||
|
||||
// currently hardcoded to missile skill
|
||||
missile, err := d2mapentity.NewMissile(
|
||||
missile, err := g.MapEngine.NewMissile(
|
||||
int(player.Position.X()),
|
||||
int(player.Position.Y()),
|
||||
d2datadict.Missiles[playerCast.SkillID],
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/robertkrimen/otto"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
|
||||
@ -42,6 +43,7 @@ type GameServer struct {
|
||||
networkServer bool
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
asset *d2asset.AssetManager
|
||||
mapEngines []*d2mapengine.MapEngine
|
||||
scriptEngine *d2script.ScriptEngine
|
||||
seed int64
|
||||
@ -57,7 +59,9 @@ var singletonServer *GameServer
|
||||
// ctx: required context item
|
||||
// networkServer: true = 0.0.0.0 | false = 127.0.0.1
|
||||
// maxConnections (default: 8): maximum number of TCP connections allowed open
|
||||
func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, error) {
|
||||
func NewGameServer(asset *d2asset.AssetManager, networkServer bool,
|
||||
maxConnections ...int) (*GameServer,
|
||||
error) {
|
||||
if len(maxConnections) == 0 {
|
||||
maxConnections = []int{8}
|
||||
}
|
||||
@ -67,6 +71,7 @@ func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, erro
|
||||
gameServer := &GameServer{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
asset: asset,
|
||||
connections: make(map[string]ClientConnection),
|
||||
networkServer: networkServer,
|
||||
maxConnections: maxConnections[0],
|
||||
@ -78,7 +83,7 @@ func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, erro
|
||||
|
||||
// TODO: In order to support dedicated mode we need to load the levels txt and files. Revisit this once this we can
|
||||
// load files independent of the app.
|
||||
mapEngine := d2mapengine.CreateMapEngine()
|
||||
mapEngine := d2mapengine.CreateMapEngine(asset)
|
||||
mapEngine.SetSeed(gameServer.seed)
|
||||
mapEngine.ResetMap(d2enum.RegionAct1Town, 100, 100) // TODO: Mapgen - Needs levels.txt stuff
|
||||
d2mapgen.GenerateAct1Overworld(mapEngine)
|
||||
|
14
main.go
14
main.go
@ -4,6 +4,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2app"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
|
||||
@ -28,13 +29,18 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Initialize our providers
|
||||
// NewAssetManager our providers
|
||||
renderer, err := ebiten.CreateRenderer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
audio, err := ebiten2.CreateAudio()
|
||||
asset, err := d2asset.NewAssetManager(renderer, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
audio, err := ebiten2.CreateAudio(asset)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -46,9 +52,11 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
asset.BindTerminalCommands(term)
|
||||
|
||||
scriptEngine := d2script.CreateScriptEngine()
|
||||
|
||||
app := d2app.Create(GitBranch, GitCommit, inputManager, term, scriptEngine, audio, renderer)
|
||||
app := d2app.Create(GitBranch, GitCommit, inputManager, term, scriptEngine, audio, renderer, asset)
|
||||
if err := app.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user