diff --git a/nbt/nbt.go b/nbt/nbt.go index bf21959..9c14996 100644 --- a/nbt/nbt.go +++ b/nbt/nbt.go @@ -26,7 +26,7 @@ const ( type Decoder struct { r interface { - io.ByteReader + io.ByteScanner io.Reader } } @@ -34,7 +34,7 @@ type Decoder struct { func NewDecoder(r io.Reader) *Decoder { d := new(Decoder) if br, ok := r.(interface { - io.ByteReader + io.ByteScanner io.Reader }); ok { d.r = br diff --git a/nbt/read.go b/nbt/read.go index 9c1474b..9e35c54 100644 --- a/nbt/read.go +++ b/nbt/read.go @@ -18,6 +18,17 @@ func (d *Decoder) Decode(v interface{}) error { if val.Kind() != reflect.Ptr { return errors.New("non-pointer passed to Unmarshal") } + + // check the head + compress, err := d.checkCompressed() + if err != nil { + return fmt.Errorf("check compressed fail: %v", err) + } + if compress != "" { + return fmt.Errorf("data may compressed with %s", compress) + } + + //start read NBT tagType, tagName, err := d.readTag() if err != nil { return err @@ -25,6 +36,29 @@ func (d *Decoder) Decode(v interface{}) error { return d.unmarshal(val.Elem(), tagType, tagName) } +// check the first byte and return if it use compress +func (d *Decoder) checkCompressed() (compress string, err error) { + var head byte + head, err = d.r.ReadByte() + if err != nil { + return + } + + if head <= 12 { //NBT + compress = "" + } else if head == 0x1f { //gzip + compress = "gzip" + } else if head == 0x78 { //zlib + compress = "zlib" + } else { + compress = "unknown" + } + + err = d.r.UnreadByte() + + return +} + // ErrEND error will be returned when reading a NBT with only Tag_End var ErrEND = errors.New("unexpected TAG_End") diff --git a/save/level.go b/save/level.go new file mode 100644 index 0000000..cc5510d --- /dev/null +++ b/save/level.go @@ -0,0 +1,4 @@ +package save + +type Level struct { +} diff --git a/save/playerdata.go b/save/playerdata.go new file mode 100644 index 0000000..1c880e7 --- /dev/null +++ b/save/playerdata.go @@ -0,0 +1,16 @@ +package save + +import ( + "github.com/Tnze/go-mc/nbt" + "io" +) + +type PlayerData struct { + Pos [3]float64 + Motion [3]float64 +} + +func ReadPlayerData(r io.Reader) (data PlayerData, err error) { + err = nbt.NewDecoder(r).Decode(&data) + return +} diff --git a/save/playerdata_test.go b/save/playerdata_test.go new file mode 100644 index 0000000..c5a7c8f --- /dev/null +++ b/save/playerdata_test.go @@ -0,0 +1,33 @@ +package save + +import ( + "compress/gzip" + "os" + "testing" +) + +func TestPlayerData(t *testing.T) { + f, err := os.Open("testdata/playerdata/58f6356e-b30c-4811-8bfc-d72a9ee99e73.dat") + if err != nil { + t.Fatal(err) + } + + r, err := gzip.NewReader(f) + if err != nil { + t.Fatal(err) + } + + data, err := ReadPlayerData(r) + if err != nil { + t.Fatal(err) + } + + want := PlayerData{ + Pos: [3]float64{-41.5, 65, -89.5}, + Motion: [3]float64{0, -0.0784000015258789, 0}, + } + + if data != want { + t.Errorf("player data parse error: get %v, want %v", data, want) + } +} diff --git a/save/save.go b/save/save.go new file mode 100644 index 0000000..16890c0 --- /dev/null +++ b/save/save.go @@ -0,0 +1 @@ +package save diff --git a/save/testdata/DIM-1/data/raids_nether.dat b/save/testdata/DIM-1/data/raids_nether.dat new file mode 100644 index 0000000..d03c17e Binary files /dev/null and b/save/testdata/DIM-1/data/raids_nether.dat differ diff --git a/save/testdata/DIM1/data/raids_end.dat b/save/testdata/DIM1/data/raids_end.dat new file mode 100644 index 0000000..d03c17e Binary files /dev/null and b/save/testdata/DIM1/data/raids_end.dat differ diff --git a/save/testdata/advancements/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json b/save/testdata/advancements/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json new file mode 100644 index 0000000..0d9008a --- /dev/null +++ b/save/testdata/advancements/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json @@ -0,0 +1,9 @@ +{ + "minecraft:adventure/adventuring_time": { + "criteria": { + "minecraft:plains": "2019-07-31 15:56:59 +0800" + }, + "done": false + }, + "DataVersion": 1976 +} \ No newline at end of file diff --git a/save/testdata/data/raids.dat b/save/testdata/data/raids.dat new file mode 100644 index 0000000..d03c17e Binary files /dev/null and b/save/testdata/data/raids.dat differ diff --git a/save/testdata/level.dat b/save/testdata/level.dat new file mode 100644 index 0000000..6c3f785 Binary files /dev/null and b/save/testdata/level.dat differ diff --git a/save/testdata/level.dat_old b/save/testdata/level.dat_old new file mode 100644 index 0000000..e9c59e8 Binary files /dev/null and b/save/testdata/level.dat_old differ diff --git a/save/testdata/playerdata/58f6356e-b30c-4811-8bfc-d72a9ee99e73.dat b/save/testdata/playerdata/58f6356e-b30c-4811-8bfc-d72a9ee99e73.dat new file mode 100644 index 0000000..c323fed Binary files /dev/null and b/save/testdata/playerdata/58f6356e-b30c-4811-8bfc-d72a9ee99e73.dat differ diff --git a/save/testdata/region/r.-1.-1.mca b/save/testdata/region/r.-1.-1.mca new file mode 100644 index 0000000..9fe43b0 Binary files /dev/null and b/save/testdata/region/r.-1.-1.mca differ diff --git a/save/testdata/region/r.-1.0.mca b/save/testdata/region/r.-1.0.mca new file mode 100644 index 0000000..642e0ec Binary files /dev/null and b/save/testdata/region/r.-1.0.mca differ diff --git a/save/testdata/region/r.0.-1.mca b/save/testdata/region/r.0.-1.mca new file mode 100644 index 0000000..25e5d10 Binary files /dev/null and b/save/testdata/region/r.0.-1.mca differ diff --git a/save/testdata/region/r.0.0.mca b/save/testdata/region/r.0.0.mca new file mode 100644 index 0000000..bb36bb0 Binary files /dev/null and b/save/testdata/region/r.0.0.mca differ diff --git a/save/testdata/session.lock b/save/testdata/session.lock new file mode 100644 index 0000000..03394fd Binary files /dev/null and b/save/testdata/session.lock differ diff --git a/save/testdata/stats/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json b/save/testdata/stats/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json new file mode 100644 index 0000000..460c316 --- /dev/null +++ b/save/testdata/stats/58f6356e-b30c-4811-8bfc-d72a9ee99e73.json @@ -0,0 +1 @@ +{"stats":{"minecraft:custom":{"minecraft:time_since_rest":6,"minecraft:play_one_minute":6,"minecraft:leave_game":1,"minecraft:time_since_death":6}},"DataVersion":1976} \ No newline at end of file