lint fixes (#727)

This commit is contained in:
Gürkan Kaymak 2020-09-12 23:25:09 +03:00 committed by GitHub
parent 3988bd7f1c
commit f4a71c72e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 327 additions and 346 deletions

View File

@ -6,8 +6,6 @@ import (
"container/ring"
"errors"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"image"
"image/gif"
"image/png"
@ -19,6 +17,9 @@ import (
"strings"
"sync"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/pkg/profile"
"golang.org/x/image/colornames"
"gopkg.in/alecthomas/kingpin.v2"
@ -678,7 +679,6 @@ func updateInitError(target d2interface.Surface) error {
func (a *App) ToMainMenu() {
buildInfo := d2gamescreen.BuildInfo{Branch: a.gitBranch, Commit: a.gitCommit}
mainMenu := d2gamescreen.CreateMainMenu(a, a.renderer, a.inputManager, a.audio, a.ui, buildInfo)
// mainMenu.SetScreenMode(d2gamescreen.ScreenModeMainMenu)
a.screen.SetNextScreen(mainMenu)
}
@ -702,8 +702,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 := d2gamescreen.CreateCharacterSelect(a, a.renderer, a.inputManager, a.audio,
a.ui, connType, connHost)
characterSelect := d2gamescreen.CreateCharacterSelect(a, a.renderer, a.inputManager, a.audio, a.ui, connType, connHost)
a.screen.SetNextScreen(characterSelect)
}

View File

@ -1,9 +1,10 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
// LevelPresetRecord is a representation of a row from lvlprest.txt

View File

@ -1,9 +1,10 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
// LevelTypeRecord is a representation of a row from lvltype.txt

View File

@ -1,8 +1,9 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
func mapHeaders(line string) map[string]int {

View File

@ -1,11 +1,11 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2calculation"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
// MissileCalcParam is a calculation parameter for a missile

View File

@ -2,7 +2,7 @@ package d2datadict
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)

View File

@ -4,7 +4,7 @@ import (
"fmt"
"log"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)

View File

@ -1,9 +1,10 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
// An ObjectRecord represents the settings for one type of object from objects.txt

View File

@ -2,7 +2,7 @@ package d2datadict
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)

View File

@ -3,7 +3,7 @@ package d2datadict
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)

View File

@ -3,7 +3,7 @@ package d2datadict
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
)

View File

@ -1,9 +1,10 @@
package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
// UniqueItemRecord is a representation of a row from uniqueitems.txt

View File

@ -1,8 +1,9 @@
package d2video
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
)
// BinkVideoMode is the video mode type

View File

@ -41,10 +41,7 @@ const (
DrawEffectNone
)
// Transparent returns true if there is no effect, false otherwise
func (d DrawEffect) Transparent() bool {
if d == DrawEffectNone {
return false
}
return true
return d != DrawEffectNone
}

View File

@ -1,9 +1,9 @@
package d2cof
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
)

View File

@ -2,6 +2,7 @@ package d2dcc
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
)

View File

@ -1,9 +1,10 @@
package d2dcc
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
)
@ -138,7 +139,12 @@ func CreateDCCDirection(bm *d2datautils.BitMuncher, file *DCC) *DCCDirection {
return result
}
func (v *DCCDirection) verify(equalCellsBitstream, pixelMaskBitstream, encodingTypeBitsream, rawPixelCodesBitstream *d2datautils.BitMuncher) {
func (v *DCCDirection) verify(
equalCellsBitstream,
pixelMaskBitstream,
encodingTypeBitstream,
rawPixelCodesBitstream *d2datautils.BitMuncher,
) {
if equalCellsBitstream.BitsRead() != v.EqualCellsBitstreamSize {
log.Panic("Did not read the correct number of bits!")
}
@ -147,7 +153,7 @@ func (v *DCCDirection) verify(equalCellsBitstream, pixelMaskBitstream, encodingT
log.Panic("Did not read the correct number of bits!")
}
if encodingTypeBitsream.BitsRead() != v.EncodingTypeBitsreamSize {
if encodingTypeBitstream.BitsRead() != v.EncodingTypeBitsreamSize {
log.Panic("Did not read the correct number of bits!")
}

View File

@ -1,9 +1,10 @@
package d2dcc
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"log"
)
// DCCDirectionFrame represents a direction frame for a DCC.

View File

@ -2,6 +2,7 @@ package d2dt1
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
)

View File

@ -6,13 +6,13 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"log"
"strings"
"github.com/JoshVarga/blast"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2compression"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
)
// Stream represents a stream of data in an MPQ archive

View File

@ -43,7 +43,7 @@ func (s *Source) fullPath(subPath string) string {
return filepath.Clean(filepath.Join(s.Root, subPath))
}
// String returns the Root dir of this file system source
// Path returns the Root dir of this file system source
func (s *Source) Path() string {
return s.Root
}

View File

@ -74,7 +74,6 @@ func TestLoader_AddSource(t *testing.T) {
t.Error("source path not the same as what we added")
}
if sourceE != nil {
t.Error("source for bad path should be nil")
}

View File

@ -573,6 +573,7 @@ func TestVector_Normalize(t *testing.T) {
v = NewVector(0, 10)
c = v.Clone()
want = NewVector(0, 1)
c.Normalize()
if !want.Equals(c) {

View File

@ -4,6 +4,7 @@ import (
"image"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util/assets"
"github.com/hajimehoshi/ebiten"
)

View File

@ -2,10 +2,10 @@ package d2asset
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"path/filepath"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)

View File

@ -2,10 +2,10 @@ package d2asset
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"path"
"sync"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"

View File

@ -1,9 +1,9 @@
package d2asset
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"

View File

@ -2,6 +2,7 @@ package d2asset
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)

View File

@ -1,3 +1,3 @@
// Package Item provides the Diablo 2 implementation of items for
// Package diablo2item provides the Diablo 2 implementation of items for
// the OpenDiablo2 interfaces
package diablo2item

View File

