Apply "network nbt" format for net/packet.

examples and tests are updated
This commit is contained in:
Tnze
2023-11-19 02:01:17 +08:00
parent 7d6e65f554
commit 61916db07a
4 changed files with 24 additions and 22 deletions

View File

@ -47,9 +47,14 @@ func (e *Encoder) NetworkFormat(enable bool) {
// expect `[]int8`, `[]int32`, `[]int64`, `[]uint8`, `[]uint32` and `[]uint64`,
// which TagByteArray, TagIntArray and TagLongArray.
// To force encode them as TagList, add a struct field tag.
func (e *Encoder) Encode(v any, tagName string) error {
func (e *Encoder) Encode(v any, tagName string) (err error) {
t, val := getTagType(reflect.ValueOf(v))
if err := writeTag(e.w, t, tagName); err != nil {
if e.networkFormat {
_, err = e.w.Write([]byte{t})
} else {
err = writeTag(e.w, t, tagName)
}
if err != nil {
return err
}
return e.marshal(val, t)

View File

@ -77,7 +77,7 @@ func ExampleMarshal_setSlot() {
// Output:
// 15 00 00 05 00
// 15 00 00 05 01 01 01 00
// 15 00 00 05 01 01 01 03 00 00 12 34 56 78
// 15 00 00 05 01 01 01 03 12 34 56 78
}
func BenchmarkPacket_Pack_packWithoutCompression(b *testing.B) {

View File

@ -469,16 +469,15 @@ func (d *Double) ReadFrom(r io.Reader) (n int64, err error) {
//
// When using as [FieldDecoder], unknown fields are not allowed by default.
// For allow unknown fields, using [NBTField] instead.
func NBT(v any, optionalTagName ...string) Field {
if len(optionalTagName) > 0 {
return NBTField{V: v, TagName: optionalTagName[0]}
}
func NBT(v any) Field {
return NBTField{V: v}
}
// NBTField is a NBT warpper for convert any type into a Field, allowing to be pack or unpack with network packets.
//
// After v1.20.2, the "network format" is used. The root tag nolonger have a tag name anymore.
type NBTField struct {
TagName string
V any
V any
AllowUnknownFields bool
}
@ -491,25 +490,27 @@ func (n NBTField) WriteTo(w io.Writer) (int64, error) {
// nbt Encode method does not count written bytes,
// so we warp the writer to count it.
cw := countingWriter{w: w}
err := nbt.NewEncoder(&cw).Encode(n.V, n.TagName)
enc := nbt.NewEncoder(&cw)
enc.NetworkFormat(true)
err := enc.Encode(n.V, "")
return cw.n, err
}
func (n NBTField) ReadFrom(r io.Reader) (int64, error) {
// LimitReader is used to count reader length
cr := countingReader{r: r}
decoder := nbt.NewDecoder(&cr)
dec := nbt.NewDecoder(&cr)
dec.NetworkFormat(true)
if !n.AllowUnknownFields {
decoder.DisallowUnknownFields()
dec.DisallowUnknownFields()
}
tagName, err := decoder.Decode(n.V)
_, err := dec.Decode(n.V)
if err != nil {
if !errors.Is(err, nbt.ErrEND) {
return cr.n, err
}
err = nil
}
n.TagName = tagName
return cr.n, nil
}

View File

@ -145,8 +145,7 @@ func ExampleNBT() {
p := pk.Marshal(
packetid.ServerboundPacketID(0),
//...
pk.NBT(send), // without tag name
pk.NBT(send, "player"), // with tag name
pk.NBT(send),
//...
)
fmt.Println("Marshal:")
@ -156,16 +155,13 @@ func ExampleNBT() {
_ = p.Scan(
//...
pk.NBT(&recv),
// pk.NBT(&recv) // The tag name are going to be ignored. To receive the tag name, pk.NBTField has to be used.
//...
)
fmt.Println("Scan:", recv.Name)
// Output:
// Marshal:
// 00000000 0a 00 00 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 |......name..Tnze|
// 00000010 00 0a 00 06 70 6c 61 79 65 72 08 00 04 6e 61 6d |....player...nam|
// 00000020 65 00 04 54 6e 7a 65 00 |e..Tnze.|
// 00000000 0a 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 00 |....name..Tnze.|
//
// Scan: Tnze
}
@ -184,7 +180,7 @@ func TestNBTField_ReadFrom(t *testing.T) {
pk.NBTField{V: send},
)
err := p.Scan(pk.NBTField{V: &recv})
err := p.Scan(&pk.NBTField{V: &recv})
if err == nil {
t.Errorf("should be a unknown field error here")
}
@ -194,7 +190,7 @@ func TestNBTField_ReadFrom(t *testing.T) {
t.Errorf("disallow unknown field by default")
}
err = p.Scan(pk.NBTField{V: &recv, AllowUnknownFields: true})
err = p.Scan(&pk.NBTField{V: &recv, AllowUnknownFields: true})
if err != nil {
t.Errorf("should allow the unknown field here: %v", err)
}