mapserver/server/mapblockparser/metadata.go

175 lines
3.4 KiB
Go
Raw Normal View History

2019-01-06 23:00:24 +03:00
package mapblockparser
import (
2019-01-07 18:06:03 +03:00
"bufio"
2019-01-06 23:00:24 +03:00
"bytes"
2019-01-07 21:38:53 +03:00
"compress/zlib"
2019-01-06 23:00:24 +03:00
"errors"
"io"
2019-01-07 21:38:53 +03:00
"strconv"
"strings"
2019-03-01 08:01:10 +03:00
"github.com/sirupsen/logrus"
2019-01-06 23:00:24 +03:00
)
2019-01-23 10:20:27 +03:00
/*
lua vm: https://github.com/yuin/gopher-lua
*/
2019-01-07 18:06:03 +03:00
const (
INVENTORY_TERMINATOR = "EndInventory"
2019-01-07 21:38:53 +03:00
INVENTORY_END = "EndInventoryList"
INVENTORY_START = "List"
2019-01-07 18:06:03 +03:00
)
2019-01-06 23:00:24 +03:00
func readU16(data []byte, offset int) int {
2019-01-07 21:38:53 +03:00
return (int(data[offset]) << 8) | int(data[offset+1])
2019-01-06 23:00:24 +03:00
}
2019-01-28 13:45:23 +03:00
func readU8(data []byte, offset int) int {
return int(data[offset])
}
2019-01-07 18:06:03 +03:00
func readU32(data []byte, offset int) int {
2019-01-07 21:38:53 +03:00
return int(data[offset])<<24 |
int(data[offset+1])<<16 |
int(data[offset+2])<<8 |
2019-01-07 18:06:03 +03:00
int(data[offset+3])
2019-01-06 23:00:24 +03:00
}
func parseMetadata(mapblock *MapBlock, data []byte) (int, error) {
r := bytes.NewReader(data)
cr := new(CountedReader)
cr.Reader = r
z, err := zlib.NewReader(cr)
if err != nil {
return 0, err
}
defer z.Close()
buf := new(bytes.Buffer)
io.Copy(buf, z)
2019-01-07 18:35:26 +03:00
if cr.Count == 0 {
return 0, errors.New("no data")
}
2019-01-06 23:00:24 +03:00
metadata := buf.Bytes()
2019-01-11 16:17:16 +03:00
log.WithFields(logrus.Fields{"metadata-length": len(metadata)}).Trace("Parsing metadata")
2019-01-11 10:58:12 +03:00
2019-01-06 23:00:24 +03:00
offset := 0
version := metadata[offset]
2019-01-11 10:58:12 +03:00
if version == 0 {
//No data?
return cr.Count, nil
}
2019-01-06 23:00:24 +03:00
if version != 2 {
return 0, errors.New("Wrong metadata version: " + strconv.Itoa(int(version)))
}
2019-01-07 21:38:53 +03:00
offset++
2019-01-06 23:00:24 +03:00
count := readU16(metadata, offset)
2019-01-07 21:38:53 +03:00
offset += 2
2019-01-06 23:00:24 +03:00
for i := 0; i < count; i++ {
2019-01-07 21:38:53 +03:00
position := readU16(metadata, offset)
2019-01-07 18:06:03 +03:00
pairsMap := mapblock.Metadata.GetPairsMap(position)
2019-01-06 23:00:24 +03:00
2019-01-07 21:38:53 +03:00
offset += 2
2019-01-07 18:06:03 +03:00
valuecount := readU32(metadata, offset)
2019-01-07 21:38:53 +03:00
offset += 4
2019-01-07 18:06:03 +03:00
for j := 0; j < valuecount; j++ {
2019-01-07 21:38:53 +03:00
keyLength := readU16(metadata, offset)
offset += 2
2019-01-07 18:06:03 +03:00
2019-01-07 21:38:53 +03:00
key := string(metadata[offset : keyLength+offset])
offset += keyLength
2019-01-07 18:06:03 +03:00
valueLength := readU32(metadata, offset)
2019-01-07 21:38:53 +03:00
offset += 4
2019-01-07 18:06:03 +03:00
2019-03-01 08:01:10 +03:00
if len(metadata) <= valueLength+offset {
return 0, errors.New("metadata too short: " + strconv.Itoa(len(metadata)) +
", valuelength: " + strconv.Itoa(int(valueLength)))
}
2019-01-07 21:38:53 +03:00
value := string(metadata[offset : valueLength+offset])
offset += valueLength
2019-01-07 18:06:03 +03:00
2019-01-07 18:35:26 +03:00
pairsMap[key] = value
2019-01-07 18:06:03 +03:00
offset++
}
2019-01-07 21:38:53 +03:00
var currentInventoryName *string
var currentInventory *Inventory
2019-01-07 18:06:03 +03:00
scanner := bufio.NewScanner(bytes.NewReader(metadata[offset:]))
for scanner.Scan() {
txt := scanner.Text()
2019-01-07 21:38:53 +03:00
offset += len(txt) + 1
2019-01-07 18:06:03 +03:00
2019-01-23 15:13:32 +03:00
log.WithFields(logrus.Fields{"txt": txt, "position": position}).Trace("Parsing inventory")
2019-01-23 10:02:59 +03:00
2019-01-07 18:06:03 +03:00
if strings.HasPrefix(txt, INVENTORY_START) {
pairs := strings.Split(txt, " ")
currentInventoryName = &pairs[1]
currentInventory = mapblock.Metadata.GetInventory(position, *currentInventoryName)
currentInventory.Size = 0
2019-01-07 21:38:53 +03:00
} 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)
}
2019-02-15 13:25:49 +03:00
currentInventory.Items = append(currentInventory.Items, &item)
2019-01-23 10:02:59 +03:00
2019-01-07 21:38:53 +03:00
}
} else if txt == INVENTORY_TERMINATOR {
break
} else {
return 0, errors.New("Malformed inventory: " + txt)
2019-01-07 18:06:03 +03:00
}
}
2019-01-06 23:00:24 +03:00
//TODO
2019-01-07 21:38:53 +03:00
2019-01-06 23:00:24 +03:00
}
return cr.Count, nil
}