@ -2,13 +2,13 @@ package diablo2item
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"math/rand"
"sort"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2item"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats/diablo2stats"
@ -249,7 +249,6 @@ func (i *Item) Description() string {
// drop modifier is supplied, it will attempt to reconcile by picked
// magic affixes as if it were a rare.
func (i *Item) applyDropModifier(modifier DropModifier) {
modifier = i.sanitizeDropModifier(modifier)
switch modifier {
@ -345,13 +344,15 @@ func (i *Item) pickMagicAffixes(mod DropModifier) {
totalAffixes = numPrefixes + numSuffixes
}
i.pickMagicPrefixes(numPrefixes, totalAffixes)
i.pickMagicSuffixes(numSuffixes, totalAffixes)
i.PrefixCodes = i.pickRandomAffixes(numPrefixes, totalAffixes, d2datadict.MagicPrefix)
i.SuffixCodes = i.pickRandomAffixes(numSuffixes, totalAffixes, d2datadict.MagicSuffix)
}
func (i *Item) pickMagicPrefixes(max, totalMax int) {
func (i *Item) pickRandomAffixes(max, totalMax int, affixMap map[string]*d2datadict.ItemAffixCommonRecord) []string {
pickedCodes := make([]string, 0)
for numPicks := 0; numPicks < max; numPicks++ {
matches := findMatchingAffixes(i.CommonRecord(), d2datadict.MagicPrefix)
matches := findMatchingAffixes(i.CommonRecord(), affixMap)
if rollPrefix := i.rand.Intn(2); rollPrefix > 0 {
affixCount := len(i.PrefixRecords()) + len(i.SuffixRecords())
@ -361,28 +362,12 @@ func (i *Item) pickMagicPrefixes(max, totalMax int) {
if len(matches) > 0 {
picked := matches[i.rand.Intn(len(matches))]
i.PrefixCodes = append(i.PrefixCodes, picked.Name)
pickedCodes = append(pickedCodes, picked.Name)
}
}
}
}
func (i *Item) pickMagicSuffixes(max, totalMax int) {
for numPicks := 0; numPicks < max; numPicks++ {
matches := findMatchingAffixes(i.CommonRecord(), d2datadict.MagicSuffix)
if rollSuffix := i.rand.Intn(2); rollSuffix > 0 {
affixCount := len(i.PrefixRecords()) + len(i.SuffixRecords())
if len(i.PrefixRecords()) > max || affixCount > totalMax {
break
}
if len(matches) > 0 {
picked := matches[i.rand.Intn(len(matches))]
i.SuffixCodes = append(i.SuffixCodes, picked.Name)
}
}
}
return pickedCodes
}
// SetSeed sets the item generator seed
@ -391,6 +376,7 @@ func (i *Item) SetSeed(seed int64) {
source := rand.NewSource(seed)
i.rand = rand.New(source)
}
i.Seed = seed
}
@ -401,6 +387,7 @@ func (i *Item) init() *Item {
i.generateAllProperties()
i.updateItemAttributes()
return i
}
@ -430,12 +417,8 @@ func (i *Item) generateProperties(pool PropertyPool) {
var props []*Property
switch pool {
case PropertyPoolPrefix:
if generated := i.generatePrefixProperties(); generated != nil {
props = generated
}
case PropertyPoolSuffix:
if generated := i.generateSuffixProperties(); generated != nil {
case PropertyPoolPrefix, PropertyPoolSuffix:
if generated := i.generateAffixProperties(pool); generated != nil {
props = generated
}
case PropertyPoolUnique:
@ -446,8 +429,7 @@ func (i *Item) generateProperties(pool PropertyPool) {
if generated := i.generateSetItemProperties(); generated != nil {
props = generated
}
case PropertyPoolSet:
// todo set bonus handling, needs player/equipment context
case PropertyPoolSet: // todo set bonus handling, needs player/equipment context
}
if props == nil {
@ -523,45 +505,30 @@ func (i *Item) updateItemAttributes() {
i.attributes.defense = def
}
func (i *Item) generatePrefixProperties() []*Property {
if i.PrefixRecords() == nil || len(i.PrefixRecords()) < 1 {
func (i *Item) generateAffixProperties(pool PropertyPool) []*Property {
var affixRecords []*d2datadict.ItemAffixCommonRecord
switch pool {
case PropertyPoolPrefix:
affixRecords = i.PrefixRecords()
case PropertyPoolSuffix:
affixRecords = i.SuffixRecords()
default:
return nil
}
if affixRecords == nil || len(affixRecords) < 1 {
return nil
}
result := make([]*Property, 0)
// for each prefix
for recIdx := range i.PrefixRecords() {
prefix := i.PrefixRecords()[recIdx]
for recIdx := range affixRecords {
affix := affixRecords[recIdx]
// for each modifier
for modIdx := range prefix.Modifiers {
mod := prefix.Modifiers[modIdx]
prop := NewProperty(mod.Code, mod.Parameter, mod.Min, mod.Max)
if prop == nil {
continue
}
result = append(result, prop)
}
}
return result
}
func (i *Item) generateSuffixProperties() []*Property {
if i.SuffixRecords() == nil || len(i.SuffixRecords()) < 1 {
return nil
}
result := make([]*Property, 0)
// for each prefix
for recIdx := range i.SuffixRecords() {
prefix := i.SuffixRecords()[recIdx]
// for each modifier
for modIdx := range prefix.Modifiers {
mod := prefix.Modifiers[modIdx]
for modIdx := range affix.Modifiers {
mod := affix.Modifiers[modIdx]
prop := NewProperty(mod.Code, mod.Parameter, mod.Min, mod.Max)
if prop == nil {
@ -846,7 +813,7 @@ func (i *Item) GetInventoryItemType() d2enum.InventoryItemType {
return d2enum.InventoryItemTypeItem
}
func (i *Item) InventoryGridSize() (int, int) {
func (i *Item) InventoryGridSize() (width, height int) {
r := i.CommonRecord()
return r.InventoryWidth, r.InventoryHeight
}
@ -867,7 +834,7 @@ func (i *Item) SetInventoryGridSlot(x, y int) {
i.GridX, i.GridY = x, y
}
func (i *Item) GetInventoryGridSize() (int, int) {
func (i *Item) GetInventoryGridSize() (x, y int) {
return i.GridX, i.GridY
}

View File

@ -1,10 +1,11 @@
package diablo2item
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"math/rand"
"regexp"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
)
const (
@ -45,6 +46,7 @@ func (ig *ItemGenerator) SetSeed(seed int64) {
ig.source = rand.NewSource(seed)
ig.rand = rand.New(ig.source)
}
ig.Seed = seed
}
@ -240,7 +242,7 @@ func getStringComponent(code string) string {
func getNumericComponent(code string) int {
result := 0
re := regexp.MustCompile(`[^\d]`)
re := regexp.MustCompile(`\D`)
numStr := string(re.ReplaceAll([]byte(code), []byte("")))
if number, err := strconv.ParseInt(numStr, 10, 32); err == nil {

View File

@ -1,21 +1,17 @@
package d2mapengine
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"log"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapstamp"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapstamp"
)
// MapEngine loads the tiles which make up the isometric map and the entities

View File

@ -3,6 +3,7 @@ package d2mapentity
import (
"errors"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"

View File

@ -44,7 +44,7 @@ func (i *Item) Highlight() {
i.AnimatedEntity.highlight = true
}
// Name returns the item name
// Label returns the item label
func (i *Item) Label() string {
return i.Item.Label()
}

View File

@ -29,7 +29,6 @@ func (m *Missile) GetVelocity() d2vector.Vector {
return m.AnimatedEntity.velocity
}
// SetRadians adjusts the entity target based on it's range, rotating it's
// current destination by the value of angle in radians.
func (m *Missile) SetRadians(angle float64, done func()) {

View File

@ -1,13 +1,13 @@
package d2mapentity
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
"math/rand"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
@ -182,6 +182,6 @@ func (v *NPC) GetVelocity() d2vector.Vector {
}
// GetSize returns the current frame size
func (v* NPC) GetSize() (width, height int) {
func (v *NPC) GetSize() (width, height int) {
return v.composite.GetSize()
}

View File

@ -2,7 +2,6 @@
package d2mapgen
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"log"
"math/rand"
"strings"
@ -10,6 +9,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen/d2wilderness"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapstamp"
@ -39,30 +39,24 @@ func GenerateAct1Overworld(mapEngine *d2mapengine.MapEngine) {
log.Printf("Region Path: %s", townStamp.RegionPath())
if strings.Contains(townStamp.RegionPath(), "E1") {
// East Exit
switch {
case strings.Contains(townStamp.RegionPath(), "E1"):
mapEngine.PlaceStamp(townStamp, 0, 0)
generateWilderness1TownEast(mapEngine, townSize.Width, 0)
} else if strings.Contains(townStamp.RegionPath(), "S1") {
// South Exit
case strings.Contains(townStamp.RegionPath(), "S1"):
mapEngine.PlaceStamp(townStamp, mapWidth-townSize.Width, 0)
// Generate the river running along the edge of the map
rightWaterBorderStamp := loadPreset(mapEngine, d2wilderness.WaterBorderEast, 0)
rightWaterBorderStamp2 := loadPreset(mapEngine, d2wilderness.WaterBorderWest, 0)
// Place the water on the right side of the map
for y := townSize.Height; y < mapHeight-9; y += 9 {
mapEngine.PlaceStamp(rightWaterBorderStamp, mapWidth-17, y)
mapEngine.PlaceStamp(rightWaterBorderStamp2, mapWidth-9, y)
}
generateWilderness1TownSouth(mapEngine, mapWidth-wilderness1Details.SizeXNormal-14, townSize.Height)
} else if strings.Contains(townStamp.RegionPath(), "W1") {
// West Exit
case strings.Contains(townStamp.RegionPath(), "W1"):
mapEngine.PlaceStamp(townStamp, mapWidth-townSize.Width, mapHeight-townSize.Height)
generateWilderness1TownWest(mapEngine, mapWidth-townSize.Width-wilderness1Details.SizeXNormal, mapHeight-wilderness1Details.SizeYNormal)
} else {
// North Exit
default:
mapEngine.PlaceStamp(townStamp, mapWidth-townSize.Width, mapHeight-townSize.Height)
}
}

View File

@ -3,17 +3,16 @@ package d2maprenderer
import (
"errors"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"image/color"
"log"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"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"
)

View File

@ -1,12 +1,12 @@
package d2maprenderer
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)

View File

@ -1,8 +1,9 @@
package d2maprenderer
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
)
type worldTrans struct {

View File

@ -1,23 +1,21 @@
package d2mapstamp
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
"math"
"math/rand"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2object"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2path"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2object"
)
// Stamp represents a pre-fabricated map stamp that can be placed on a map.
@ -95,7 +93,7 @@ func (mr *Stamp) LevelType() d2datadict.LevelTypeRecord {
return mr.levelType
}
// RegionPath returns the file path of the region.
// RegionID returns the regionID
func (mr *Stamp) RegionID() d2enum.RegionIdType {
return mr.regionID
}

View File

@ -2,13 +2,14 @@
package d2object
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"fmt"
"math/rand"
uuid "github.com/satori/go.uuid"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
@ -17,7 +18,7 @@ import (
// Object represents a composite of animations that can be projected onto the map.
type Object struct {
uuid string
uuid string
Position d2vector.Position
composite *d2asset.Composite
highlight bool
@ -46,9 +47,13 @@ func CreateObject(x, y int, objectRec *d2datadict.ObjectRecord, palettePath stri
entity.composite = composite
entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false)
if err := entity.setMode(d2enum.ObjectAnimationModeNeutral, 0, false); err != nil {
return nil, err
}
initObject(entity)
if _, err := initObject(entity); err != nil {
return nil, err
}
return entity, nil
}
@ -62,7 +67,6 @@ func (ob *Object) setMode(animationMode d2enum.ObjectAnimationMode, direction in
ob.composite.SetDirection(direction)
// mode := d2enum.ObjectAnimationModeFromString(animationMode)
ob.drawLayer = ob.objectRecord.OrderFlag[d2enum.ObjectAnimationModeNeutral]
// For objects their txt record entry overrides animationdata
@ -98,6 +102,7 @@ func (ob *Object) Highlight() {
ob.highlight = true
}
// Selectable returns if the object is selectable or not
func (ob *Object) Selectable() bool {
mode := ob.composite.ObjectAnimationMode()
return ob.objectRecord.Selectable[mode]
@ -117,13 +122,19 @@ func (ob *Object) Render(target d2interface.Surface) {
}
defer target.Pop()
ob.composite.Render(target)
if err := ob.composite.Render(target); err != nil {
fmt.Printf("failed to render composite animation, err: %v\n", err)
}
ob.highlight = false
}
// Advance updates the animation
func (ob *Object) Advance(elapsed float64) {
ob.composite.Advance(elapsed)
if err := ob.composite.Advance(elapsed); err != nil {
fmt.Printf("failed to advance composiste animation, err: %v\n", err)
}
}
// GetLayer returns which layer of the map the object is drawn

View File

@ -9,17 +9,17 @@ import (
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
)
const (
maxAlpha = 0xff
cacheLimit = 512
Transparency25 = 0.25
Transparency50 = 0.50
Transparency75 = 0.75
maxAlpha = 0xff
cacheLimit = 512
transparency25 = 0.25
transparency50 = 0.50
transparency75 = 0.75
)
type colorMCacheKey uint32
@ -129,54 +129,31 @@ func (s *ebitenSurface) PopN(n int) {
// Render renders the given surface
func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
opts := &ebiten.DrawImageOptions{}
if s.stateCurrent.skewX != 0 || s.stateCurrent.skewY != 0 {
opts.GeoM.Skew(s.stateCurrent.skewX, s.stateCurrent.skewY)
}
if s.stateCurrent.scaleX != 1.0 || s.stateCurrent.scaleY != 1.0 {
opts.GeoM.Scale(s.stateCurrent.scaleX, s.stateCurrent.scaleY)
}
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
opts.Filter = s.stateCurrent.filter
if s.stateCurrent.color != nil {
opts.ColorM = s.colorToColorM(s.stateCurrent.color)
}
opts := s.createDrawImageOptions()
if s.stateCurrent.brightness != 1 || s.stateCurrent.saturation != 1 {
opts.ColorM.ChangeHSV(0, s.stateCurrent.saturation, s.stateCurrent.brightness)
}
// Are these correct? who even knows
switch s.stateCurrent.effect {
case d2enum.DrawEffectPctTransparency25:
opts.ColorM.Translate(0, 0, 0, -Transparency25)
case d2enum.DrawEffectPctTransparency50:
opts.ColorM.Translate(0, 0, 0, -Transparency50)
case d2enum.DrawEffectPctTransparency75:
opts.ColorM.Translate(0, 0, 0, -Transparency75)
case d2enum.DrawEffectModulate:
opts.CompositeMode = ebiten.CompositeModeLighter
// TODO: idk what to do when ebiten doesn't exactly match, pick closest?
case d2enum.DrawEffectBurn:
case d2enum.DrawEffectNormal:
case d2enum.DrawEffectMod2XTrans:
case d2enum.DrawEffectMod2X:
case d2enum.DrawEffectNone:
opts.CompositeMode = ebiten.CompositeModeSourceOver
}
s.handleStateEffect(opts)
var img = sfc.(*ebitenSurface).image
return s.image.DrawImage(img, opts)
return s.image.DrawImage(sfc.(*ebitenSurface).image, opts)
}
// Renders the section of the surface, given the bounds
func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
opts := s.createDrawImageOptions()
if s.stateCurrent.brightness != 0 {
opts.ColorM.ChangeHSV(0, s.stateCurrent.saturation, s.stateCurrent.brightness)
}
s.handleStateEffect(opts)
return s.image.DrawImage(sfc.(*ebitenSurface).image.SubImage(bound).(*ebiten.Image), opts)
}
func (s *ebitenSurface) createDrawImageOptions() *ebiten.DrawImageOptions {
opts := &ebiten.DrawImageOptions{}
if s.stateCurrent.skewX != 0 || s.stateCurrent.skewY != 0 {
@ -195,18 +172,17 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
opts.ColorM = s.colorToColorM(s.stateCurrent.color)
}
if s.stateCurrent.brightness != 0 {
opts.ColorM.ChangeHSV(0, s.stateCurrent.saturation, s.stateCurrent.brightness)
}
return opts
}
// Are these correct? who even knows
func (s *ebitenSurface) handleStateEffect(opts *ebiten.DrawImageOptions) {
switch s.stateCurrent.effect {
case d2enum.DrawEffectPctTransparency25:
opts.ColorM.Translate(0, 0, 0, -0.25)
opts.ColorM.Translate(0, 0, 0, -transparency25)
case d2enum.DrawEffectPctTransparency50:
opts.ColorM.Translate(0, 0, 0, -0.50)
opts.ColorM.Translate(0, 0, 0, -transparency50)
case d2enum.DrawEffectPctTransparency75:
opts.ColorM.Translate(0, 0, 0, -0.75)
opts.ColorM.Translate(0, 0, 0, -transparency75)
case d2enum.DrawEffectModulate:
opts.CompositeMode = ebiten.CompositeModeLighter
// TODO: idk what to do when ebiten doesn't exactly match, pick closest?
@ -217,10 +193,6 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
case d2enum.DrawEffectNone:
opts.CompositeMode = ebiten.CompositeModeSourceOver
}
var img = sfc.(*ebitenSurface).image
return s.image.DrawImage(img.SubImage(bound).(*ebiten.Image), opts)
}
// DrawTextf renders the string to the surface with the given format string and a set of parameters

View File

@ -2,10 +2,10 @@ package diablo2stats
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats"
)
@ -50,7 +50,7 @@ type diablo2Stat struct {
// depending on the stat record, sets up the proper number of values,
// as well as set up the stat value number types, value combination types, and
// the value stringer functions used
func (s *diablo2Stat) init(numbers ...float64) {//nolint:funlen doesn't make sense to split
func (s *diablo2Stat) init(numbers ...float64) { //nolint:funlen doesn't make sense to split
if s.record == nil {
return
}

View File

@ -2,10 +2,10 @@ package diablo2stats
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats"
)

View File

@ -2,15 +2,14 @@ package d2ui
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"image"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"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"
)
// ButtonType defines the type of button

View File

@ -1,13 +1,13 @@
package d2ui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"image/color"
"log"
"regexp"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
)

View File

@ -23,7 +23,7 @@ func (v *BlizzardIntro) OnLoad(loading d2screen.LoadingState) {
loading.Error(err)
return
}
loading.Progress(fiftyPercent)
v.videoDecoder = d2video.CreateBinkDecoder(videoBytes)

View File

@ -3,7 +3,6 @@ package d2gamescreen
import (
"bufio"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"log"
"os"
"path"
@ -11,6 +10,7 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"

View File

@ -58,12 +58,15 @@ func CreateGame(
) *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
}
@ -97,7 +100,7 @@ func CreateGame(
func (v *Game) OnLoad(_ d2screen.LoadingState) {
v.audioProvider.PlayBGM("")
v.terminal.BindAction(
err := v.terminal.BindAction(
"spawnitem",
"spawns an item at the local player position",
func(code1, code2, code3, code4, code5 string) {
@ -105,8 +108,11 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
v.debugSpawnItemAtPlayer(codes...)
},
)
if err != nil {
fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnitem", err)
}
v.terminal.BindAction(
err = v.terminal.BindAction(
"spawnitemat",
"spawns an item at the x,y coordinates",
func(x, y int, code1, code2, code3, code4, code5 string) {
@ -114,8 +120,11 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
v.debugSpawnItemAtLocation(x, y, codes...)
},
)
if err != nil {
fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnitemat", err)
}
v.terminal.BindAction(
err = v.terminal.BindAction(
"spawnmon",
"spawn monster at the local player position",
func(name string) {
@ -126,7 +135,8 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
v.terminal.OutputErrorf("no monstat entry for \"%s\"", name)
return
}
monster, err := d2mapentity.NewNPC(x, y, monstat, 0)
var monster *d2mapentity.NPC
monster, err = d2mapentity.NewNPC(x, y, monstat, 0)
if err != nil {
v.terminal.OutputErrorf("error generating monster \"%s\": %v", name, err)
return
@ -134,6 +144,9 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
v.gameClient.MapEngine.AddEntity(monster)
},
)
if err != nil {
fmt.Printf("failed to bind the '%s' action, err: %v\n", "spawnmon", err)
}
}
// OnUnload releases the resources of Gameplay screen
@ -146,8 +159,13 @@ func (v *Game) OnUnload() error {
return err
}
v.terminal.UnbindAction("spawnItemAt")
v.terminal.UnbindAction("spawnItem")
if err := v.terminal.UnbindAction("spawnItemAt"); err != nil {
return err
}
if err := v.terminal.UnbindAction("spawnItem"); err != nil {
return err
}
if err := v.gameClient.Close(); err != nil {
return err
@ -302,6 +320,7 @@ func (v *Game) debugSpawnItemAtPlayer(codes ...string) {
func (v *Game) debugSpawnItemAtLocation(x, y int, codes ...string) {
packet := d2netpacket.CreateSpawnItemPacket(x, y, codes...)
err := v.gameClient.SendPacketToServer(packet)
if err != nil {
fmt.Printf(spawnItemErrStr, x, y, codes)

View File

@ -3,13 +3,13 @@ package d2gamescreen
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"log"
"os"
"os/exec"
"runtime"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -138,7 +138,7 @@ func CreateMainMenu(
audioProvider: audioProvider,
navigator: navigator,
buildInfo: buildInfo,
uiManager: ui,
uiManager: ui,
}
}

View File

@ -2,12 +2,13 @@ package d2gamescreen
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"log"
"os"
"strings"
"time"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
@ -173,7 +174,6 @@ func (met *MapEngineTest) loadRegionByIndex(n, levelPreset, fileIndex int) {
met.mapEngine = d2mapengine.CreateMapEngine() // necessary for map name update
met.mapEngine.SetSeed(time.Now().UnixNano())
met.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
//met.mapEngine.RegenerateWalkPaths()
}
met.mapRenderer.SetMapEngine(met.mapEngine)
@ -325,20 +325,10 @@ func (met *MapEngineTest) OnMouseMove(event d2interface.MouseMoveEvent) bool {
return false
}
// OnMouseButtonDown handles mouse button down events
func (met *MapEngineTest) OnMouseButtonDown(event d2interface.MouseEvent) bool {
if event.Button() == d2enum.MouseButtonLeft {
px, py := met.mapRenderer.ScreenToWorld(met.lastMouseX, met.lastMouseY)
met.selX = int(px)
met.selY = int(py)
met.selectedTile = met.mapEngine.TileAt(int(px), int(py))
camVect := met.mapRenderer.Camera.GetPosition().Vector
x, y := float64(met.lastMouseX-400)/5, float64(met.lastMouseY-300)/5
targetPosition := d2vector.NewPositionTile(x, y)
targetPosition.Add(&camVect)
met.mapRenderer.SetCameraTarget(&targetPosition)
met.handleLeftClick()
return true
}
@ -352,20 +342,10 @@ func (met *MapEngineTest) OnMouseButtonDown(event d2interface.MouseEvent) bool {
return false
}
// OnMouseButtonRepeat handles repeated mouse clicks
func (met *MapEngineTest) OnMouseButtonRepeat(event d2interface.MouseEvent) bool {
if event.Button() == d2enum.MouseButtonLeft {
px, py := met.mapRenderer.ScreenToWorld(met.lastMouseX, met.lastMouseY)
met.selX = int(px)
met.selY = int(py)
met.selectedTile = met.mapEngine.TileAt(int(px), int(py))
camVect := met.mapRenderer.Camera.GetPosition().Vector
x, y := float64(met.lastMouseX-400)/5, float64(met.lastMouseY-300)/5
targetPosition := d2vector.NewPositionTile(x, y)
targetPosition.Add(&camVect)
met.mapRenderer.SetCameraTarget(&targetPosition)
met.handleLeftClick()
return true
}
@ -373,6 +353,21 @@ func (met *MapEngineTest) OnMouseButtonRepeat(event d2interface.MouseEvent) bool
return false
}
func (met *MapEngineTest) handleLeftClick() {
px, py := met.mapRenderer.ScreenToWorld(met.lastMouseX, met.lastMouseY)
met.selX = int(px)
met.selY = int(py)
met.selectedTile = met.mapEngine.TileAt(int(px), int(py))
camVect := met.mapRenderer.Camera.GetPosition().Vector
x, y := float64(met.lastMouseX-400)/5, float64(met.lastMouseY-300)/5
targetPosition := d2vector.NewPositionTile(x, y)
targetPosition.Add(&camVect)
met.mapRenderer.SetCameraTarget(&targetPosition)
}
// Advance runs the update logic on the Map Engine Test screen
func (met *MapEngineTest) Advance(tickTime float64) error {
met.mapEngine.Advance(tickTime)

View File

@ -2,9 +2,10 @@ package d2gamescreen
import (
"fmt"
"image"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"image"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"

View File

@ -29,7 +29,7 @@ func genEquipmentSlotsMap(record *d2datadict.InventoryRecord) map[d2enum.Equippe
d2enum.EquippedSlotBelt,
d2enum.EquippedSlotGloves,
}
for _, slot := range slots {
box := record.Slots[slot]
equipmentSlot := EquipmentSlot{

View File

@ -2,15 +2,16 @@ package d2player
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player/help"
"image"
"image/color"
"log"
"math"
"time"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player/help"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
@ -80,7 +81,7 @@ type GameControls struct {
type ActionableType int
type ActionableRegion struct {
ActionableTypeId ActionableType
ActionableTypeID ActionableType
Rect d2geom.Rectangle
}
@ -149,7 +150,7 @@ func NewGameControls(
case d2enum.HeroSorceress:
inventoryRecordKey = "Sorceress2"
default:
inventoryRecordKey = "Amazon2"
return nil, fmt.Errorf("unknown hero class: %d", hero.Class)
}
inventoryRecord := d2datadict.Inventory[inventoryRecordKey]
@ -333,7 +334,7 @@ func (g *GameControls) OnMouseMove(event d2interface.MouseMoveEvent) bool {
for i := range g.actionableRegions {
// Mouse over a game control element
if g.actionableRegions[i].Rect.IsInRect(mx, my) {
g.onHoverActionable(g.actionableRegions[i].ActionableTypeId)
g.onHoverActionable(g.actionableRegions[i].ActionableTypeID)
}
}
@ -347,7 +348,7 @@ func (g *GameControls) OnMouseButtonDown(event d2interface.MouseEvent) bool {
for i := range g.actionableRegions {
// If click is on a game control element
if g.actionableRegions[i].Rect.IsInRect(mx, my) {
g.onClickActionable(g.actionableRegions[i].ActionableTypeId)
g.onClickActionable(g.actionableRegions[i].ActionableTypeID)
return false
}
}
@ -478,8 +479,8 @@ func (g *GameControls) isInActiveMenusRect(px, py int) bool {
// TODO: consider caching the panels to single image that is reused.
// Render draws the GameControls onto the target
func (g *GameControls) Render(target d2interface.Surface) error {
mx, my := g.lastMouseX, g.lastMouseY
for entityIdx := range g.mapEngine.Entities() {
entity := (g.mapEngine.Entities())[entityIdx]
if !entity.Selectable() {
@ -637,7 +638,7 @@ func (g *GameControls) Render(target d2interface.Surface) error {
return err
}
w, _ = g.mainPanel.GetCurrentFrameSize()
g.mainPanel.GetCurrentFrameSize()
g.menuButton.SetPosition((width/2)-8, height-16)
@ -699,7 +700,7 @@ func (g *GameControls) Render(target d2interface.Surface) error {
return err
}
w, _ = g.mainPanel.GetCurrentFrameSize()
g.mainPanel.GetCurrentFrameSize()
g.mainPanel.SetPosition(offset, height)
@ -741,12 +742,15 @@ func (g *GameControls) Render(target d2interface.Surface) error {
g.zoneChangeText.Render(target)
}
hpWithin := (95 >= mx) && (30 <= mx) && (575 >= my) && (525 <= my)
manaWithin := (765 >= mx) && (700 <= mx) && (575 >= my) && (525 <= my)
hpWithin := (mx <= 95) && (mx >= 30) && (my <= 575) && (my >= 525)
manaWithin := (mx <= 765) && (mx >= 700) && (my <= 575) && (my >= 525)
// Display current hp and mana stats hpGlobe or manaGlobe region is clicked
if hpWithin || g.hpStatsIsVisible {
g.hpManaStatsLabel.SetText(d2ui.ColorTokenize(fmt.Sprintf("LIFE: %v / %v", float64(g.hero.Stats.Health), float64(g.hero.Stats.MaxHealth)), d2ui.ColorTokenWhite))
g.hpManaStatsLabel.SetText(d2ui.ColorTokenize(
fmt.Sprintf("LIFE: %v / %v", float64(g.hero.Stats.Health), float64(g.hero.Stats.MaxHealth)),
d2ui.ColorTokenWhite),
)
g.hpManaStatsLabel.SetPosition(15, 485)
g.hpManaStatsLabel.Render(target)
}

View File

@ -28,9 +28,9 @@ type InventoryItem interface {
GetItemDescription() []string
}
var ErrorInventoryFull = errors.New("inventory full")
var errorInventoryFull = errors.New("inventory full")
// Reusable grid for use with player and merchant inventory.
// ItemGrid is a reusable grid for use with player and merchant inventory.
// Handles layout and rendering item icons based on code.
type ItemGrid struct {
uiManager *d2ui.UIManager
@ -59,14 +59,14 @@ func NewItemGrid(ui *d2ui.UIManager, record *d2datadict.InventoryRecord) *ItemGr
}
}
func (g *ItemGrid) SlotToScreen(slotX int, slotY int) (screenX int, screenY int) {
func (g *ItemGrid) SlotToScreen(slotX, slotY int) (screenX, screenY int) {
screenX = g.originX + slotX*g.slotSize
screenY = g.originY + slotY*g.slotSize
return screenX, screenY
}
func (g *ItemGrid) ScreenToSlot(screenX int, screenY int) (slotX int, slotY int) {
func (g *ItemGrid) ScreenToSlot(screenX, screenY int) (slotX, slotY int) {
slotX = (screenX - g.originX) / g.slotSize
slotY = (screenY - g.originY) / g.slotSize
@ -103,7 +103,7 @@ func (g *ItemGrid) Add(items ...InventoryItem) (int, error) {
if g.add(item) {
added++
} else {
err = ErrorInventoryFull
err = errorInventoryFull
break
}
}

View File

@ -21,6 +21,7 @@ func newMiniPanel(uiManager *d2ui.UIManager, isSinglePlayer bool) *miniPanel {
if isSinglePlayer {
miniPanelContainerPath = d2resource.MinipanelSmall
}
animation, _ := d2asset.LoadAnimation(miniPanelContainerPath, d2resource.PaletteSky)
containerSprite, _ := uiManager.NewSprite(animation)

View File

@ -44,7 +44,7 @@ func GetAllPlayerStates() []*PlayerState {
for _, file := range files {
fileName := file.Name()
if file.IsDir() || len(fileName) < 5 || strings.ToLower(fileName[len(fileName)-4:]) != ".od2" {
if file.IsDir() || len(fileName) < 5 || !strings.EqualFold(fileName[len(fileName)-4:], ".od2") {
continue
}

View File

@ -52,6 +52,7 @@ func (l *LocalClientConnection) Open(_, saveFilePath string) error {
var err error
l.SetPlayerState(d2player.LoadPlayerState(saveFilePath))
l.gameServer, err = d2server.NewGameServer(l.openNetworkServer, 30)
if err != nil {
return err

View File

@ -121,10 +121,15 @@ func (r *RemoteClientConnection) SendPacketToServer(packet d2netpacket.NetPacket
// connection.
func (r *RemoteClientConnection) serverListener() {
var packet d2netpacket.NetPacket
decoder := json.NewDecoder(r.tcpConnection)
for {
err := decoder.Decode(&packet)
if err != nil {
log.Printf("failed to decode the packet, err: %v\n", err)
return
}
p, err := r.decodeToPacket(packet.PacketType, string(packet.PacketData))
if err != nil {

View File

@ -2,8 +2,9 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
// NetPacket is used to wrap and send all packet types under d2netpacket.

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2inventory"

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)

View File

@ -2,10 +2,11 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
// CreateItemPacket contains the data required to create a Item entity
// SpawnItemPacket contains the data required to create a Item entity
type SpawnItemPacket struct {
X int `json:"x"`
Y int `json:"y"`

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
@ -34,5 +35,6 @@ func UnmarshalPlayerConnectionRequest(packet []byte) (PlayerConnectionRequestPac
if err := json.Unmarshal(packet, &resp); err != nil {
return PlayerConnectionRequestPacket{}, err
}
return resp, nil
}

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
@ -33,5 +34,6 @@ func UnmarshalPlayerDisconnectionRequest(packet []byte) (PlayerDisconnectRequest
if err := json.Unmarshal(packet, &resp); err != nil {
return resp, err
}
return resp, nil
}

View File

@ -35,5 +35,6 @@ func UnmarshalPong(packet []byte) (PongPacket, error) {
if err := json.Unmarshal(packet, &resp); err != nil {
return resp, err
}
return resp, nil
}

View File

@ -33,5 +33,6 @@ func UnmarshalServerClosed(packet []byte) (ServerClosedPacket, error) {
if err := json.Unmarshal(packet, &resp); err != nil {
return resp, err
}
return resp, nil
}

View File

@ -2,6 +2,7 @@ package d2netpacket
import (
"encoding/json"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
)
@ -33,5 +34,6 @@ func UnmarshalUpdateServerInfo(packet []byte) (UpdateServerInfoPacket, error) {
if err := json.Unmarshal(packet, &resp); err != nil {
return resp, err
}
return resp, nil
}

View File

@ -2,9 +2,10 @@ package d2tcpclientconnection
import (
"encoding/json"
"net"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
"net"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
)

View File

@ -1,4 +1,4 @@
// Package d2server provides connection management and client synchronisation.
// Package d2server provides connection management and client synchronization.
/*
Data is encoded to JSON and compressed using gzip. Transport is over UDP.
The server is authoritative for both local and remote clients.*/

View File

@ -5,31 +5,32 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2server/d2tcpclientconnection"
"log"
"net"
"sync"
"time"
"github.com/robertkrimen/otto"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapgen"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2server/d2tcpclientconnection"
"github.com/OpenDiablo2/OpenDiablo2/d2script"
"github.com/robertkrimen/otto"
)
const (
Port = "6669"
ChunkSize int = 4096
port = "6669"
chunkSize int = 4096
subtilesPerTile = 5
middleOfTileOffset = 3
)
var (
ErrPlayerAlreadyExists = errors.New("player already exists")
ErrServerFull = errors.New("server full") // Server currently at maximum TCP connections
errPlayerAlreadyExists = errors.New("player already exists")
errServerFull = errors.New("server full") // Server currently at maximum TCP connections
)
// GameServer manages a copy of the map and entities as well as manages packet routing and connections.
@ -102,12 +103,13 @@ func NewGameServer(networkServer bool, maxConnections ...int) (*GameServer, erro
// Start essentially starts all of the game server go routines as well as begins listening for connection. This will
// return an error if it is unable to bind to a socket.
func (g *GameServer) Start() error {
listenerAddress := "127.0.0.1:" + Port
listenerAddress := "127.0.0.1:" + port
if g.networkServer {
listenerAddress = "0.0.0.0:" + Port
listenerAddress = "0.0.0.0:" + port
}
log.Printf("Starting Game Server @ %s\n", listenerAddress)
l, err := net.Listen("tcp4", listenerAddress)
if err != nil {
return err
@ -132,11 +134,14 @@ func (g *GameServer) Start() error {
return nil
}
// Stop stops the game server
func (g *GameServer) Stop() {
g.Lock()
g.cancel()
g.listener.Close()
if err := g.listener.Close(); err != nil {
log.Printf("failed to close the listener %s, err: %v\n", g.listener.Addr(), err)
}
}
// packetManager is meant to be started as a Goroutine and is used to manage routing of packets to clients.
@ -155,6 +160,7 @@ func (g *GameServer) packetManager() {
if err != nil {
log.Printf("Unable to unmarshal PlayerConnectionRequestPacket: %s\n", err)
}
g.sendPacketToClients(player)
case d2netpackettype.MovePlayer:
move, err := d2netpacket.UnmarshalNetPacket(p)
@ -162,6 +168,7 @@ func (g *GameServer) packetManager() {
log.Println(err)
continue
}
g.sendPacketToClients(move)
case d2netpackettype.SpawnItem:
item, err := d2netpacket.UnmarshalNetPacket(p)
@ -169,6 +176,7 @@ func (g *GameServer) packetManager() {
log.Println(err)
continue
}
g.sendPacketToClients(item)
case d2netpackettype.ServerClosed:
g.Stop()
@ -179,7 +187,9 @@ func (g *GameServer) packetManager() {
func (g *GameServer) sendPacketToClients(packet d2netpacket.NetPacket) {
for _, c := range g.connections {
c.SendPacketToClient(packet)
if err := c.SendPacketToClient(packet); err != nil {
log.Printf("GameServer: error sending packet: %s to client %s: %s", packet.PacketType, c.GetUniqueID(), err)
}
}
}
@ -187,10 +197,16 @@ func (g *GameServer) sendPacketToClients(packet d2netpacket.NetPacket) {
// via Go Routine. Context should be a property of the GameServer Struct.
func (g *GameServer) handleConnection(conn net.Conn) {
var connected int
var packet d2netpacket.NetPacket
log.Printf("Accepting connection: %s", conn.RemoteAddr().String())
defer conn.Close()
log.Printf("Accepting connection: %s\n", conn.RemoteAddr().String())
defer func() {
if err := conn.Close(); err != nil {
log.Printf("failed to close the connection: %s\n", conn.RemoteAddr())
}
}()
decoder := json.NewDecoder(conn)
@ -212,11 +228,11 @@ func (g *GameServer) handleConnection(conn net.Conn) {
// TODO: I do not think this error check actually works. Need to retrofit with Errors.Is().
if err := g.registerConnection(packet.PacketData, conn); err != nil {
switch err {
case ErrServerFull: // Server is currently full and not accepting new connections.
case errServerFull: // Server is currently full and not accepting new connections.
// TODO: Need to create a new Server Full packet to return to clients.
log.Println(err)
return
case ErrPlayerAlreadyExists: // Player is already registered and did not disconnection correctly.
case errPlayerAlreadyExists: // Player is already registered and did not disconnection correctly.
log.Println(err)
return
}
@ -237,14 +253,14 @@ func (g *GameServer) handleConnection(conn net.Conn) {
// registerConnection accepts a PlayerConnectionRequestPacket and thread safely updates the connection pool
//
// Errors:
// - ErrServerFull
// - ErrPlayerAlreadyExists
// - errServerFull
// - errPlayerAlreadyExists
func (g *GameServer) registerConnection(b []byte, conn net.Conn) error {
g.Lock()
// check to see if the server is full
if len(g.connections) >= g.maxConnections {
return ErrServerFull
return errServerFull
}
// if it is not full, unmarshal the playerConnectionRequest
@ -255,7 +271,7 @@ func (g *GameServer) registerConnection(b []byte, conn net.Conn) error {
// check to see if the player is already registered
if _, ok := g.connections[packet.ID]; ok {
return ErrPlayerAlreadyExists
return errPlayerAlreadyExists
}
// Client a new TCP Client Connection and add it to the connections map
@ -274,48 +290,7 @@ func (g *GameServer) registerConnection(b []byte, conn net.Conn) error {
// This really should be deferred however to much time will be spend holding a lock when we attempt to send a packet
g.Unlock()
if err := client.SendPacketToClient(d2netpacket.CreateUpdateServerInfoPacket(g.seed, client.GetUniqueID())); err != nil {
log.Printf("GameServer: error sending UpdateServerInfoPacket to client %s: %s", client.GetUniqueID(), err)
}
if err := client.SendPacketToClient(d2netpacket.CreateGenerateMapPacket(d2enum.RegionAct1Town)); err != nil {
log.Printf("GameServer: error sending GenerateMapPacket to client %s: %s", client.GetUniqueID(), err)
}
playerState := client.GetPlayerState()
// these are in subtiles
playerX := int(sx*subtilesPerTile) + middleOfTileOffset
playerY := int(sy*subtilesPerTile) + middleOfTileOffset
createPlayerPacket := d2netpacket.CreateAddPlayerPacket(client.GetUniqueID(),
playerState.HeroName, playerX, playerY,
playerState.HeroType, playerState.Stats, playerState.Equipment)
for _, connection := range g.connections {
err := connection.SendPacketToClient(createPlayerPacket)
if err != nil {
log.Printf("GameServer: error sending %T to client %s: %s", createPlayerPacket, connection.GetUniqueID(), err)
}
if connection.GetUniqueID() == client.GetUniqueID() {
continue
}
conPlayerState := connection.GetPlayerState()
playerX := int(conPlayerState.X*subtilesPerTile) + middleOfTileOffset
playerY := int(conPlayerState.Y*subtilesPerTile) + middleOfTileOffset
err = client.SendPacketToClient(d2netpacket.CreateAddPlayerPacket(
connection.GetUniqueID(),
conPlayerState.HeroName,
playerX, playerY,
conPlayerState.HeroType,
conPlayerState.Stats, conPlayerState.Equipment),
)
if err != nil {
log.Printf("GameServer: error sending CreateAddPlayerPacket to client %s: %s", connection.GetUniqueID(), err)
}
}
handleClientConnection(g, client, sx, sy)
return nil
}
@ -338,14 +313,17 @@ func OnClientConnected(client ClientConnection) {
log.Printf("Client connected with an id of %s", client.GetUniqueID())
singletonServer.connections[client.GetUniqueID()] = client
err := client.SendPacketToClient(d2netpacket.CreateUpdateServerInfoPacket(singletonServer.seed, client.GetUniqueID()))
handleClientConnection(singletonServer, client, sx, sy)
}
func handleClientConnection(gameServer *GameServer, client ClientConnection, x, y float64) {
err := client.SendPacketToClient(d2netpacket.CreateUpdateServerInfoPacket(gameServer.seed, client.GetUniqueID()))
if err != nil {
log.Printf("GameServer: error sending UpdateServerInfoPacket to client %s: %s", client.GetUniqueID(), err)
}
err = client.SendPacketToClient(d2netpacket.CreateGenerateMapPacket(d2enum.RegionAct1Town))
if err != nil {
log.Printf("GameServer: error sending GenerateMapPacket to client %s: %s", client.GetUniqueID(), err)
}
@ -353,14 +331,20 @@ func OnClientConnected(client ClientConnection) {
playerState := client.GetPlayerState()
// these are in subtiles
playerX := int(sx*subtilesPerTile) + middleOfTileOffset
playerY := int(sy*subtilesPerTile) + middleOfTileOffset
playerX := int(x*subtilesPerTile) + middleOfTileOffset
playerY := int(y*subtilesPerTile) + middleOfTileOffset
createPlayerPacket := d2netpacket.CreateAddPlayerPacket(client.GetUniqueID(),
playerState.HeroName, playerX, playerY,
playerState.HeroType, playerState.Stats, playerState.Equipment)
createPlayerPacket := d2netpacket.CreateAddPlayerPacket(
client.GetUniqueID(),
playerState.HeroName,
playerX,
playerY,
playerState.HeroType,
playerState.Stats,
playerState.Equipment,
)
for _, connection := range singletonServer.connections {
for _, connection := range gameServer.connections {
err := connection.SendPacketToClient(createPlayerPacket)
if err != nil {
log.Printf("GameServer: error sending %T to client %s: %s", createPlayerPacket, connection.GetUniqueID(), err)
@ -373,12 +357,16 @@ func OnClientConnected(client ClientConnection) {
conPlayerState := connection.GetPlayerState()
playerX := int(conPlayerState.X*subtilesPerTile) + middleOfTileOffset
playerY := int(conPlayerState.Y*subtilesPerTile) + middleOfTileOffset
err = client.SendPacketToClient(d2netpacket.CreateAddPlayerPacket(
connection.GetUniqueID(),
conPlayerState.HeroName,
playerX, playerY,
conPlayerState.HeroType,
conPlayerState.Stats, conPlayerState.Equipment),
err = client.SendPacketToClient(
d2netpacket.CreateAddPlayerPacket(
connection.GetUniqueID(),
conPlayerState.HeroName,
playerX,
playerY,
conPlayerState.HeroType,
conPlayerState.Stats,
conPlayerState.Equipment,
),
)
if err != nil {