md parser and tests

This commit is contained in:
Thomas Rudin 2019-01-07 19:38:53 +01:00
parent 904cb3496d
commit d9db2c1d67
6 changed files with 111 additions and 72 deletions

View File

@ -1,24 +1,31 @@
package mapblockparser
type MapBlock struct {
Version byte
Version byte
Underground bool
Mapdata []byte
Metadata Metadata
Mapdata []byte
Metadata Metadata
}
func NewMapblock() MapBlock {
mb := MapBlock{}
mb.Metadata = NewMetadata()
return mb
}
type Metadata struct {
Inventories map[int]map[string]*Inventory
Pairs map[int]map[string]string
Pairs map[int]map[string]string
}
func NewMetadata() Metadata {
md := Metadata{}
md.Inventories = make(map[int]map[string]*Inventory)
md.Pairs = make(map[int]map[string]string)
return md
}
func (md *Metadata) GetPairsMap(pos int) map[string]string {
if md.Pairs == nil {
md.Pairs = make(map[int]map[string]string)
}
pairsMap := md.Pairs[pos]
if pairsMap == nil {
pairsMap = make(map[string]string)
@ -50,12 +57,12 @@ func (md *Metadata) GetInventory(pos int, name string) *Inventory {
}
type Item struct {
Name string
Name string
Count int
Wear int
Wear int
}
type Inventory struct {
Size int
Size int
Items []Item
}
}

View File

@ -1,17 +1,17 @@
package mapblockparser
import (
"errors"
"compress/zlib"
"bytes"
"compress/zlib"
"errors"
"io"
"strconv"
log "github.com/sirupsen/logrus"
)
//TODO: mapdata struct with accessors
func parseMapdata(mapblock *MapBlock, data []byte) (int, error) {
log.WithFields(log.Fields{
"data-length": len(data),

View File

@ -1,34 +1,34 @@
package mapblockparser
import (
"compress/zlib"
"bufio"
"bytes"
"strings"
"compress/zlib"
"errors"
"strconv"
"io"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
)
const (
INVENTORY_TERMINATOR = "EndInventory"
INVENTORY_END = "EndInventoryList"
INVENTORY_START = "List"
INVENTORY_END = "EndInventoryList"
INVENTORY_START = "List"
)
func readU16(data []byte, offset int) int {
return (int(data[offset]) << 8) | int(data[offset + 1])
return (int(data[offset]) << 8) | int(data[offset+1])
}
func readU32(data []byte, offset int) int {
return int(data[offset]) << 24 |
int(data[offset+1]) << 16 |
int(data[offset+2]) << 8 |
return int(data[offset])<<24 |
int(data[offset+1])<<16 |
int(data[offset+2])<<8 |
int(data[offset+3])
}
func parseMetadata(mapblock *MapBlock, data []byte) (int, error) {
log.WithFields(log.Fields{
"data-length": len(data),
@ -62,76 +62,98 @@ func parseMetadata(mapblock *MapBlock, data []byte) (int, error) {
return 0, errors.New("Wrong metadata version: " + strconv.Itoa(int(version)))
}
offset++;
offset++
count := readU16(metadata, offset)
log.WithFields(log.Fields{
"count": count,
"count": count,
"version": version,
}).Debug("Parsed metadata-header")
offset+=2
log.Println("Metadata", buf.String())//XXX
offset += 2
for i := 0; i < count; i++ {
position := readU16(metadata, offset);
position := readU16(metadata, offset)
pairsMap := mapblock.Metadata.GetPairsMap(position)
offset+=2
offset += 2
valuecount := readU32(metadata, offset)
offset+=4
offset += 4
for j := 0; j < valuecount; j++ {
keyLength := readU16(metadata, offset);
offset+=2;
keyLength := readU16(metadata, offset)
offset += 2
key := string(metadata[offset:keyLength+offset])
offset+=keyLength
key := string(metadata[offset : keyLength+offset])
offset += keyLength
valueLength := readU32(metadata, offset)
offset+=4
offset += 4
value := string(metadata[offset:valueLength+offset])
offset+=valueLength
value := string(metadata[offset : valueLength+offset])
offset += valueLength
pairsMap[key] = value
offset++
}
var currentInventoryName *string = nil
var currentInventory *Inventory = nil
var currentInventoryName *string
var currentInventory *Inventory
scanner := bufio.NewScanner(bytes.NewReader(metadata[offset:]))
for scanner.Scan() {
txt := scanner.Text()
offset += len(txt) + 1;
log.Println("inv", txt)//XXX
if txt == INVENTORY_END {
currentInventoryName = nil
currentInventory = nil
}
if txt == INVENTORY_TERMINATOR {
break
}
offset += len(txt) + 1
if strings.HasPrefix(txt, INVENTORY_START) {
pairs := strings.Split(txt, " ")
currentInventoryName = &pairs[1]
currentInventory = mapblock.Metadata.GetInventory(position, *currentInventoryName)
currentInventory.Size = 0
} else if txt == INVENTORY_END {
currentInventoryName = nil
currentInventory = nil
} else if currentInventory != nil {
//content
if strings.HasPrefix(txt, "Item") {
item := Item{}
parts := strings.Split(txt, " ")
if len(parts) >= 2 {
item.Name = parts[1]
}
if len(parts) >= 3 {
val, err := strconv.ParseInt(parts[2], 10, 32)
if err != nil {
return 0, err
}
item.Count = int(val)
}
if len(parts) >= 4 {
val, err := strconv.ParseInt(parts[3], 10, 32)
if err != nil {
return 0, err
}
item.Count = int(val)
}
}
} else if txt == INVENTORY_TERMINATOR {
break
} else {
return 0, errors.New("Malformed inventory: " + txt)
}
}
//TODO
}
return cr.Count, nil
}

View File

@ -3,13 +3,12 @@ package mapblockparser
import (
"errors"
"strconv"
log "github.com/sirupsen/logrus"
)
func Parse(data []byte) (*MapBlock, error) {
mapblock := MapBlock{}
mapblock := NewMapblock()
if len(data) == 0 {
return nil, errors.New("no data")
}
@ -56,4 +55,3 @@ func Parse(data []byte) (*MapBlock, error) {
return &mapblock, nil
}

View File

@ -1,14 +1,14 @@
package mapblockparser
import (
"fmt"
"testing"
"io/ioutil"
"strconv"
"testing"
log "github.com/sirupsen/logrus"
)
func TestReadU16(t *testing.T){
func TestReadU16(t *testing.T) {
v := readU16([]byte{0x00, 0x00}, 0)
if v != 0 {
t.Error(v)
@ -25,14 +25,14 @@ func TestReadU16(t *testing.T){
}
}
func TestReadU32(t *testing.T){
func TestReadU32(t *testing.T) {
v := readU32([]byte{0x00, 0x00, 0x00, 0x00}, 0)
if v != 0 {
t.Error(v)
}
}
func TestParse(t *testing.T){
func TestParse(t *testing.T) {
log.SetLevel(log.DebugLevel)
data, err := ioutil.ReadFile("testdata/0.0.0")
@ -41,7 +41,6 @@ func TestParse(t *testing.T){
}
mapblock, err := Parse(data)
fmt.Println("mapblock.Metadata", mapblock.Metadata)
if err != nil {
t.Error(err)
@ -65,17 +64,30 @@ func TestParse(t *testing.T){
}
}
func TestParse2(t *testing.T){
func TestParse2(t *testing.T) {
log.SetLevel(log.DebugLevel)
data, err := ioutil.ReadFile("testdata/0.9.0")
data, err := ioutil.ReadFile("testdata/11.0.2")
if err != nil {
t.Error(err)
}
_, err = Parse(data)
if err != nil {
t.Error(err)
}
}
func TestParse3(t *testing.T) {
log.SetLevel(log.DebugLevel)
data, err := ioutil.ReadFile("testdata/0.1.0")
if err != nil {
t.Error(err)
}
_, err = Parse(data)
//fmt.Println("mapblock.Metadata", mapblock.Metadata)
if err != nil {
t.Error(err)

BIN
mapblockparser/testdata/11.0.2 vendored Normal file

Binary file not shown.