From 29baaa00789ea4b01040f7fe54bc0ed5c560137d Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Sat, 16 Jul 2022 17:12:47 +0200 Subject: [PATCH] Add deserialization --- deserialize.go | 283 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 5 + go.sum | 2 + 3 files changed, 290 insertions(+) create mode 100644 deserialize.go create mode 100644 go.mod create mode 100644 go.sum 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 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2d76405 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/EliasFleckenstein03/mtmap + +go 1.18 + +require github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a9fbb58 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f h1:tZU8VPYLyRrG3Lj9zBZvTVF5tUGciC/2aUIgTcU4WaM= +github.com/anon55555/mt v0.0.0-20210919124550-bcc58cb3048f/go.mod h1:jH4ER+ahjl7H6TczzK+q4V9sXY++U2Geh6/vt3r4Xvs= -- 2.44.0