lint fixes (#727)
This commit is contained in:
parent
3988bd7f1c
commit
f4a71c72e4
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,7 +2,7 @@ package d2datadict
|
|||
|
||||
import (
|
||||
"log"
|
||||
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||
)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,7 +2,7 @@ package d2datadict
|
|||
|
||||
import (
|
||||
"log"
|
||||
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package d2datadict
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package d2datadict
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2txt"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2dcc
|
|||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
|
||||
)
|
||||
|
||||
|
|
|
@ -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!")
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2dt1
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"image"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util/assets"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2asset
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2cache"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package d2maprenderer
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
|
||||
)
|
||||
|
||||
type worldTrans struct {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -23,7 +23,7 @@ func (v *BlizzardIntro) OnLoad(loading d2screen.LoadingState) {
|
|||
loading.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
loading.Progress(fiftyPercent)
|
||||
|
||||
v.videoDecoder = d2video.CreateBinkDecoder(videoBytes)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2netpacket
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
|
||||
)
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2netpacket
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package d2netpacket
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2netpacket/d2netpackettype"
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -35,5 +35,6 @@ func UnmarshalPong(packet []byte) (PongPacket, error) {
|
|||
if err := json.Unmarshal(packet, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
|
|
@ -33,5 +33,6 @@ func UnmarshalServerClosed(packet []byte) (ServerClosedPacket, error) {
|
|||
if err := json.Unmarshal(packet, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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.*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue