-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
147 lines (115 loc) · 2.7 KB
/
parse.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package mapparser
import (
"encoding/binary"
"errors"
"fmt"
"github.com/minetest-go/types"
)
var ErrNoData = errors.New("no data")
var ErrMapblockVersion = errors.New("mapblock version unsupported")
func ParseNetwork(ser_ver uint8, data []byte) (*types.MapBlock, error) {
offsetData := make([]byte, len(data)+1)
offsetData[0] = ser_ver
copy(offsetData[1:], data)
return Parse(offsetData)
}
func Parse(data []byte) (*types.MapBlock, error) {
if len(data) == 0 {
return nil, ErrNoData
}
mapblock := types.NewMapblock()
mapblock.Size = len(data)
// version
mapblock.Version = data[0]
if mapblock.Version < 25 || mapblock.Version > 29 {
return mapblock, ErrMapblockVersion
}
if mapblock.Version <= 28 {
// zlib compressed mapblock
//flags
flags := data[1]
mapblock.Underground = (flags & 0x01) == 0x01
var offset int
if mapblock.Version >= 27 {
offset = 4
} else {
//u16 lighting_complete not present
offset = 2
}
content_width := data[offset]
params_width := data[offset+1]
if content_width != 2 {
return nil, fmt.Errorf("content_width unexpected: %d", content_width)
}
if params_width != 2 {
return nil, fmt.Errorf("params_width unexpected: %d", params_width)
}
// mapdata offset
if mapblock.Version >= 27 {
offset = 6
} else {
offset = 4
}
// mapdata
mapdata, skip_bytes, err := decompress_zlib(data[offset:])
if err != nil {
return nil, err
}
err = parseMapdata(mapdata, mapblock)
if err != nil {
return nil, err
}
offset += skip_bytes
// metadata
metadata, skip_bytes, err := decompress_zlib(data[offset:])
if err != nil {
return nil, err
}
err = parseMetadata(metadata, mapblock)
if err != nil {
return nil, err
}
offset += skip_bytes
//static objects
parseStaticObjects(data, &offset)
//timestamp
offset += 4
//mapping version
offset++
parseBlockMapping(data, &offset, mapblock)
return mapblock, nil
}
if mapblock.Version >= 29 {
uncompressed_data, _, err := decompress_zstd(data[1:])
if err != nil {
return nil, err
}
offset := 0
//flags
flags := uncompressed_data[1]
mapblock.Underground = (flags & 0x01) == 0x01
offset++
//lighting complete
offset += 2
mapblock.Timestamp = binary.BigEndian.Uint32(uncompressed_data[offset:])
offset += 4
//mapping version
offset++
parseBlockMapping(uncompressed_data, &offset, mapblock)
// content width * 2
offset += 2
// mapdata
err = parseMapdata(uncompressed_data[offset:], mapblock)
if err != nil {
return nil, err
}
offset += MapDataSize
// metadata
err = parseMetadata(uncompressed_data[offset:], mapblock)
if err != nil {
return nil, err
}
return mapblock, nil
}
return nil, nil
}