From 2859eae91c1dd4e5897fee5e6453c2786a30b83b Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 10:02:10 +0100 Subject: [PATCH 1/7] Revert "data encoding: tbl" This reverts commit 5a0571763ed5e5f76550bfb5e0d4be5b810f3f0e. --- .../d2fileformats/d2tbl/text_dictionary.go | 161 ++++-------------- .../d2tbl/text_dictionary_test.go | 11 ++ d2core/d2asset/asset_manager.go | 27 ++- d2core/d2asset/d2asset.go | 2 +- 4 files changed, 54 insertions(+), 147 deletions(-) create mode 100644 d2common/d2fileformats/d2tbl/text_dictionary_test.go diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index 8aea6139..b744bfc9 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -2,36 +2,25 @@ package d2tbl import ( "errors" - "sort" "strconv" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils" ) // TextDictionary is a string map -type TextDictionary struct { - crcBytes []byte - elementIndex []uint16 - hashTableSize uint32 - version byte - stringOffset uint32 - unknown1 uint32 - fileSize uint32 - hashEntries []*textDictionaryHashEntry - Entries map[string]string -} +type TextDictionary map[string]string -func (td *TextDictionary) loadHashEntries(br *d2datautils.StreamReader) error { - var err error - - for i := 0; i < len(td.hashEntries); i++ { +func (td TextDictionary) loadHashEntries(hashEntries []*textDictionaryHashEntry, br *d2datautils.StreamReader) error { + for i := 0; i < len(hashEntries); i++ { entry := textDictionaryHashEntry{} - entry.active, err = br.ReadByte() + active, err := br.ReadByte() if err != nil { return err } + entry.IsActive = active > 0 + entry.Index, err = br.ReadUInt16() if err != nil { return err @@ -57,15 +46,15 @@ func (td *TextDictionary) loadHashEntries(br *d2datautils.StreamReader) error { return err } - td.hashEntries[i] = &entry + hashEntries[i] = &entry } - for idx := range td.hashEntries { - if !td.hashEntries[idx].IsActive() { + for idx := range hashEntries { + if !hashEntries[idx].IsActive { continue } - if err := td.loadHashEntry(idx, td.hashEntries[idx], br); err != nil { + if err := td.loadHashEntry(idx, hashEntries[idx], br); err != nil { return err } } @@ -73,9 +62,7 @@ func (td *TextDictionary) loadHashEntries(br *d2datautils.StreamReader) error { return nil } -func (td *TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEntry, br *d2datautils.StreamReader) error { - var err error - +func (td TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEntry, br *d2datautils.StreamReader) error { br.SetPosition(uint64(hashEntry.NameString)) nameVal, err := br.ReadBytes(int(hashEntry.NameLength - 1)) @@ -83,7 +70,7 @@ func (td *TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEn return err } - hashEntry.name = string(nameVal) + value := string(nameVal) br.SetPosition(uint64(hashEntry.IndexString)) @@ -102,33 +89,25 @@ func (td *TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEn key += string(b) } - hashEntry.key = key - - if hashEntry.key == "x" || hashEntry.key == "X" { + if key == "x" || key == "X" { key = "#" + strconv.Itoa(idx) } - _, exists := td.Entries[key] + _, exists := td[key] if !exists { - td.Entries[key] = hashEntry.name + td[key] = value } return nil } type textDictionaryHashEntry struct { - name string - key string + IsActive bool + Index uint16 HashValue uint32 IndexString uint32 NameString uint32 - Index uint16 NameLength uint16 - active byte -} - -func (t *textDictionaryHashEntry) IsActive() bool { - return t.active > 0 } const ( @@ -136,54 +115,38 @@ const ( ) // LoadTextDictionary loads the text dictionary from the given data -func LoadTextDictionary(dictionaryData []byte) (*TextDictionary, error) { - var err error - - lookupTable := &TextDictionary{ - Entries: make(map[string]string), - } +func LoadTextDictionary(dictionaryData []byte) (TextDictionary, error) { + lookupTable := make(TextDictionary) br := d2datautils.CreateStreamReader(dictionaryData) // skip past the CRC - lookupTable.crcBytes, err = br.ReadBytes(crcByteCount) - if err != nil { - return nil, err - } + _, _ = br.ReadBytes(crcByteCount) + + var err error numberOfElements, err := br.ReadUInt16() if err != nil { return nil, err } - lookupTable.hashTableSize, err = br.ReadUInt32() + hashTableSize, err := br.ReadUInt32() if err != nil { return nil, err } // Version (always 0) - if lookupTable.version, err = br.ReadByte(); err != nil { + if _, err = br.ReadByte(); err != nil { return nil, errors.New("error reading Version record") } - // StringOffset - lookupTable.stringOffset, err = br.ReadUInt32() - if err != nil { - return nil, errors.New("error reading string offset") - } + _, _ = br.ReadUInt32() // StringOffset // When the number of times you have missed a match with a // hash key equals this value, you give up because it is not there. - lookupTable.unknown1, err = br.ReadUInt32() - if err != nil { - return nil, err - } + _, _ = br.ReadUInt32() - // FileSize - lookupTable.fileSize, err = br.ReadUInt32() - if err != nil { - return nil, err - } + _, _ = br.ReadUInt32() // FileSize elementIndex := make([]uint16, numberOfElements) for i := 0; i < int(numberOfElements); i++ { @@ -193,78 +156,12 @@ func LoadTextDictionary(dictionaryData []byte) (*TextDictionary, error) { } } - lookupTable.elementIndex = elementIndex + hashEntries := make([]*textDictionaryHashEntry, hashTableSize) - lookupTable.hashEntries = make([]*textDictionaryHashEntry, lookupTable.hashTableSize) - - err = lookupTable.loadHashEntries(br) + err = lookupTable.loadHashEntries(hashEntries, br) if err != nil { return nil, err } return lookupTable, nil } - -// Marshal encodes text dictionary back to byte slice -func (td *TextDictionary) Marshal() []byte { - // create stream writter - sw := d2datautils.CreateStreamWriter() - - sw.PushBytes(td.crcBytes...) - sw.PushUint16(uint16(len(td.elementIndex))) - sw.PushUint32(td.hashTableSize) - sw.PushBytes(td.version) - sw.PushUint32(td.stringOffset) - sw.PushUint32(td.unknown1) - - sw.PushUint32(td.fileSize) - - for _, i := range td.elementIndex { - sw.PushUint16(i) - } - - for i := 0; i < len(td.hashEntries); i++ { - sw.PushBytes(td.hashEntries[i].active) - sw.PushUint16(td.hashEntries[i].Index) - sw.PushUint32(td.hashEntries[i].HashValue) - sw.PushUint32(td.hashEntries[i].IndexString) - sw.PushUint32(td.hashEntries[i].NameString) - sw.PushUint16(td.hashEntries[i].NameLength) - } - - // values are table entries data (key & values) - var values map[int]string = make(map[int]string) - // valuesSorted are sorted values - var valuesSorted map[int]string = make(map[int]string) - - // add values key / names to map - for _, i := range td.hashEntries { - values[int(i.IndexString)] = i.key - values[int(i.NameString)] = i.name - } - - // added map keys - keys := make([]int, 0, len(values)) - for k := range values { - keys = append(keys, k) - } - - // sort keys - sort.Ints(keys) - - // create sorted values map - for _, k := range keys { - valuesSorted[k] = values[k] - } - - // add first value (without 0-byte separator) - sw.PushBytes([]byte(valuesSorted[keys[0]])...) - - // adds values to result - for i := 1; i < len(valuesSorted); i++ { - sw.PushBytes([]byte(valuesSorted[keys[i]])...) - sw.PushBytes(0) - } - - return sw.GetBytes() -} diff --git a/d2common/d2fileformats/d2tbl/text_dictionary_test.go b/d2common/d2fileformats/d2tbl/text_dictionary_test.go new file mode 100644 index 00000000..7a450953 --- /dev/null +++ b/d2common/d2fileformats/d2tbl/text_dictionary_test.go @@ -0,0 +1,11 @@ +package d2tbl + +import ( + "testing" +) + +func exampleData() *TextDictionary { + result := &TextDictionary{ + crcBytes: make([]byte, crcByteCount), + } +} diff --git a/d2core/d2asset/asset_manager.go b/d2core/d2asset/asset_manager.go index d3c8cb6f..cba1be27 100644 --- a/d2core/d2asset/asset_manager.go +++ b/d2core/d2asset/asset_manager.go @@ -65,18 +65,17 @@ type AssetManager struct { *d2util.Logger *d2loader.Loader - tables []*d2tbl.TextDictionary - dt1s d2interface.Cache - ds1s d2interface.Cache - cofs d2interface.Cache - dccs d2interface.Cache - animations d2interface.Cache - fonts d2interface.Cache - palettes d2interface.Cache - transforms d2interface.Cache - Records *d2records.RecordManager - language string - languageModifier int + tables []d2tbl.TextDictionary + dt1s d2interface.Cache + ds1s d2interface.Cache + cofs d2interface.Cache + dccs d2interface.Cache + animations d2interface.Cache + fonts d2interface.Cache + palettes d2interface.Cache + transforms d2interface.Cache + Records *d2records.RecordManager + language string } // SetLogLevel sets the log level for the asset manager, record manager, and file loader @@ -268,7 +267,7 @@ func (am *AssetManager) LoadPalette(palettePath string) (d2interface.Palette, er } // LoadStringTable loads a string table from the given path -func (am *AssetManager) LoadStringTable(tablePath string) (*d2tbl.TextDictionary, error) { +func (am *AssetManager) LoadStringTable(tablePath string) (d2tbl.TextDictionary, error) { data, err := am.LoadFile(tablePath) if err != nil { return nil, err @@ -302,7 +301,7 @@ func (am *AssetManager) TranslateString(input interface{}) string { } for idx := range am.tables { - if value, found := am.tables[idx].Entries[key]; found { + if value, found := am.tables[idx][key]; found { return value } } diff --git a/d2core/d2asset/d2asset.go b/d2core/d2asset/d2asset.go index 768a2ac0..ed5260c4 100644 --- a/d2core/d2asset/d2asset.go +++ b/d2core/d2asset/d2asset.go @@ -27,7 +27,7 @@ func NewAssetManager(logLevel d2util.LogLevel) (*AssetManager, error) { manager := &AssetManager{ Logger: logger, Loader: loader, - tables: make([]*d2tbl.TextDictionary, 0), + tables: make([]d2tbl.TextDictionary, 0), animations: d2cache.CreateCache(animationBudget), fonts: d2cache.CreateCache(fontBudget), palettes: d2cache.CreateCache(paletteBudget), From 522f749cfcfeab56a7031f780da362e91c3819f6 Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 11:58:32 +0100 Subject: [PATCH 2/7] tbl: encoder --- .../d2fileformats/d2tbl/text_dictionary.go | 106 ++++++++++++++++-- .../d2tbl/text_dictionary_test.go | 22 +++- 2 files changed, 116 insertions(+), 12 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index b744bfc9..3d53b478 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -1,7 +1,8 @@ package d2tbl import ( - "errors" + "fmt" + "strconv" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils" @@ -16,14 +17,14 @@ func (td TextDictionary) loadHashEntries(hashEntries []*textDictionaryHashEntry, active, err := br.ReadByte() if err != nil { - return err + return fmt.Errorf("reading active: %v", err) } entry.IsActive = active > 0 entry.Index, err = br.ReadUInt16() if err != nil { - return err + return fmt.Errorf("reading Index: %v", err) } entry.HashValue, err = br.ReadUInt32() @@ -55,7 +56,7 @@ func (td TextDictionary) loadHashEntries(hashEntries []*textDictionaryHashEntry, } if err := td.loadHashEntry(idx, hashEntries[idx], br); err != nil { - return err + return fmt.Errorf("loading entry %d: %v", idx, err) } } @@ -67,7 +68,7 @@ func (td TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEnt nameVal, err := br.ReadBytes(int(hashEntry.NameLength - 1)) if err != nil { - return err + return fmt.Errorf("reading name value: %v", err) } value := string(nameVal) @@ -125,19 +126,32 @@ func LoadTextDictionary(dictionaryData []byte) (TextDictionary, error) { var err error + /* + number of indicates + (https://d2mods.info/forum/viewtopic.php?p=202077#p202077) + Indices ... + An array of WORD. Each entry is an index into the hash table. + The actual string key index in the .bin file is an index into this table. + So to get a string from a key index ... + */ numberOfElements, err := br.ReadUInt16() if err != nil { - return nil, err + return nil, fmt.Errorf("reading number of elements: %v", err) } hashTableSize, err := br.ReadUInt32() if err != nil { - return nil, err + return nil, fmt.Errorf("reading hash table size: %v", err) } // Version (always 0) - if _, err = br.ReadByte(); err != nil { - return nil, errors.New("error reading Version record") + version, err := br.ReadByte() + if err != nil { + return nil, fmt.Errorf("reading version: %v", err) + } + + if version != 0 { + return nil, fmt.Errorf("version isn't equal to 0") } _, _ = br.ReadUInt32() // StringOffset @@ -152,7 +166,7 @@ func LoadTextDictionary(dictionaryData []byte) (TextDictionary, error) { for i := 0; i < int(numberOfElements); i++ { elementIndex[i], err = br.ReadUInt16() if err != nil { - return nil, err + return nil, fmt.Errorf("reading element index %d: %v", i, err) } } @@ -160,8 +174,78 @@ func LoadTextDictionary(dictionaryData []byte) (TextDictionary, error) { err = lookupTable.loadHashEntries(hashEntries, br) if err != nil { - return nil, err + return nil, fmt.Errorf("loading has entries: %v", err) } return lookupTable, nil } + +// Marshal encodes text dictionary back into byte slice +func (td *TextDictionary) Marshal() []byte { + sw := d2datautils.CreateStreamWriter() + + // https://github.com/OpenDiablo2/OpenDiablo2/issues/1043 + sw.PushBytes(0, 0) + + sw.PushUint16(0) + + sw.PushInt32(int32(len(*td))) + + // version (always 0) + sw.PushBytes(0) + + // offset of start of data (unnecessary for our decoder) + sw.PushUint32(0) + + // Max retry count for a hash hit. + sw.PushUint32(0) + + // offset to end of data (noop) + sw.PushUint32(0) + + // indicates (len = 0, so nothing here) + + // nolint:gomnd // 17 comes from the size of one "data-header index" + // dataPos is a position, when we're placing data stream + dataPos := len(sw.GetBytes()) + 17*len(*td) + + for key, value := range *td { + // non-zero if record is used (for us, every record is used ;-) + sw.PushBytes(1) + + // generally unused; + // string key index (used in .bin) + sw.PushUint16(0) + + // also unused in our decoder + // calculated hash of the string. + sw.PushUint32(0) + + sw.PushUint32(uint32(dataPos)) + dataPos += len(key) + 1 + + sw.PushUint32(uint32(dataPos)) + dataPos += len(value) + 1 + + sw.PushUint16(uint16(len(value) + 0)) + } + + // data stream: put all data in appropiate order + for key, value := range *td { + for _, i := range key { + sw.PushBytes(byte(i)) + } + + // 0 as separator + sw.PushBytes(0) + + for _, i := range value { + sw.PushBytes(byte(i)) + } + + // 0 as separator + sw.PushBytes(0) + } + + return sw.GetBytes() +} diff --git a/d2common/d2fileformats/d2tbl/text_dictionary_test.go b/d2common/d2fileformats/d2tbl/text_dictionary_test.go index 7a450953..5f04bcf4 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary_test.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary_test.go @@ -1,11 +1,31 @@ package d2tbl import ( + "fmt" + "testing" ) func exampleData() *TextDictionary { result := &TextDictionary{ - crcBytes: make([]byte, crcByteCount), + "abc": "def", + "someStr": "Some long string", + "lolstring": "lol", + } + + return result +} + +func TestTBL_Marshal(t *testing.T) { + tbl := exampleData() + data := tbl.Marshal() + newTbl, err := LoadTextDictionary(data) + if err != nil { + t.Error(err) + } + + _, ok := newTbl["lolstring"] + if !ok { + t.Fatal("no string found") } } From 91b32903221f72c892d93aa029a8b2a804aeb168 Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 12:03:00 +0100 Subject: [PATCH 3/7] tbl: completed test --- d2common/d2fileformats/d2tbl/text_dictionary.go | 2 +- .../d2fileformats/d2tbl/text_dictionary_test.go | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index 3d53b478..257be33e 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -227,7 +227,7 @@ func (td *TextDictionary) Marshal() []byte { sw.PushUint32(uint32(dataPos)) dataPos += len(value) + 1 - sw.PushUint16(uint16(len(value) + 0)) + sw.PushUint16(uint16(len(value) + 1)) } // data stream: put all data in appropiate order diff --git a/d2common/d2fileformats/d2tbl/text_dictionary_test.go b/d2common/d2fileformats/d2tbl/text_dictionary_test.go index 5f04bcf4..df5012cf 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary_test.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary_test.go @@ -19,13 +19,20 @@ func exampleData() *TextDictionary { func TestTBL_Marshal(t *testing.T) { tbl := exampleData() data := tbl.Marshal() + newTbl, err := LoadTextDictionary(data) if err != nil { t.Error(err) } - _, ok := newTbl["lolstring"] - if !ok { - t.Fatal("no string found") + for key, value := range *tbl { + newValue, ok := newTbl[key] + fmt.Println(newValue, value) + if !ok { + t.Fatal("string wasn't encoded to table") + } + if newValue != value { + t.Fatal("unexpected value set") + } } } From e163c40107ca316d0fa7178e84190f527e21a90f Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 12:06:37 +0100 Subject: [PATCH 4/7] tbl: completed error mesages --- d2common/d2fileformats/d2tbl/text_dictionary.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index 257be33e..cb108dd8 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -29,22 +29,22 @@ func (td TextDictionary) loadHashEntries(hashEntries []*textDictionaryHashEntry, entry.HashValue, err = br.ReadUInt32() if err != nil { - return err + return fmt.Errorf("reading hash value: %v", err) } entry.IndexString, err = br.ReadUInt32() if err != nil { - return err + return fmt.Errorf("reading index string pos: %v", err) } entry.NameString, err = br.ReadUInt32() if err != nil { - return err + return fmt.Errorf("reading name string pos: %v", err) } entry.NameLength, err = br.ReadUInt16() if err != nil { - return err + return fmt.Errorf("reading name length: %v", err) } hashEntries[i] = &entry @@ -84,7 +84,7 @@ func (td TextDictionary) loadHashEntry(idx int, hashEntry *textDictionaryHashEnt } if err != nil { - return err + return fmt.Errorf("reading kay char: %v", err) } key += string(b) From 3b8cdffe151c9b5965fd0141f7a88906665055ba Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 12:08:02 +0100 Subject: [PATCH 5/7] tbl: lintfix --- d2common/d2fileformats/d2tbl/text_dictionary.go | 2 +- d2common/d2fileformats/d2tbl/text_dictionary_test.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index cb108dd8..4413d5c2 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -230,7 +230,7 @@ func (td *TextDictionary) Marshal() []byte { sw.PushUint16(uint16(len(value) + 1)) } - // data stream: put all data in appropiate order + // data stream: put all data in appropriate order for key, value := range *td { for _, i := range key { sw.PushBytes(byte(i)) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary_test.go b/d2common/d2fileformats/d2tbl/text_dictionary_test.go index df5012cf..bfb0794a 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary_test.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary_test.go @@ -1,8 +1,6 @@ package d2tbl import ( - "fmt" - "testing" ) @@ -27,10 +25,11 @@ func TestTBL_Marshal(t *testing.T) { for key, value := range *tbl { newValue, ok := newTbl[key] - fmt.Println(newValue, value) + if !ok { t.Fatal("string wasn't encoded to table") } + if newValue != value { t.Fatal("unexpected value set") } From 8d5cf7a26b47e4c28a8fd3adc2ab81f34afd91fd Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 13:09:38 +0100 Subject: [PATCH 6/7] tbl: replaced lolstring with teststring in tests --- d2common/d2fileformats/d2tbl/text_dictionary_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary_test.go b/d2common/d2fileformats/d2tbl/text_dictionary_test.go index bfb0794a..26188cd5 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary_test.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary_test.go @@ -6,9 +6,9 @@ import ( func exampleData() *TextDictionary { result := &TextDictionary{ - "abc": "def", - "someStr": "Some long string", - "lolstring": "lol", + "abc": "def", + "someStr": "Some long string", + "teststring": "TeSt", } return result From c933e4b89188b81f666add706fd4c9fd2a8a717c Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Thu, 25 Feb 2021 14:11:13 +0100 Subject: [PATCH 7/7] fixed build error & tbl: removed version check (because of error screen; we don't need to check version) --- .../d2fileformats/d2tbl/text_dictionary.go | 8 ++----- d2core/d2asset/asset_manager.go | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/d2common/d2fileformats/d2tbl/text_dictionary.go b/d2common/d2fileformats/d2tbl/text_dictionary.go index 4413d5c2..b0b8e51b 100644 --- a/d2common/d2fileformats/d2tbl/text_dictionary.go +++ b/d2common/d2fileformats/d2tbl/text_dictionary.go @@ -144,16 +144,12 @@ func LoadTextDictionary(dictionaryData []byte) (TextDictionary, error) { return nil, fmt.Errorf("reading hash table size: %v", err) } - // Version (always 0) - version, err := br.ReadByte() + // Version + _, err = br.ReadByte() if err != nil { return nil, fmt.Errorf("reading version: %v", err) } - if version != 0 { - return nil, fmt.Errorf("version isn't equal to 0") - } - _, _ = br.ReadUInt32() // StringOffset // When the number of times you have missed a match with a diff --git a/d2core/d2asset/asset_manager.go b/d2core/d2asset/asset_manager.go index cba1be27..a5ac1467 100644 --- a/d2core/d2asset/asset_manager.go +++ b/d2core/d2asset/asset_manager.go @@ -65,17 +65,18 @@ type AssetManager struct { *d2util.Logger *d2loader.Loader - tables []d2tbl.TextDictionary - dt1s d2interface.Cache - ds1s d2interface.Cache - cofs d2interface.Cache - dccs d2interface.Cache - animations d2interface.Cache - fonts d2interface.Cache - palettes d2interface.Cache - transforms d2interface.Cache - Records *d2records.RecordManager - language string + tables []d2tbl.TextDictionary + dt1s d2interface.Cache + ds1s d2interface.Cache + cofs d2interface.Cache + dccs d2interface.Cache + animations d2interface.Cache + fonts d2interface.Cache + palettes d2interface.Cache + transforms d2interface.Cache + Records *d2records.RecordManager + language string + languageModifier int } // SetLogLevel sets the log level for the asset manager, record manager, and file loader