From 2153f5ce64dcd48426495502dd591b1b99220989 Mon Sep 17 00:00:00 2001 From: gucio321 <73652197+gucio321@users.noreply.github.com> Date: Wed, 18 Nov 2020 22:02:49 +0100 Subject: [PATCH] implemented logger in d2gamescreen (#925) * implemented logger in d2gamescreen * logger in d2game/d2player * logger for app.go --- d2app/app.go | 67 ++++++----- d2common/d2util/logger.go | 21 ++++ d2game/d2gamescreen/character_select.go | 93 +++++++------- d2game/d2gamescreen/cinematics.go | 51 ++++---- d2game/d2gamescreen/credits.go | 52 ++++---- d2game/d2gamescreen/game.go | 140 ++++++++++++---------- d2game/d2gamescreen/gui_testing.go | 29 +++-- d2game/d2gamescreen/main_menu.go | 111 +++++++++-------- d2game/d2gamescreen/map_engine_testing.go | 81 +++++++------ d2game/d2gamescreen/select_hero_class.go | 114 +++++++++--------- d2game/d2player/escape_menu.go | 102 ++++++++-------- d2game/d2player/game_controls.go | 135 +++++++++++---------- d2game/d2player/globeWidget.go | 36 +++--- d2game/d2player/help_overlay.go | 59 +++++---- d2game/d2player/hero_stats_panel.go | 52 ++++---- d2game/d2player/hud.go | 45 ++++--- d2game/d2player/inventory.go | 56 +++++---- d2game/d2player/inventory_grid.go | 48 +++++--- d2game/d2player/key_binding_menu.go | 116 +++++++++--------- d2game/d2player/mini_panel.go | 38 +++--- d2game/d2player/skill_select_menu.go | 7 +- d2game/d2player/skill_select_panel.go | 66 +++++----- d2game/d2player/skillicon.go | 29 +++-- d2game/d2player/skilltree.go | 86 +++++++------ 24 files changed, 920 insertions(+), 714 deletions(-) diff --git a/d2app/app.go b/d2app/app.go index e1c16d94..3359a484 100644 --- a/d2app/app.go +++ b/d2app/app.go @@ -10,7 +10,6 @@ import ( "image" "image/gif" "image/png" - "log" "os" "os/signal" "path/filepath" @@ -154,7 +153,7 @@ func (a *App) startDedicatedServer() error { for { for data := range srvChanLog { - log.Println(data) + a.logger.Info(data) } } } @@ -327,7 +326,7 @@ func (a *App) Run() error { // start profiler if argument was supplied if len(*a.Options.profiler) > 0 { - profiler := enableProfiler(*a.Options.profiler) + profiler := enableProfiler(*a.Options.profiler, a) if profiler != nil { defer profiler.Stop() } @@ -406,7 +405,7 @@ func (a *App) initialize() error { action := &terminalActions[idx] if err := a.terminal.BindAction(action.name, action.description, action.action); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } } @@ -684,21 +683,21 @@ func (a *App) allocRate(totalAlloc uint64, fps float64) float64 { func (a *App) dumpHeap() { if _, err := os.Stat("./pprof/"); os.IsNotExist(err) { if err := os.Mkdir("./pprof/", 0750); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } } fileOut, err := os.Create("./pprof/heap.pprof") if err != nil { - log.Print(err) + a.logger.Error(err.Error()) } if err := pprof.WriteHeapProfile(fileOut); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } if err := fileOut.Close(); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } } @@ -709,7 +708,7 @@ func (a *App) evalJS(code string) { return } - log.Printf("%s", val) + a.logger.Info("%s" + val) } func (a *App) toggleFullScreen() { @@ -732,7 +731,7 @@ func (a *App) doCaptureFrame(target d2interface.Surface) error { defer func() { if err := fp.Close(); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } }() @@ -741,7 +740,7 @@ func (a *App) doCaptureFrame(target d2interface.Surface) error { return err } - log.Printf("saved frame to %s", a.capturePath) + a.logger.Info(fmt.Sprintf("saved frame to %s", a.capturePath)) return nil } @@ -759,7 +758,7 @@ func (a *App) convertFramesToGif() error { defer func() { if err := fp.Close(); err != nil { - log.Fatal(err) + a.logger.Fatal(err.Error()) } }() @@ -801,7 +800,7 @@ func (a *App) convertFramesToGif() error { return err } - log.Printf("saved animation to %s", a.capturePath) + a.logger.Info(fmt.Sprintf("saved animation to %s", a.capturePath)) return nil } @@ -841,7 +840,7 @@ func (a *App) quitGame() { } func (a *App) enterGuiPlayground() { - a.screen.SetNextScreen(d2gamescreen.CreateGuiTestMain(a.renderer, a.guiManager, a.asset)) + a.screen.SetNextScreen(d2gamescreen.CreateGuiTestMain(a.renderer, a.guiManager, a.config.LogLevel, a.asset)) } func createZeroedRing(n int) *ring.Ring { @@ -854,36 +853,36 @@ func createZeroedRing(n int) *ring.Ring { return r } -func enableProfiler(profileOption string) interface{ Stop() } { +func enableProfiler(profileOption string, a *App) interface{ Stop() } { var options []func(*profile.Profile) switch strings.ToLower(strings.Trim(profileOption, " ")) { case "cpu": - log.Printf("CPU profiling is enabled.") + a.logger.Debug("CPU profiling is enabled.") options = append(options, profile.CPUProfile) case "mem": - log.Printf("Memory profiling is enabled.") + a.logger.Debug("Memory profiling is enabled.") options = append(options, profile.MemProfile) case "block": - log.Printf("Block profiling is enabled.") + a.logger.Debug("Block profiling is enabled.") options = append(options, profile.BlockProfile) case "goroutine": - log.Printf("Goroutine profiling is enabled.") + a.logger.Debug("Goroutine profiling is enabled.") options = append(options, profile.GoroutineProfile) case "trace": - log.Printf("Trace profiling is enabled.") + a.logger.Debug("Trace profiling is enabled.") options = append(options, profile.TraceProfile) case "thread": - log.Printf("Thread creation profiling is enabled.") + a.logger.Debug("Thread creation profiling is enabled.") options = append(options, profile.ThreadcreationProfile) case "mutex": - log.Printf("Mutex profiling is enabled.") + a.logger.Debug("Mutex profiling is enabled.") options = append(options, profile.MutexProfile) } @@ -909,9 +908,10 @@ func (a *App) updateInitError(target d2interface.Surface) error { func (a *App) ToMainMenu(errorMessageOptional ...string) { buildInfo := d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit} - mainMenu, err := d2gamescreen.CreateMainMenu(a, a.asset, a.renderer, a.inputManager, a.audio, a.ui, buildInfo, errorMessageOptional...) + mainMenu, err := d2gamescreen.CreateMainMenu(a, a.asset, a.renderer, a.inputManager, a.audio, a.ui, buildInfo, + a.config.LogLevel, errorMessageOptional...) if err != nil { - log.Print(err) + a.logger.Error(err.Error()) return } @@ -920,9 +920,9 @@ func (a *App) ToMainMenu(errorMessageOptional ...string) { // ToSelectHero forces the game to transition to the Select Hero (create character) screen func (a *App) ToSelectHero(connType d2clientconnectiontype.ClientConnectionType, host string) { - selectHero, err := d2gamescreen.CreateSelectHeroClass(a, a.asset, a.renderer, a.audio, a.ui, connType, host) + selectHero, err := d2gamescreen.CreateSelectHeroClass(a, a.asset, a.renderer, a.audio, a.ui, connType, a.config.LogLevel, host) if err != nil { - log.Print(err) + a.logger.Error(err.Error()) return } @@ -933,7 +933,7 @@ func (a *App) ToSelectHero(connType d2clientconnectiontype.ClientConnectionType, func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.ClientConnectionType, host string) { gameClient, err := d2client.Create(connType, a.asset, a.scriptEngine) if err != nil { - log.Print(err) + a.logger.Error(err.Error()) } if err = gameClient.Open(host, filePath); err != nil { @@ -942,7 +942,7 @@ func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.Clie a.ToMainMenu(errorMessage) } else { a.screen.SetNextScreen(d2gamescreen.CreateGame( - a, a.asset, a.ui, a.renderer, a.inputManager, a.audio, gameClient, a.terminal, a.guiManager, + a, a.asset, a.ui, a.renderer, a.inputManager, a.audio, gameClient, a.terminal, a.config.LogLevel, a.guiManager, )) } } @@ -950,7 +950,7 @@ func (a *App) ToCreateGame(filePath string, connType d2clientconnectiontype.Clie // ToCharacterSelect forces the game to transition to the Character Select (load character) screen func (a *App) ToCharacterSelect(connType d2clientconnectiontype.ClientConnectionType, connHost string) { characterSelect, err := d2gamescreen.CreateCharacterSelect(a, a.asset, a.renderer, a.inputManager, - a.audio, a.ui, connType, connHost) + a.audio, a.ui, connType, a.config.LogLevel, connHost) if err != nil { fmt.Printf("unable to create character select screen: %s", err) } @@ -960,9 +960,10 @@ func (a *App) ToCharacterSelect(connType d2clientconnectiontype.ClientConnection // ToMapEngineTest forces the game to transition to the map engine test screen func (a *App) ToMapEngineTest(region, level int) { - met, err := d2gamescreen.CreateMapEngineTest(region, level, a.asset, a.terminal, a.renderer, a.inputManager, a.audio, a.screen) + met, err := d2gamescreen.CreateMapEngineTest(region, level, a.asset, a.terminal, a.renderer, a.inputManager, a.audio, + a.config.LogLevel, a.screen) if err != nil { - log.Print(err) + a.logger.Error(err.Error()) return } @@ -971,10 +972,10 @@ func (a *App) ToMapEngineTest(region, level int) { // ToCredits forces the game to transition to the credits screen func (a *App) ToCredits() { - a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.asset, a.renderer, a.ui)) + a.screen.SetNextScreen(d2gamescreen.CreateCredits(a, a.asset, a.renderer, a.config.LogLevel, a.ui)) } // ToCinematics forces the game to transition to the cinematics menu func (a *App) ToCinematics() { - a.screen.SetNextScreen(d2gamescreen.CreateCinematics(a, a.asset, a.renderer, a.audio, a.ui)) + a.screen.SetNextScreen(d2gamescreen.CreateCinematics(a, a.asset, a.renderer, a.audio, a.config.LogLevel, a.ui)) } diff --git a/d2common/d2util/logger.go b/d2common/d2util/logger.go index 204991ed..e705a88f 100644 --- a/d2common/d2util/logger.go +++ b/d2common/d2util/logger.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "log" + "os" "runtime" ) @@ -13,6 +14,7 @@ type LogLevel = int // Log levels const ( LogLevelNone LogLevel = iota + LogLevelFatal LogLevelError LogLevelWarning LogLevelInfo @@ -41,6 +43,7 @@ const ( LogFmtInfo = "[INFO]" + colorEscapeReset + " %s\r\n" LogFmtWarning = "[WARNING]" + colorEscapeReset + " %s\r\n" LogFmtError = "[ERROR]" + colorEscapeReset + " %s\r\n" + LogFmtFatal = "[FATAL]" + colorEscapeReset + " %s\r\n" ) // NewLogger creates a new logger with a default @@ -131,6 +134,21 @@ func (l *Logger) Errorf(fmtMsg string, args ...interface{}) { l.Error(fmt.Sprintf(fmtMsg, args...)) } +// Fatal logs an fatal error message and exits programm +func (l *Logger) Fatal(msg string) { + if l == nil || l.level < LogLevelFatal { + return + } + + l.print(LogLevelFatal, msg) + os.Exit(1) +} + +// Fatalf formats and then logs a error message +func (l *Logger) Fatalf(fmtMsg string, args ...interface{}) { + l.Fatal(fmt.Sprintf(fmtMsg, args...)) +} + // Debug logs a debug message func (l *Logger) Debug(msg string) { if l == nil || l.level < LogLevelDebug { @@ -155,6 +173,7 @@ func (l *Logger) print(level LogLevel, msg string) { LogLevelInfo: green, LogLevelWarning: yellow, LogLevelError: red, + LogLevelFatal: red, } fmtString := "" @@ -180,6 +199,8 @@ func (l *Logger) print(level LogLevel, msg string) { fmtString += LogFmtWarning case LogLevelError: fmtString += LogFmtError + case LogLevelFatal: + fmtString += LogFmtFatal case LogLevelNone: default: return diff --git a/d2game/d2gamescreen/character_select.go b/d2game/d2gamescreen/character_select.go index 8360d157..d1d6a0a5 100644 --- a/d2game/d2gamescreen/character_select.go +++ b/d2game/d2gamescreen/character_select.go @@ -1,9 +1,7 @@ package d2gamescreen import ( - "fmt" "image/color" - "log" "math" "os" @@ -12,6 +10,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2map/d2mapentity" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen" @@ -19,6 +18,49 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype" ) +// CreateCharacterSelect creates the character select screen and returns a pointer to it +func CreateCharacterSelect( + navigator d2interface.Navigator, + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + inputManager d2interface.InputManager, + audioProvider d2interface.AudioProvider, + ui *d2ui.UIManager, + connectionType d2clientconnectiontype.ClientConnectionType, + l d2util.LogLevel, + connectionHost string, +) (*CharacterSelect, error) { + playerStateFactory, err := d2hero.NewHeroStateFactory(asset) + if err != nil { + return nil, err + } + + entityFactory, err := d2mapentity.NewMapEntityFactory(asset) + if err != nil { + return nil, err + } + + characterSelect := &CharacterSelect{ + selectedCharacter: -1, + asset: asset, + MapEntityFactory: entityFactory, + renderer: renderer, + connectionType: connectionType, + connectionHost: connectionHost, + inputManager: inputManager, + audioProvider: audioProvider, + navigator: navigator, + uiManager: ui, + HeroStateFactory: playerStateFactory, + } + + characterSelect.logger = d2util.NewLogger() + characterSelect.logger.SetLevel(l) + characterSelect.logger.SetPrefix(logPrefix) + + return characterSelect, nil +} + // CharacterSelect represents the character select screen type CharacterSelect struct { asset *d2asset.AssetManager @@ -55,42 +97,7 @@ type CharacterSelect struct { audioProvider d2interface.AudioProvider renderer d2interface.Renderer navigator d2interface.Navigator -} - -// CreateCharacterSelect creates the character select screen and returns a pointer to it -func CreateCharacterSelect( - navigator d2interface.Navigator, - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - inputManager d2interface.InputManager, - audioProvider d2interface.AudioProvider, - ui *d2ui.UIManager, - connectionType d2clientconnectiontype.ClientConnectionType, - connectionHost string, -) (*CharacterSelect, error) { - playerStateFactory, err := d2hero.NewHeroStateFactory(asset) - if err != nil { - return nil, err - } - - entityFactory, err := d2mapentity.NewMapEntityFactory(asset) - if err != nil { - return nil, err - } - - return &CharacterSelect{ - selectedCharacter: -1, - asset: asset, - MapEntityFactory: entityFactory, - renderer: renderer, - connectionType: connectionType, - connectionHost: connectionHost, - inputManager: inputManager, - audioProvider: audioProvider, - navigator: navigator, - uiManager: ui, - HeroStateFactory: playerStateFactory, - }, nil + logger *d2util.Logger } const ( @@ -153,7 +160,7 @@ func (v *CharacterSelect) OnLoad(loading d2screen.LoadingState) { err := v.inputManager.BindHandler(v) if err != nil { - fmt.Println("failed to add Character Select screen as event handler") + v.logger.Error("failed to add Character Select screen as event handler") } loading.Progress(tenPercent) @@ -205,7 +212,7 @@ func (v *CharacterSelect) loadBackground() { v.background, err = v.uiManager.NewSprite(d2resource.CharacterSelectionBackground, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.background.SetPosition(bgX, bgY) @@ -232,7 +239,7 @@ func (v *CharacterSelect) loadSelectionBox() { v.selectionBox, err = v.uiManager.NewSprite(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } selBoxX, selBoxY := 37, 86 @@ -244,7 +251,7 @@ func (v *CharacterSelect) loadOkCancelBox() { v.okCancelBox, err = v.uiManager.NewSprite(d2resource.PopUpOkCancel, d2resource.PaletteFechar) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } okCancelX, okCancelY := 270, 175 @@ -494,7 +501,7 @@ func (v *CharacterSelect) onDeleteCharButtonClicked() { func (v *CharacterSelect) onDeleteCharacterConfirmClicked() { err := os.Remove(v.gameStates[v.selectedCharacter].FilePath) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.charScrollbar.SetCurrentOffset(0) diff --git a/d2game/d2gamescreen/cinematics.go b/d2game/d2gamescreen/cinematics.go index ae5d1cb2..f4c9717f 100644 --- a/d2game/d2gamescreen/cinematics.go +++ b/d2game/d2gamescreen/cinematics.go @@ -1,11 +1,10 @@ package d2gamescreen import ( - "log" - "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2video" "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/d2screen" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -24,6 +23,29 @@ const ( cinematicsExitBtnX, cinematicsExitBtnY = 340, 470 ) +// CreateCinematics creates an instance of the credits screen +func CreateCinematics( + navigator d2interface.Navigator, + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + aup d2interface.AudioProvider, + l d2util.LogLevel, + ui *d2ui.UIManager) *Cinematics { + cinematics := &Cinematics{ + asset: asset, + renderer: renderer, + navigator: navigator, + uiManager: ui, + audioProvider: aup, + } + + cinematics.logger = d2util.NewLogger() + cinematics.logger.SetPrefix(logPrefix) + cinematics.logger.SetLevel(l) + + return cinematics +} + // Cinematics represents the cinematics screen type Cinematics struct { cinematicsBackground *d2ui.Sprite @@ -44,24 +66,7 @@ type Cinematics struct { uiManager *d2ui.UIManager videoDecoder *d2video.BinkDecoder audioProvider d2interface.AudioProvider -} - -// CreateCinematics creates an instance of the credits screen -func CreateCinematics( - navigator d2interface.Navigator, - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - aup d2interface.AudioProvider, - ui *d2ui.UIManager) *Cinematics { - result := &Cinematics{ - asset: asset, - renderer: renderer, - navigator: navigator, - uiManager: ui, - audioProvider: aup, - } - - return result + logger *d2util.Logger } // OnLoad is called to load the resources for the credits screen @@ -73,7 +78,7 @@ func (v *Cinematics) OnLoad(_ d2screen.LoadingState) { v.background, err = v.uiManager.NewSprite(d2resource.GameSelectScreen, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.background.SetPosition(backgroundX, backgroundY) @@ -81,7 +86,7 @@ func (v *Cinematics) OnLoad(_ d2screen.LoadingState) { v.cinematicsBackground, err = v.uiManager.NewSprite(d2resource.CinematicsBackground, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.cinematicsBackground.SetPosition(cinematicsX, cinematicsY) @@ -173,7 +178,7 @@ func (v *Cinematics) onEndCreditExpBtnClicked() { func (v *Cinematics) playVideo(path string) { videoBytes, err := v.asset.LoadFile(path) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) return } diff --git a/d2game/d2gamescreen/credits.go b/d2game/d2gamescreen/credits.go index a71b4e8b..9da44376 100644 --- a/d2game/d2gamescreen/credits.go +++ b/d2game/d2gamescreen/credits.go @@ -2,8 +2,6 @@ package d2gamescreen import ( "bufio" - "fmt" - "log" "os" "path" "strings" @@ -29,6 +27,30 @@ type labelItem struct { Available bool } +// CreateCredits creates an instance of the credits screen +func CreateCredits(navigator d2interface.Navigator, + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + l d2util.LogLevel, + ui *d2ui.UIManager) *Credits { + credits := &Credits{ + asset: asset, + labels: make([]*labelItem, 0), + cycleTime: 0, + doneWithCredits: false, + cyclesTillNextLine: 0, + renderer: renderer, + navigator: navigator, + uiManager: ui, + } + + credits.logger = d2util.NewLogger() + credits.logger.SetLevel(l) + credits.logger.SetPrefix(logPrefix) + + return credits +} + // Credits represents the credits screen type Credits struct { creditsBackground *d2ui.Sprite @@ -43,36 +65,20 @@ type Credits struct { renderer d2interface.Renderer navigator d2interface.Navigator uiManager *d2ui.UIManager -} - -// CreateCredits creates an instance of the credits screen -func CreateCredits(navigator d2interface.Navigator, asset *d2asset.AssetManager, renderer d2interface.Renderer, - ui *d2ui.UIManager) *Credits { - result := &Credits{ - asset: asset, - labels: make([]*labelItem, 0), - cycleTime: 0, - doneWithCredits: false, - cyclesTillNextLine: 0, - renderer: renderer, - navigator: navigator, - uiManager: ui, - } - - return result + logger *d2util.Logger } // LoadContributors loads the contributors data from file func (v *Credits) LoadContributors() []string { file, err := os.Open(path.Join("./", "CONTRIBUTORS")) if err != nil || file == nil { - log.Print("CONTRIBUTORS file is missing") + v.logger.Warning("CONTRIBUTORS file is missing") return []string{"MISSING CONTRIBUTOR FILES!"} } defer func() { if err = file.Close(); err != nil { - fmt.Printf("an error occurred while closing file: %s, err: %q\n", file.Name(), err) + v.logger.Error("an error occurred while closing file: %s, err: %q\n" + file.Name() + err.Error()) } }() @@ -92,7 +98,7 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) { v.creditsBackground, err = v.uiManager.NewSprite(d2resource.CreditsBackground, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.creditsBackground.SetPosition(creditsX, creditsY) @@ -113,7 +119,7 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) { creditData, err := d2util.Utf16BytesToString(fileData[2:]) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.creditsText = strings.Split(creditData, "\r\n") diff --git a/d2game/d2gamescreen/game.go b/d2game/d2gamescreen/game.go index e2e6926e..7b6408e9 100644 --- a/d2game/d2gamescreen/game.go +++ b/d2game/d2gamescreen/game.go @@ -35,6 +35,70 @@ const ( black50alpha = 0x0000007f // rgba ) +// CreateGame creates the Gameplay screen and returns a pointer to it +func CreateGame( + navigator d2interface.Navigator, + asset *d2asset.AssetManager, + ui *d2ui.UIManager, + renderer d2interface.Renderer, + inputManager d2interface.InputManager, + audioProvider d2interface.AudioProvider, + gameClient *d2client.GameClient, + term d2interface.Terminal, + l d2util.LogLevel, + guiManager *d2gui.GuiManager, +) *Game { + // find the local player and its initial location + var startX, startY float64 + + for _, player := range gameClient.Players { + if player.ID() != gameClient.PlayerID { + continue + } + + worldPosition := player.Position.World() + startX, startY = worldPosition.X(), worldPosition.Y() + + break + } + + keyMap := d2player.GetDefaultKeyMap(asset) + + game := &Game{ + asset: asset, + gameClient: gameClient, + gameControls: nil, + localPlayer: nil, + lastRegionType: d2enum.RegionNone, + ticksSinceLevelCheck: 0, + mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer, + gameClient.MapEngine, term, startX, startY), + escapeMenu: d2player.NewEscapeMenu(navigator, renderer, audioProvider, ui, guiManager, asset, l, keyMap), + inputManager: inputManager, + audioProvider: audioProvider, + renderer: renderer, + terminal: term, + soundEngine: d2audio.NewSoundEngine(audioProvider, asset, term), + uiManager: ui, + guiManager: guiManager, + keyMap: keyMap, + logLevel: l, + } + game.logger = d2util.NewLogger() + game.logger.SetLevel(l) + game.logger.SetPrefix(logPrefix) + + game.soundEnv = d2audio.NewSoundEnvironment(game.soundEngine) + + game.escapeMenu.OnLoad() + + if err := inputManager.BindHandler(game.escapeMenu); err != nil { + game.logger.Error("failed to add gameplay screen as event handler") + } + + return game +} + // Game represents the Gameplay screen type Game struct { *d2mapentity.MapEntityFactory @@ -56,64 +120,8 @@ type Game struct { inputManager d2interface.InputManager audioProvider d2interface.AudioProvider terminal d2interface.Terminal -} - -// CreateGame creates the Gameplay screen and returns a pointer to it -func CreateGame( - navigator d2interface.Navigator, - asset *d2asset.AssetManager, - ui *d2ui.UIManager, - renderer d2interface.Renderer, - inputManager d2interface.InputManager, - audioProvider d2interface.AudioProvider, - gameClient *d2client.GameClient, - term d2interface.Terminal, - guiManager *d2gui.GuiManager, -) *Game { - // find the local player and its initial location - var startX, startY float64 - - for _, player := range gameClient.Players { - if player.ID() != gameClient.PlayerID { - continue - } - - worldPosition := player.Position.World() - startX, startY = worldPosition.X(), worldPosition.Y() - - break - } - - keyMap := d2player.GetDefaultKeyMap(asset) - - result := &Game{ - asset: asset, - gameClient: gameClient, - gameControls: nil, - localPlayer: nil, - lastRegionType: d2enum.RegionNone, - ticksSinceLevelCheck: 0, - mapRenderer: d2maprenderer.CreateMapRenderer(asset, renderer, - gameClient.MapEngine, term, startX, startY), - escapeMenu: d2player.NewEscapeMenu(navigator, renderer, audioProvider, ui, guiManager, asset, keyMap), - inputManager: inputManager, - audioProvider: audioProvider, - renderer: renderer, - terminal: term, - soundEngine: d2audio.NewSoundEngine(audioProvider, asset, term), - uiManager: ui, - guiManager: guiManager, - keyMap: keyMap, - } - result.soundEnv = d2audio.NewSoundEnvironment(result.soundEngine) - - result.escapeMenu.OnLoad() - - if err := inputManager.BindHandler(result.escapeMenu); err != nil { - fmt.Println("failed to add gameplay screen as event handler") - } - - return result + logger *d2util.Logger + logLevel d2util.LogLevel } // OnLoad loads the resources for the Gameplay screen @@ -129,7 +137,7 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) { }, ) if err != nil { - fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnitem", err) + v.logger.Error("failed to bind the '%s' action, err: %v\nspawnitem" + err.Error()) } err = v.terminal.BindAction( @@ -141,7 +149,7 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) { }, ) if err != nil { - fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnitemat", err) + v.logger.Error("failed to bind the '%s' action, err: %v\nspawnitemat" + err.Error()) } err = v.terminal.BindAction( @@ -166,7 +174,7 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) { }, ) if err != nil { - fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnmon", err) + v.logger.Error("failed to bind the '%s' action, err: %v\nspawnmon" + err.Error()) } } @@ -294,7 +302,7 @@ func (v *Game) bindGameControls() error { var err error v.gameControls, err = d2player.NewGameControls(v.asset, v.renderer, player, v.gameClient.MapEngine, - v.escapeMenu, v.mapRenderer, v, v.terminal, v.uiManager, v.guiManager, v.keyMap, v.gameClient.IsSinglePlayer()) + v.escapeMenu, v.mapRenderer, v, v.terminal, v.uiManager, v.guiManager, v.keyMap, v.logLevel, v.gameClient.IsSinglePlayer()) if err != nil { return err @@ -303,7 +311,7 @@ func (v *Game) bindGameControls() error { v.gameControls.Load() if err := v.inputManager.BindHandler(v.gameControls); err != nil { - fmt.Printf(bindControlsErrStr, player.ID()) + v.logger.Error(bindControlsErrStr + player.ID()) } break @@ -321,7 +329,7 @@ func (v *Game) OnPlayerMove(targetX, targetY float64) { err := v.gameClient.SendPacketToServer(createMovePlayerPacket) if err != nil { - fmt.Printf(moveErrStr, v.gameClient.PlayerID, targetX, targetY) + v.logger.Error(fmt.Sprintf(moveErrStr, v.gameClient.PlayerID, targetX, targetY)) } } @@ -341,7 +349,7 @@ func (v *Game) OnPlayerSave() error { func (v *Game) OnPlayerCast(skillID int, targetX, targetY float64) { err := v.gameClient.SendPacketToServer(d2netpacket.CreateCastPacket(v.gameClient.PlayerID, skillID, targetX, targetY)) if err != nil { - fmt.Printf(castErrStr, v.gameClient.PlayerID, skillID, targetX, targetY) + v.logger.Error(fmt.Sprintf(castErrStr, v.gameClient.PlayerID, skillID, targetX, targetY)) } } @@ -362,6 +370,6 @@ func (v *Game) debugSpawnItemAtLocation(x, y int, codes ...string) { err := v.gameClient.SendPacketToServer(packet) if err != nil { - fmt.Printf(spawnItemErrStr, x, y, codes) + v.logger.Error(fmt.Sprintf(spawnItemErrStr, x, y, codes)) } } diff --git a/d2game/d2gamescreen/gui_testing.go b/d2game/d2gamescreen/gui_testing.go index 921c1a08..3375993f 100644 --- a/d2game/d2gamescreen/gui_testing.go +++ b/d2game/d2gamescreen/gui_testing.go @@ -4,25 +4,36 @@ import ( "fmt" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen" ) +// CreateGuiTestMain creates a GuiTestMain screen +func CreateGuiTestMain(renderer d2interface.Renderer, + guiManager *d2gui.GuiManager, + l d2util.LogLevel, + assetManager *d2asset.AssetManager) *GuiTestMain { + guiTestMain := &GuiTestMain{ + renderer: renderer, + guiManager: guiManager, + assetManager: assetManager, + } + + guiTestMain.logger = d2util.NewLogger() + guiTestMain.logger.SetLevel(l) + guiTestMain.logger.SetPrefix(logPrefix) + + return guiTestMain +} + // GuiTestMain is a playground screen for the gui components type GuiTestMain struct { renderer d2interface.Renderer guiManager *d2gui.GuiManager assetManager *d2asset.AssetManager -} - -// CreateGuiTestMain creates a GuiTestMain screen -func CreateGuiTestMain(renderer d2interface.Renderer, guiManager *d2gui.GuiManager, assetManager *d2asset.AssetManager) *GuiTestMain { - return &GuiTestMain{ - renderer: renderer, - guiManager: guiManager, - assetManager: assetManager, - } + logger *d2util.Logger } // OnLoad loads the resources and creates the gui components diff --git a/d2game/d2gamescreen/main_menu.go b/d2game/d2gamescreen/main_menu.go index c99150ee..5daed326 100644 --- a/d2game/d2gamescreen/main_menu.go +++ b/d2game/d2gamescreen/main_menu.go @@ -3,7 +3,6 @@ package d2gamescreen import ( "fmt" - "log" "net" "os" "os/exec" @@ -14,6 +13,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2screen" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -74,11 +74,57 @@ const ( joinGameCharacterFilter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:" ) +const ( + logPrefix = "Game Screen" +) + // BuildInfo contains information about the current build type BuildInfo struct { Branch, Commit string } +// CreateMainMenu creates an instance of MainMenu +func CreateMainMenu( + navigator d2interface.Navigator, + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + inputManager d2interface.InputManager, + audioProvider d2interface.AudioProvider, + ui *d2ui.UIManager, + buildInfo BuildInfo, + l d2util.LogLevel, + errorMessageOptional ...string, +) (*MainMenu, error) { + heroStateFactory, err := d2hero.NewHeroStateFactory(asset) + if err != nil { + return nil, err + } + + mainMenu := &MainMenu{ + asset: asset, + screenMode: ScreenModeUnknown, + leftButtonHeld: true, + renderer: renderer, + inputManager: inputManager, + audioProvider: audioProvider, + navigator: navigator, + buildInfo: buildInfo, + uiManager: ui, + heroState: heroStateFactory, + } + + mainMenu.logger = d2util.NewLogger() + mainMenu.logger.SetPrefix(logPrefix) + mainMenu.logger.SetLevel(l) + + if len(errorMessageOptional) != 0 { + mainMenu.errorLabel = ui.NewLabel(d2resource.FontFormal12, d2resource.PaletteUnits) + mainMenu.errorLabel.SetText(errorMessageOptional[0]) + } + + return mainMenu, nil +} + // MainMenu represents the main menu type MainMenu struct { tcpIPBackground *d2ui.Sprite @@ -126,43 +172,8 @@ type MainMenu struct { heroState *d2hero.HeroStateFactory buildInfo BuildInfo -} -// CreateMainMenu creates an instance of MainMenu -func CreateMainMenu( - navigator d2interface.Navigator, - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - inputManager d2interface.InputManager, - audioProvider d2interface.AudioProvider, - ui *d2ui.UIManager, - buildInfo BuildInfo, - errorMessageOptional ...string, -) (*MainMenu, error) { - heroStateFactory, err := d2hero.NewHeroStateFactory(asset) - if err != nil { - return nil, err - } - - mainMenu := &MainMenu{ - asset: asset, - screenMode: ScreenModeUnknown, - leftButtonHeld: true, - renderer: renderer, - inputManager: inputManager, - audioProvider: audioProvider, - navigator: navigator, - buildInfo: buildInfo, - uiManager: ui, - heroState: heroStateFactory, - } - - if len(errorMessageOptional) != 0 { - mainMenu.errorLabel = ui.NewLabel(d2resource.FontFormal12, d2resource.PaletteUnits) - mainMenu.errorLabel.SetText(errorMessageOptional[0]) - } - - return mainMenu, nil + logger *d2util.Logger } // OnLoad is called to load the resources for the main menu @@ -187,7 +198,7 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) { } if err := v.inputManager.BindHandler(v); err != nil { - fmt.Println("failed to add main menu as event handler") + v.logger.Error("failed to add main menu as event handler") } } @@ -196,28 +207,28 @@ func (v *MainMenu) loadBackgroundSprites() { v.background, err = v.uiManager.NewSprite(d2resource.GameSelectScreen, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.background.SetPosition(backgroundX, backgroundY) v.trademarkBackground, err = v.uiManager.NewSprite(d2resource.TrademarkScreen, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.trademarkBackground.SetPosition(backgroundX, backgroundY) v.tcpIPBackground, err = v.uiManager.NewSprite(d2resource.TCPIPBackground, d2resource.PaletteSky) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.tcpIPBackground.SetPosition(backgroundX, backgroundY) v.serverIPBackground, err = v.uiManager.NewSprite(d2resource.PopUpOkCancel, d2resource.PaletteFechar) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.serverIPBackground.SetPosition(serverIPbackgroundX, serverIPbackgroundY) @@ -285,7 +296,7 @@ func (v *MainMenu) createLogos(loading d2screen.LoadingState) { v.diabloLogoLeft, err = v.uiManager.NewSprite(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.diabloLogoLeft.SetEffect(d2enum.DrawEffectModulate) @@ -295,7 +306,7 @@ func (v *MainMenu) createLogos(loading d2screen.LoadingState) { v.diabloLogoRight, err = v.uiManager.NewSprite(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.diabloLogoRight.SetEffect(d2enum.DrawEffectModulate) @@ -304,14 +315,14 @@ func (v *MainMenu) createLogos(loading d2screen.LoadingState) { v.diabloLogoLeftBack, err = v.uiManager.NewSprite(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.diabloLogoLeftBack.SetPosition(diabloLogoX, diabloLogoY) v.diabloLogoRightBack, err = v.uiManager.NewSprite(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) } v.diabloLogoRightBack.SetPosition(diabloLogoX, diabloLogoY) @@ -415,7 +426,7 @@ func (v *MainMenu) onGithubButtonClicked() { } if err != nil { - log.Fatal(err) + v.logger.Error(err.Error()) } } @@ -625,15 +636,13 @@ func (v *MainMenu) getLocalIP() string { conn, err := net.Dial("udp", "8.8.8.8:80") if err != nil { - log.Println(err) - + v.logger.Error(err.Error()) return "cannot reach network" } err = conn.Close() if err != nil { - log.Println(err) - + v.logger.Error(err.Error()) return "unexpected error occurred while closing test connection" } diff --git a/d2game/d2gamescreen/map_engine_testing.go b/d2game/d2gamescreen/map_engine_testing.go index 3d4c0975..ac4dae7f 100644 --- a/d2game/d2gamescreen/map_engine_testing.go +++ b/d2game/d2gamescreen/map_engine_testing.go @@ -2,7 +2,6 @@ package d2gamescreen import ( "fmt" - "log" "os" "strings" "time" @@ -13,6 +12,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen" @@ -87,6 +87,46 @@ func getRegions() []regionSpec { } } +// 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, + audioProvider d2interface.AudioProvider, + l d2util.LogLevel, + screen *d2screen.ScreenManager, +) (*MapEngineTest, error) { + heroStateFactory, err := d2hero.NewHeroStateFactory(asset) + if err != nil { + return nil, err + } + + mapEngineTest := &MapEngineTest{ + currentRegion: currentRegion, + levelPreset: levelPreset, + fileIndex: 0, + regionSpec: regionSpec{}, + filesCount: 0, + asset: asset, + terminal: term, + renderer: renderer, + inputManager: inputManager, + audioProvider: audioProvider, + screen: screen, + playerStateFactory: heroStateFactory, + } + + mapEngineTest.playerState = heroStateFactory.CreateTestGameState() + + mapEngineTest.logger = d2util.NewLogger() + mapEngineTest.logger.SetLevel(l) + mapEngineTest.logger.SetPrefix(logPrefix) + + return mapEngineTest, nil +} + // MapEngineTest represents the MapEngineTest screen type MapEngineTest struct { asset *d2asset.AssetManager @@ -111,45 +151,12 @@ type MapEngineTest struct { fileIndex int regionSpec regionSpec filesCount int -} -// 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, - audioProvider d2interface.AudioProvider, - screen *d2screen.ScreenManager, -) (*MapEngineTest, error) { - heroStateFactory, err := d2hero.NewHeroStateFactory(asset) - if err != nil { - return nil, err - } - - result := &MapEngineTest{ - currentRegion: currentRegion, - levelPreset: levelPreset, - fileIndex: 0, - regionSpec: regionSpec{}, - filesCount: 0, - asset: asset, - terminal: term, - renderer: renderer, - inputManager: inputManager, - audioProvider: audioProvider, - screen: screen, - playerStateFactory: heroStateFactory, - } - - result.playerState = heroStateFactory.CreateTestGameState() - - return result, nil + logger *d2util.Logger } func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) { - log.Printf("Loaded region: Type(%d) LevelPreset(%d) FileIndex(%d)", n, levelPreset, fileIndex) + met.logger.Info(fmt.Sprintf("Loaded region: Type(%d) LevelPreset(%d) FileIndex(%d)", n, levelPreset, fileIndex)) met.mapRenderer.InvalidateImageCache() for _, spec := range getRegions() { @@ -204,7 +211,7 @@ func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) { // OnLoad loads the resources for the Map Engine Test screen func (met *MapEngineTest) OnLoad(loading d2screen.LoadingState) { if err := met.inputManager.BindHandler(met); err != nil { - fmt.Printf("could not add MapEngineTest as event handler") + met.logger.Error("could not add MapEngineTest as event handler") } loading.Progress(twentyPercent) diff --git a/d2game/d2gamescreen/select_hero_class.go b/d2game/d2gamescreen/select_hero_class.go index 5d07e73a..0f749da5 100644 --- a/d2game/d2gamescreen/select_hero_class.go +++ b/d2game/d2gamescreen/select_hero_class.go @@ -3,7 +3,6 @@ package d2gamescreen import ( "fmt" "image" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero" @@ -258,17 +257,60 @@ type HeroRenderInfo struct { SelectionBounds image.Rectangle SelectSfx d2interface.SoundEffect DeselectSfx d2interface.SoundEffect + shc *SelectHeroClass } func (hri *HeroRenderInfo) advance(elapsed float64) { - advanceSprite(hri.IdleSprite, elapsed) - advanceSprite(hri.IdleSelectedSprite, elapsed) - advanceSprite(hri.ForwardWalkSprite, elapsed) - advanceSprite(hri.ForwardWalkSpriteOverlay, elapsed) - advanceSprite(hri.SelectedSprite, elapsed) - advanceSprite(hri.SelectedSpriteOverlay, elapsed) - advanceSprite(hri.BackWalkSprite, elapsed) - advanceSprite(hri.BackWalkSpriteOverlay, elapsed) + advanceSprite(hri.shc, hri.IdleSprite, elapsed) + advanceSprite(hri.shc, hri.IdleSelectedSprite, elapsed) + advanceSprite(hri.shc, hri.ForwardWalkSprite, elapsed) + advanceSprite(hri.shc, hri.ForwardWalkSpriteOverlay, elapsed) + advanceSprite(hri.shc, hri.SelectedSprite, elapsed) + advanceSprite(hri.shc, hri.SelectedSpriteOverlay, elapsed) + advanceSprite(hri.shc, hri.BackWalkSprite, elapsed) + advanceSprite(hri.shc, hri.BackWalkSpriteOverlay, elapsed) +} + +// CreateSelectHeroClass creates an instance of a SelectHeroClass +func CreateSelectHeroClass( + navigator d2interface.Navigator, + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + audioProvider d2interface.AudioProvider, + ui *d2ui.UIManager, + connectionType d2clientconnectiontype.ClientConnectionType, + l d2util.LogLevel, + connectionHost string, +) (*SelectHeroClass, error) { + playerStateFactory, err := d2hero.NewHeroStateFactory(asset) + if err != nil { + return nil, err + } + + inventoryItemFactory, err := d2inventory.NewInventoryItemFactory(asset) + if err != nil { + return nil, err + } + + selectHeroClass := &SelectHeroClass{ + asset: asset, + heroRenderInfo: make(map[d2enum.Hero]*HeroRenderInfo), + selectedHero: d2enum.HeroNone, + connectionType: connectionType, + connectionHost: connectionHost, + audioProvider: audioProvider, + renderer: renderer, + navigator: navigator, + uiManager: ui, + HeroStateFactory: playerStateFactory, + InventoryItemFactory: inventoryItemFactory, + } + + selectHeroClass.logger = d2util.NewLogger() + selectHeroClass.logger.SetLevel(l) + selectHeroClass.logger.SetPrefix(logPrefix) + + return selectHeroClass, nil } // SelectHeroClass represents the Select Hero Class screen @@ -300,43 +342,7 @@ type SelectHeroClass struct { audioProvider d2interface.AudioProvider renderer d2interface.Renderer navigator d2interface.Navigator -} - -// CreateSelectHeroClass creates an instance of a SelectHeroClass -func CreateSelectHeroClass( - navigator d2interface.Navigator, - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - audioProvider d2interface.AudioProvider, - ui *d2ui.UIManager, - connectionType d2clientconnectiontype.ClientConnectionType, - connectionHost string, -) (*SelectHeroClass, error) { - playerStateFactory, err := d2hero.NewHeroStateFactory(asset) - if err != nil { - return nil, err - } - - inventoryItemFactory, err := d2inventory.NewInventoryItemFactory(asset) - if err != nil { - return nil, err - } - - result := &SelectHeroClass{ - asset: asset, - heroRenderInfo: make(map[d2enum.Hero]*HeroRenderInfo), - selectedHero: d2enum.HeroNone, - connectionType: connectionType, - connectionHost: connectionHost, - audioProvider: audioProvider, - renderer: renderer, - navigator: navigator, - uiManager: ui, - HeroStateFactory: playerStateFactory, - InventoryItemFactory: inventoryItemFactory, - } - - return result, nil + logger *d2util.Logger } // OnLoad loads the resources for the Select Hero Class screen @@ -494,13 +500,13 @@ func (v *SelectHeroClass) onOkButtonClicked() { playerState, err := v.CreateHeroState(heroName, v.selectedHero, statsState) if err != nil { - fmt.Printf("failed to create hero state!, err: %v\n", err) + v.logger.Error("failed to create hero state!, err: %v\n" + err.Error()) return } err = v.Save(playerState) if err != nil { - fmt.Printf("failed to save game state!, err: %v\n", err) + v.logger.Error("failed to save game state!, err: %v\n" + err.Error()) return } @@ -640,13 +646,13 @@ func (v *SelectHeroClass) handleCursorButtonPress(hero d2enum.Hero, renderInfo * func (v *SelectHeroClass) setCurrentFrame(mouseHover bool, renderInfo *HeroRenderInfo) { if mouseHover && renderInfo.Stance != d2enum.HeroStanceIdleSelected { if err := renderInfo.IdleSelectedSprite.SetCurrentFrame(renderInfo.IdleSprite.GetCurrentFrame()); err != nil { - fmt.Printf("could not set current frame to: %d\n", renderInfo.IdleSprite.GetCurrentFrame()) + v.logger.Error(fmt.Sprintf("could not set current frame to: %d\n", renderInfo.IdleSprite.GetCurrentFrame())) } renderInfo.Stance = d2enum.HeroStanceIdleSelected } else if !mouseHover && renderInfo.Stance != d2enum.HeroStanceIdle { if err := renderInfo.IdleSprite.SetCurrentFrame(renderInfo.IdleSelectedSprite.GetCurrentFrame()); err != nil { - fmt.Printf("could not set current frame to: %d\n", renderInfo.IdleSelectedSprite.GetCurrentFrame()) + v.logger.Error(fmt.Sprintf("could not set current frame to: %d\n", renderInfo.IdleSelectedSprite.GetCurrentFrame())) } renderInfo.Stance = d2enum.HeroStanceIdle @@ -739,10 +745,10 @@ func drawSprite(sprite *d2ui.Sprite, target d2interface.Surface) { } } -func advanceSprite(sprite *d2ui.Sprite, elapsed float64) { +func advanceSprite(v *SelectHeroClass, sprite *d2ui.Sprite, elapsed float64) { if sprite != nil { if err := sprite.Advance(elapsed); err != nil { - fmt.Printf("could not advance the sprite\n") + v.logger.Error("could not advance the sprite:" + err.Error()) } } } @@ -757,7 +763,7 @@ func (v *SelectHeroClass) loadSprite(animationPath string, position image.Point, sprite, err := v.uiManager.NewSprite(animationPath, d2resource.PaletteFechar) if err != nil { - fmt.Printf("could not load sprite for the animation: %s\n", animationPath) + v.logger.Error("could not load sprite for the animation: %s\n" + animationPath + "with error: " + err.Error()) return nil } @@ -780,7 +786,7 @@ func (v *SelectHeroClass) loadSprite(animationPath string, position image.Point, func (v *SelectHeroClass) loadSoundEffect(sfx string) d2interface.SoundEffect { result, err := v.audioProvider.LoadSound(sfx, false, false) if err != nil { - log.Print(err) + v.logger.Error(err.Error()) return nil } diff --git a/d2game/d2player/escape_menu.go b/d2game/d2player/escape_menu.go index f086f236..2b9f46bb 100644 --- a/d2game/d2player/escape_menu.go +++ b/d2game/d2player/escape_menu.go @@ -2,12 +2,12 @@ package d2player import ( "fmt" - "log" "time" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2ui" @@ -62,6 +62,42 @@ const ( singleFrame = time.Millisecond * 16 ) +// NewEscapeMenu creates a new escape menu +func NewEscapeMenu(navigator d2interface.Navigator, + renderer d2interface.Renderer, + audioProvider d2interface.AudioProvider, + uiManager *d2ui.UIManager, + guiManager *d2gui.GuiManager, + assetManager *d2asset.AssetManager, + l d2util.LogLevel, + keyMap *KeyMap, +) *EscapeMenu { + m := &EscapeMenu{ + audioProvider: audioProvider, + renderer: renderer, + navigator: navigator, + guiManager: guiManager, + assetManager: assetManager, + keyMap: keyMap, + } + + keyBindingMenu := NewKeyBindingMenu(assetManager, renderer, uiManager, guiManager, keyMap, l, m) + m.keyBindingMenu = keyBindingMenu + + m.layouts = make(map[layoutID]*layout) + m.layouts[mainLayoutID] = m.newMainLayout() + m.layouts[optionsLayoutID] = m.newOptionsLayout() + m.layouts[soundOptionsLayoutID] = m.newSoundOptionsLayout() + m.layouts[videoOptionsLayoutID] = m.newVideoOptionsLayout() + m.layouts[automapOptionsLayoutID] = m.newAutomapOptionsLayout() + + m.logger = d2util.NewLogger() + m.logger.SetLevel(l) + m.logger.SetPrefix(logPrefix) + + return m +} + // EscapeMenu represents the in-game menu that shows up when the esc key is pressed type EscapeMenu struct { isOpen bool @@ -82,6 +118,8 @@ type EscapeMenu struct { keyBindingMenu *KeyBindingMenu onCloseCb func() + + logger *d2util.Logger } type layout struct { @@ -116,6 +154,7 @@ type enumLabel struct { current int playSound func() updateValue func(optID optionID, value string) + *EscapeMenu } func (l *enumLabel) Trigger() { @@ -125,7 +164,7 @@ func (l *enumLabel) Trigger() { currentValue := l.values[l.current] if err := l.textChangingLabel.SetText(currentValue); err != nil { - fmt.Printf("could not change the label text to: %s\n", currentValue) + l.EscapeMenu.logger.Error(fmt.Sprintf("could not change the label text to: %s\n", currentValue)) } l.updateValue(l.optionID, currentValue) @@ -136,37 +175,6 @@ type actionableElement interface { Trigger() } -// NewEscapeMenu creates a new escape menu -func NewEscapeMenu(navigator d2interface.Navigator, - renderer d2interface.Renderer, - audioProvider d2interface.AudioProvider, - uiManager *d2ui.UIManager, - guiManager *d2gui.GuiManager, - assetManager *d2asset.AssetManager, - keyMap *KeyMap, -) *EscapeMenu { - m := &EscapeMenu{ - audioProvider: audioProvider, - renderer: renderer, - navigator: navigator, - guiManager: guiManager, - assetManager: assetManager, - keyMap: keyMap, - } - - keyBindingMenu := NewKeyBindingMenu(assetManager, renderer, uiManager, guiManager, keyMap, m) - m.keyBindingMenu = keyBindingMenu - - m.layouts = make(map[layoutID]*layout) - m.layouts[mainLayoutID] = m.newMainLayout() - m.layouts[optionsLayoutID] = m.newOptionsLayout() - m.layouts[soundOptionsLayoutID] = m.newSoundOptionsLayout() - m.layouts[videoOptionsLayoutID] = m.newVideoOptionsLayout() - m.layouts[automapOptionsLayoutID] = m.newAutomapOptionsLayout() - - return m -} - func (m *EscapeMenu) newMainLayout() *layout { return m.wrapLayout(func(l *layout) { m.addBigSelectionLabel(l, "OPTIONS", optionsLayoutID) @@ -243,7 +251,7 @@ func (m *EscapeMenu) wrapLayout(fn func(*layout)) *layout { leftPent, err := left.AddAnimatedSprite(d2resource.PentSpin, d2resource.PaletteUnits, d2gui.DirectionBackward) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) return nil } @@ -263,7 +271,7 @@ func (m *EscapeMenu) wrapLayout(fn func(*layout)) *layout { rightPent, err := right.AddAnimatedSprite(d2resource.PentSpin, d2resource.PaletteUnits, d2gui.DirectionForward) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) return nil } @@ -282,7 +290,7 @@ func (m *EscapeMenu) wrapLayout(fn func(*layout)) *layout { func (m *EscapeMenu) addTitle(l *layout, text string) { _, err := l.AddLabel(text, d2gui.FontStyle42Units) if err != nil { - fmt.Printf("could not add label: %s to the escape menu\n", text) + m.logger.Error("could not add label: %s to the escape menu\n" + text) } l.AddSpacerStatic(spacerWidth, labelGutter) @@ -291,7 +299,7 @@ func (m *EscapeMenu) addTitle(l *layout, text string) { func (m *EscapeMenu) addBigSelectionLabel(l *layout, text string, targetLayout layoutID) { guiLabel, err := l.AddLabel(text, d2gui.FontStyle42Units) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) } label := &showLayoutLabel{Label: guiLabel, target: targetLayout, showLayout: m.showLayout} @@ -314,7 +322,7 @@ func (m *EscapeMenu) addPreviousMenuLabel(l *layout) { guiLabel, err := l.AddLabel("PREVIOUS MENU", d2gui.FontStyle30Units) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) } label := &showLayoutLabel{Label: guiLabel, target: optionsLayoutID, showLayout: m.showLayout} @@ -338,7 +346,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values _, err := layout.AddLabel(text, d2gui.FontStyle30Units) if err != nil { - fmt.Printf("could not add label: %s to the escape menu\n", text) + m.logger.Error("could not add label: %s to the escape menu\n" + text) } elID := len(l.actionableElements) @@ -351,7 +359,7 @@ func (m *EscapeMenu) addEnumLabel(l *layout, optID optionID, text string, values guiLabel, err := layout.AddLabel(values[0], d2gui.FontStyle30Units) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) } label := &enumLabel{ @@ -378,14 +386,14 @@ func (m *EscapeMenu) OnLoad() { err = m.keyBindingMenu.Load() if err != nil { - log.Printf("unable to load the configure controls window: %v", err) + m.logger.Error("unable to load the configure controls window: %v" + err.Error()) } m.layouts[configureControlsLayoutID] = m.newConfigureControlsLayout(m.keyBindingMenu) m.selectSound, err = m.audioProvider.LoadSound(d2resource.SFXCursorSelect, false, false) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) } } @@ -403,7 +411,7 @@ func (m *EscapeMenu) OnEscKey() { m.setLayout(optionsLayoutID) if err := m.keyBindingMenu.Close(); err != nil { - log.Printf("unable to close the configure controls menu: %v", err) + m.logger.Error("unable to close the configure controls menu: %v" + err.Error()) } return @@ -451,7 +459,7 @@ func (m *EscapeMenu) showLayout(id layoutID) { if id == configureControlsLayoutID { m.keyBindingMenu.Open() } else if err := m.keyBindingMenu.Close(); err != nil { - fmt.Printf("unable to close the configure controls menu: %v", err) + m.logger.Error("unable to close the configure controls menu: %v" + err.Error()) } } @@ -467,7 +475,7 @@ func (m *EscapeMenu) onHoverElement(id int) { } func (m *EscapeMenu) onUpdateValue(optID optionID, value string) { - fmt.Printf("updating value %d with %s\n", optID, value) + m.logger.Info(fmt.Sprintf("updating value %d with %s\n", optID, value)) } func (m *EscapeMenu) setLayout(id layoutID) { @@ -574,7 +582,7 @@ func (m *EscapeMenu) OnMouseButtonDown(event d2interface.MouseEvent) bool { if m.currentLayout == configureControlsLayoutID { if err := m.keyBindingMenu.onMouseButtonDown(event); err != nil { - log.Printf("unable to handle mouse down on configure controls menu: %v", err) + m.logger.Error("unable to handle mouse down on configure controls menu: %v" + err.Error()) } } @@ -611,7 +619,7 @@ func (m *EscapeMenu) OnMouseMove(event d2interface.MouseMoveEvent) bool { func (m *EscapeMenu) OnKeyDown(event d2interface.KeyEvent) bool { if m.keyBindingMenu.IsOpen() { if err := m.keyBindingMenu.OnKeyDown(event); err != nil { - log.Printf("unable to handle key down on configure controls menu: %v", err) + m.logger.Error("unable to handle key down on configure controls menu: %v" + err.Error()) } return false diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index 532cab25..e87c5d00 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -2,7 +2,6 @@ package d2player import ( "fmt" - "log" "strings" "time" @@ -22,6 +21,10 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" ) +const ( + logPrefix = "Player" +) + // Panel represents the panel at the bottom of the game screen type Panel interface { IsOpen() bool @@ -109,50 +112,6 @@ const ( menuRightRectH = 400, 0, 400, 600 ) -// GameControls represents the game's controls on the screen -type GameControls struct { - keyMap *KeyMap - actionableRegions []actionableRegion - asset *d2asset.AssetManager - renderer d2interface.Renderer // https://github.com/OpenDiablo2/OpenDiablo2/issues/798 - inputListener inputCallbackListener - hero *d2mapentity.Player - heroState *d2hero.HeroStateFactory - mapRenderer *d2maprenderer.MapRenderer - escapeMenu *EscapeMenu - ui *d2ui.UIManager - inventory *Inventory - hud *HUD - skilltree *skillTree - heroStatsPanel *HeroStatsPanel - HelpOverlay *HelpOverlay - bottomMenuRect *d2geom.Rectangle - leftMenuRect *d2geom.Rectangle - rightMenuRect *d2geom.Rectangle - lastMouseX int - lastMouseY int - lastLeftBtnActionTime float64 - lastRightBtnActionTime float64 - FreeCam bool - isSinglePlayer bool -} - -type actionableType int - -type actionableRegion struct { - actionableTypeID actionableType - rect d2geom.Rectangle -} - -// SkillResource represents a Skill with its corresponding icon sprite, path to DC6 file and icon number. -// SkillResourcePath points to a DC6 resource which contains the icons of multiple skills as frames. -// The IconNumber is the frame at which we can find our skill sprite in the DC6 file. -type SkillResource struct { - SkillResourcePath string // path to a skills DC6 file(see getSkillResourceByClass) - IconNumber int // the index of the frame in the DC6 file - SkillIcon *d2ui.Sprite -} - // NewGameControls creates a GameControls instance and returns a pointer to it // nolint:funlen // doesn't make sense to split this up func NewGameControls( @@ -167,6 +126,7 @@ func NewGameControls( ui *d2ui.UIManager, guiManager *d2gui.GuiManager, keyMap *KeyMap, + l d2util.LogLevel, isSinglePlayer bool, ) (*GameControls, error) { var inventoryRecordKey string @@ -248,19 +208,19 @@ func NewGameControls( } inventoryRecord := asset.Records.Layout.Inventory[inventoryRecordKey] - heroStatsPanel := NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats) - inventory := NewInventory(asset, ui, inventoryRecord) - skilltree := newSkillTree(hero.Skills, hero.Class, asset, ui) + heroStatsPanel := NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, l, hero.Stats) + inventory := NewInventory(asset, ui, l, inventoryRecord) + skilltree := newSkillTree(hero.Skills, hero.Class, asset, l, ui) - miniPanel := newMiniPanel(asset, ui, isSinglePlayer) + miniPanel := newMiniPanel(asset, ui, l, isSinglePlayer) heroState, err := d2hero.NewHeroStateFactory(asset) if err != nil { return nil, err } - helpOverlay := NewHelpOverlay(asset, renderer, ui, guiManager, keyMap) - hud := NewHUD(asset, ui, hero, helpOverlay, miniPanel, actionableRegions, mapEngine, mapRenderer) + helpOverlay := NewHelpOverlay(asset, renderer, ui, guiManager, l, keyMap) + hud := NewHUD(asset, ui, hero, helpOverlay, miniPanel, actionableRegions, mapEngine, l, mapRenderer) const blackAlpha50percent = 0x0000007f @@ -317,9 +277,59 @@ func NewGameControls( return nil, err } + gc.logger = d2util.NewLogger() + gc.logger.SetLevel(l) + gc.logger.SetPrefix(logPrefix) + return gc, nil } +// GameControls represents the game's controls on the screen +type GameControls struct { + keyMap *KeyMap + actionableRegions []actionableRegion + asset *d2asset.AssetManager + renderer d2interface.Renderer // https://github.com/OpenDiablo2/OpenDiablo2/issues/798 + inputListener inputCallbackListener + hero *d2mapentity.Player + heroState *d2hero.HeroStateFactory + mapRenderer *d2maprenderer.MapRenderer + escapeMenu *EscapeMenu + ui *d2ui.UIManager + inventory *Inventory + hud *HUD + skilltree *skillTree + heroStatsPanel *HeroStatsPanel + HelpOverlay *HelpOverlay + bottomMenuRect *d2geom.Rectangle + leftMenuRect *d2geom.Rectangle + rightMenuRect *d2geom.Rectangle + lastMouseX int + lastMouseY int + lastLeftBtnActionTime float64 + lastRightBtnActionTime float64 + FreeCam bool + isSinglePlayer bool + + logger *d2util.Logger +} + +type actionableType int + +type actionableRegion struct { + actionableTypeID actionableType + rect d2geom.Rectangle +} + +// SkillResource represents a Skill with its corresponding icon sprite, path to DC6 file and icon number. +// SkillResourcePath points to a DC6 resource which contains the icons of multiple skills as frames. +// The IconNumber is the frame at which we can find our skill sprite in the DC6 file. +type SkillResource struct { + SkillResourcePath string // path to a skills DC6 file(see getSkillResourceByClass) + IconNumber int // the index of the frame in the DC6 file + SkillIcon *d2ui.Sprite +} + // OnKeyRepeat is called to handle repeated key presses func (g *GameControls) OnKeyRepeat(event d2interface.KeyEvent) bool { if g.FreeCam { @@ -800,7 +810,7 @@ func (g *GameControls) onHoverActionable(item actionableType) { onHover, found := hoverMap[item] if !found { - log.Printf("Unrecognized actionableType(%d) being hovered\n", item) + g.logger.Error(fmt.Sprintf("Unrecognized actionableType(%d) being hovered\n", item)) return } @@ -815,23 +825,23 @@ func (g *GameControls) onClickActionable(item actionableType) { }, newStats: func() { - log.Println("New Stats Selector Action Pressed") + g.logger.Info("New Stats Selector Action Pressed") }, xp: func() { - log.Println("XP Action Pressed") + g.logger.Info("XP Action Pressed") }, walkRun: func() { - log.Println("Walk/Run Action Pressed") + g.logger.Info("Walk/Run Action Pressed") }, stamina: func() { - log.Println("Stamina Action Pressed") + g.logger.Info("Stamina Action Pressed") }, newSkills: func() { - log.Println("New Skills Selector Action Pressed") + g.logger.Info("New Skills Selector Action Pressed") }, rightSkill: func() { @@ -840,18 +850,19 @@ func (g *GameControls) onClickActionable(item actionableType) { hpGlobe: func() { g.ToggleHpStats() - log.Println("HP Globe Pressed") + g.logger.Info("HP Globe Pressed") }, manaGlobe: func() { g.ToggleManaStats() - log.Println("Mana Globe Pressed") + g.logger.Info("Mana Globe Pressed") }, } action, found := actionMap[item] if !found { - log.Printf("Unrecognized actionableType(%d) being clicked\n", item) + // Warning, because some action types are still todo, and could return this error + g.logger.Warning(fmt.Sprintf("Unrecognized actionableType(%d) being clicked\n", item)) return } @@ -961,7 +972,7 @@ func (g *GameControls) bindLearnSkillsCommand(term d2interface.Terminal) error { } g.hud.skillSelectMenu.RegenerateImageCache() - log.Printf("Learned %d skills", learnedSkillsCount) + g.logger.Info(fmt.Sprintf("Learned %d skills", learnedSkillsCount)) if err != nil { term.OutputErrorf("cannot learn skill for class, error: %s", err) @@ -998,7 +1009,7 @@ func (g *GameControls) bindLearnSkillByIDCommand(term d2interface.Terminal) erro } g.hud.skillSelectMenu.RegenerateImageCache() - log.Println("Learned skill: ", skill.Skill) + g.logger.Info("Learned skill: " + skill.Skill) } return term.BindAction( diff --git a/d2game/d2player/globeWidget.go b/d2game/d2player/globeWidget.go index 16d31293..6074fa72 100644 --- a/d2game/d2player/globeWidget.go +++ b/d2game/d2player/globeWidget.go @@ -2,10 +2,10 @@ package d2player import ( "image" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" ) @@ -40,11 +40,12 @@ type globeFrame struct { offsetX int offsetY int idx int + gw *globeWidget } func (gf *globeFrame) setFrameIndex() { if err := gf.sprite.SetCurrentFrame(gf.idx); err != nil { - log.Print(err) + gf.gw.logger.Error(err.Error()) } } @@ -57,15 +58,7 @@ func (gf *globeFrame) getSize() (x, y int) { return w + gf.offsetX, h + gf.offsetY } -type globeWidget struct { - *d2ui.BaseWidget - value *int - valueMax *int - globe *globeFrame - overlap *globeFrame -} - -func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value, valueMax *int) *globeWidget { +func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value *int, l d2util.LogLevel, valueMax *int) *globeWidget { var globe, overlap *globeFrame base := d2ui.NewBaseWidget(ui) @@ -95,13 +88,28 @@ func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value, valueM } } - return &globeWidget{ + gw := &globeWidget{ BaseWidget: base, value: value, valueMax: valueMax, globe: globe, overlap: overlap, } + + gw.logger = d2util.NewLogger() + gw.logger.SetLevel(l) + gw.logger.SetPrefix(logPrefix) + + return gw +} + +type globeWidget struct { + *d2ui.BaseWidget + value *int + valueMax *int + globe *globeFrame + overlap *globeFrame + logger *d2util.Logger } func (g *globeWidget) load() { @@ -109,14 +117,14 @@ func (g *globeWidget) load() { g.globe.sprite, err = g.GetManager().NewSprite(d2resource.HealthManaIndicator, d2resource.PaletteSky) if err != nil { - log.Print(err) + g.logger.Error(err.Error()) } g.globe.setFrameIndex() g.overlap.sprite, err = g.GetManager().NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky) if err != nil { - log.Print(err) + g.logger.Error(err.Error()) } g.overlap.setFrameIndex() diff --git a/d2game/d2player/help_overlay.go b/d2game/d2player/help_overlay.go index 58f64cf0..a5dd77a3 100644 --- a/d2game/d2player/help_overlay.go +++ b/d2game/d2player/help_overlay.go @@ -3,12 +3,12 @@ package d2player import ( "fmt" "image/color" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -156,6 +156,30 @@ const ( beltDotY = 568 ) +// NewHelpOverlay creates a new HelpOverlay instance +func NewHelpOverlay( + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + ui *d2ui.UIManager, + guiManager *d2gui.GuiManager, + l d2util.LogLevel, + keyMap *KeyMap, +) *HelpOverlay { + h := &HelpOverlay{ + asset: asset, + renderer: renderer, + uiManager: ui, + guiManager: guiManager, + keyMap: keyMap, + } + + h.logger = d2util.NewLogger() + h.logger.SetLevel(l) + h.logger.SetPrefix(logPrefix) + + return h +} + // HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed type HelpOverlay struct { asset *d2asset.AssetManager @@ -169,30 +193,13 @@ type HelpOverlay struct { closeButton *d2ui.Button guiManager *d2gui.GuiManager keyMap *KeyMap -} -// NewHelpOverlay creates a new HelpOverlay instance -func NewHelpOverlay( - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - ui *d2ui.UIManager, - guiManager *d2gui.GuiManager, - keyMap *KeyMap, -) *HelpOverlay { - h := &HelpOverlay{ - asset: asset, - renderer: renderer, - uiManager: ui, - guiManager: guiManager, - keyMap: keyMap, - } - - return h + logger *d2util.Logger } // Toggle the visibility state of the overlay func (h *HelpOverlay) Toggle() { - fmt.Print("Help overlay toggled\n") + h.logger.Info("Help overlay toggled") if h.isOpen { h.Close() @@ -265,12 +272,12 @@ func (h *HelpOverlay) setupOverlayFrame() { for _, frameIndex := range frames { f, err := h.uiManager.NewSprite(d2resource.HelpBorder, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } err = f.SetCurrentFrame(frameIndex) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } frameWidth, frameHeight := f.GetCurrentFrameSize() @@ -559,12 +566,12 @@ func (h *HelpOverlay) createBullet(c callout) { newDot, err := h.uiManager.NewSprite(d2resource.HelpYellowBullet, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } err = newDot.SetCurrentFrame(0) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } newDot.SetPosition(c.DotX, c.DotY+bulletOffsetY) @@ -601,12 +608,12 @@ func (h *HelpOverlay) createCallout(c callout) { newDot, err := h.uiManager.NewSprite(d2resource.HelpWhiteBullet, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } err = newDot.SetCurrentFrame(0) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } newDot.SetPosition(c.DotX, c.DotY) diff --git a/d2game/d2player/hero_stats_panel.go b/d2game/d2player/hero_stats_panel.go index c5bcf3a7..11240d8a 100644 --- a/d2game/d2player/hero_stats_panel.go +++ b/d2game/d2player/hero_stats_panel.go @@ -1,12 +1,12 @@ package d2player import ( - "log" "strconv" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2hero" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -82,6 +82,34 @@ type StatsPanelLabels struct { Stamina *d2ui.Label } +// NewHeroStatsPanel creates a new hero status panel +func NewHeroStatsPanel(asset *d2asset.AssetManager, + ui *d2ui.UIManager, + heroName string, + heroClass d2enum.Hero, + l d2util.LogLevel, + heroState *d2hero.HeroStatsState) *HeroStatsPanel { + originX := 0 + originY := 0 + + hsp := &HeroStatsPanel{ + asset: asset, + uiManager: ui, + originX: originX, + originY: originY, + heroState: heroState, + heroName: heroName, + heroClass: heroClass, + labels: &StatsPanelLabels{}, + } + + hsp.logger = d2util.NewLogger() + hsp.logger.SetLevel(l) + hsp.logger.SetPrefix(logPrefix) + + return hsp +} + // HeroStatsPanel represents the hero status panel type HeroStatsPanel struct { asset *d2asset.AssetManager @@ -97,24 +125,8 @@ type HeroStatsPanel struct { originX int originY int isOpen bool -} -// NewHeroStatsPanel creates a new hero status panel -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, - originX: originX, - originY: originY, - heroState: heroState, - heroName: heroName, - heroClass: heroClass, - labels: &StatsPanelLabels{}, - } + logger *d2util.Logger } // Load the data for the hero status panel @@ -128,7 +140,7 @@ func (s *HeroStatsPanel) Load() { s.panel, err = s.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky) if err != nil { - log.Print(err) + s.logger.Error(err.Error()) } w, h := frame.GetSize() @@ -204,7 +216,7 @@ func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) { for _, frameIndex := range frames { if err := s.panel.SetCurrentFrame(frameIndex); err != nil { - log.Printf("%e", err) + s.logger.Error(err.Error()) } w, h := s.panel.GetCurrentFrameSize() diff --git a/d2game/d2player/hud.go b/d2game/d2player/hud.go index b09393f4..5244e393 100644 --- a/d2game/d2player/hud.go +++ b/d2game/d2player/hud.go @@ -2,7 +2,6 @@ package d2player import ( "fmt" - "log" "math" "strings" @@ -116,6 +115,7 @@ type HUD struct { widgetLeftSkill *d2ui.CustomWidget widgetRightSkill *d2ui.CustomWidget panelBackground *d2ui.CustomWidget + logger *d2util.Logger } // NewHUD creates a HUD object @@ -127,6 +127,7 @@ func NewHUD( miniPanel *miniPanel, actionableRegions []actionableRegion, mapEngine *d2mapengine.MapEngine, + l d2util.LogLevel, mapRenderer *d2maprenderer.MapRenderer, ) *HUD { nameLabel := ui.NewLabel(d2resource.Font16, d2resource.PaletteStatic) @@ -136,10 +137,10 @@ func NewHUD( zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits) zoneLabel.Alignment = d2ui.HorizontalAlignCenter - healthGlobe := newGlobeWidget(ui, 0, screenHeight, typeHealthGlobe, &hero.Stats.Health, &hero.Stats.MaxHealth) - manaGlobe := newGlobeWidget(ui, screenWidth-manaGlobeScreenOffsetX, screenHeight, typeManaGlobe, &hero.Stats.Mana, &hero.Stats.MaxMana) + healthGlobe := newGlobeWidget(ui, 0, screenHeight, typeHealthGlobe, &hero.Stats.Health, l, &hero.Stats.MaxHealth) + manaGlobe := newGlobeWidget(ui, screenWidth-manaGlobeScreenOffsetX, screenHeight, typeManaGlobe, &hero.Stats.Mana, l, &hero.Stats.MaxMana) - return &HUD{ + hud := &HUD{ asset: asset, uiManager: ui, hero: hero, @@ -149,11 +150,17 @@ func NewHUD( miniPanel: miniPanel, actionableRegions: actionableRegions, nameLabel: nameLabel, - skillSelectMenu: NewSkillSelectMenu(asset, ui, hero), + skillSelectMenu: NewSkillSelectMenu(asset, ui, l, hero), zoneChangeText: zoneLabel, healthGlobe: healthGlobe, manaGlobe: manaGlobe, } + + hud.logger = d2util.NewLogger() + hud.logger.SetPrefix(logPrefix) + hud.logger.SetLevel(l) + + return hud } // Load creates the ui elemets @@ -173,7 +180,7 @@ func (h *HUD) loadCustomWidgets() { // static background _, height, err := h.mainPanel.GetFrameSize(0) // health globe is the frame with max height if err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -210,7 +217,7 @@ func (h *HUD) loadSkillResources() { // https://github.com/OpenDiablo2/OpenDiablo2/issues/799 genericSkillsSprite, err := h.uiManager.NewSprite(d2resource.GenericSkills, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } attackIconID := 2 @@ -233,17 +240,17 @@ func (h *HUD) loadSprites() { h.globeSprite, err = h.uiManager.NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } h.hpManaStatusSprite, err = h.uiManager.NewSprite(d2resource.HealthManaIndicator, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } h.mainPanel, err = h.uiManager.NewSprite(d2resource.GamePanels, d2resource.PaletteSky) if err != nil { - log.Print(err) + h.logger.Error(err.Error()) } } @@ -348,7 +355,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { // Main panel background if err := h.renderPanel(offsetX, offsetY, target); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -357,7 +364,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { offsetX += w + skillIconWidth if err := h.renderNewStatsButton(offsetX, offsetY, target); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -366,7 +373,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { offsetX += w if err := h.renderStamina(offsetX, offsetY, target); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -375,7 +382,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { offsetX += w if err := h.renderPotions(offsetX, offsetY, target); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -384,7 +391,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { offsetX += w if err := h.renderNewSkillsButton(offsetX, offsetY, target); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -393,7 +400,7 @@ func (h *HUD) renderPanelStatic(target d2interface.Surface) { offsetX += w + skillIconWidth if err := h.mainPanel.SetCurrentFrame(frameRightGlobeHolder); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -420,7 +427,7 @@ func (h *HUD) renderLeftSkill(x, y int, target d2interface.Surface) { } if err := h.leftSkillResource.SkillIcon.SetCurrentFrame(h.hero.LeftSkill.IconCel); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -438,7 +445,7 @@ func (h *HUD) renderRightSkill(x, _ int, target d2interface.Surface) { } if err := h.rightSkillResource.SkillIcon.SetCurrentFrame(h.hero.RightSkill.IconCel); err != nil { - log.Print(err) + h.logger.Error(err.Error()) return } @@ -704,7 +711,7 @@ func (h *HUD) getSkillResourceByClass(class string) string { entry, found := resourceMap[class] if !found { - log.Fatalf("Unknown class token: '%s'", class) + h.logger.Error("Unknown class token: '%s'" + class) } return entry diff --git a/d2game/d2player/inventory.go b/d2game/d2player/inventory.go index 3d8bc062..bc083f5a 100644 --- a/d2game/d2player/inventory.go +++ b/d2game/d2player/inventory.go @@ -1,14 +1,12 @@ package d2player import ( - "fmt" - "log" - "github.com/OpenDiablo2/OpenDiablo2/d2core/d2records" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2item/diablo2item" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -25,6 +23,34 @@ const ( invCloseButtonX, invCloseButtonY = 419, 449 ) +// NewInventory creates an inventory instance and returns a pointer to it +func NewInventory(asset *d2asset.AssetManager, + ui *d2ui.UIManager, + l d2util.LogLevel, + record *d2records.InventoryRecord) *Inventory { + itemTooltip := ui.NewTooltip(d2resource.FontFormal11, d2resource.PaletteStatic, d2ui.TooltipXCenter, d2ui.TooltipYBottom) + + // https://github.com/OpenDiablo2/OpenDiablo2/issues/797 + itemFactory, _ := diablo2item.NewItemFactory(asset) + + inventory := &Inventory{ + asset: asset, + uiManager: ui, + item: itemFactory, + grid: NewItemGrid(asset, ui, l, record), + originX: record.Panel.Left, + itemTooltip: itemTooltip, + // originY: record.Panel.Top, + originY: 0, // expansion data has these all offset by +60 ... + } + + inventory.logger = d2util.NewLogger() + inventory.logger.SetLevel(l) + inventory.logger.SetPrefix(logPrefix) + + return inventory +} + // Inventory represents the inventory type Inventory struct { asset *d2asset.AssetManager @@ -44,26 +70,8 @@ type Inventory struct { hovering bool isOpen bool onCloseCb func() -} -// NewInventory creates an inventory instance and returns a pointer to it -func NewInventory(asset *d2asset.AssetManager, ui *d2ui.UIManager, - record *d2records.InventoryRecord) *Inventory { - itemTooltip := ui.NewTooltip(d2resource.FontFormal11, d2resource.PaletteStatic, d2ui.TooltipXCenter, d2ui.TooltipYBottom) - - // https://github.com/OpenDiablo2/OpenDiablo2/issues/797 - itemFactory, _ := diablo2item.NewItemFactory(asset) - - return &Inventory{ - asset: asset, - uiManager: ui, - item: itemFactory, - grid: NewItemGrid(asset, ui, record), - originX: record.Panel.Left, - itemTooltip: itemTooltip, - // originY: record.Panel.Top, - originY: 0, // expansion data has these all offset by +60 ... - } + logger *d2util.Logger } // IsOpen returns true if the inventory is open @@ -154,7 +162,7 @@ func (g *Inventory) Load() { _, err := g.grid.Add(inventoryItems...) if err != nil { - fmt.Printf("could not add items to the inventory, err: %v\n", err) + g.logger.Error("could not add items to the inventory, err: %v\n" + err.Error()) } } @@ -166,7 +174,7 @@ func (g *Inventory) Render(target d2interface.Surface) { err := g.renderFrame(target) if err != nil { - log.Println(err) + g.logger.Error(err.Error()) } g.grid.Render(target) diff --git a/d2game/d2player/inventory_grid.go b/d2game/d2player/inventory_grid.go index 2c30a648..7080ac35 100644 --- a/d2game/d2player/inventory_grid.go +++ b/d2game/d2player/inventory_grid.go @@ -3,7 +3,6 @@ package d2player import ( "errors" "fmt" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2records" @@ -14,6 +13,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" ) // images for 1x1 grid tile items (rings and stuff) are 28x28 pixel @@ -36,6 +36,32 @@ type InventoryItem interface { var errorInventoryFull = errors.New("inventory full") +// NewItemGrid creates a new ItemGrid instance +func NewItemGrid(asset *d2asset.AssetManager, + ui *d2ui.UIManager, + l d2util.LogLevel, + record *d2records.InventoryRecord) *ItemGrid { + grid := record.Grid + + itemGrid := &ItemGrid{ + asset: asset, + uiManager: ui, + width: grid.Box.Width, + height: grid.Box.Height, + originX: grid.Box.Left, + originY: grid.Box.Top + (grid.Rows * cellPadding), + slotSize: grid.CellWidth, + sprites: make(map[string]*d2ui.Sprite), + equipmentSlots: genEquipmentSlotsMap(record), + } + + itemGrid.logger = d2util.NewLogger() + itemGrid.logger.SetLevel(l) + itemGrid.logger.SetPrefix(logPrefix) + + return itemGrid +} + // ItemGrid is a reusable grid for use with player and merchant inventory. // Handles layout and rendering item icons based on code. type ItemGrid struct { @@ -49,24 +75,8 @@ type ItemGrid struct { originY int sprites map[string]*d2ui.Sprite slotSize int -} -// NewItemGrid creates a new ItemGrid instance -func NewItemGrid(asset *d2asset.AssetManager, ui *d2ui.UIManager, - record *d2records.InventoryRecord) *ItemGrid { - grid := record.Grid - - return &ItemGrid{ - asset: asset, - uiManager: ui, - width: grid.Box.Width, - height: grid.Box.Height, - originX: grid.Box.Left, - originY: grid.Box.Top + (grid.Rows * cellPadding), - slotSize: grid.CellWidth, - sprites: make(map[string]*d2ui.Sprite), - equipmentSlots: genEquipmentSlotsMap(record), - } + logger *d2util.Logger } // SlotToScreen translates slot coordinates to screen coordinates @@ -135,7 +145,7 @@ func (g *ItemGrid) loadItem(item InventoryItem) { itemSprite, err := g.uiManager.NewSprite(imgPath, d2resource.PaletteSky) if err != nil { - log.Printf("Failed to load sprite, error: " + err.Error()) + g.logger.Error("Failed to load sprite, error: " + err.Error()) } g.sprites[item.GetItemCode()] = itemSprite diff --git a/d2game/d2player/key_binding_menu.go b/d2game/d2player/key_binding_menu.go index 1dce1d42..6402fd94 100644 --- a/d2game/d2player/key_binding_menu.go +++ b/d2game/d2player/key_binding_menu.go @@ -2,7 +2,6 @@ package d2player import ( "image/color" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" @@ -44,6 +43,66 @@ type bindingChange struct { secondary d2enum.Key } +// NewKeyBindingMenu generates a new instance of the "Configure Keys" +// menu found in the options +func NewKeyBindingMenu( + asset *d2asset.AssetManager, + renderer d2interface.Renderer, + ui *d2ui.UIManager, + guiManager *d2gui.GuiManager, + keyMap *KeyMap, + l d2util.LogLevel, + escapeMenu *EscapeMenu, +) *KeyBindingMenu { + mainLayout := d2gui.CreateLayout(renderer, d2gui.PositionTypeAbsolute, asset) + contentLayout := mainLayout.AddLayout(d2gui.PositionTypeAbsolute) + + ret := &KeyBindingMenu{ + keyMap: keyMap, + asset: asset, + ui: ui, + guiManager: guiManager, + renderer: renderer, + mainLayout: mainLayout, + contentLayout: contentLayout, + bindingLayouts: []*bindingLayout{}, + changesToBeSaved: make(map[d2enum.GameEvent]*bindingChange), + escapeMenu: escapeMenu, + } + + ret.logger = d2util.NewLogger() + ret.logger.SetLevel(l) + ret.logger.SetPrefix(logPrefix) + + ret.Box = d2gui.NewBox( + asset, renderer, ui, ret.mainLayout, + keyBindingMenuWidth, keyBindingMenuHeight, + keyBindingMenuX, keyBindingMenuY, "", + ) + + ret.Box.SetPadding(keyBindingMenuPaddingX, keyBindingSettingPaddingY) + + ret.Box.SetOptions([]*d2gui.LabelButton{ + d2gui.NewLabelButton(0, 0, "Cancel", d2util.Color(d2gui.ColorRed), func() { + if err := ret.onCancelClicked(); err != nil { + ret.logger.Error("error while clicking option Cancel: %v" + err.Error()) + } + }), + d2gui.NewLabelButton(0, 0, "Default", d2util.Color(d2gui.ColorBlue), func() { + if err := ret.onDefaultClicked(); err != nil { + ret.logger.Error("error while clicking option Default: %v" + err.Error()) + } + }), + d2gui.NewLabelButton(0, 0, "Accept", d2util.Color(d2gui.ColorGreen), func() { + if err := ret.onAcceptClicked(); err != nil { + ret.logger.Error("error while clicking option Accept: %v" + err.Error()) + } + }), + }) + + return ret +} + // KeyBindingMenu represents the menu to view/edit the // key bindings type KeyBindingMenu struct { @@ -67,61 +126,8 @@ type KeyBindingMenu struct { currentBindingModifier d2enum.GameEvent currentBindingLayout *bindingLayout lastBindingLayout *bindingLayout -} -// NewKeyBindingMenu generates a new instance of the "Configure Keys" -// menu found in the options -func NewKeyBindingMenu( - asset *d2asset.AssetManager, - renderer d2interface.Renderer, - ui *d2ui.UIManager, - guiManager *d2gui.GuiManager, - keyMap *KeyMap, - escapeMenu *EscapeMenu, -) *KeyBindingMenu { - mainLayout := d2gui.CreateLayout(renderer, d2gui.PositionTypeAbsolute, asset) - contentLayout := mainLayout.AddLayout(d2gui.PositionTypeAbsolute) - - ret := &KeyBindingMenu{ - keyMap: keyMap, - asset: asset, - ui: ui, - guiManager: guiManager, - renderer: renderer, - mainLayout: mainLayout, - contentLayout: contentLayout, - bindingLayouts: []*bindingLayout{}, - changesToBeSaved: make(map[d2enum.GameEvent]*bindingChange), - escapeMenu: escapeMenu, - } - - ret.Box = d2gui.NewBox( - asset, renderer, ui, ret.mainLayout, - keyBindingMenuWidth, keyBindingMenuHeight, - keyBindingMenuX, keyBindingMenuY, "", - ) - - ret.Box.SetPadding(keyBindingMenuPaddingX, keyBindingSettingPaddingY) - - ret.Box.SetOptions([]*d2gui.LabelButton{ - d2gui.NewLabelButton(0, 0, "Cancel", d2util.Color(d2gui.ColorRed), func() { - if err := ret.onCancelClicked(); err != nil { - log.Printf("error while clicking option Cancel: %v", err) - } - }), - d2gui.NewLabelButton(0, 0, "Default", d2util.Color(d2gui.ColorBlue), func() { - if err := ret.onDefaultClicked(); err != nil { - log.Printf("error while clicking option Default: %v", err) - } - }), - d2gui.NewLabelButton(0, 0, "Accept", d2util.Color(d2gui.ColorGreen), func() { - if err := ret.onAcceptClicked(); err != nil { - log.Printf("error while clicking option Accept: %v", err) - } - }), - }) - - return ret + logger *d2util.Logger } // Close will disable the render of the menu and clear diff --git a/d2game/d2player/mini_panel.go b/d2game/d2player/mini_panel.go index a36150e7..01dffb23 100644 --- a/d2game/d2player/mini_panel.go +++ b/d2game/d2player/mini_panel.go @@ -1,9 +1,8 @@ package d2player import ( - "log" - "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" ) @@ -41,6 +40,24 @@ type miniPanelActions struct { menuToggle func() } +func newMiniPanel(asset *d2asset.AssetManager, + uiManager *d2ui.UIManager, + l d2util.LogLevel, + isSinglePlayer bool) *miniPanel { + mp := &miniPanel{ + ui: uiManager, + asset: asset, + isOpen: false, + isSinglePlayer: isSinglePlayer, + } + + mp.logger = d2util.NewLogger() + mp.logger.SetLevel(l) + mp.logger.SetPrefix(logPrefix) + + return mp +} + type miniPanel struct { ui *d2ui.UIManager asset *d2asset.AssetManager @@ -52,15 +69,8 @@ type miniPanel struct { movedRight bool panelGroup *d2ui.WidgetGroup tooltipGroup *d2ui.WidgetGroup -} -func newMiniPanel(asset *d2asset.AssetManager, uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel { - return &miniPanel{ - ui: uiManager, - asset: asset, - isOpen: false, - isSinglePlayer: isSinglePlayer, - } + logger *d2util.Logger } func (m *miniPanel) load(actions *miniPanelActions) { @@ -68,7 +78,7 @@ func (m *miniPanel) load(actions *miniPanelActions) { m.sprite, err = m.ui.NewSprite(d2resource.MinipanelButton, d2resource.PaletteSky) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) return } @@ -90,12 +100,12 @@ func (m *miniPanel) createWidgets(actions *miniPanelActions) { m.container, err = m.ui.NewSprite(miniPanelContainerPath, d2resource.PaletteSky) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) return } if err = m.container.SetCurrentFrame(0); err != nil { - log.Print(err) + m.logger.Error(err.Error()) return } @@ -106,7 +116,7 @@ func (m *miniPanel) createWidgets(actions *miniPanelActions) { buttonWidth, buttonHeight, err := m.sprite.GetFrameSize(0) if err != nil { - log.Print(err) + m.logger.Error(err.Error()) return } diff --git a/d2game/d2player/skill_select_menu.go b/d2game/d2player/skill_select_menu.go index 2c70c9bb..6ddb1360 100644 --- a/d2game/d2player/skill_select_menu.go +++ b/d2game/d2player/skill_select_menu.go @@ -2,6 +2,7 @@ package d2player import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -14,10 +15,10 @@ type SkillSelectMenu struct { } // NewSkillSelectMenu creates a skill select menu. -func NewSkillSelectMenu(asset *d2asset.AssetManager, ui *d2ui.UIManager, hero *d2mapentity.Player) *SkillSelectMenu { +func NewSkillSelectMenu(asset *d2asset.AssetManager, ui *d2ui.UIManager, l d2util.LogLevel, hero *d2mapentity.Player) *SkillSelectMenu { skillSelectMenu := &SkillSelectMenu{ - LeftPanel: NewHeroSkillsPanel(asset, ui, hero, true), - RightPanel: NewHeroSkillsPanel(asset, ui, hero, false), + LeftPanel: NewHeroSkillsPanel(asset, ui, hero, l, true), + RightPanel: NewHeroSkillsPanel(asset, ui, hero, l, false), } return skillSelectMenu diff --git a/d2game/d2player/skill_select_panel.go b/d2game/d2player/skill_select_panel.go index d5785c1e..aee05ca1 100644 --- a/d2game/d2player/skill_select_panel.go +++ b/d2game/d2player/skill_select_panel.go @@ -2,12 +2,12 @@ package d2player import ( "fmt" - "log" "sort" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom" "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/d2hero" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity" @@ -25,6 +25,40 @@ const ( skillListsLength = 5 // 0 to 4. 0 - General Skills, 1 to 3 - Class-specific skills(based on the 3 different skill trees), 4 - Other skills ) +// NewHeroSkillsPanel creates a new hero status panel +func NewHeroSkillsPanel(asset *d2asset.AssetManager, + ui *d2ui.UIManager, + hero *d2mapentity.Player, + l d2util.LogLevel, + isLeftPanel bool) *SkillPanel { + var activeSkill *d2hero.HeroSkill + if isLeftPanel { + activeSkill = hero.LeftSkill + } else { + activeSkill = hero.RightSkill + } + + hoverTooltip := ui.NewTooltip(d2resource.Font16, d2resource.PaletteStatic, d2ui.TooltipXLeft, d2ui.TooltipYTop) + + skillPanel := &SkillPanel{ + asset: asset, + activeSkill: activeSkill, + ui: ui, + isOpen: false, + ListRows: make([]*SkillListRow, skillListsLength), + renderer: ui.Renderer(), + isLeftPanel: isLeftPanel, + hero: hero, + hoverTooltip: hoverTooltip, + } + + skillPanel.logger = d2util.NewLogger() + skillPanel.logger.SetLevel(l) + skillPanel.logger.SetPrefix(logPrefix) + + return skillPanel +} + // SkillPanel represents a skill select menu popup that is displayed when the player left clicks on his active left/right skill. type SkillPanel struct { asset *d2asset.AssetManager @@ -38,30 +72,8 @@ type SkillPanel struct { isOpen bool regenerateImageCache bool isLeftPanel bool -} -// NewHeroSkillsPanel creates a new hero status panel -func NewHeroSkillsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, hero *d2mapentity.Player, isLeftPanel bool) *SkillPanel { - var activeSkill *d2hero.HeroSkill - if isLeftPanel { - activeSkill = hero.LeftSkill - } else { - activeSkill = hero.RightSkill - } - - hoverTooltip := ui.NewTooltip(d2resource.Font16, d2resource.PaletteStatic, d2ui.TooltipXLeft, d2ui.TooltipYTop) - - return &SkillPanel{ - asset: asset, - activeSkill: activeSkill, - ui: ui, - isOpen: false, - ListRows: make([]*SkillListRow, skillListsLength), - renderer: ui.Renderer(), - isLeftPanel: isLeftPanel, - hero: hero, - hoverTooltip: hoverTooltip, - } + logger *d2util.Logger } // Open opens the hero skills panel @@ -204,7 +216,7 @@ func (s *SkillPanel) generateSkillRowImageCache() error { cachedImage, err := s.createSkillListImage(skillListRow) if err != nil { - log.Println(err) + s.logger.Error(err.Error()) return err } @@ -231,7 +243,7 @@ func (s *SkillPanel) createSkillListImage(skillsListRow *SkillListRow) (d2interf if skillSprite.GetFrameCount() <= skill.IconCel { // happens for non-player skills, since they do not have an icon - log.Printf("Invalid IconCel(sprite frame index) [%d] - Skill name: %s, skipping.", skill.IconCel, skill.Name) + s.logger.Error(fmt.Sprintf("Invalid IconCel(sprite frame index) [%d] - Skill name: %s, skipping.", skill.IconCel, skill.Name)) continue } @@ -353,7 +365,7 @@ func (s *SkillPanel) getSkillResourceByClass(class string) string { case "dru": resource = d2resource.DruidSkills default: - log.Fatalf("Unknown class token: '%s'", class) + s.logger.Error(fmt.Sprintf("Unknown class token: '%s'", class)) } return resource diff --git a/d2game/d2player/skillicon.go b/d2game/d2player/skillicon.go index feb7a4c0..3a08b21b 100644 --- a/d2game/d2player/skillicon.go +++ b/d2game/d2player/skillicon.go @@ -1,11 +1,11 @@ package d2player import ( - "log" "strconv" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" ) @@ -20,14 +20,10 @@ const ( skillIconDistY = 68 ) -type skillIcon struct { - *d2ui.BaseWidget - lvlLabel *d2ui.Label - sprite *d2ui.Sprite - skill *d2hero.HeroSkill -} - -func newSkillIcon(ui *d2ui.UIManager, baseSprite *d2ui.Sprite, skill *d2hero.HeroSkill) *skillIcon { +func newSkillIcon(ui *d2ui.UIManager, + baseSprite *d2ui.Sprite, + l d2util.LogLevel, + skill *d2hero.HeroSkill) *skillIcon { base := d2ui.NewBaseWidget(ui) label := ui.NewLabel(d2resource.Font16, d2resource.PaletteSky) @@ -41,11 +37,24 @@ func newSkillIcon(ui *d2ui.UIManager, baseSprite *d2ui.Sprite, skill *d2hero.Her lvlLabel: label, } + res.logger = d2util.NewLogger() + res.logger.SetLevel(l) + res.logger.SetPrefix(logPrefix) + res.SetPosition(x, y) return res } +type skillIcon struct { + *d2ui.BaseWidget + lvlLabel *d2ui.Label + sprite *d2ui.Sprite + skill *d2hero.HeroSkill + + logger *d2util.Logger +} + func (si *skillIcon) SetVisible(visible bool) { si.BaseWidget.SetVisible(visible) si.lvlLabel.SetVisible(visible) @@ -55,7 +64,7 @@ func (si *skillIcon) renderSprite(target d2interface.Surface) { x, y := si.GetPosition() if err := si.sprite.SetCurrentFrame(si.skill.IconCel); err != nil { - log.Printf("Cannot set Frame %e", err) + si.logger.Error("Cannot set Frame %e" + err.Error()) return } diff --git a/d2game/d2player/skilltree.go b/d2game/d2player/skilltree.go index 58fd12bc..2c0a6562 100644 --- a/d2game/d2player/skilltree.go +++ b/d2game/d2player/skilltree.go @@ -1,12 +1,13 @@ package d2player import ( + "errors" "fmt" - "log" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "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/d2hero" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" @@ -83,6 +84,35 @@ type skillTreeHeroTypeResources struct { skillPanelPath string } +func newSkillTree( + skills map[int]*d2hero.HeroSkill, + heroClass d2enum.Hero, + asset *d2asset.AssetManager, + l d2util.LogLevel, + ui *d2ui.UIManager, +) *skillTree { + st := &skillTree{ + skills: skills, + heroClass: heroClass, + asset: asset, + uiManager: ui, + originX: skillTreePanelX, + originY: skillTreePanelY, + tab: [numTabs]*skillTreeTab{ + {}, + {}, + {}, + }, + l: l, + } + + st.logger = d2util.NewLogger() + st.logger.SetLevel(l) + st.logger.SetPrefix(logPrefix) + + return st +} + type skillTree struct { resources *skillTreeHeroTypeResources asset *d2asset.AssetManager @@ -102,29 +132,9 @@ type skillTree struct { panelGroup *d2ui.WidgetGroup iconGroup *d2ui.WidgetGroup panel *d2ui.CustomWidget -} -func newSkillTree( - skills map[int]*d2hero.HeroSkill, - heroClass d2enum.Hero, - asset *d2asset.AssetManager, - ui *d2ui.UIManager, -) *skillTree { - st := &skillTree{ - skills: skills, - heroClass: heroClass, - asset: asset, - uiManager: ui, - originX: skillTreePanelX, - originY: skillTreePanelY, - tab: [numTabs]*skillTreeTab{ - {}, - {}, - {}, - }, - } - - return st + logger *d2util.Logger + l d2util.LogLevel } func (s *skillTree) load() { @@ -142,11 +152,14 @@ func (s *skillTree) load() { s.closeButton.OnActivated(func() { s.Close() }) s.panelGroup.AddWidget(s.closeButton) - s.setHeroTypeResourcePath() + if err := s.setHeroTypeResourcePath(); err != nil { + s.logger.Error(err.Error()) + } + s.loadForHeroType() for _, skill := range s.skills { - si := newSkillIcon(s.uiManager, s.resources.skillSprite, skill) + si := newSkillIcon(s.uiManager, s.resources.skillSprite, s.l, skill) s.skillIcons = append(s.skillIcons, si) s.iconGroup.AddWidget(si) } @@ -159,14 +172,14 @@ func (s *skillTree) load() { func (s *skillTree) loadForHeroType() { sp, err := s.uiManager.NewSprite(s.resources.skillPanelPath, d2resource.PaletteSky) if err != nil { - log.Print(err) + s.logger.Error(err.Error()) } s.resources.skillPanel = sp si, err := s.uiManager.NewSprite(s.resources.skillIconPath, d2resource.PaletteSky) if err != nil { - log.Print(err) + s.logger.Error(err.Error()) } s.resources.skillSprite = si @@ -315,10 +328,11 @@ func (s *skillTree) getTab(class d2enum.Hero) *heroTabData { return tabMap[class] } -func (s *skillTree) setHeroTypeResourcePath() { +func (s *skillTree) setHeroTypeResourcePath() error { entry := s.getTab(s.heroClass) + if entry == nil { - log.Fatal("Unknown Hero Type") + return errors.New("unknown hero type") } s.resources = entry.resources @@ -329,11 +343,13 @@ func (s *skillTree) setHeroTypeResourcePath() { for i := 0; i < numTabs; i++ { s.tab[i].closeButtonPosX = entry.closeButtonPos[i] } + + return nil } // Toggle the skill tree visibility func (s *skillTree) Toggle() { - fmt.Println("SkillTree toggled") + s.logger.Info("SkillTree toggled") if s.isOpen { s.Close() @@ -385,7 +401,7 @@ func (s *skillTree) renderPanelSegment( target d2interface.Surface, frame int) { if err := s.resources.skillPanel.SetCurrentFrame(frame); err != nil { - log.Printf("%e", err) + s.logger.Error("%e" + err.Error()) return } @@ -399,7 +415,7 @@ func (s *skillTree) renderTabCommon(target d2interface.Surface) { // top w, h, err := skillPanel.GetFrameSize(frameCommonTabTopLeft) if err != nil { - log.Printf("%e", err) + s.logger.Error("%e" + err.Error()) return } @@ -414,7 +430,7 @@ func (s *skillTree) renderTabCommon(target d2interface.Surface) { // bottom _, h, err = skillPanel.GetFrameSize(frameCommonTabBottomLeft) if err != nil { - log.Printf("%e", err) + s.logger.Error("%e" + err.Error()) return } @@ -437,7 +453,7 @@ func (s *skillTree) renderTab(target d2interface.Surface, tab int) { // top _, h0, err := skillPanel.GetFrameSize(topFrame) if err != nil { - log.Printf("%e", err) + s.logger.Error("%e" + err.Error()) return } @@ -449,7 +465,7 @@ func (s *skillTree) renderTab(target d2interface.Surface, tab int) { // bottom w, h1, err := skillPanel.GetFrameSize(bottomFrame) if err != nil { - log.Printf("%e", err) + s.logger.Error("%e" + err.Error()) return }