diff options
author | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-07-16 17:12:47 +0200 |
---|---|---|
committer | Elias Fleckenstein <eliasfleckenstein@web.de> | 2022-07-16 17:12:47 +0200 |
commit | 29baaa00789ea4b01040f7fe54bc0ed5c560137d (patch) | |
tree | f616800429c9333782591ed5042de03342a5d2c9 /deserialize.go | |
download | mtmap-29baaa00789ea4b01040f7fe54bc0ed5c560137d.tar.xz |
Add deserialization
Diffstat (limited to 'deserialize.go')
-rw-r--r-- | deserialize.go | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/deserialize.go b/deserialize.go new file mode 100644 index 0000000..a6bc965 --- /dev/null +++ b/deserialize.go @@ -0,0 +1,283 @@ +package mtmap + +import ( + "bytes" + "compress/zlib" + "encoding/binary" + "errors" + "github.com/anon55555/mt" + "io" +) + +type MapBlk struct { + mt.MapBlk + Flags MapBlkFlags + LightingComplete uint16 + StaticObjs []StaticObj + Timestamp uint32 +} + +type MapBlkFlags uint8 + +const ( + IsUnderground MapBlkFlags = 1 << iota + DayNightDiffers + NotGenerated = 1 << 4 +) + +var SerializeVer uint8 = 28 + +var ( + ErrInvalidSerializeVer = errors.New("invalid serialize version") + ErrInvalidContentWidth = errors.New("invalid content width") + ErrInvalidParamsWidth = errors.New("invalid params width") + ErrInvalidNodeMetaVer = errors.New("invalid node meta version") + ErrInvalidNameIdMapVer = errors.New("invalid name id mapping version") + ErrInvalidNode = errors.New("invalid node") +) + +type StaticObj struct { + Type uint8 + Pos [3]float32 + Data string +} + +func Deserialize(data []byte, idNameMap map[string]mt.Content) (blk *MapBlk, err error) { + r := bytes.NewReader(data) + blk = &MapBlk{} + + var ver uint8 + if err := binary.Read(r, binary.BigEndian, &ver); err != nil { + return nil, err + } + + if ver != SerializeVer { + return nil, ErrInvalidSerializeVer + } + + if err := binary.Read(r, binary.BigEndian, &blk.Flags); err != nil { + return nil, err + } + + if err := binary.Read(r, binary.BigEndian, &blk.LightingComplete); err != nil { + return nil, err + } + + var contentWidth uint8 + if err := binary.Read(r, binary.BigEndian, &contentWidth); err != nil { + return nil, err + } + + if contentWidth != 2 { + return nil, ErrInvalidContentWidth + } + + var paramsWidth uint8 + if err := binary.Read(r, binary.BigEndian, ¶msWidth); err != nil { + return nil, err + } + + if paramsWidth != 2 { + return nil, ErrInvalidParamsWidth + } + + { + r, err := zlib.NewReader(r) + if err != nil { + return nil, err + } + + if err := binary.Read(r, binary.BigEndian, &blk.Param0); err != nil { + return nil, err + } + + if _, err := io.Copy(io.Discard, r); err != nil { + return nil, err + } + + if err := r.Close(); err != nil { + return nil, err + } + } + + blk.NodeMetas = make(map[uint16]*mt.NodeMeta) + { + r, err := zlib.NewReader(r) + if err != nil { + return nil, err + } + + var version uint8 + if err := binary.Read(r, binary.BigEndian, &version); err != nil { + return nil, err + } + + if version != 2 { + return nil, ErrInvalidNodeMetaVer + } + + var count uint16 + if err := binary.Read(r, binary.BigEndian, &count); err != nil { + return nil, err + } + + for i := uint16(0); i < count; i++ { + var pos uint16 + if err := binary.Read(r, binary.BigEndian, &pos); err != nil { + return nil, err + } + + var num uint32 + if err := binary.Read(r, binary.BigEndian, &num); err != nil { + return nil, err + } + + var data = &mt.NodeMeta{} + data.Fields = make([]mt.NodeMetaField, 0) + for j := uint32(0); j < num; j++ { + var field mt.NodeMetaField + + var lenName uint16 + if err := binary.Read(r, binary.BigEndian, &lenName); err != nil { + return nil, err + } + + var name = make([]byte, lenName) + if err := binary.Read(r, binary.BigEndian, &name); err != nil { + return nil, err + } + field.Name = string(name) + + var lenValue uint32 + if err := binary.Read(r, binary.BigEndian, &lenValue); err != nil { + return nil, err + } + + var value = make([]byte, lenValue) + if err := binary.Read(r, binary.BigEndian, &value); err != nil { + return nil, err + } + field.Value = string(value) + + if err := binary.Read(r, binary.BigEndian, &field.Private); err != nil { + return nil, err + } + + data.Fields = append(data.Fields, field) + } + + if err := data.Inv.Deserialize(r); err != nil { + return nil, err + } + + blk.NodeMetas[pos] = data + } + + if _, err := io.Copy(io.Discard, r); err != nil { + return nil, err + } + + if err := r.Close(); err != nil { + return nil, err + } + } + + var staticObjVer uint8 + if err := binary.Read(r, binary.BigEndian, &staticObjVer); err != nil { + return nil, err + } + + var staticObjCount uint16 + if err := binary.Read(r, binary.BigEndian, &staticObjCount); err != nil { + return nil, err + } + + blk.StaticObjs = make([]StaticObj, 0) + for i := uint16(0); i < staticObjCount; i++ { + var obj StaticObj + + if err := binary.Read(r, binary.BigEndian, &obj.Type); err != nil { + return nil, err + } + + var pos [3]int32 + if err := binary.Read(r, binary.BigEndian, &pos); err != nil { + return nil, err + } + + obj.Pos = [3]float32{ + float32(pos[0]) / 1000.0, + float32(pos[1]) / 1000.0, + float32(pos[2]) / 1000.0, + } + + var dataLen uint16 + if err := binary.Read(r, binary.BigEndian, &dataLen); err != nil { + return nil, err + } + + var data = make([]byte, dataLen) + if err := binary.Read(r, binary.BigEndian, &data); err != nil { + return nil, err + } + + obj.Data = string(data) + + blk.StaticObjs = append(blk.StaticObjs, obj) + } + + if err := binary.Read(r, binary.BigEndian, &blk.Timestamp); err != nil { + return nil, err + } + + var nameIdMapVer uint8 + if err := binary.Read(r, binary.BigEndian, &nameIdMapVer); err != nil { + return nil, err + } + + if nameIdMapVer != 0 { + return nil, ErrInvalidNameIdMapVer + } + + var nameIdMapCount uint16 + if err := binary.Read(r, binary.BigEndian, &nameIdMapCount); err != nil { + return nil, err + } + + nameIdMap := make(map[mt.Content]string) + + for i := uint16(0); i < nameIdMapCount; i++ { + var id uint16 + if err := binary.Read(r, binary.BigEndian, &id); err != nil { + return nil, err + } + + var nameLen mt.Content + if err := binary.Read(r, binary.BigEndian, &nameLen); err != nil { + return nil, err + } + + var name = make([]byte, nameLen) + if err := binary.Read(r, binary.BigEndian, &name); err != nil { + return nil, err + } + + nameIdMap[mt.Content(id)] = string(name) + } + + for i := 0; i < 4096; i++ { + name, ok := nameIdMap[blk.Param0[i]] + if !ok { + return nil, ErrInvalidNode + } + + id, ok := idNameMap[name] + if !ok { + return nil, ErrInvalidNode + } + + blk.Param0[i] = id + } + + return +} |