diff --git a/nbt/decode.go b/nbt/decode.go index a6a56d7..e5589dd 100644 --- a/nbt/decode.go +++ b/nbt/decode.go @@ -35,7 +35,14 @@ func (d *Decoder) Decode(v any) (string, error) { return "", errors.New("nbt: non-pointer passed to Decode") } // start read NBT - tagType, tagName, err := d.readTag() + var tagType byte + var tagName string + var err error + if d.networkFormat { + tagType, err = d.r.ReadByte() + } else { + tagType, tagName, err = d.readTag() + } if err != nil { return tagName, fmt.Errorf("nbt: %w", err) } diff --git a/nbt/encode.go b/nbt/encode.go index c855420..9ca805b 100644 --- a/nbt/encode.go +++ b/nbt/encode.go @@ -22,13 +22,22 @@ func Marshal(v any) ([]byte, error) { } type Encoder struct { - w io.Writer + w io.Writer + networkFormat bool } func NewEncoder(w io.Writer) *Encoder { return &Encoder{w: w} } +// NetworkFormat controls wether encoder encoding nbt in "network format". +// Means it haven't a tag name for root tag. +// +// It is disabled by default. +func (e *Encoder) NetworkFormat(enable bool) { + e.networkFormat = enable +} + // Encode encodes v into the writer inside Encoder with the root tag named tagName. // In most cases, the root tag typed TagCompound and the tag name is empty string, // but any other type is allowed just because there is valid technically. Once if @@ -40,13 +49,13 @@ func NewEncoder(w io.Writer) *Encoder { // To force encode them as TagList, add a struct field tag. func (e *Encoder) Encode(v any, tagName string) error { t, val := getTagType(reflect.ValueOf(v)) - return e.marshal(val, t, tagName) -} - -func (e *Encoder) marshal(val reflect.Value, tagType byte, tagName string) error { - if err := writeTag(e.w, tagType, tagName); err != nil { + if err := writeTag(e.w, t, tagName); err != nil { return err } + return e.marshal(val, t) +} + +func (e *Encoder) marshal(val reflect.Value, tagType byte) error { if val.CanInterface() { if encoder, ok := val.Interface().(Marshaler); ok { return encoder.MarshalNBT(e.w) @@ -214,7 +223,10 @@ func (e *Encoder) writeValue(val reflect.Value, tagType byte) error { } } - if err := e.marshal(v, typ, t.name); err != nil { + if err := writeTag(e.w, typ, t.name); err != nil { + return err + } + if err := e.marshal(v, typ); err != nil { return err } } @@ -232,7 +244,10 @@ func (e *Encoder) writeValue(val reflect.Value, tagType byte) error { return fmt.Errorf("encoding %q error: unsupport type %v", tagName, tagValue.Type()) } - if err := e.marshal(tagValue, tagType, tagName); err != nil { + if err := writeTag(e.w, tagType, tagName); err != nil { + return err + } + if err := e.marshal(tagValue, tagType); err != nil { return err } } diff --git a/nbt/nbt.go b/nbt/nbt.go index 75668b6..3843c67 100644 --- a/nbt/nbt.go +++ b/nbt/nbt.go @@ -30,6 +30,7 @@ type DecoderReader = interface { type Decoder struct { r DecoderReader disallowUnknownFields bool + networkFormat bool } func NewDecoder(r io.Reader) *Decoder { @@ -48,6 +49,14 @@ func (d *Decoder) DisallowUnknownFields() { d.disallowUnknownFields = true } +// NetworkFormat controls wether the decoder parsing nbt in "network format". +// Means it haven't a tag name for root tag. +// +// It is disabled by default. +func (d *Decoder) NetworkFormat(enable bool) { + d.networkFormat = enable +} + type reader struct { io.Reader }