diff --git a/mapblockparser/mapblock.go b/mapblockparser/mapblock.go index 32bae51..3aa3f84 100644 --- a/mapblockparser/mapblock.go +++ b/mapblockparser/mapblock.go @@ -10,8 +10,43 @@ type MapBlock struct { type Metadata struct { - Inventories map[int]map[string]Inventory - Pairs map[int]map[string]string + Inventories map[int]map[string]*Inventory + Pairs map[int]map[string]*string +} + +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) + md.Pairs[pos] = pairsMap + } + + return pairsMap +} + +func (md *Metadata) GetInventoryMap(pos int) map[string]*Inventory { + invMap := md.Inventories[pos] + if invMap == nil { + invMap = make(map[string]*Inventory) + md.Inventories[pos] = invMap + } + + return invMap +} + +func (md *Metadata) GetInventory(pos int, name string) *Inventory { + m := md.GetInventoryMap(pos) + inv := m[name] + if inv == nil { + inv = &Inventory{} + m[name] = inv + } + + return inv } type Item struct { diff --git a/mapblockparser/metadata.go b/mapblockparser/metadata.go index cb027b5..35aeb26 100644 --- a/mapblockparser/metadata.go +++ b/mapblockparser/metadata.go @@ -2,21 +2,33 @@ package mapblockparser import ( "compress/zlib" + "bufio" "bytes" + "strings" "errors" "strconv" "io" log "github.com/sirupsen/logrus" ) +const ( + INVENTORY_TERMINATOR = "EndInventory" + INVENTORY_END = "EndInventoryList" + INVENTORY_START = "List" +) func readU16(data []byte, offset int) int { return (int(data[offset]) << 8) | int(data[offset + 1]) } -func readU32(data []byte, offset int){ +func readU32(data []byte, offset int) int { + 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), @@ -60,11 +72,63 @@ func parseMetadata(mapblock *MapBlock, data []byte) (int, error) { for i := 0; i < count; i++ { position := readU16(metadata, offset); - log.Println("MD item", i, position)//XXX + pairsMap := mapblock.Metadata.GetPairsMap(position) offset+=2 + valuecount := readU32(metadata, offset) + + offset+=4 + for j := 0; j < valuecount; j++ { + keyLength := readU16(metadata, offset); + offset+=2; + + key := string(metadata[offset:keyLength+offset]) + offset+=keyLength + + valueLength := readU32(metadata, offset) + offset+=4; + + value := string(metadata[offset:keyLength+offset]) + offset+=valueLength + + pairsMap[key] = &value + + offset++ + + log.Println("MD item", i, offset, position, valuecount, valueLength, keyLength, pairsMap)//XXX + + } + + var currentInventoryName *string = nil + var currentInventory *Inventory = nil + + + scanner := bufio.NewScanner(bytes.NewReader(metadata[offset:])) + for scanner.Scan() { + txt := scanner.Text() + offset += len(txt) + 1; + + log.Println("inv", txt) + + if txt == INVENTORY_END { + currentInventoryName = nil + currentInventory = nil + } + + if txt == INVENTORY_TERMINATOR { + break + } + + if strings.HasPrefix(txt, INVENTORY_START) { + pairs := strings.Split(txt, " ") + currentInventoryName = &pairs[1] + currentInventory = mapblock.Metadata.GetInventory(position, *currentInventoryName) + currentInventory.Size = 0 + } + } //TODO + } return cr.Count, nil diff --git a/mapblockparser/parse_test.go b/mapblockparser/parse_test.go index 6f06219..e519d79 100644 --- a/mapblockparser/parse_test.go +++ b/mapblockparser/parse_test.go @@ -7,6 +7,30 @@ import ( log "github.com/sirupsen/logrus" ) +func TestReadU16(t *testing.T){ + v := readU16([]byte{0x00, 0x00}, 0) + if v != 0 { + t.Error(v) + } + + v = readU16([]byte{0x00, 0x01}, 0) + if v != 1 { + t.Error(v) + } + + v = readU16([]byte{0x01, 0x00}, 0) + if v != 256 { + t.Error(v) + } + +} +func TestReadU32(t *testing.T){ + v := readU32([]byte{0x00, 0x00, 0x00, 0x00}, 0) + if v != 0 { + t.Error(v) + } +} + func TestParse(t *testing.T){ log.SetLevel(log.DebugLevel)