Skip to content

Commit

Permalink
optimize acts/waypoints/dialogs titles
Browse files Browse the repository at this point in the history
add benchmark
optimize calc header
  • Loading branch information
Vitalick committed Oct 17, 2021
1 parent a2d376b commit 2611a11
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 237 deletions.
89 changes: 48 additions & 41 deletions character.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,9 @@ func NewCharacter(r io.Reader) (*Character, error) {
return c, nil
}

//Fix changes struct for export
func (c *Character) Fix() error {
if err := c.Header.Fix(c); err != nil {
return err
}
return nil
}

//ToWriter write not prepared for export byte struct to io.Writer
func (c *Character) ToWriter(w io.Writer) error {
ww := &writerWrapper{w: w}
var values []interface{}
values = append(values, *c.Header)
values = append(values, c.ActiveWeapon)
Expand All @@ -241,6 +234,30 @@ func (c *Character) ToWriter(w io.Writer) error {
c.Name = c.Name[:nameSize]
}
copy(charName[:], c.Name[:])

type packedChan struct {
result []byte
err error
}

locationsCh := make(chan packedChan)
questsCh := make(chan packedChan)
waypointsCh := make(chan packedChan)
dialogsCh := make(chan packedChan)

getPackedChan := func(f func() ([]byte, error), ch chan packedChan) {
b, err := f()
if err != nil {
ch <- packedChan{nil, err}
return
}
ch <- packedChan{b, nil}
}
go getPackedChan(func() ([]byte, error) { return c.Locations.GetPacked(), nil }, locationsCh)
go getPackedChan(c.Quests.GetPacked, questsCh)
go getPackedChan(c.Waypoints.GetPacked, waypointsCh)
go getPackedChan(c.NPCDialogs.GetPacked, dialogsCh)

values = append(values, charName)
values = append(values, c.Status.GetFlags())
values = append(values, c.Progression)
Expand All @@ -257,42 +274,42 @@ func (c *Character) ToWriter(w io.Writer) error {
values = append(values, c.LeftSwapSkill)
values = append(values, c.RightSwapSkill)
values = append(values, c.Appearances)
values = append(values, c.Locations.GetPacked())

values = append(values, (<-locationsCh).result)

values = append(values, c.MapID)
values = append(values, c.Unk0x00af)
values = append(values, c.Mercenary)
values = append(values, c.RealmData)
packedData, err := c.Quests.GetPacked()
if err != nil {
return err

questsB := <-questsCh
if questsB.err != nil {
return questsB.err
}
values = append(values, packedData)
packedData, err = c.Waypoints.GetPacked()
if err != nil {
return err

values = append(values, questsB.result)

waypointsB := <-waypointsCh
if waypointsB.err != nil {
return waypointsB.err
}
values = append(values, packedData)

values = append(values, waypointsB.result)
values = append(values, c.UnkUnk1)
packedData, err = c.NPCDialogs.GetPacked()
if err != nil {
return err

dialogsB := <-dialogsCh
if dialogsB.err != nil {
return dialogsB.err
}
values = append(values, packedData)

values = append(values, dialogsB.result)

for _, val := range values {
if err := binary.Write(w, consts.BinaryEndian, val); err != nil {
if err := binary.Write(ww, consts.BinaryEndian, val); err != nil {
return err
}
}
return nil
}

//ToWriterCorrect write prepared for export byte struct to io.Writer
func (c *Character) ToWriterCorrect(w io.Writer) error {
if err := c.Fix(); err != nil {
return err
}
if err := c.ToWriter(w); err != nil {
if _, err := ww.EndWrite(); err != nil {
return err
}
return nil
Expand All @@ -306,13 +323,3 @@ func (c *Character) GetBytes() ([]byte, error) {
}
return buf.Bytes(), nil
}

//GetCorrectBytes return prepared for export []byte
func (c *Character) GetCorrectBytes() ([]byte, error) {
var buf bytes.Buffer
//bw := bufio.NewWriter(&buf)
if err := c.ToWriterCorrect(&buf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
2 changes: 1 addition & 1 deletion d2editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func Save(c *Character, folder string) error {

defer file.Close()

err = c.ToWriterCorrect(file)
err = c.ToWriter(file)
if err != nil {
fmt.Fprintln(os.Stderr, "Error while writing buffer file")
return err
Expand Down
101 changes: 88 additions & 13 deletions d2editor_test.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,102 @@
package d2editor_test

import (
"encoding/json"
"github.com/vitalick/go-d2editor"
"testing"
)

func benchOne(b *testing.B, ch chan []byte) {
func createEmpty(b *testing.B) *d2editor.Character {
c, _ := d2editor.NewEmptyCharacter(97)
bts, _ := c.GetCorrectBytes()
ch <- bts
return c
}

func BenchmarkCreateEmpty(b *testing.B) {
var c = make(chan []byte)
count := 0
func openOne(b *testing.B) *d2editor.Character {
c, _ := d2editor.Open("LoD-Druid.d2s")
return c
}

func openJSON(b *testing.B) *d2editor.Character {
c, _ := d2editor.OpenJSON("LoD-Druid2.json")
return c
}

func saveOne(b *testing.B, c *d2editor.Character) {
c.GetBytes()
}

func saveJSON(b *testing.B, c *d2editor.Character) {
json.Marshal(c)
}

func createSaveEmpty(b *testing.B) {
saveOne(b, createEmpty(b))
}

func openSaveOne(b *testing.B) {
saveOne(b, openOne(b))
}

func openSaveJSON(b *testing.B) {
saveJSON(b, openJSON(b))
}

func BenchmarkCreateEmptyConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go createEmpty(b)
}
}

func BenchmarkSaveEmptyConcurrently(b *testing.B) {
c := createEmpty(b)
b.ResetTimer()
for range make([]bool, b.N) {
go benchOne(b, c)
go saveOne(b, c)
}
for range c {
count++
if count == b.N {
break
}
}

func BenchmarkCreateSaveEmptyConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go createSaveEmpty(b)
}
}

func BenchmarkOpenConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go openOne(b)
}
}

func BenchmarkSaveFileConcurrently(b *testing.B) {
c := openOne(b)
b.ResetTimer()
for range make([]bool, b.N) {
go saveOne(b, c)
}
}

func BenchmarkOpenSaveConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go openSaveOne(b)
}
}

func BenchmarkOpenJSONConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go openJSON(b)
}
}

func BenchmarkSaveJSONConcurrently(b *testing.B) {
c := openJSON(b)
b.ResetTimer()
for range make([]bool, b.N) {
go saveJSON(b, c)
}
}

func BenchmarkOpenSaveJSONConcurrently(b *testing.B) {
for range make([]bool, b.N) {
go openSaveJSON(b)
}
close(c)
}
49 changes: 6 additions & 43 deletions header.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,48 +33,11 @@ func NewHeader(r io.Reader) (*Header, error) {
return h, nil
}

//Fix changes filesize and checksum on struct
func (h *Header) Fix(c *Character) error {
err := h.fixBytes(c)
if err != nil {
return err
func ChecksumAppend(b byte, c int) int {
secondVal := 0
if c < 0 {
secondVal = 1
}
return nil
}

func (h *Header) fixBytes(c *Character) error {
if err := h.fixSize(c); err != nil {
return err
}
if err := h.fixChecksum(c); err != nil {
return err
}
return nil
}

func (h *Header) fixChecksum(c *Character) error {
h.Checksum = 0
b, err := c.GetBytes()
if err != nil {
return err
}
checksum := 0
for _, b := range b {
secondVal := 0
if checksum < 0 {
secondVal = 1
}
checksum = int(b) + checksum*2 + secondVal
}
h.Checksum = uint32(checksum)
return nil
}

func (h *Header) fixSize(c *Character) error {
b, err := c.GetBytes()
if err != nil {
return err
}
h.Filesize = uint32(len(b))
return nil
c = int(b) + c*2 + secondVal
return c
}
6 changes: 3 additions & 3 deletions locations.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewLocations(r io.Reader) (*Locations, error) {
}, nil
}

//GetPacked returns packed locations to 3 bytes
func (l *Locations) GetPacked() [locationsCount]byte {
return [3]byte{l.Normal.GetPacked(), l.Nightmare.GetPacked(), l.Hell.GetPacked()}
//GetPacked returns packed locations to bytes
func (l *Locations) GetPacked() []byte {
return []byte{l.Normal.GetPacked(), l.Nightmare.GetPacked(), l.Hell.GetPacked()}
}
14 changes: 7 additions & 7 deletions quests/act.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ type Act struct {
//NewEmptyAct returns empty Act
func NewEmptyAct(a consts.ActID) (*Act, error) {
act := &Act{id: a}
actLength, ok := actLengths[a]
if !ok {
if int(a) >= len(actLengths) {
return nil, actNotExists
}
actLength := actLengths[a]
act.quests = make([]Quest, actLength)
for q := range act.quests {
quest, err := NewEmptyQuest(a, ActQuest(q))
Expand Down Expand Up @@ -83,16 +83,16 @@ func (a *Act) MarshalJSON() ([]byte, error) {

// ImportMap ...
func (a *Act) ImportMap(importMap ActImportMap) error {
actMap, ok := actQuestsMap[a.id]
if !ok {
if int(a.id) >= consts.ActsCount {
return actNotExists
}
actMap := actQuestsMap[a.id]
for quest := range make([]bool, actLengths[a.id]) {
actQuest := ActQuest(quest)
questMapTitle, ok := actMap[actQuest]
if !ok {
if quest >= actLengths[a.id] {
continue
}
actQuest := ActQuest(quest)
questMapTitle := actMap[actQuest]
questMapTitle = utils.TitleToJSONTitle(questMapTitle)
questImportMap, ok := importMap[questMapTitle]
if !ok {
Expand Down
Loading

0 comments on commit 2611a11

Please sign in to comment.