From ae6bfb839e63ba49a1266ad36360ec4bf87459e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrkan=20Kaymak?= <7164005+gurkankaymak@users.noreply.github.com> Date: Wed, 1 Jul 2020 00:04:41 +0300 Subject: [PATCH] Lint fixes for the following packages (#505) * fixed lint issues of the package d2core/d2inventory * fixed lint issues of the d2script package * fixed lint issues of the d2common/d2interface package * fixed lint issues of the d2common/d2resource package * fixed lint issues of the d2core/d2term package * fixed conflict errors --- d2app/app.go | 10 +- d2common/d2interface/filter.go | 6 +- d2common/d2interface/render_type.go | 3 +- d2common/d2interface/renderer.go | 1 + d2common/d2interface/terminal.go | 9 +- d2common/d2resource/resource_paths.go | 11 +- d2core/d2asset/d2asset.go | 16 +- d2core/d2inventory/character_equipment.go | 1 + d2core/d2inventory/hero_objects.go | 2 + d2core/d2inventory/inventory_item.go | 1 + d2core/d2inventory/inventory_item_armor.go | 18 +- d2core/d2inventory/inventory_item_misc.go | 20 +- d2core/d2inventory/inventory_item_weapon.go | 22 +- d2core/d2term/d2term.go | 5 +- d2core/d2term/terminal.go | 240 +++++++++++--------- d2core/d2term/terminal_logger.go | 20 +- d2game/d2gamescreen/main_menu.go | 2 +- d2script/scriptengine.go | 24 +- 18 files changed, 251 insertions(+), 160 deletions(-) diff --git a/d2app/app.go b/d2app/app.go index 97878f54..82809997 100644 --- a/d2app/app.go +++ b/d2app/app.go @@ -472,7 +472,7 @@ func (p *App) dumpHeap() { func (p *App) toggleFullScreen() { fullscreen := !d2render.IsFullScreen() d2render.SetFullScreen(fullscreen) - p.terminal.OutputInfo("fullscreen is now: %v", fullscreen) + p.terminal.OutputInfof("fullscreen is now: %v", fullscreen) } func (p *App) captureFrame(path string) { @@ -494,19 +494,19 @@ func (p *App) stopAnimationCapture() { func (p *App) toggleVsync() { vsync := !d2render.GetVSyncEnabled() d2render.SetVSyncEnabled(vsync) - p.terminal.OutputInfo("vsync is now: %v", vsync) + p.terminal.OutputInfof("vsync is now: %v", vsync) } func (p *App) toggleFpsCounter() { p.showFPS = !p.showFPS - p.terminal.OutputInfo("fps counter is now: %v", p.showFPS) + p.terminal.OutputInfof("fps counter is now: %v", p.showFPS) } func (p *App) setTimeScale(timeScale float64) { if timeScale <= 0 { - p.terminal.OutputError("invalid time scale value") + p.terminal.OutputErrorf("invalid time scale value") } else { - p.terminal.OutputInfo("timescale changed from %f to %f", p.timeScale, timeScale) + p.terminal.OutputInfof("timescale changed from %f to %f", p.timeScale, timeScale) p.timeScale = timeScale } } diff --git a/d2common/d2interface/filter.go b/d2common/d2interface/filter.go index c8b40871..bb2467c4 100644 --- a/d2common/d2interface/filter.go +++ b/d2common/d2interface/filter.go @@ -5,11 +5,11 @@ type Filter int const ( // FilterDefault represents the default filter. - FilterDefault Filter = 0 + FilterDefault Filter = iota // FilterNearest represents nearest (crisp-edged) filter - FilterNearest = Filter(1) + FilterNearest // FilterLinear represents linear filter - FilterLinear = Filter(2) + FilterLinear ) diff --git a/d2common/d2interface/render_type.go b/d2common/d2interface/render_type.go index fad64f1a..acaf5796 100644 --- a/d2common/d2interface/render_type.go +++ b/d2common/d2interface/render_type.go @@ -1,8 +1,9 @@ package d2interface -// Defines the type of rendering engine to use +// RenderType defines the type of rendering engine to use type RenderType int const ( + // Ebiten is the render type of ebiten Ebiten = RenderType(1) ) diff --git a/d2common/d2interface/renderer.go b/d2common/d2interface/renderer.go index 0eae3ccd..e2f8391f 100644 --- a/d2common/d2interface/renderer.go +++ b/d2common/d2interface/renderer.go @@ -1,5 +1,6 @@ package d2interface +// Renderer interface defines the functionality of a renderer type Renderer interface { GetRendererName() string SetWindowIcon(fileName string) diff --git a/d2common/d2interface/terminal.go b/d2common/d2interface/terminal.go index 9f86a4bb..9f7a65d6 100644 --- a/d2common/d2interface/terminal.go +++ b/d2common/d2interface/terminal.go @@ -7,6 +7,7 @@ import ( // TermCategory applies styles to the lines in the Terminal type TermCategory int +// Terminal Category types const ( TermCategoryNone TermCategory = iota TermCategoryInfo @@ -26,10 +27,10 @@ type Terminal interface { Render(surface Surface) error Execute(command string) error OutputRaw(text string, category TermCategory) - Output(format string, params ...interface{}) - OutputInfo(format string, params ...interface{}) - OutputWarning(format string, params ...interface{}) - OutputError(format string, params ...interface{}) + Outputf(format string, params ...interface{}) + OutputInfof(format string, params ...interface{}) + OutputWarningf(format string, params ...interface{}) + OutputErrorf(format string, params ...interface{}) OutputClear() IsVisible() bool Hide() diff --git a/d2common/d2resource/resource_paths.go b/d2common/d2resource/resource_paths.go index c78e784f..a97b5676 100644 --- a/d2common/d2resource/resource_paths.go +++ b/d2common/d2resource/resource_paths.go @@ -1,7 +1,9 @@ +// Package d2resource stores the paths of the resources inside the mpq files. package d2resource var LanguageCode string +// Paths of the resources inside the mpq files. const ( // --- Screens --- @@ -11,7 +13,7 @@ const ( TrademarkScreen = "/data/global/ui/FrontEnd/trademarkscreenEXP.dc6" GameSelectScreen = "/data/global/ui/FrontEnd/gameselectscreenEXP.dc6" - TcpIpBackground = "/data/global/ui/FrontEnd/TCPIPscreen.dc6" + TCPIPBackground = "/data/global/ui/FrontEnd/TCPIPscreen.dc6" Diablo2LogoFireLeft = "/data/global/ui/FrontEnd/D2logoFireLeft.DC6" Diablo2LogoFireRight = "/data/global/ui/FrontEnd/D2logoFireRight.DC6" Diablo2LogoBlackLeft = "/data/global/ui/FrontEnd/D2logoBlackLeft.DC6" @@ -207,6 +209,7 @@ const ( MagicSuffix = "/data/global/excel/MagicSuffix.txt" // --- Monster Prefix/Suffixes (?) --- + RarePrefix = "/data/global/excel/RarePrefix.txt" RareSuffix = "/data/global/excel/RareSuffix.txt" UniquePrefix = "/data/global/excel/UniquePrefix.txt" @@ -278,9 +281,9 @@ const ( // --- Enemy Data --- - MonStats = "/data/global/excel/monstats.txt" - MonStats2 = "/data/global/excel/monstats2.txt" - MonPreset = "/data/global/excel/monpreset.txt" + MonStats = "/data/global/excel/monstats.txt" + MonStats2 = "/data/global/excel/monstats2.txt" + MonPreset = "/data/global/excel/monpreset.txt" SuperUniques = "/data/global/excel/SuperUniques.txt" // --- Skill Data --- diff --git a/d2core/d2asset/d2asset.go b/d2core/d2asset/d2asset.go index ebfebde7..bee0f4c7 100644 --- a/d2core/d2asset/d2asset.go +++ b/d2core/d2asset/d2asset.go @@ -38,9 +38,9 @@ func Initialize(term d2interface.Terminal) error { term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) { if verbose { - term.OutputInfo("asset manager verbose logging enabled") + term.OutputInfof("asset manager verbose logging enabled") } else { - term.OutputInfo("asset manager verbose logging disabled") + term.OutputInfof("asset manager verbose logging disabled") } archiveManager.cache.SetVerbose(verbose) @@ -51,12 +51,12 @@ func Initialize(term d2interface.Terminal) error { }) term.BindAction("assetstat", "display asset manager cache statistics", func() { - term.OutputInfo("archive cache: %f", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0) - term.OutputInfo("file cache: %f", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0) - term.OutputInfo("palette cache: %f", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0) - term.OutputInfo("palette transform cache: %f", float64(paletteTransformManager.cache.GetWeight())/float64(paletteTransformManager.cache.GetBudget())*100.0) - term.OutputInfo("animation cache: %f", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0) - term.OutputInfo("font cache: %f", float64(fontManager.cache.GetWeight())/float64(fontManager.cache.GetBudget())*100.0) + term.OutputInfof("archive cache: %f", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0) + term.OutputInfof("file cache: %f", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0) + term.OutputInfof("palette cache: %f", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0) + term.OutputInfof("palette transform cache: %f", float64(paletteTransformManager.cache.GetWeight())/float64(paletteTransformManager.cache.GetBudget())*100.0) + term.OutputInfof("animation cache: %f", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0) + term.OutputInfof("font cache: %f", float64(fontManager.cache.GetWeight())/float64(fontManager.cache.GetBudget())*100.0) }) term.BindAction("assetclear", "clear asset manager cache", func() { diff --git a/d2core/d2inventory/character_equipment.go b/d2core/d2inventory/character_equipment.go index e220be7f..bdb5e032 100644 --- a/d2core/d2inventory/character_equipment.go +++ b/d2core/d2inventory/character_equipment.go @@ -1,5 +1,6 @@ package d2inventory +// CharacterEquipment stores equipments of a character type CharacterEquipment struct { Head *InventoryItemArmor `json:"head"` // Head Torso *InventoryItemArmor `json:"torso"` // TR diff --git a/d2core/d2inventory/hero_objects.go b/d2core/d2inventory/hero_objects.go index 419574c2..e1b979ce 100644 --- a/d2core/d2inventory/hero_objects.go +++ b/d2core/d2inventory/hero_objects.go @@ -4,8 +4,10 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" ) +// HeroObjects map contains the hero type to CharacterEquipments var HeroObjects map[d2enum.Hero]CharacterEquipment +// LoadHeroObjects loads the equipment objects of the hero func LoadHeroObjects() { //Mode: d2enum.AnimationModePlayerNeutral.String(), //Base: "/data/global/chars", diff --git a/d2core/d2inventory/inventory_item.go b/d2core/d2inventory/inventory_item.go index a47a610c..e024539d 100644 --- a/d2core/d2inventory/inventory_item.go +++ b/d2core/d2inventory/inventory_item.go @@ -2,6 +2,7 @@ package d2inventory import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" +// InventoryItem defines the functionality of an inventory item type InventoryItem interface { // GetInventoryItemName returns the name of this inventory item GetInventoryItemName() string diff --git a/d2core/d2inventory/inventory_item_armor.go b/d2core/d2inventory/inventory_item_armor.go index 86bf7e6b..24011f15 100644 --- a/d2core/d2inventory/inventory_item_armor.go +++ b/d2core/d2inventory/inventory_item_armor.go @@ -7,6 +7,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" ) +// InventoryItemArmor stores the info of an armor item in the inventory type InventoryItemArmor struct { InventorySizeX int `json:"inventorySizeX"` InventorySizeY int `json:"inventorySizeY"` @@ -17,11 +18,13 @@ type InventoryItemArmor struct { ArmorClass string `json:"armorClass"` } +// GetArmorItemByCode returns the armor item for the given code func GetArmorItemByCode(code string) *InventoryItemArmor { result := d2datadict.Armors[code] if result == nil { log.Fatalf("Could not find armor entry for code '%s'", code) } + return &InventoryItemArmor{ InventorySizeX: result.InventoryWidth, InventorySizeY: result.InventoryHeight, @@ -31,13 +34,16 @@ func GetArmorItemByCode(code string) *InventoryItemArmor { } } +// GetArmorClass returns the class of the armor func (v *InventoryItemArmor) GetArmorClass() string { if v == nil || v.ItemCode == "" { return "lit" } + return v.ArmorClass } +// InventoryItemName returns the name of the armor func (v *InventoryItemArmor) InventoryItemName() string { if v == nil { return "" @@ -46,26 +52,32 @@ func (v *InventoryItemArmor) InventoryItemName() string { return v.ItemName } +// InventoryItemType returns the item type of the armor func (v *InventoryItemArmor) InventoryItemType() d2enum.InventoryItemType { return d2enum.InventoryItemTypeArmor } -func (v *InventoryItemArmor) InventoryGridSize() (int, int) { +// InventoryGridSize returns the grid size of the armor +func (v *InventoryItemArmor) InventoryGridSize() (sizeX, sizeY int) { return v.InventorySizeX, v.InventorySizeY } -func (v *InventoryItemArmor) InventoryGridSlot() (int, int) { +// InventoryGridSlot returns the grid slot coordinates of the armor +func (v *InventoryItemArmor) InventoryGridSlot() (slotX, slotY int) { return v.InventorySlotX, v.InventorySlotY } -func (v *InventoryItemArmor) SetInventoryGridSlot(x int, y int) { +// SetInventoryGridSlot sets the InventorySlotX and InventorySlotY of the armor with the given x and y values +func (v *InventoryItemArmor) SetInventoryGridSlot(x, y int) { v.InventorySlotX, v.InventorySlotY = x, y } +// Serialize returns the armor object as a byte array func (v *InventoryItemArmor) Serialize() []byte { return []byte{} } +// GetItemCode returns the item code of the armor func (v *InventoryItemArmor) GetItemCode() string { if v == nil { return "" diff --git a/d2core/d2inventory/inventory_item_misc.go b/d2core/d2inventory/inventory_item_misc.go index 107503b1..c8faba52 100644 --- a/d2core/d2inventory/inventory_item_misc.go +++ b/d2core/d2inventory/inventory_item_misc.go @@ -1,11 +1,13 @@ package d2inventory import ( + "log" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" - "log" ) +// InventoryItemMisc stores the info of an miscellaneous item in the inventory type InventoryItemMisc struct { InventorySizeX int `json:"inventorySizeX"` InventorySizeY int `json:"inventorySizeY"` @@ -15,11 +17,13 @@ type InventoryItemMisc struct { ItemCode string `json:"itemCode"` } +// GetMiscItemByCode returns the miscellaneous item for the given code func GetMiscItemByCode(code string) *InventoryItemMisc { result := d2datadict.MiscItems[code] if result == nil { log.Fatalf("Could not find misc item entry for code '%s'", code) } + return &InventoryItemMisc{ InventorySizeX: result.InventoryWidth, InventorySizeY: result.InventoryHeight, @@ -28,33 +32,41 @@ func GetMiscItemByCode(code string) *InventoryItemMisc { } } +// InventoryItemName returns the name of the miscellaneous item func (v *InventoryItemMisc) InventoryItemName() string { if v == nil { return "" } + return v.ItemName } +// InventoryItemType returns the item type of the miscellaneous item func (v *InventoryItemMisc) InventoryItemType() d2enum.InventoryItemType { return d2enum.InventoryItemTypeItem } -func (v *InventoryItemMisc) InventoryGridSize() (int, int) { +// InventoryGridSize returns the grid size of the miscellaneous item +func (v *InventoryItemMisc) InventoryGridSize() (sizeX, sizeY int) { return v.InventorySizeX, v.InventorySizeY } -func (v *InventoryItemMisc) InventoryGridSlot() (int, int) { +// InventoryGridSlot returns the grid slot coordinates of the miscellaneous item +func (v *InventoryItemMisc) InventoryGridSlot() (slotX, slotY int) { return v.InventorySlotX, v.InventorySlotY } -func (v *InventoryItemMisc) SetInventoryGridSlot(x int, y int) { +// SetInventoryGridSlot sets the InventorySlotX and InventorySlotY of the miscellaneous item with the given x and y values +func (v *InventoryItemMisc) SetInventoryGridSlot(x, y int) { v.InventorySlotX, v.InventorySlotY = x, y } +// Serialize returns the miscellaneous item object as a byte array func (v *InventoryItemMisc) Serialize() []byte { return []byte{} } +// GetItemCode returns the item code of the miscellaneous item func (v *InventoryItemMisc) GetItemCode() string { if v == nil { return "" diff --git a/d2core/d2inventory/inventory_item_weapon.go b/d2core/d2inventory/inventory_item_weapon.go index 95688d8b..b47ac887 100644 --- a/d2core/d2inventory/inventory_item_weapon.go +++ b/d2core/d2inventory/inventory_item_weapon.go @@ -7,6 +7,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" ) +// InventoryItemWeapon stores the info of an weapon item in the inventory type InventoryItemWeapon struct { InventorySizeX int `json:"inventorySizeX"` InventorySizeY int `json:"inventorySizeY"` @@ -18,12 +19,14 @@ type InventoryItemWeapon struct { WeaponClassOffHand string `json:"weaponClassOffHand"` } +// GetWeaponItemByCode returns the weapon item for the given code func GetWeaponItemByCode(code string) *InventoryItemWeapon { // TODO: Non-normal codes will fail here... result := d2datadict.Weapons[code] if result == nil { log.Fatalf("Could not find weapon entry for code '%s'", code) } + return &InventoryItemWeapon{ InventorySizeX: result.InventoryWidth, InventorySizeY: result.InventoryHeight, @@ -34,50 +37,63 @@ func GetWeaponItemByCode(code string) *InventoryItemWeapon { } } +// GetWeaponClass returns the class of the weapon func (v *InventoryItemWeapon) GetWeaponClass() string { if v == nil || v.ItemCode == "" { return "hth" } + return v.WeaponClass } +// GetWeaponClassOffHand returns the class of the off hand weapon func (v *InventoryItemWeapon) GetWeaponClassOffHand() string { if v == nil || v.ItemCode == "" { return "" } + return v.WeaponClassOffHand } +// InventoryItemName returns the name of the weapon func (v *InventoryItemWeapon) InventoryItemName() string { if v == nil { return "" } + return v.ItemName } +// InventoryItemType returns the item type of the weapon func (v *InventoryItemWeapon) InventoryItemType() d2enum.InventoryItemType { return d2enum.InventoryItemTypeWeapon } -func (v *InventoryItemWeapon) InventoryGridSize() (int, int) { +// InventoryGridSize returns the grid size of the weapon +func (v *InventoryItemWeapon) InventoryGridSize() (sizeX, sizeY int) { return v.InventorySizeX, v.InventorySizeY } -func (v *InventoryItemWeapon) InventoryGridSlot() (int, int) { +// InventoryGridSlot returns the grid slot coordinates of the weapon +func (v *InventoryItemWeapon) InventoryGridSlot() (slotX, slotY int) { return v.InventorySlotX, v.InventorySlotY } -func (v *InventoryItemWeapon) SetInventoryGridSlot(x int, y int) { +// SetInventoryGridSlot sets the InventorySlotX and InventorySlotY of the weapon with the given x and y values +func (v *InventoryItemWeapon) SetInventoryGridSlot(x, y int) { v.InventorySlotX, v.InventorySlotY = x, y } +// Serialize returns the weapon object as a byte array func (v *InventoryItemWeapon) Serialize() []byte { return []byte{} } +// GetItemCode returns the item code of the weapon func (v *InventoryItemWeapon) GetItemCode() string { if v == nil { return "" } + return v.ItemCode } diff --git a/d2core/d2term/d2term.go b/d2core/d2term/d2term.go index 7ae7e6f9..429445f3 100644 --- a/d2core/d2term/d2term.go +++ b/d2core/d2term/d2term.go @@ -1,11 +1,12 @@ package d2term import ( + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input" ) -func Initialize() (*terminal, error) { - +// Initialize creates and initializes the terminal +func Initialize() (d2interface.Terminal, error) { term, err := createTerminal() if err != nil { return nil, err diff --git a/d2core/d2term/terminal.go b/d2core/d2term/terminal.go index 58ef38a0..bd673bb6 100644 --- a/d2core/d2term/terminal.go +++ b/d2core/d2term/terminal.go @@ -17,8 +17,10 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input" ) +// TermCategory applies styles to the lines in the Terminal type TermCategory d2interface.TermCategory +// Terminal Category types const ( TermCategoryNone = TermCategory(d2interface.TermCategoryNone) TermCategoryInfo = TermCategory(d2interface.TermCategoryInfo) @@ -43,15 +45,7 @@ const ( termVisHiding ) -var ( - termBgColor = color.RGBA{R: 0x2e, G: 0x34, B: 0x36, A: 0xb0} - termFgColor = color.RGBA{R: 0x55, G: 0x57, B: 0x53, A: 0xb0} - termInfoColor = color.RGBA{R: 0x34, G: 0x65, B: 0xa4, A: 0xb0} - termWarningColor = color.RGBA{R: 0xfc, G: 0xe9, B: 0x4f, A: 0xb0} - termErrorColor = color.RGBA{R: 0xcc, A: 0xb0} -) - -type termHistroyEntry struct { +type termHistoryEntry struct { text string category d2interface.TermCategory } @@ -62,7 +56,7 @@ type termActionEntry struct { } type terminal struct { - outputHistory []termHistroyEntry + outputHistory []termHistoryEntry outputIndex int command string @@ -73,6 +67,12 @@ type terminal struct { visState termVis visAnim float64 + bgColor color.RGBA + fgColor color.RGBA + infoColor color.RGBA + warningColor color.RGBA + errorColor color.RGBA + actions map[string]termActionEntry } @@ -98,108 +98,102 @@ func (t *terminal) Advance(elapsed float64) error { } func (t *terminal) OnKeyDown(event d2input.KeyEvent) bool { - if t.visState == termVisHiding || t.visState == termVisHidden && event.Key == d2input.KeyGraveAccent { - t.Show() - return true + if event.Key == d2input.KeyGraveAccent { + t.toggleTerminal() } if !t.IsVisible() { return false } - if event.Key == d2input.KeyGraveAccent { - t.Hide() - return true - } - - if event.Key == d2input.KeyEscape { + switch event.Key { + case d2input.KeyEscape: t.command = "" - return true - } - - maxoutputIndex := d2common.MaxInt(0, len(t.outputHistory)-t.lineCount) - - if event.Key == d2input.KeyHome { - t.outputIndex = maxoutputIndex - return true - } - - if event.Key == d2input.KeyEnd { + case d2input.KeyEnd: t.outputIndex = 0 - return true - } - - if event.Key == d2input.KeyPageUp { - if t.outputIndex += t.lineCount; t.outputIndex >= maxoutputIndex { - t.outputIndex = maxoutputIndex + case d2input.KeyHome: + t.outputIndex = d2common.MaxInt(0, len(t.outputHistory)-t.lineCount) + case d2input.KeyPageUp: + maxOutputIndex := d2common.MaxInt(0, len(t.outputHistory)-t.lineCount) + if t.outputIndex += t.lineCount; t.outputIndex >= maxOutputIndex { + t.outputIndex = maxOutputIndex } - - return true - } - - if event.Key == d2input.KeyPageDown { + case d2input.KeyPageDown: if t.outputIndex -= t.lineCount; t.outputIndex < 0 { t.outputIndex = 0 } - - return true - } - - if event.Key == d2input.KeyUp { + case d2input.KeyUp: + t.handleKeyUp(event.KeyMod) + case d2input.KeyDown: if event.KeyMod == d2input.KeyModControl { - t.lineCount = d2common.MaxInt(0, t.lineCount-1) - } else if len(t.commandHistory) > 0 { - t.command = t.commandHistory[t.commandIndex] - if t.commandIndex == 0 { - t.commandIndex = len(t.commandHistory) - 1 - } else { - t.commandIndex-- - } + t.lineCount = d2common.MinInt(t.lineCount+1, termRowCountMax) } - - return true - } - - if event.Key == d2input.KeyDown && event.KeyMod == d2input.KeyModControl { - t.lineCount = d2common.MinInt(t.lineCount+1, termRowCountMax) - return true - } - - if event.Key == d2input.KeyEnter && len(t.command) > 0 { - var commandHistory []string - for _, command := range t.commandHistory { - if command != t.command { - commandHistory = append(commandHistory, command) - } + case d2input.KeyEnter: + t.processCommand() + case d2input.KeyBackspace: + if len(t.command) > 0 { + t.command = t.command[:len(t.command)-1] } - - t.commandHistory = append(commandHistory, t.command) - - t.Output(t.command) - if err := t.Execute(t.command); err != nil { - t.OutputError(err.Error()) - } - - t.commandIndex = len(t.commandHistory) - 1 - t.command = "" - - return true - } - - if event.Key == d2input.KeyBackspace && len(t.command) > 0 { - t.command = t.command[:len(t.command)-1] - return true } return true } +func (t *terminal) processCommand() { + if t.command == "" { + return + } + + n := 0 + + for _, command := range t.commandHistory { + if command != t.command { + t.commandHistory[n] = command + n++ + } + } + + t.commandHistory = t.commandHistory[:n] + t.commandHistory = append(t.commandHistory, t.command) + + t.Outputf(t.command) + + if err := t.Execute(t.command); err != nil { + t.OutputErrorf(err.Error()) + } + + t.commandIndex = len(t.commandHistory) - 1 + t.command = "" +} + +func (t *terminal) handleKeyUp(keyMod d2input.KeyMod) { + if keyMod == d2input.KeyModControl { + t.lineCount = d2common.MaxInt(0, t.lineCount-1) + } else if len(t.commandHistory) > 0 { + t.command = t.commandHistory[t.commandIndex] + if t.commandIndex == 0 { + t.commandIndex = len(t.commandHistory) - 1 + } else { + t.commandIndex-- + } + } +} + +func (t *terminal) toggleTerminal() { + if t.visState == termVisHiding || t.visState == termVisHidden { + t.Show() + } else { + t.Hide() + } +} + func (t *terminal) OnKeyChars(event d2input.KeyCharsEvent) bool { if !t.IsVisible() { return false } var handled bool + for _, c := range event.Chars { if c != '`' { t.command += string(c) @@ -222,7 +216,7 @@ func (t *terminal) Render(surface d2interface.Surface) error { offset := -int((1.0 - easeInOut(t.visAnim)) * float64(totalHeight)) surface.PushTranslation(0, offset) - surface.DrawRect(totalWidth, outputHeight, termBgColor) + surface.DrawRect(totalWidth, outputHeight, t.bgColor) for i := 0; i < t.lineCount; i++ { historyIndex := len(t.outputHistory) - i - t.outputIndex - 1 @@ -231,23 +225,26 @@ func (t *terminal) Render(surface d2interface.Surface) error { } historyEntry := t.outputHistory[historyIndex] + surface.PushTranslation(termCharWidth*2, outputHeight-(i+1)*termCharHeight) surface.DrawText(historyEntry.text) surface.PushTranslation(-termCharWidth*2, 0) + switch historyEntry.category { case d2interface.TermCategoryInfo: - surface.DrawRect(termCharWidth, termCharHeight, termInfoColor) + surface.DrawRect(termCharWidth, termCharHeight, t.infoColor) case d2interface.TermCategoryWarning: - surface.DrawRect(termCharWidth, termCharHeight, termWarningColor) + surface.DrawRect(termCharWidth, termCharHeight, t.warningColor) case d2interface.TermCategoryError: - surface.DrawRect(termCharWidth, termCharHeight, termErrorColor) + surface.DrawRect(termCharWidth, termCharHeight, t.errorColor) } + surface.Pop() surface.Pop() } surface.PushTranslation(0, outputHeight) - surface.DrawRect(totalWidth, termCharHeight, termFgColor) + surface.DrawRect(totalWidth, termCharHeight, t.fgColor) surface.DrawText("> " + t.command) surface.Pop() @@ -274,13 +271,16 @@ func (t *terminal) Execute(command string) error { if actionType.Kind() != reflect.Func { return errors.New("action is not a function") } + if len(actionParams) != actionType.NumIn() { return errors.New("action requires different argument count") } var paramValues []reflect.Value + for i := 0; i < actionType.NumIn(); i++ { actionParam := actionParams[i] + switch actionType.In(i).Kind() { case reflect.String: paramValues = append(paramValues, reflect.ValueOf(actionParam)) @@ -289,24 +289,28 @@ func (t *terminal) Execute(command string) error { if err != nil { return err } + paramValues = append(paramValues, reflect.ValueOf(int(value))) case reflect.Uint: value, err := strconv.ParseUint(actionParam, 10, 64) if err != nil { return err } + paramValues = append(paramValues, reflect.ValueOf(uint(value))) case reflect.Float64: value, err := strconv.ParseFloat(actionParam, 64) if err != nil { return err } + paramValues = append(paramValues, reflect.ValueOf(value)) case reflect.Bool: value, err := strconv.ParseBool(actionParam) if err != nil { return err } + paramValues = append(paramValues, reflect.ValueOf(value)) default: return errors.New("action has unsupported arguments") @@ -317,9 +321,10 @@ func (t *terminal) Execute(command string) error { actionReturnValues := actionValue.Call(paramValues) if actionReturnValueCount := len(actionReturnValues); actionReturnValueCount > 0 { - t.OutputInfo("function returned %d values:", actionReturnValueCount) + t.OutputInfof("function returned %d values:", actionReturnValueCount) + for _, actionReturnValue := range actionReturnValues { - t.OutputInfo("%v: %s", actionReturnValue.Interface(), actionReturnValue.String()) + t.OutputInfof("%v: %s", actionReturnValue.Interface(), actionReturnValue.String()) } } @@ -328,6 +333,7 @@ func (t *terminal) Execute(command string) error { func (t *terminal) OutputRaw(text string, category d2interface.TermCategory) { var line string + for _, word := range strings.Split(text, " ") { if len(line) > 0 { line += " " @@ -337,29 +343,29 @@ func (t *terminal) OutputRaw(text string, category d2interface.TermCategory) { wordLength := len(word) if lineLength+wordLength >= termColCountMax { - t.outputHistory = append(t.outputHistory, termHistroyEntry{line, category}) + t.outputHistory = append(t.outputHistory, termHistoryEntry{line, category}) line = word } else { line += word } } - t.outputHistory = append(t.outputHistory, termHistroyEntry{line, category}) + t.outputHistory = append(t.outputHistory, termHistoryEntry{line, category}) } -func (t *terminal) Output(format string, params ...interface{}) { +func (t *terminal) Outputf(format string, params ...interface{}) { t.OutputRaw(fmt.Sprintf(format, params...), d2interface.TermCategoryNone) } -func (t *terminal) OutputInfo(format string, params ...interface{}) { +func (t *terminal) OutputInfof(format string, params ...interface{}) { t.OutputRaw(fmt.Sprintf(format, params...), d2interface.TermCategoryInfo) } -func (t *terminal) OutputWarning(format string, params ...interface{}) { +func (t *terminal) OutputWarningf(format string, params ...interface{}) { t.OutputRaw(fmt.Sprintf(format, params...), d2interface.TermCategoryWarning) } -func (t *terminal) OutputError(format string, params ...interface{}) { +func (t *terminal) OutputErrorf(format string, params ...interface{}) { t.OutputRaw(fmt.Sprintf(format, params...), d2interface.TermCategoryError) } @@ -403,6 +409,7 @@ func (t *terminal) BindAction(name, description string, action interface{}) erro } t.actions[name] = termActionEntry{action, description} + return nil } @@ -419,10 +426,11 @@ func easeInOut(t float64) float64 { t *= 2 if t < 1 { return 0.5 * t * t * t * t - } else { - t -= 2 - return -0.5 * (t*t*t*t - 2) } + + t -= 2 + + return -0.5 * (t*t*t*t - 2) } func parseCommand(command string) []string { @@ -470,14 +478,19 @@ func parseCommand(command string) []string { func createTerminal() (*terminal, error) { terminal := &terminal{ - lineCount: termRowCount, - actions: make(map[string]termActionEntry), + lineCount: termRowCount, + bgColor: color.RGBA{R: 0x2e, G: 0x34, B: 0x36, A: 0xb0}, + fgColor: color.RGBA{R: 0x55, G: 0x57, B: 0x53, A: 0xb0}, + infoColor: color.RGBA{R: 0x34, G: 0x65, B: 0xa4, A: 0xb0}, + warningColor: color.RGBA{R: 0xfc, G: 0xe9, B: 0x4f, A: 0xb0}, + errorColor: color.RGBA{R: 0xcc, A: 0xb0}, + actions: make(map[string]termActionEntry), } - terminal.OutputInfo("::: OpenDiablo2 Terminal :::") - terminal.OutputInfo("type \"ls\" for a list of actions") + terminal.OutputInfof("::: OpenDiablo2 Terminal :::") + terminal.OutputInfof("type \"ls\" for a list of actions") - terminal.BindAction("ls", "list available actions", func() { + err := terminal.BindAction("ls", "list available actions", func() { var names []string for name := range terminal.actions { names = append(names, name) @@ -485,15 +498,22 @@ func createTerminal() (*terminal, error) { sort.Strings(names) - terminal.OutputInfo("available actions (%d):", len(names)) + terminal.OutputInfof("available actions (%d):", len(names)) for _, name := range names { entry := terminal.actions[name] - terminal.OutputInfo("%s: %s; %s", name, entry.description, reflect.TypeOf(entry.action).String()) + terminal.OutputInfof("%s: %s; %s", name, entry.description, reflect.TypeOf(entry.action).String()) } }) - terminal.BindAction("clear", "clear terminal", func() { + if err != nil { + return nil, fmt.Errorf("failed to bind the '%s' action, err: %w", "ls", err) + } + + err = terminal.BindAction("clear", "clear terminal", func() { terminal.OutputClear() }) + if err != nil { + return nil, fmt.Errorf("failed to bind the '%s' action, err: %w", "clear", err) + } return terminal, nil } diff --git a/d2core/d2term/terminal_logger.go b/d2core/d2term/terminal_logger.go index fc3059a4..62eb67c8 100644 --- a/d2core/d2term/terminal_logger.go +++ b/d2core/d2term/terminal_logger.go @@ -9,8 +9,8 @@ import ( type terminalLogger struct { terminal *terminal - buffer bytes.Buffer - writer io.Writer + buffer bytes.Buffer + writer io.Writer } func (tl *terminalLogger) Write(p []byte) (int, error) { @@ -21,19 +21,21 @@ func (tl *terminalLogger) Write(p []byte) (int, error) { reader := bufio.NewReader(&tl.buffer) termBytes, _, err := reader.ReadLine() + if err != nil { return n, err } - line := string(termBytes[:]) + line := string(termBytes) lineLower := strings.ToLower(line) - if strings.Index(lineLower, "error") > 0 { - tl.terminal.OutputError(line) - } else if strings.Index(lineLower, "warning") > 0 { - tl.terminal.OutputWarning(line) - } else { - tl.terminal.Output(line) + switch { + case strings.Index(lineLower, "error") > 0: + tl.terminal.OutputErrorf(line) + case strings.Index(lineLower, "warning") > 0: + tl.terminal.OutputWarningf(line) + default: + tl.terminal.Outputf(line) } return tl.writer.Write(p) diff --git a/d2game/d2gamescreen/main_menu.go b/d2game/d2gamescreen/main_menu.go index fbdc308b..ae96c285 100644 --- a/d2game/d2gamescreen/main_menu.go +++ b/d2game/d2gamescreen/main_menu.go @@ -128,7 +128,7 @@ func (v *MainMenu) OnLoad(loading d2screen.LoadingState) { v.trademarkBackground, _ = d2ui.LoadSprite(animation) v.trademarkBackground.SetPosition(0, 0) - animation, _ = d2asset.LoadAnimation(d2resource.TcpIpBackground, d2resource.PaletteSky) + animation, _ = d2asset.LoadAnimation(d2resource.TCPIPBackground, d2resource.PaletteSky) v.tcpIpBackground, _ = d2ui.LoadSprite(animation) v.tcpIpBackground.SetPosition(0, 0) diff --git a/d2script/scriptengine.go b/d2script/scriptengine.go index 722ead6c..efa9425e 100644 --- a/d2script/scriptengine.go +++ b/d2script/scriptengine.go @@ -3,42 +3,60 @@ package d2script import ( "fmt" "io/ioutil" + "path/filepath" "github.com/robertkrimen/otto" _ "github.com/robertkrimen/otto/underscore" // This causes the runtime to support underscore.js ) +// ScriptEngine allows running JavaScript scripts type ScriptEngine struct { vm *otto.Otto } +// CreateScriptEngine creates the script engine and returns a pointer to it. func CreateScriptEngine() *ScriptEngine { result := &ScriptEngine{ vm: otto.New(), } - result.vm.Set("debugPrint", func(call otto.FunctionCall) otto.Value { + err := result.vm.Set("debugPrint", func(call otto.FunctionCall) otto.Value { fmt.Printf("Script: %s\n", call.Argument(0).String()) return otto.Value{} }) + if err != nil { + fmt.Printf("could not bind the 'debugPrint' to the given function in script engine") + } return result } +// ToValue converts the given interface{} value to a otto.Value func (s *ScriptEngine) ToValue(source interface{}) (otto.Value, error) { return s.vm.ToValue(source) } +// AddFunction adds the given function to the script engine with the given name. func (s *ScriptEngine) AddFunction(name string, value interface{}) { - s.vm.Set(name, value) + err := s.vm.Set(name, value) + if err != nil { + fmt.Printf("could not add the '%s' function to the script engine", name) + } } +// RunScript runs the script file within the given path. func (s *ScriptEngine) RunScript(fileName string) (*otto.Value, error) { - fileData, _ := ioutil.ReadFile(fileName) + fileData, err := ioutil.ReadFile(filepath.Clean(fileName)) + if err != nil { + fmt.Printf("could not read script file: %s\n", err.Error()) + return nil, err + } + val, err := s.vm.Run(string(fileData)) if err != nil { fmt.Printf("Error running script: %s\n", err.Error()) return nil, err } + return &val, nil }