diff --git a/nbt/README.md b/nbt/README.md index eb55621..4099af4 100644 --- a/nbt/README.md +++ b/nbt/README.md @@ -1,11 +1,11 @@ # NBT [![Go Reference](https://pkg.go.dev/badge/github.com/Tnze/go-mc/nbt.svg)](https://pkg.go.dev/github.com/Tnze/go-mc/nbt) -This package implement the [Named Binary Tag](https://wiki.vg/NBT) format of Minecraft. -The API is very similar to the standard library `encoding/json`. If you (high probability) have used that, it is easy to use this. +This package implement the [Named Binary Tag](https://wiki.vg/NBT) format of Minecraft. -# Basic Usage -> I don't know why `Marshal` looks like that, and **I will change it** to `func Marshal(v interface{}) ([]byte, error)`. -> **Use `Encoder` is recommended now.** +The API is very similar to the standard library `encoding/json`. If you (high probability) have used that, it is easy to +use this. + +## Basic Usage For the following NBT tag: @@ -20,7 +20,6 @@ To read and write would look like: ```go package main -import "bytes" import "github.com/Tnze/go-mc/nbt" type Compound struct { @@ -28,27 +27,26 @@ type Compound struct { } func main() { - var out bytes.Buffer banana := Compound{Name: "Bananrama"} - _ = nbt.Marshal(&out, banana) + data, _ := nbt.Marshal(banana) var rama Compound - _ = nbt.Unmarshal(out.Bytes(), &rama) + _ = nbt.Unmarshal(data, &rama) } ``` - - -# Struct field tags +## Struct field tags There are two tags supported: + - nbt - nbt_type The `nbt` tag is used to change the name of the NBT Tag field, whereas the `nbt_type` - tag is used to enforce a certain NBT Tag type when it is ambiguous. +tag is used to enforce a certain NBT Tag type when it is ambiguous. For example: + ```go type Compound struct { LongArray []int64 @@ -56,5 +54,25 @@ type Compound struct { } ``` +## Stringified NBT +You can transform SNBT string into binary NBT by using go-mc, which could be useful when parsing command, but the +reverse conversion is not supported at the moment. +```go +package main + +import ( + "bytes" + "github.com/Tnze/go-mc/nbt" +) + +func main() { + var buf bytes.Buffer + e := nbt.NewEncoder(&buf) + err := e.WriteSNBT(`{Tnze: 1, 'sp ace': [I;1,2,3]}`) + if err != nil { + panic(err) + } +} +``` \ No newline at end of file diff --git a/nbt/encode.go b/nbt/encode.go index 6f3836f..29e5044 100644 --- a/nbt/encode.go +++ b/nbt/encode.go @@ -1,6 +1,7 @@ package nbt import ( + "bytes" "errors" "fmt" "io" @@ -10,8 +11,10 @@ import ( "strings" ) -func Marshal(w io.Writer, v interface{}, optionalTagName ...string) error { - return NewEncoder(w).Encode(v, optionalTagName...) +func Marshal(v interface{}, optionalTagName ...string) ([]byte, error) { + var buf bytes.Buffer + err := NewEncoder(&buf).Encode(v, optionalTagName...) + return buf.Bytes(), err } type Encoder struct { diff --git a/nbt/encode_test.go b/nbt/encode_test.go index f388a56..ea40e81 100644 --- a/nbt/encode_test.go +++ b/nbt/encode_test.go @@ -17,11 +17,10 @@ func TestMarshal_IntArray(t *testing.T) { 0xff, 0xff, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x03, } - var buf bytes.Buffer - if err := Marshal(&buf, v); err != nil { + if data, err := Marshal(v); err != nil { t.Error(err) - } else if !bytes.Equal(buf.Bytes(), out) { - t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } else if !bytes.Equal(data, out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", data, out) } // Test marshal in a struct @@ -35,11 +34,10 @@ func TestMarshal_IntArray(t *testing.T) { 0x00, 0x00, 0x00, 0x03, // 3 TagEnd, } - buf.Reset() - if err := Marshal(&buf, v2); err != nil { + if data, err := Marshal(v2); err != nil { t.Error(err) - } else if !bytes.Equal(buf.Bytes(), out) { - t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } else if !bytes.Equal(data, out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", data, out) } } @@ -51,11 +49,10 @@ func TestMarshal_FloatArray(t *testing.T) { 0xc2, 0xc8, 0x00, 0x00, // -100 0x7f, 0xc0, 0x00, 0x00, // NaN } - var buf bytes.Buffer - if err := Marshal(&buf, v); err != nil { + if data, err := Marshal(v); err != nil { t.Error(err) - } else if !bytes.Equal(buf.Bytes(), out) { - t.Errorf("output binary not right: get % 02x, want % 02x ", buf.Bytes(), out) + } else if !bytes.Equal(data, out) { + t.Errorf("output binary not right: get % 02x, want % 02x ", data, out) } } @@ -64,11 +61,10 @@ func TestMarshal_String(t *testing.T) { out := []byte{TagString, 0x00, 0x00, 0, 4, 'T', 'e', 's', 't'} - var buf bytes.Buffer - if err := Marshal(&buf, v); err != nil { + if data, err := Marshal(v); err != nil { t.Error(err) - } else if !bytes.Equal(buf.Bytes(), out) { - t.Errorf("output binary not right: got % 02x, want % 02x ", buf.Bytes(), out) + } else if !bytes.Equal(data, out) { + t.Errorf("output binary not right: got % 02x, want % 02x ", data, out) } } @@ -103,12 +99,11 @@ func TestMarshal_InterfaceArray(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - w := &bytes.Buffer{} - err := Marshal(w, tt.args) + data, err := Marshal(tt.args) if err != nil { t.Error(err) - } else if !bytes.Equal(w.Bytes(), tt.want) { - t.Errorf("Marshal([]interface{}) got = % 02x, want % 02x", w.Bytes(), tt.want) + } else if !bytes.Equal(data, tt.want) { + t.Errorf("Marshal([]interface{}) got = % 02x, want % 02x", data, tt.want) return } }) @@ -158,12 +153,11 @@ func TestMarshal_StructArray(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - w := &bytes.Buffer{} - err := Marshal(w, tt.args) + data, err := Marshal(tt.args) if err != nil { t.Error(err) - } else if !bytes.Equal(w.Bytes(), tt.want) { - t.Errorf("Marshal([]struct{}) got = % 02x, want % 02x", w.Bytes(), tt.want) + } else if !bytes.Equal(data, tt.want) { + t.Errorf("Marshal([]struct{}) got = % 02x, want % 02x", data, tt.want) return } }) @@ -171,8 +165,7 @@ func TestMarshal_StructArray(t *testing.T) { } func TestMarshal_bigTest(t *testing.T) { - var b bytes.Buffer - err := Marshal(&b, MakeBigTestStruct(), "Level") + data, err := Marshal(MakeBigTestStruct(), "Level") if err != nil { t.Error(err) } @@ -183,8 +176,8 @@ func TestMarshal_bigTest(t *testing.T) { t.Error(err) } - if !bytes.Equal(b.Bytes(), want) { - t.Errorf("got:\n[% 2x]\nwant:\n[% 2x]", b.Bytes(), want) + if !bytes.Equal(data, want) { + t.Errorf("got:\n[% 2x]\nwant:\n[% 2x]", data, want) } } @@ -194,8 +187,8 @@ func TestMarshal_map(t *testing.T) { "Xi_Xi_Mi": {0, 0, 4, 7, 2}, } - var buf bytes.Buffer - if err := Marshal(&buf, v); err != nil { + b, err := Marshal(v) + if err != nil { t.Fatal(err) } @@ -204,7 +197,7 @@ func TestMarshal_map(t *testing.T) { XXM []int32 `nbt:"Xi_Xi_Mi"` } - if err := NewDecoder(&buf).Decode(&data); err != nil { + if err := NewDecoder(bytes.NewReader(b)).Decode(&data); err != nil { t.Fatal(err) } if !reflect.DeepEqual(data.Tnze, v["Tnze"]) { diff --git a/nbt/example_test.go b/nbt/example_test.go index 5f69088..1952ae2 100644 --- a/nbt/example_test.go +++ b/nbt/example_test.go @@ -28,13 +28,24 @@ func ExampleMarshal() { Name string `nbt:"name"` }{"Tnze"} - var buf bytes.Buffer - if err := Marshal(&buf, value); err != nil { + data, err := Marshal(value) + if err != nil { panic(err) } - fmt.Printf("% 02x ", buf.Bytes()) + fmt.Printf("% 02x ", data) // Output: // 0a 00 00 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 00 } + +func ExampleEncoder_WriteSNBT() { + var buf bytes.Buffer + if err := NewEncoder(&buf).WriteSNBT(`{ name: [Tnze, "Xi_Xi_Mi"]}`); err != nil { + panic(err) + } + fmt.Printf("% 02x ", buf.Bytes()) + + // Output: + // 0a 00 00 09 00 04 6e 61 6d 65 08 00 00 00 02 00 04 54 6e 7a 65 00 08 58 69 5f 58 69 5f 4d 69 00 +}