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`, // expect `[]int8`, `[]int32`, `[]int64`, `[]uint8`, `[]uint32` and `[]uint64`,
// which TagByteArray, TagIntArray and TagLongArray. // which TagByteArray, TagIntArray and TagLongArray.
// To force encode them as TagList, add a struct field tag. // 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)) 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 err
} }
return e.marshal(val, t) return e.marshal(val, t)

View File

@ -77,7 +77,7 @@ func ExampleMarshal_setSlot() {
// Output: // Output:
// 15 00 00 05 00 // 15 00 00 05 00
// 15 00 00 05 01 01 01 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) { func BenchmarkPacket_Pack_packWithoutCompression(b *testing.B) {

View File

@ -469,15 +469,14 @@ func (d *Double) ReadFrom(r io.Reader) (n int64, err error) {
// //
// When using as [FieldDecoder], unknown fields are not allowed by default. // When using as [FieldDecoder], unknown fields are not allowed by default.
// For allow unknown fields, using [NBTField] instead. // For allow unknown fields, using [NBTField] instead.
func NBT(v any, optionalTagName ...string) Field { func NBT(v any) Field {
if len(optionalTagName) > 0 {
return NBTField{V: v, TagName: optionalTagName[0]}
}
return NBTField{V: v} 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 { type NBTField struct {
TagName string
V any V any
AllowUnknownFields bool AllowUnknownFields bool
@ -491,25 +490,27 @@ func (n NBTField) WriteTo(w io.Writer) (int64, error) {
// nbt Encode method does not count written bytes, // nbt Encode method does not count written bytes,
// so we warp the writer to count it. // so we warp the writer to count it.
cw := countingWriter{w: w} 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 return cw.n, err
} }
func (n NBTField) ReadFrom(r io.Reader) (int64, error) { func (n NBTField) ReadFrom(r io.Reader) (int64, error) {
// LimitReader is used to count reader length // LimitReader is used to count reader length
cr := countingReader{r: r} cr := countingReader{r: r}
decoder := nbt.NewDecoder(&cr) dec := nbt.NewDecoder(&cr)
dec.NetworkFormat(true)
if !n.AllowUnknownFields { if !n.AllowUnknownFields {
decoder.DisallowUnknownFields() dec.DisallowUnknownFields()
} }
tagName, err := decoder.Decode(n.V) _, err := dec.Decode(n.V)
if err != nil { if err != nil {
if !errors.Is(err, nbt.ErrEND) { if !errors.Is(err, nbt.ErrEND) {
return cr.n, err return cr.n, err
} }
err = nil err = nil
} }
n.TagName = tagName
return cr.n, nil return cr.n, nil
} }

View File

@ -145,8 +145,7 @@ func ExampleNBT() {
p := pk.Marshal( p := pk.Marshal(
packetid.ServerboundPacketID(0), packetid.ServerboundPacketID(0),
//... //...
pk.NBT(send), // without tag name pk.NBT(send),
pk.NBT(send, "player"), // with tag name
//... //...
) )
fmt.Println("Marshal:") fmt.Println("Marshal:")
@ -156,16 +155,13 @@ func ExampleNBT() {
_ = p.Scan( _ = p.Scan(
//... //...
pk.NBT(&recv), 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) fmt.Println("Scan:", recv.Name)
// Output: // Output:
// Marshal: // Marshal:
// 00000000 0a 00 00 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 |......name..Tnze| // 00000000 0a 08 00 04 6e 61 6d 65 00 04 54 6e 7a 65 00 |....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.|
// //
// Scan: Tnze // Scan: Tnze
} }
@ -184,7 +180,7 @@ func TestNBTField_ReadFrom(t *testing.T) {
pk.NBTField{V: send}, pk.NBTField{V: send},
) )
err := p.Scan(pk.NBTField{V: &recv}) err := p.Scan(&pk.NBTField{V: &recv})
if err == nil { if err == nil {
t.Errorf("should be a unknown field error here") 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") 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 { if err != nil {
t.Errorf("should allow the unknown field here: %v", err) t.Errorf("should allow the unknown field here: %v", err)
} }