-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse_metadata.go
120 lines (94 loc) · 2.65 KB
/
parse_metadata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package mapparser
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"strconv"
"strings"
"github.com/minetest-go/types"
)
/*
lua vm: https://github.com/yuin/gopher-lua
*/
const (
INVENTORY_TERMINATOR = "EndInventory"
INVENTORY_END = "EndInventoryList"
INVENTORY_START = "List"
ITEM_PREFIX = "Item"
ITEM_EMPTY = "Empty"
)
func parseMetadata(metadata []byte, mapblock *types.MapBlock) error {
offset := 0
version := metadata[offset]
if version == 0 {
//No data?
return nil
}
offset++
count := int(binary.BigEndian.Uint16(metadata[offset:]))
offset += 2
for i := 0; i < count; i++ {
position := int(binary.BigEndian.Uint16(metadata[offset:]))
fields := map[string]string{}
mapblock.Fields[position] = fields
offset += 2
valuecount := int(binary.BigEndian.Uint32(metadata[offset:]))
offset += 4
for j := 0; j < valuecount; j++ {
keyLength := int(binary.BigEndian.Uint16(metadata[offset:]))
offset += 2
key := string(metadata[offset : keyLength+offset])
offset += keyLength
valueLength := int(binary.BigEndian.Uint32(metadata[offset:]))
offset += 4
if len(metadata) <= valueLength+offset {
return errors.New("metadata too short: " + strconv.Itoa(len(metadata)) +
", valuelength: " + strconv.Itoa(int(valueLength)))
}
value := string(metadata[offset : valueLength+offset])
offset += valueLength
fields[key] = value
if version >= 2 { /* private tag doesn't exist in version=1 */
offset++
}
}
var currentInventoryName *string
var currentInventory []string
scanner := bufio.NewScanner(bytes.NewReader(metadata[offset:]))
for scanner.Scan() {
txt := scanner.Text()
offset += len(txt) + 1
if strings.HasPrefix(txt, INVENTORY_START) {
pairs := strings.Split(txt, " ")
currentInventoryName = &pairs[1]
currentInventory = make([]string, 0)
inv := mapblock.Inventory[position]
if inv == nil {
inv = map[string][]string{}
mapblock.Inventory[position] = inv
}
inv[*currentInventoryName] = currentInventory
} else if txt == INVENTORY_END {
currentInventoryName = nil
currentInventory = nil
} else if currentInventory != nil {
//content
inv := mapblock.Inventory[position]
if strings.HasPrefix(txt, ITEM_PREFIX) {
item := txt[len(ITEM_PREFIX)+1:]
currentInventory = append(currentInventory, item)
} else if txt == ITEM_EMPTY {
currentInventory = append(currentInventory, "")
}
inv[*currentInventoryName] = currentInventory
} else if txt == INVENTORY_TERMINATOR {
break
} else {
return errors.New("Malformed inventory: " + txt)
}
}
//TODO
}
return nil
}