diff --git a/character.go b/character.go index 9f0db06..7450446 100644 --- a/character.go +++ b/character.go @@ -223,17 +223,23 @@ func NewCharacter(r io.Reader) (*Character, error) { return c, nil } +func (c *Character) GetName() string { + if len(c.Name) > nameSize { + return c.Name[:nameSize] + } + return c.Name +} + +func (c *Character) getNameBytes() [nameSize]byte { + var charName [nameSize]byte + copy(charName[:], c.GetName()[:]) + return charName +} + //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) - var charName [nameSize]byte - if len(c.Name) > nameSize { - c.Name = c.Name[:nameSize] - } - copy(charName[:], c.Name[:]) + var values [27]interface{} type packedChan struct { result []byte @@ -258,52 +264,52 @@ func (c *Character) ToWriter(w io.Writer) error { 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) - values = append(values, c.Unk0x0026) - values = append(values, c.Class) - values = append(values, c.Unk0x0029) - values = append(values, c.Level) - values = append(values, c.Created) - values = append(values, c.LastPlayed) - values = append(values, c.Unk0x0034) - values = append(values, c.HotkeySkills) - values = append(values, c.LeftSkill) - values = append(values, c.RightSkill) - values = append(values, c.LeftSwapSkill) - values = append(values, c.RightSwapSkill) - values = append(values, c.Appearances) - - 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) - - questsB := <-questsCh - if questsB.err != nil { - return questsB.err - } - - values = append(values, questsB.result) - - waypointsB := <-waypointsCh - if waypointsB.err != nil { - return waypointsB.err - } - - values = append(values, waypointsB.result) - values = append(values, c.UnkUnk1) - - dialogsB := <-dialogsCh - if dialogsB.err != nil { - return dialogsB.err + values[0] = *c.Header + values[1] = c.ActiveWeapon + values[2] = c.getNameBytes() + values[3] = c.Status.GetFlags() + values[4] = c.Progression + values[5] = c.Unk0x0026 + values[6] = c.Class + values[7] = c.Unk0x0029 + values[8] = c.Level + values[9] = c.Created + values[10] = c.LastPlayed + values[11] = c.Unk0x0034 + values[12] = c.HotkeySkills + values[13] = c.LeftSkill + values[14] = c.RightSkill + values[15] = c.LeftSwapSkill + values[16] = c.RightSwapSkill + values[17] = c.Appearances + values[19] = c.MapID + values[20] = c.Unk0x00af + values[21] = c.Mercenary + values[22] = c.RealmData + values[25] = c.UnkUnk1 + + for range make([]bool, 4) { + select { + case locationsB := <-locationsCh: + values[18] = locationsB.result + case questsB := <-questsCh: + if questsB.err != nil { + return questsB.err + } + values[23] = questsB.result + case waypointsB := <-waypointsCh: + if waypointsB.err != nil { + return waypointsB.err + } + values[24] = waypointsB.result + case dialogsB := <-dialogsCh: + if dialogsB.err != nil { + return dialogsB.err + } + values[26] = dialogsB.result + } } - values = append(values, dialogsB.result) - for _, val := range values { if err := binary.Write(ww, consts.BinaryEndian, val); err != nil { return err diff --git a/d2editor_test.go b/d2editor_test.go index e981661..95ac749 100644 --- a/d2editor_test.go +++ b/d2editor_test.go @@ -3,100 +3,169 @@ package d2editor_test import ( "encoding/json" "github.com/vitalick/go-d2editor" + "sync" "testing" ) -func createEmpty(b *testing.B) *d2editor.Character { +func createEmpty(b *testing.B, wg *sync.WaitGroup) *d2editor.Character { c, _ := d2editor.NewEmptyCharacter(97) + if wg != nil { + wg.Done() + } return c } -func openOne(b *testing.B) *d2editor.Character { +func openOne(b *testing.B, wg *sync.WaitGroup) *d2editor.Character { c, _ := d2editor.Open("LoD-Druid.d2s") + if wg != nil { + wg.Done() + } return c } -func openJSON(b *testing.B) *d2editor.Character { +func openJSON(b *testing.B, wg *sync.WaitGroup) *d2editor.Character { c, _ := d2editor.OpenJSON("LoD-Druid2.json") + if wg != nil { + wg.Done() + } return c } -func saveOne(b *testing.B, c *d2editor.Character) { +func saveOne(b *testing.B, c *d2editor.Character, wg *sync.WaitGroup) { c.GetBytes() + if wg != nil { + wg.Done() + } } -func saveJSON(b *testing.B, c *d2editor.Character) { +func saveJSON(b *testing.B, c *d2editor.Character, wg *sync.WaitGroup) { json.Marshal(c) + if wg != nil { + wg.Done() + } } -func createSaveEmpty(b *testing.B) { - saveOne(b, createEmpty(b)) +func createSaveEmpty(b *testing.B, wg *sync.WaitGroup) { + saveOne(b, createEmpty(b, nil), nil) + if wg != nil { + wg.Done() + } } -func openSaveOne(b *testing.B) { - saveOne(b, openOne(b)) +func openSaveOne(b *testing.B, wg *sync.WaitGroup) { + saveOne(b, openOne(b, nil), nil) + if wg != nil { + wg.Done() + } } -func openSaveJSON(b *testing.B) { - saveJSON(b, openJSON(b)) +func openSaveJSON(b *testing.B, wg *sync.WaitGroup) { + saveJSON(b, openJSON(b, nil), nil) + if wg != nil { + wg.Done() + } } -func BenchmarkCreateEmptyConcurrently(b *testing.B) { +func BenchmarkCreateEmpty(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go createEmpty(b) + wg.Add(1) + go createEmpty(b, wg) } + wg.Wait() } -func BenchmarkSaveEmptyConcurrently(b *testing.B) { - c := createEmpty(b) +func BenchmarkSaveEmpty(b *testing.B) { + wg := &sync.WaitGroup{} + c := createEmpty(b, nil) b.ResetTimer() for range make([]bool, b.N) { - go saveOne(b, c) + wg.Add(1) + go saveOne(b, c, wg) } + wg.Wait() } -func BenchmarkCreateSaveEmptyConcurrently(b *testing.B) { +func BenchmarkCreateSaveEmpty(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go createSaveEmpty(b) + wg.Add(1) + go createSaveEmpty(b, wg) } + wg.Wait() } -func BenchmarkOpenConcurrently(b *testing.B) { +func BenchmarkOpen(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go openOne(b) + wg.Add(1) + go openOne(b, wg) } + wg.Wait() } -func BenchmarkSaveFileConcurrently(b *testing.B) { - c := openOne(b) +func BenchmarkSaveFile(b *testing.B) { + wg := &sync.WaitGroup{} + c := openOne(b, nil) b.ResetTimer() for range make([]bool, b.N) { - go saveOne(b, c) + wg.Add(1) + go saveOne(b, c, wg) } + wg.Wait() } -func BenchmarkOpenSaveConcurrently(b *testing.B) { +func BenchmarkOpenSave(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go openSaveOne(b) + wg.Add(1) + go openSaveOne(b, wg) } + wg.Wait() } -func BenchmarkOpenJSONConcurrently(b *testing.B) { +func BenchmarkOpenJSON(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go openJSON(b) + wg.Add(1) + go openJSON(b, wg) } + wg.Wait() } -func BenchmarkSaveJSONConcurrently(b *testing.B) { - c := openJSON(b) +func BenchmarkSaveJSON(b *testing.B) { + wg := &sync.WaitGroup{} + c := openJSON(b, nil) b.ResetTimer() for range make([]bool, b.N) { - go saveJSON(b, c) + wg.Add(1) + go saveJSON(b, c, wg) } + wg.Wait() } -func BenchmarkOpenSaveJSONConcurrently(b *testing.B) { +func BenchmarkOpenSaveJSON(b *testing.B) { + wg := &sync.WaitGroup{} + b.ResetTimer() + for range make([]bool, b.N) { + wg.Add(1) + go openSaveJSON(b, wg) + } + wg.Wait() +} + +func BenchmarkOpenD2sSaveJSON(b *testing.B) { + c := openOne(b, nil) + wg := &sync.WaitGroup{} + b.ResetTimer() for range make([]bool, b.N) { - go openSaveJSON(b) + wg.Add(1) + go saveJSON(b, c, wg) } + wg.Wait() }