mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-01-25 18:57:23 -05:00
moved asset manager initialization logic to d2app (#905)
* move asset manager initialization logic to d2app * updating to loogger printf statements
This commit is contained in:
parent
d5a26fd495
commit
f2ab13afae
180
d2app/app.go
180
d2app/app.go
@ -4,6 +4,7 @@ package d2app
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"container/ring"
|
"container/ring"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -19,6 +21,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
||||||
|
|
||||||
"github.com/pkg/profile"
|
"github.com/pkg/profile"
|
||||||
"golang.org/x/image/colornames"
|
"golang.org/x/image/colornames"
|
||||||
"gopkg.in/alecthomas/kingpin.v2"
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
@ -73,6 +77,7 @@ type App struct {
|
|||||||
tAllocSamples *ring.Ring
|
tAllocSamples *ring.Ring
|
||||||
guiManager *d2gui.GuiManager
|
guiManager *d2gui.GuiManager
|
||||||
config *d2config.Configuration
|
config *d2config.Configuration
|
||||||
|
logger *d2util.Logger
|
||||||
errorMessage error
|
errorMessage error
|
||||||
*Options
|
*Options
|
||||||
}
|
}
|
||||||
@ -98,21 +103,25 @@ const (
|
|||||||
debugPopN = 6
|
debugPopN = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
appLoggerPrefix = "App"
|
||||||
|
)
|
||||||
|
|
||||||
// Create creates a new instance of the application
|
// Create creates a new instance of the application
|
||||||
func Create(gitBranch, gitCommit string) *App {
|
func Create(gitBranch, gitCommit string) *App {
|
||||||
assetManager, assetError := d2asset.NewAssetManager()
|
assetManager, assetError := d2asset.NewAssetManager()
|
||||||
|
logger := d2util.NewLogger()
|
||||||
// we can throw away the error here because by this time it's already been loaded
|
logger.SetPrefix(appLoggerPrefix)
|
||||||
config, _ := assetManager.LoadConfig()
|
logger.SetLevel(d2util.LogLevelNone)
|
||||||
|
|
||||||
return &App{
|
return &App{
|
||||||
gitBranch: gitBranch,
|
gitBranch: gitBranch,
|
||||||
gitCommit: gitCommit,
|
gitCommit: gitCommit,
|
||||||
asset: assetManager,
|
asset: assetManager,
|
||||||
config: config,
|
|
||||||
Options: &Options{
|
Options: &Options{
|
||||||
Server: &d2networking.ServerOptions{},
|
Server: &d2networking.ServerOptions{},
|
||||||
},
|
},
|
||||||
|
logger: logger,
|
||||||
errorMessage: assetError,
|
errorMessage: assetError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,10 +249,53 @@ func (a *App) parseArguments() {
|
|||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadConfig loads the OpenDiablo2 config file
|
||||||
|
func (a *App) LoadConfig() (*d2config.Configuration, error) {
|
||||||
|
// by now the, the loader has initialized and added our config dirs as sources...
|
||||||
|
configBaseName := filepath.Base(d2config.DefaultConfigPath())
|
||||||
|
|
||||||
|
configAsset, _ := a.asset.LoadAsset(configBaseName)
|
||||||
|
|
||||||
|
config := &d2config.Configuration{}
|
||||||
|
|
||||||
|
// create the default if not found
|
||||||
|
if configAsset == nil {
|
||||||
|
config = d2config.DefaultConfig()
|
||||||
|
|
||||||
|
fullPath := filepath.Join(config.Dir(), config.Base())
|
||||||
|
config.SetPath(fullPath)
|
||||||
|
|
||||||
|
a.logger.Infof("creating default configuration file at %s...", fullPath)
|
||||||
|
|
||||||
|
saveErr := config.Save()
|
||||||
|
|
||||||
|
return config, saveErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(configAsset).Decode(config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.SetPath(filepath.Join(configAsset.Source().Path(), configAsset.Path()))
|
||||||
|
|
||||||
|
a.logger.Infof("loaded configuration file from %s", config.Path())
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Run executes the application and kicks off the entire game process
|
// Run executes the application and kicks off the entire game process
|
||||||
func (a *App) Run() error {
|
func (a *App) Run() error {
|
||||||
a.parseArguments()
|
a.parseArguments()
|
||||||
|
|
||||||
|
config, err := a.LoadConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.config = config
|
||||||
|
|
||||||
|
a.asset.SetLogLevel(config.LogLevel)
|
||||||
|
|
||||||
// print version and exit if `--version` was supplied
|
// print version and exit if `--version` was supplied
|
||||||
if *a.Options.printVersion {
|
if *a.Options.printVersion {
|
||||||
fmtVersion := "OpenDiablo2 (%s %s)"
|
fmtVersion := "OpenDiablo2 (%s %s)"
|
||||||
@ -256,7 +308,8 @@ func (a *App) Run() error {
|
|||||||
a.gitCommit = "build"
|
a.gitCommit = "build"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf(fmtVersion, a.gitBranch, a.gitCommit)
|
fmt.Printf(fmtVersion, a.gitBranch, a.gitCommit)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
logLevel := *a.Options.LogLevel
|
logLevel := *a.Options.LogLevel
|
||||||
@ -287,14 +340,15 @@ func (a *App) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", a.gitBranch)
|
windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", a.gitBranch)
|
||||||
|
|
||||||
// If we fail to initialize, we will show the error screen
|
// If we fail to initialize, we will show the error screen
|
||||||
if err := a.initialize(); err != nil {
|
if err := a.initialize(); err != nil {
|
||||||
if a.errorMessage == nil {
|
if a.errorMessage == nil {
|
||||||
a.errorMessage = err // if there was an error during init, don't clobber it
|
a.errorMessage = err // if there was an error during init, don't clobber it
|
||||||
}
|
}
|
||||||
|
|
||||||
if gameErr := a.renderer.Run(a.updateInitError, updateNOOP, 800, 600,
|
gameErr := a.renderer.Run(a.updateInitError, updateNOOP, 800, 600, windowTitle)
|
||||||
windowTitle); gameErr != nil {
|
if gameErr != nil {
|
||||||
return gameErr
|
return gameErr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +365,14 @@ func (a *App) Run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) initialize() error {
|
func (a *App) initialize() error {
|
||||||
|
if err := a.initConfig(a.config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := a.initDataDictionaries(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
a.timeScale = 1.0
|
a.timeScale = 1.0
|
||||||
a.lastTime = d2util.Now()
|
a.lastTime = d2util.Now()
|
||||||
a.lastScreenAdvance = a.lastTime
|
a.lastScreenAdvance = a.lastTime
|
||||||
@ -340,13 +402,13 @@ func (a *App) initialize() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
gui, err := d2gui.CreateGuiManager(a.asset, a.inputManager)
|
||||||
|
|
||||||
a.guiManager, err = d2gui.CreateGuiManager(a.asset, a.inputManager)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.guiManager = gui
|
||||||
|
|
||||||
a.screen = d2screen.NewScreenManager(a.ui, a.guiManager)
|
a.screen = d2screen.NewScreenManager(a.ui, a.guiManager)
|
||||||
|
|
||||||
a.audio.SetVolumes(a.config.BgmVolume, a.config.SfxVolume)
|
a.audio.SetVolumes(a.config.BgmVolume, a.config.SfxVolume)
|
||||||
@ -360,6 +422,104 @@ func (a *App) initialize() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
fmtErrSourceNotFound = `file not found: %s
|
||||||
|
|
||||||
|
Please check your config file at %s
|
||||||
|
|
||||||
|
Also, verify that the MPQ files exist at %s
|
||||||
|
|
||||||
|
Capitalization in the file name matters.
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) initConfig(config *d2config.Configuration) error {
|
||||||
|
a.config = config
|
||||||
|
|
||||||
|
for _, mpqName := range a.config.MpqLoadOrder {
|
||||||
|
cleanDir := filepath.Clean(a.config.MpqPath)
|
||||||
|
srcPath := filepath.Join(cleanDir, mpqName)
|
||||||
|
|
||||||
|
_, err := a.asset.AddSource(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
// nolint:stylecheck // we want a multiline error message here..
|
||||||
|
return fmt.Errorf(fmtErrSourceNotFound, srcPath, a.config.Path(), a.config.MpqPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) initDataDictionaries() error {
|
||||||
|
dictPaths := []string{
|
||||||
|
d2resource.LevelType, d2resource.LevelPreset, d2resource.LevelWarp,
|
||||||
|
d2resource.ObjectType, d2resource.ObjectDetails, d2resource.Weapons,
|
||||||
|
d2resource.Armor, d2resource.Misc, d2resource.Books, d2resource.ItemTypes,
|
||||||
|
d2resource.UniqueItems, d2resource.Missiles, d2resource.SoundSettings,
|
||||||
|
d2resource.MonStats, d2resource.MonStats2, d2resource.MonPreset,
|
||||||
|
d2resource.MonProp, d2resource.MonType, d2resource.MonMode,
|
||||||
|
d2resource.MagicPrefix, d2resource.MagicSuffix, d2resource.ItemStatCost,
|
||||||
|
d2resource.ItemRatio, d2resource.StorePage, d2resource.Overlays,
|
||||||
|
d2resource.CharStats, d2resource.Hireling, d2resource.Experience,
|
||||||
|
d2resource.Gems, d2resource.QualityItems, d2resource.Runes,
|
||||||
|
d2resource.DifficultyLevels, d2resource.AutoMap, d2resource.LevelDetails,
|
||||||
|
d2resource.LevelMaze, d2resource.LevelSubstitutions, d2resource.CubeRecipes,
|
||||||
|
d2resource.SuperUniques, d2resource.Inventory, d2resource.Skills,
|
||||||
|
d2resource.SkillCalc, d2resource.MissileCalc, d2resource.Properties,
|
||||||
|
d2resource.SkillDesc, d2resource.BodyLocations, d2resource.Sets,
|
||||||
|
d2resource.SetItems, d2resource.AutoMagic, d2resource.TreasureClass,
|
||||||
|
d2resource.TreasureClassEx, d2resource.States, d2resource.SoundEnvirons,
|
||||||
|
d2resource.Shrines, d2resource.ElemType, d2resource.PlrMode,
|
||||||
|
d2resource.PetType, d2resource.NPC, d2resource.MonsterUniqueModifier,
|
||||||
|
d2resource.MonsterEquipment, d2resource.UniqueAppellation, d2resource.MonsterLevel,
|
||||||
|
d2resource.MonsterSound, d2resource.MonsterSequence, d2resource.PlayerClass,
|
||||||
|
d2resource.MonsterPlacement, d2resource.ObjectGroup, d2resource.CompCode,
|
||||||
|
d2resource.MonsterAI, d2resource.RarePrefix, d2resource.RareSuffix,
|
||||||
|
d2resource.Events, d2resource.Colors, d2resource.ArmorType,
|
||||||
|
d2resource.WeaponClass, d2resource.PlayerType, d2resource.Composite,
|
||||||
|
d2resource.HitClass, d2resource.UniquePrefix, d2resource.UniqueSuffix,
|
||||||
|
d2resource.CubeModifier, d2resource.CubeType, d2resource.HirelingDescription,
|
||||||
|
d2resource.LowQualityItems,
|
||||||
|
}
|
||||||
|
|
||||||
|
a.logger.Info("Initializing asset manager")
|
||||||
|
|
||||||
|
for _, path := range dictPaths {
|
||||||
|
err := a.asset.LoadRecords(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.initAnimationData(d2resource.AnimationData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
fmtLoadAnimData = "loading animation data from: %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *App) initAnimationData(path string) error {
|
||||||
|
animDataBytes, err := a.asset.LoadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.logger.Debug(fmt.Sprintf(fmtLoadAnimData, path))
|
||||||
|
|
||||||
|
animData := d2data.LoadAnimationData(animDataBytes)
|
||||||
|
|
||||||
|
a.logger.Infof("Loaded %d animation data records", len(animData))
|
||||||
|
|
||||||
|
a.asset.Records.Animation.Data = animData
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) loadStrings() error {
|
func (a *App) loadStrings() error {
|
||||||
tablePaths := []string{
|
tablePaths := []string{
|
||||||
d2resource.PatchStringTable,
|
d2resource.PatchStringTable,
|
||||||
|
@ -1,19 +1,11 @@
|
|||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||||
@ -51,14 +43,12 @@ const (
|
|||||||
fmtLoadStringTable = "loading string table: %s"
|
fmtLoadStringTable = "loading string table: %s"
|
||||||
fmtLoadTransform = "loading palette transform: %s"
|
fmtLoadTransform = "loading palette transform: %s"
|
||||||
fmtLoadDict = "loading data dictionary: %s"
|
fmtLoadDict = "loading data dictionary: %s"
|
||||||
fmtLoadAnimData = "loading animation data from: %s"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AssetManager loads files and game objects
|
// AssetManager loads files and game objects
|
||||||
type AssetManager struct {
|
type AssetManager struct {
|
||||||
config *d2config.Configuration
|
*d2util.Logger
|
||||||
logger *d2util.Logger
|
*d2loader.Loader
|
||||||
loader *d2loader.Loader
|
|
||||||
tables []d2tbl.TextDictionary
|
tables []d2tbl.TextDictionary
|
||||||
animations d2interface.Cache
|
animations d2interface.Cache
|
||||||
fonts d2interface.Cache
|
fonts d2interface.Cache
|
||||||
@ -67,155 +57,20 @@ type AssetManager struct {
|
|||||||
Records *d2records.RecordManager
|
Records *d2records.RecordManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *AssetManager) init() error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
config, err := am.LoadConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
am.logger.SetLevel(config.LogLevel)
|
|
||||||
am.Records.Logger.SetLevel(config.LogLevel)
|
|
||||||
am.loader.Logger.SetLevel(config.LogLevel)
|
|
||||||
|
|
||||||
err = am.initConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := am.initDataDictionaries(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *AssetManager) initConfig(config *d2config.Configuration) error {
|
|
||||||
am.config = config
|
|
||||||
|
|
||||||
for _, mpqName := range am.config.MpqLoadOrder {
|
|
||||||
cleanDir := filepath.Clean(am.config.MpqPath)
|
|
||||||
srcPath := filepath.Join(cleanDir, mpqName)
|
|
||||||
|
|
||||||
_, err := am.loader.AddSource(srcPath)
|
|
||||||
if err != nil {
|
|
||||||
// nolint:stylecheck // we want a multiline error message here..
|
|
||||||
return fmt.Errorf(fmtErrSourceNotFound, srcPath, am.config.Path(), am.config.MpqPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLogLevel sets the log level for the asset manager, record manager, and file loader
|
// SetLogLevel sets the log level for the asset manager, record manager, and file loader
|
||||||
func (am *AssetManager) SetLogLevel(level d2util.LogLevel) {
|
func (am *AssetManager) SetLogLevel(level d2util.LogLevel) {
|
||||||
am.logger.SetLevel(level)
|
am.Logger.SetLevel(level)
|
||||||
am.Records.Logger.SetLevel(level)
|
am.Records.Logger.SetLevel(level)
|
||||||
am.loader.Logger.SetLevel(level)
|
am.Loader.Logger.SetLevel(level)
|
||||||
}
|
|
||||||
|
|
||||||
// LoadConfig loads the OpenDiablo2 config file
|
|
||||||
func (am *AssetManager) LoadConfig() (*d2config.Configuration, error) {
|
|
||||||
// by now the, the loader has initialized and added our config dirs as sources...
|
|
||||||
configBaseName := filepath.Base(d2config.DefaultConfigPath())
|
|
||||||
|
|
||||||
configAsset, _ := am.LoadAsset(configBaseName)
|
|
||||||
|
|
||||||
config := &d2config.Configuration{}
|
|
||||||
|
|
||||||
// create the default if not found
|
|
||||||
if configAsset == nil {
|
|
||||||
config = d2config.DefaultConfig()
|
|
||||||
|
|
||||||
fullPath := filepath.Join(config.Dir(), config.Base())
|
|
||||||
config.SetPath(fullPath)
|
|
||||||
|
|
||||||
am.logger.Infof("creating default configuration file at %s...", fullPath)
|
|
||||||
|
|
||||||
saveErr := config.Save()
|
|
||||||
|
|
||||||
return config, saveErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.NewDecoder(configAsset).Decode(config); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
config.SetPath(filepath.Join(configAsset.Source().Path(), configAsset.Path()))
|
|
||||||
|
|
||||||
am.logger.Infof("loaded configuration file from %s", config.Path())
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
fmtErrSourceNotFound = `file not found: %s
|
|
||||||
|
|
||||||
Please check your config file at %s
|
|
||||||
|
|
||||||
Also, verify that the MPQ files exist at %s
|
|
||||||
|
|
||||||
Capitalization matters!
|
|
||||||
`
|
|
||||||
)
|
|
||||||
|
|
||||||
func (am *AssetManager) initDataDictionaries() error {
|
|
||||||
dictPaths := []string{
|
|
||||||
d2resource.LevelType, d2resource.LevelPreset, d2resource.LevelWarp,
|
|
||||||
d2resource.ObjectType, d2resource.ObjectDetails, d2resource.Weapons,
|
|
||||||
d2resource.Armor, d2resource.Misc, d2resource.Books, d2resource.ItemTypes,
|
|
||||||
d2resource.UniqueItems, d2resource.Missiles, d2resource.SoundSettings,
|
|
||||||
d2resource.MonStats, d2resource.MonStats2, d2resource.MonPreset,
|
|
||||||
d2resource.MonProp, d2resource.MonType, d2resource.MonMode,
|
|
||||||
d2resource.MagicPrefix, d2resource.MagicSuffix, d2resource.ItemStatCost,
|
|
||||||
d2resource.ItemRatio, d2resource.StorePage, d2resource.Overlays,
|
|
||||||
d2resource.CharStats, d2resource.Hireling, d2resource.Experience,
|
|
||||||
d2resource.Gems, d2resource.QualityItems, d2resource.Runes,
|
|
||||||
d2resource.DifficultyLevels, d2resource.AutoMap, d2resource.LevelDetails,
|
|
||||||
d2resource.LevelMaze, d2resource.LevelSubstitutions, d2resource.CubeRecipes,
|
|
||||||
d2resource.SuperUniques, d2resource.Inventory, d2resource.Skills,
|
|
||||||
d2resource.SkillCalc, d2resource.MissileCalc, d2resource.Properties,
|
|
||||||
d2resource.SkillDesc, d2resource.BodyLocations, d2resource.Sets,
|
|
||||||
d2resource.SetItems, d2resource.AutoMagic, d2resource.TreasureClass,
|
|
||||||
d2resource.TreasureClassEx, d2resource.States, d2resource.SoundEnvirons,
|
|
||||||
d2resource.Shrines, d2resource.ElemType, d2resource.PlrMode,
|
|
||||||
d2resource.PetType, d2resource.NPC, d2resource.MonsterUniqueModifier,
|
|
||||||
d2resource.MonsterEquipment, d2resource.UniqueAppellation, d2resource.MonsterLevel,
|
|
||||||
d2resource.MonsterSound, d2resource.MonsterSequence, d2resource.PlayerClass,
|
|
||||||
d2resource.MonsterPlacement, d2resource.ObjectGroup, d2resource.CompCode,
|
|
||||||
d2resource.MonsterAI, d2resource.RarePrefix, d2resource.RareSuffix,
|
|
||||||
d2resource.Events, d2resource.Colors, d2resource.ArmorType,
|
|
||||||
d2resource.WeaponClass, d2resource.PlayerType, d2resource.Composite,
|
|
||||||
d2resource.HitClass, d2resource.UniquePrefix, d2resource.UniqueSuffix,
|
|
||||||
d2resource.CubeModifier, d2resource.CubeType, d2resource.HirelingDescription,
|
|
||||||
d2resource.LowQualityItems,
|
|
||||||
}
|
|
||||||
|
|
||||||
am.logger.Info("Initializing asset manager")
|
|
||||||
|
|
||||||
for _, path := range dictPaths {
|
|
||||||
err := am.LoadRecords(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := am.initAnimationData(d2resource.AnimationData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAsset loads an asset
|
// LoadAsset loads an asset
|
||||||
func (am *AssetManager) LoadAsset(filePath string) (asset.Asset, error) {
|
func (am *AssetManager) LoadAsset(filePath string) (asset.Asset, error) {
|
||||||
data, err := am.loader.Load(filePath)
|
data, err := am.Loader.Load(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := fmt.Sprintf(fmtLoadAsset, filePath, err.Error())
|
errStr := fmt.Sprintf(fmtLoadAsset, filePath, err.Error())
|
||||||
|
|
||||||
am.logger.Error(errStr)
|
am.Error(errStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, err
|
return data, err
|
||||||
@ -223,6 +78,7 @@ func (am *AssetManager) LoadAsset(filePath string) (asset.Asset, error) {
|
|||||||
|
|
||||||
// LoadFileStream streams an MPQ file from a source file path
|
// LoadFileStream streams an MPQ file from a source file path
|
||||||
func (am *AssetManager) LoadFileStream(filePath string) (d2interface.DataStream, error) {
|
func (am *AssetManager) LoadFileStream(filePath string) (d2interface.DataStream, error) {
|
||||||
|
am.Logger.Debugf("Loading FileStream: %s", filePath)
|
||||||
return am.LoadAsset(filePath)
|
return am.LoadAsset(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +99,9 @@ func (am *AssetManager) LoadFile(filePath string) ([]byte, error) {
|
|||||||
|
|
||||||
// FileExists checks if a file exists on the underlying file system at the given file path.
|
// FileExists checks if a file exists on the underlying file system at the given file path.
|
||||||
func (am *AssetManager) FileExists(filePath string) (bool, error) {
|
func (am *AssetManager) FileExists(filePath string) (bool, error) {
|
||||||
if loadedAsset, err := am.loader.Load(filePath); err != nil || loadedAsset == nil {
|
am.Logger.Debugf("Checking if file exists %s", filePath)
|
||||||
|
|
||||||
|
if loadedAsset, err := am.Loader.Load(filePath); err != nil || loadedAsset == nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +122,7 @@ func (am *AssetManager) LoadAnimationWithEffect(animationPath, palettePath strin
|
|||||||
return animation.(d2interface.Animation).Clone(), nil
|
return animation.(d2interface.Animation).Clone(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadAnimation, animationPath, palettePath, effect))
|
am.Debugf(fmtLoadAnimation, animationPath, palettePath, effect)
|
||||||
|
|
||||||
animAsset, err := am.LoadAsset(animationPath)
|
animAsset, err := am.LoadAsset(animationPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -300,7 +158,7 @@ func (am *AssetManager) LoadAnimationWithEffect(animationPath, palettePath strin
|
|||||||
|
|
||||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||||
func (am *AssetManager) LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
func (am *AssetManager) LoadComposite(baseType d2enum.ObjectType, token, palettePath string) (*Composite, error) {
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadComposite, baseType, token, palettePath))
|
am.Debugf(fmtLoadComposite, baseType, token, palettePath)
|
||||||
|
|
||||||
c := &Composite{
|
c := &Composite{
|
||||||
AssetManager: am,
|
AssetManager: am,
|
||||||
@ -337,7 +195,7 @@ func (am *AssetManager) LoadFont(tablePath, spritePath, palettePath string) (*Fo
|
|||||||
return nil, fmt.Errorf("invalid font table format: %s", tablePath)
|
return nil, fmt.Errorf("invalid font table format: %s", tablePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadFont, tablePath, spritePath, palettePath))
|
am.Debugf(fmtLoadFont, tablePath, spritePath, palettePath)
|
||||||
|
|
||||||
font := &Font{
|
font := &Font{
|
||||||
table: tableData,
|
table: tableData,
|
||||||
@ -365,7 +223,7 @@ func (am *AssetManager) LoadPalette(palettePath string) (d2interface.Palette, er
|
|||||||
return nil, fmt.Errorf("not an instance of a palette: %s", palettePath)
|
return nil, fmt.Errorf("not an instance of a palette: %s", palettePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadPalette, palettePath))
|
am.Debugf(fmtLoadPalette, palettePath)
|
||||||
|
|
||||||
data, err := am.LoadFile(palettePath)
|
data, err := am.LoadFile(palettePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -394,7 +252,7 @@ func (am *AssetManager) LoadStringTable(tablePath string) (d2tbl.TextDictionary,
|
|||||||
return nil, fmt.Errorf("table not found: %s", tablePath)
|
return nil, fmt.Errorf("table not found: %s", tablePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadStringTable, tablePath))
|
am.Debugf(fmtLoadStringTable, tablePath)
|
||||||
|
|
||||||
am.tables = append(am.tables, table)
|
am.tables = append(am.tables, table)
|
||||||
|
|
||||||
@ -431,7 +289,7 @@ func (am *AssetManager) LoadPaletteTransform(path string) (*d2pl2.PL2, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadTransform, path))
|
am.Debugf(fmtLoadTransform, path)
|
||||||
|
|
||||||
if err := am.transforms.Insert(path, pl2, 1); err != nil {
|
if err := am.transforms.Insert(path, pl2, 1); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -453,7 +311,7 @@ func (am *AssetManager) LoadDataDictionary(path string) (*d2txt.DataDictionary,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadDict, path))
|
am.Debugf(fmtLoadDict, path)
|
||||||
|
|
||||||
return d2txt.LoadDataDictionary(data), nil
|
return d2txt.LoadDataDictionary(data), nil
|
||||||
}
|
}
|
||||||
@ -513,23 +371,6 @@ func (am *AssetManager) loadDCC(path string,
|
|||||||
return animation, nil
|
return animation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *AssetManager) initAnimationData(path string) error {
|
|
||||||
animDataBytes, err := am.LoadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
am.logger.Debug(fmt.Sprintf(fmtLoadAnimData, path))
|
|
||||||
|
|
||||||
animData := d2data.LoadAnimationData(animDataBytes)
|
|
||||||
|
|
||||||
am.logger.Infof("Loaded %d animation data records", len(animData))
|
|
||||||
|
|
||||||
am.Records.Animation.Data = animData
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindTerminalCommands binds the in-game terminal comands for the asset manager.
|
// BindTerminalCommands binds the in-game terminal comands for the asset manager.
|
||||||
func (am *AssetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
func (am *AssetManager) BindTerminalCommands(term d2interface.Terminal) error {
|
||||||
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
||||||
|
@ -21,8 +21,8 @@ func NewAssetManager() (*AssetManager, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager := &AssetManager{
|
manager := &AssetManager{
|
||||||
logger: d2util.NewLogger(),
|
Logger: d2util.NewLogger(),
|
||||||
loader: loader,
|
Loader: loader,
|
||||||
tables: make([]d2tbl.TextDictionary, 0),
|
tables: make([]d2tbl.TextDictionary, 0),
|
||||||
animations: d2cache.CreateCache(animationBudget),
|
animations: d2cache.CreateCache(animationBudget),
|
||||||
fonts: d2cache.CreateCache(fontBudget),
|
fonts: d2cache.CreateCache(fontBudget),
|
||||||
@ -31,9 +31,7 @@ func NewAssetManager() (*AssetManager, error) {
|
|||||||
Records: records,
|
Records: records,
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.logger.SetPrefix(logPrefix)
|
manager.SetPrefix(logPrefix)
|
||||||
|
|
||||||
err = manager.init()
|
|
||||||
|
|
||||||
return manager, err
|
return manager, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user