Fix other code for compatible with new go-mc/net packet

This commit is contained in:
Tnze
2021-02-25 20:22:06 +08:00
parent 27a30efe7b
commit f8b3501b60
16 changed files with 461 additions and 478 deletions

View File

@ -294,22 +294,16 @@ func handleEntityStatusPacket(c *Client, p pk.Packet) error {
} }
func handleDestroyEntitiesPacket(c *Client, p pk.Packet) error { func handleDestroyEntitiesPacket(c *Client, p pk.Packet) error {
var ( var count pk.VarInt
count pk.VarInt var data = pk.Ary{
r = bytes.NewReader(p.Data) Len: &count,
) Ary: []pk.VarInt{},
if err := count.Decode(r); err != nil { }
if err := p.Scan(&count, &data); err != nil {
return err return err
} }
entities := make([]pk.VarInt, int(count)) return c.Wd.OnEntityDestroy(data.Ary.([]pk.VarInt))
for i := 0; i < int(count); i++ {
if err := entities[i].Decode(r); err != nil {
return err
}
}
return c.Wd.OnEntityDestroy(entities)
} }
func handleSoundEffect(c *Client, p pk.Packet) error { func handleSoundEffect(c *Client, p pk.Packet) error {
@ -378,34 +372,24 @@ func handleMultiBlockChangePacket(c *Client, p pk.Packet) error {
if !c.settings.ReceiveMap { if !c.settings.ReceiveMap {
return nil return nil
} }
r := bytes.NewReader(p.Data)
var ( var (
loc pk.Long loc pk.Long
dontTrustEdges pk.Boolean dontTrustEdges pk.Boolean
sz pk.VarInt sz pk.VarInt
packedBlocks = pk.Ary{
Len: &sz,
Ary: []pk.VarLong{},
}
) )
err := p.Scan(&loc, &dontTrustEdges, &sz, &packedBlocks)
if err := loc.Decode(r); err != nil { if err != nil {
return fmt.Errorf("packed location: %v", err) return err
}
if err := dontTrustEdges.Decode(r); err != nil {
return fmt.Errorf("unknown 1: %v", err)
}
if err := sz.Decode(r); err != nil {
return fmt.Errorf("array size: %v", err)
} }
packedBlocks := make([]pk.VarLong, int(sz)) x := int((loc >> 42) & ((1 << 22) - 1))
for i := 0; i < int(sz); i++ { y := int((loc >> 20) & ((1 << 22) - 1))
if err := packedBlocks[i].Decode(r); err != nil { z := int(loc & ((1 << 20) - 1))
return fmt.Errorf("block[%d]: %v", i, err)
}
}
x, z, y := int((loc>>42)&((1<<22)-1)),
int((loc>>20)&((1<<22)-1)),
int(loc&((1<<20)-1))
// Apply transform into negative (these numbers are signed) // Apply transform into negative (these numbers are signed)
if x >= 1<<21 { if x >= 1<<21 {
@ -415,7 +399,7 @@ func handleMultiBlockChangePacket(c *Client, p pk.Packet) error {
z -= 1 << 22 z -= 1 << 22
} }
c.Wd.MultiBlockUpdate(world.ChunkLoc{X: x, Z: z}, y, packedBlocks) c.Wd.MultiBlockUpdate(world.ChunkLoc{X: x, Z: z}, y, packedBlocks.Ary.([]pk.VarLong))
return nil return nil
} }
@ -520,14 +504,14 @@ func handlePluginPacket(c *Client, p pk.Packet) error {
switch msg.Channel { switch msg.Channel {
case "minecraft:brand": case "minecraft:brand":
var brandRaw pk.String var brandRaw pk.String
if err := brandRaw.Decode(bytes.NewReader(msg.Data)); err != nil { if _, err := brandRaw.ReadFrom(bytes.NewReader(msg.Data)); err != nil {
return err return err
} }
c.ServInfo.Brand = string(brandRaw) c.ServInfo.Brand = string(brandRaw)
} }
if c.Events.PluginMessage != nil { if c.Events.PluginMessage != nil {
return c.Events.PluginMessage(string(msg.Channel), []byte(msg.Data)) return c.Events.PluginMessage(string(msg.Channel), msg.Data)
} }
return nil return nil
} }
@ -622,7 +606,7 @@ func handleChunkDataPacket(c *Client, p pk.Packet) error {
} }
var pkt ptypes.ChunkData var pkt ptypes.ChunkData
if err := pkt.Decode(p); err != nil { if _, err := pkt.ReadFrom(bytes.NewReader(p.Data)); err != nil {
return err return err
} }
@ -641,7 +625,7 @@ func handleChunkDataPacket(c *Client, p pk.Packet) error {
func handleTileEntityDataPacket(c *Client, p pk.Packet) error { func handleTileEntityDataPacket(c *Client, p pk.Packet) error {
var pkt ptypes.TileEntityData var pkt ptypes.TileEntityData
if err := pkt.Decode(p); err != nil { if _, err := pkt.ReadFrom(bytes.NewReader(p.Data)); err != nil {
return err return err
} }
return c.Wd.TileEntityUpdate(pkt) return c.Wd.TileEntityUpdate(pkt)
@ -712,7 +696,7 @@ func handleKeepAlivePacket(c *Client, p pk.Packet) error {
func handleWindowItemsPacket(c *Client, p pk.Packet) error { func handleWindowItemsPacket(c *Client, p pk.Packet) error {
var pkt ptypes.WindowItems var pkt ptypes.WindowItems
if err := pkt.Decode(p); err != nil { if _, err := pkt.ReadFrom(bytes.NewReader(p.Data)); err != nil {
return err return err
} }

View File

@ -62,34 +62,12 @@ type encryptionRequest struct {
VerifyToken []byte VerifyToken []byte
} }
func (e *encryptionRequest) Decode(r pk.DecodeReader) error { func (e *encryptionRequest) ReadFrom(r io.Reader) (int64, error) {
var serverID pk.String return pk.Tuple{
if err := serverID.Decode(r); err != nil { (*pk.String)(&e.ServerID),
return err (*pk.ByteArray)(&e.PublicKey),
} (*pk.ByteArray)(&e.VerifyToken),
}.ReadFrom(r)
var publicKeyLength, verifyTokenLength pk.VarInt
if err := publicKeyLength.Decode(r); err != nil {
return err
}
publicKey, err := pk.ReadNBytes(r, int(publicKeyLength))
if err != nil {
return err
}
if err := verifyTokenLength.Decode(r); err != nil {
return err
}
verifyToken, err := pk.ReadNBytes(r, int(verifyTokenLength))
if err != nil {
return err
}
e.ServerID = string(serverID)
e.PublicKey = publicKey
e.VerifyToken = verifyToken
return nil
} }
// authDigest computes a special SHA-1 digest required for Minecraft web // authDigest computes a special SHA-1 digest required for Minecraft web
@ -216,14 +194,9 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte) (erp p
err = fmt.Errorf("encryption verfy tokenfail: %v", err) err = fmt.Errorf("encryption verfy tokenfail: %v", err)
return return
} }
var data []byte return pk.Marshal(
data = append(data, pk.VarInt(int32(len(cryptPK))).Encode()...) 0x01,
data = append(data, cryptPK...) pk.ByteArray(cryptPK),
data = append(data, pk.VarInt(int32(len(verifyT))).Encode()...) pk.ByteArray(verifyT),
data = append(data, verifyT...) ), nil
erp = pk.Packet{
ID: 0x01,
Data: data,
}
return
} }

View File

@ -3,6 +3,7 @@ package world
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"math" "math"
"github.com/Tnze/go-mc/data/block" "github.com/Tnze/go-mc/data/block"
@ -41,13 +42,13 @@ func perBits(bpb byte) uint {
} }
} }
func readSection(data pk.DecodeReader) (s Section, err error) { func readSection(data io.Reader) (s Section, err error) {
var nonAirBlockCount pk.Short var nonAirBlockCount pk.Short
if err := nonAirBlockCount.Decode(data); err != nil { if _, err := nonAirBlockCount.ReadFrom(data); err != nil {
return nil, fmt.Errorf("block count: %w", err) return nil, fmt.Errorf("block count: %w", err)
} }
var bpb pk.UnsignedByte var bpb pk.UnsignedByte
if err := bpb.Decode(data); err != nil { if _, err := bpb.ReadFrom(data); err != nil {
return nil, fmt.Errorf("bits per block: %w", err) return nil, fmt.Errorf("bits per block: %w", err)
} }
// If bpb values greater than or equal to 9, use directSection. // If bpb values greater than or equal to 9, use directSection.
@ -57,14 +58,14 @@ func readSection(data pk.DecodeReader) (s Section, err error) {
if bpb <= maxPaletteBits { if bpb <= maxPaletteBits {
// read palettes // read palettes
var length pk.VarInt var length pk.VarInt
if err := length.Decode(data); err != nil { if _, err := length.ReadFrom(data); err != nil {
return nil, fmt.Errorf("palette length: %w", err) return nil, fmt.Errorf("palette length: %w", err)
} }
palettes = make([]BlockStatus, length) palettes = make([]BlockStatus, length)
palettesIndex = make(map[BlockStatus]int, length) palettesIndex = make(map[BlockStatus]int, length)
for i := 0; i < int(length); i++ { for i := 0; i < int(length); i++ {
var v pk.VarInt var v pk.VarInt
if err := v.Decode(data); err != nil { if _, err := v.ReadFrom(data); err != nil {
return nil, fmt.Errorf("read palettes[%d] error: %w", i, err) return nil, fmt.Errorf("read palettes[%d] error: %w", i, err)
} }
palettes[i] = BlockStatus(v) palettes[i] = BlockStatus(v)
@ -74,7 +75,7 @@ func readSection(data pk.DecodeReader) (s Section, err error) {
// read data array // read data array
var dataLen pk.VarInt var dataLen pk.VarInt
if err := dataLen.Decode(data); err != nil { if _, err := dataLen.ReadFrom(data); err != nil {
return nil, fmt.Errorf("read data array length error: %w", err) return nil, fmt.Errorf("read data array length error: %w", err)
} }
if int(dataLen) < 16*16*16*int(bpb)/64 { if int(dataLen) < 16*16*16*int(bpb)/64 {
@ -83,7 +84,7 @@ func readSection(data pk.DecodeReader) (s Section, err error) {
dataArray := make([]uint64, dataLen) dataArray := make([]uint64, dataLen)
for i := 0; i < int(dataLen); i++ { for i := 0; i < int(dataLen); i++ {
var v pk.Long var v pk.Long
if err := v.Decode(data); err != nil { if _, err := v.ReadFrom(data); err != nil {
return nil, fmt.Errorf("read dataArray[%d] error: %w", i, err) return nil, fmt.Errorf("read dataArray[%d] error: %w", i, err)
} }
dataArray[i] = uint64(v) dataArray[i] = uint64(v)

View File

@ -1,11 +1,10 @@
package entity package entity
import ( import (
"bytes" "io"
"github.com/Tnze/go-mc/data/entity" "github.com/Tnze/go-mc/data/entity"
item "github.com/Tnze/go-mc/data/item" item "github.com/Tnze/go-mc/data/item"
"github.com/Tnze/go-mc/nbt"
pk "github.com/Tnze/go-mc/net/packet" pk "github.com/Tnze/go-mc/net/packet"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -49,53 +48,48 @@ type Slot struct {
Present bool Present bool
ItemID item.ID ItemID item.ID
Count int8 Count int8
NBT interface{} NBT pk.NBT
}
type SlotNBT struct {
data interface{}
} }
//Decode implement packet.FieldDecoder interface //Decode implement packet.FieldDecoder interface
func (s *Slot) Decode(r pk.DecodeReader) error { func (s *Slot) ReadFrom(r io.Reader) (int64, error) {
if err := (*pk.Boolean)(&s.Present).Decode(r); err != nil {
return err
}
if s.Present {
var itemID pk.VarInt var itemID pk.VarInt
if err := itemID.Decode(r); err != nil { n, err := pk.Tuple{
return err (*pk.Boolean)(&s.Present),
pk.Opt{
Has: (*pk.Boolean)(&s.Present),
Field: pk.Tuple{
&itemID,
(*pk.Byte)(&s.Count),
&s.NBT,
},
},
}.ReadFrom(r)
if err != nil {
return n, err
} }
s.ItemID = item.ID(itemID) s.ItemID = item.ID(itemID)
if err := (*pk.Byte)(&s.Count).Decode(r); err != nil { return n, nil
return err
}
if err := nbt.NewDecoder(r).Decode(&s.NBT); err != nil {
return err
}
}
return nil
} }
func (s Slot) Encode() []byte { func (s Slot) WriteTo(w io.Writer) (int64, error) {
if !s.Present { return pk.Tuple{
return pk.Boolean(false).Encode() pk.Boolean(s.Present),
} pk.Opt{
Has: (*pk.Boolean)(&s.Present),
var b bytes.Buffer Field: pk.Tuple{
b.Write(pk.Boolean(true).Encode()) pk.VarInt(s.ItemID),
b.Write(pk.VarInt(s.ItemID).Encode()) pk.Byte(s.Count),
b.Write(pk.Byte(s.Count).Encode()) s.NBT,
},
if s.NBT != nil { },
if err := nbt.NewEncoder(&b).Encode(s.NBT); err != nil { }.WriteTo(w)
panic(err)
}
} else {
if _, err := b.Write([]byte{nbt.TagEnd}); err != nil {
panic(err)
}
}
return b.Bytes()
} }
func (s Slot) String() string { func (s Slot) String() string {
return item.ByID[item.ID(s.ItemID)].DisplayName return item.ByID[s.ItemID].DisplayName
} }

View File

@ -51,22 +51,23 @@ func (m *Message) UnmarshalJSON(jsonMsg []byte) (err error) {
} }
//Decode for a ChatMsg packet //Decode for a ChatMsg packet
func (m *Message) Decode(r pk.DecodeReader) error { func (m *Message) ReadFrom(r io.Reader) (int64, error) {
var Len pk.VarInt var Len pk.VarInt
if err := Len.Decode(r); err != nil { if n, err := Len.ReadFrom(r); err != nil {
return err return n, err
} }
lr := &io.LimitedReader{R: r, N: int64(Len)}
return json.NewDecoder(io.LimitReader(r, int64(Len))).Decode(m) err := json.NewDecoder(lr).Decode(m)
return int64(Len) - lr.N, err
} }
//Encode for a ChatMsg packet //Encode for a ChatMsg packet
func (m Message) Encode() []byte { func (m Message) WriteTo(w io.Writer) (int64, error) {
code, err := json.Marshal(m) code, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return pk.String(code).Encode() return pk.String(code).WriteTo(w)
} }
func (m *Message) Append(extraMsg ...Message) { func (m *Message) Append(extraMsg ...Message) {

View File

@ -101,10 +101,11 @@ func TestChatMsgClearString(t *testing.T) {
} }
func TestMessage_Encode(t *testing.T) { func TestMessage_Encode(t *testing.T) {
codeMsg := chat.Message{Translate: "multiplayer.disconnect.server_full"}.Encode() var codeMsg bytes.Buffer
_, _ = chat.Message{Translate: "multiplayer.disconnect.server_full"}.WriteTo(&codeMsg)
var msg pk.Chat var msg pk.Chat
if err := msg.Decode(bytes.NewReader(codeMsg)); err != nil { if _, err := msg.ReadFrom(&codeMsg); err != nil {
t.Errorf("decode message fail: %v", err) t.Errorf("decode message fail: %v", err)
} }

View File

@ -65,7 +65,7 @@ func onPluginMessage(channel string, data []byte) error {
switch channel { switch channel {
case "minecraft:brand": case "minecraft:brand":
var brand pk.String var brand pk.String
if err := brand.Decode(bytes.NewReader(data)); err != nil { if _, err := brand.ReadFrom(bytes.NewReader(data)); err != nil {
return err return err
} }
log.Println("Server brand is:", brand) log.Println("Server brand is:", brand)

View File

@ -85,8 +85,7 @@ func (c *Conn) ReadPacket(p *pk.Packet) error {
//WritePacket write a Packet to Conn. //WritePacket write a Packet to Conn.
func (c *Conn) WritePacket(p pk.Packet) error { func (c *Conn) WritePacket(p pk.Packet) error {
_, err := c.Write(p.Pack(c.threshold)) return p.Pack(c, c.threshold)
return err
} }
// SetCipher load the decode/encode stream to this Conn // SetCipher load the decode/encode stream to this Conn

View File

@ -8,7 +8,10 @@ type Builder struct {
func (p *Builder) WriteField(fields ...FieldEncoder) { func (p *Builder) WriteField(fields ...FieldEncoder) {
for _, f := range fields { for _, f := range fields {
p.buf.Write(f.Encode()) _, err := f.WriteTo(&p.buf)
if err != nil {
panic(err)
}
} }
} }

View File

@ -15,20 +15,18 @@ type Packet struct {
//Marshal generate Packet with the ID and Fields //Marshal generate Packet with the ID and Fields
func Marshal(id int32, fields ...FieldEncoder) (pk Packet) { func Marshal(id int32, fields ...FieldEncoder) (pk Packet) {
pk.ID = id var pb Builder
for _, v := range fields { for _, v := range fields {
pk.Data = append(pk.Data, v.Encode()...) pb.WriteField(v)
} }
return pb.Packet(id)
return
} }
//Scan decode the packet and fill data into fields //Scan decode the packet and fill data into fields
func (p Packet) Scan(fields ...FieldDecoder) error { func (p Packet) Scan(fields ...FieldDecoder) error {
r := bytes.NewReader(p.Data) r := bytes.NewReader(p.Data)
for _, v := range fields { for _, v := range fields {
err := v.Decode(r) _, err := v.ReadFrom(r)
if err != nil { if err != nil {
return err return err
} }
@ -37,34 +35,48 @@ func (p Packet) Scan(fields ...FieldDecoder) error {
} }
// Pack 打包一个数据包 // Pack 打包一个数据包
func (p *Packet) Pack(threshold int) (pack []byte) { func (p *Packet) Pack(w io.Writer, threshold int) error {
d := append(VarInt(p.ID).Encode(), p.Data...) var content bytes.Buffer
if _, err := VarInt(p.ID).WriteTo(&content); err != nil {
panic(err)
}
if _, err := content.Write(p.Data); err != nil {
panic(err)
}
if threshold > 0 { //是否启用了压缩 if threshold > 0 { //是否启用了压缩
if len(d) > threshold { //是否需要压缩 Len := content.Len()
Len := len(d) var VarLen bytes.Buffer
VarLen := VarInt(Len).Encode() if _, err := VarInt(Len).WriteTo(&VarLen); err != nil {
d = compress(d) panic(err)
}
pack = append(pack, VarInt(len(VarLen)+len(d)).Encode()...) if _, err := VarInt(VarLen.Len() + Len).WriteTo(w); err != nil {
pack = append(pack, VarLen...) return err
pack = append(pack, d...) }
} else { if Len > threshold { //是否需要压缩
pack = append(pack, VarInt(int32(len(d)+1)).Encode()...) compress(&content)
pack = append(pack, 0x00) }
pack = append(pack, d...) if _, err := VarLen.WriteTo(w); err != nil {
return err
}
if _, err := content.WriteTo(w); err != nil {
return err
} }
} else { } else {
pack = append(pack, VarInt(int32(len(d))).Encode()...) //len if _, err := VarInt(content.Len()).WriteTo(w); err != nil {
pack = append(pack, d...) return err
}
if _, err := content.WriteTo(w); err != nil {
return err
}
} }
return return nil
} }
// UnPack in-place decompression a packet // UnPack in-place decompression a packet
func (p *Packet) UnPack(r DecodeReader, threshold int) error { func (p *Packet) UnPack(r io.Reader, threshold int) error {
var length VarInt var length VarInt
if err := length.Decode(r); err != nil { if _, err := length.ReadFrom(r); err != nil {
return err return err
} }
if length < 1 { if length < 1 {
@ -84,7 +96,7 @@ func (p *Packet) UnPack(r DecodeReader, threshold int) error {
} }
var packetID VarInt var packetID VarInt
if err := packetID.Decode(buf); err != nil { if _, err := packetID.ReadFrom(buf); err != nil {
return fmt.Errorf("read packet id fail: %v", err) return fmt.Errorf("read packet id fail: %v", err)
} }
p.ID = int32(packetID) p.ID = int32(packetID)
@ -97,7 +109,7 @@ func unCompress(data *bytes.Buffer) error {
reader := bytes.NewReader(data.Bytes()) reader := bytes.NewReader(data.Bytes())
var sizeUncompressed VarInt var sizeUncompressed VarInt
if err := sizeUncompressed.Decode(reader); err != nil { if _, err := sizeUncompressed.ReadFrom(reader); err != nil {
return err return err
} }
@ -121,14 +133,15 @@ func unCompress(data *bytes.Buffer) error {
} }
// compress 压缩数据 // compress 压缩数据
func compress(data []byte) []byte { func compress(data *bytes.Buffer) {
var b bytes.Buffer var b bytes.Buffer
w := zlib.NewWriter(&b) w := zlib.NewWriter(&b)
if _, err := w.Write(data); err != nil { if _, err := data.WriteTo(w); err != nil {
panic(err) panic(err)
} }
if err := w.Close(); err != nil { if err := w.Close(); err != nil {
panic(err) panic(err)
} }
return b.Bytes() *data = b
return
} }

View File

@ -20,9 +20,15 @@ var PackedVarInts = [][]byte{
} }
func TestPackVarInt(t *testing.T) { func TestPackVarInt(t *testing.T) {
var buf bytes.Buffer
for i, v := range VarInts { for i, v := range VarInts {
p := v.Encode() buf.Reset()
if !bytes.Equal(p, PackedVarInts[i]) { if n, err := v.WriteTo(&buf); err != nil {
t.Fatalf("Write to bytes.Buffer should never fail: %v", err)
} else if n != int64(buf.Len()) {
t.Errorf("Number of byte returned by WriteTo should equal to buffer.Len()")
}
if p := buf.Bytes(); !bytes.Equal(p, PackedVarInts[i]) {
t.Errorf("pack int %d should be \"% x\", get \"% x\"", v, PackedVarInts[i], p) t.Errorf("pack int %d should be \"% x\", get \"% x\"", v, PackedVarInts[i], p)
} }
} }
@ -30,7 +36,7 @@ func TestPackVarInt(t *testing.T) {
func TestUnpackVarInt(t *testing.T) { func TestUnpackVarInt(t *testing.T) {
for i, v := range PackedVarInts { for i, v := range PackedVarInts {
var vi VarInt var vi VarInt
if err := vi.Decode(bytes.NewReader(v)); err != nil { if _, err := vi.ReadFrom(bytes.NewReader(v)); err != nil {
t.Errorf("unpack \"% x\" error: %v", v, err) t.Errorf("unpack \"% x\" error: %v", v, err)
} }
if vi != VarInts[i] { if vi != VarInts[i] {
@ -42,7 +48,7 @@ func TestUnpackVarInt(t *testing.T) {
func TestUnpackVarInt_TooLongData(t *testing.T) { func TestUnpackVarInt_TooLongData(t *testing.T) {
var vi VarInt var vi VarInt
var data = []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} var data = []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}
if err := vi.Decode(bytes.NewReader(data)); err != nil { if _, err := vi.ReadFrom(bytes.NewReader(data)); err != nil {
t.Logf("unpack \"% x\" error: %v", data, err) t.Logf("unpack \"% x\" error: %v", data, err)
} else { } else {
t.Errorf("unpack \"% x\" should be error, get %d", data, vi) t.Errorf("unpack \"% x\" should be error, get %d", data, vi)
@ -76,7 +82,7 @@ func TestPackVarLong(t *testing.T) {
func TestUnpackVarLong(t *testing.T) { func TestUnpackVarLong(t *testing.T) {
for i, v := range PackedVarLongs { for i, v := range PackedVarLongs {
var vi VarLong var vi VarLong
if err := vi.Decode(bytes.NewReader(v)); err != nil { if _, err := vi.ReadFrom(bytes.NewReader(v)); err != nil {
t.Errorf("unpack \"% x\" error: %v", v, err) t.Errorf("unpack \"% x\" error: %v", v, err)
} }
if vi != VarLongs[i] { if vi != VarLongs[i] {

View File

@ -18,20 +18,10 @@ type Field interface {
} }
// A FieldEncoder can be encode as minecraft protocol used. // A FieldEncoder can be encode as minecraft protocol used.
type FieldEncoder interface { type FieldEncoder io.WriterTo
Encode() []byte
}
// A FieldDecoder can Decode from minecraft protocol // A FieldDecoder can Decode from minecraft protocol
type FieldDecoder interface { type FieldDecoder io.ReaderFrom
Decode(r DecodeReader) error
}
//DecodeReader is both io.Reader and io.ByteReader
type DecodeReader interface {
io.ByteReader
io.Reader
}
type ( type (
//Boolean of True is encoded as 0x01, false as 0x00. //Boolean of True is encoded as 0x01, false as 0x00.
@ -71,7 +61,7 @@ type (
} }
//Angle is rotation angle in steps of 1/256 of a full turn //Angle is rotation angle in steps of 1/256 of a full turn
Angle int8 Angle Byte
//UUID encoded as an unsigned 128-bit integer //UUID encoded as an unsigned 128-bit integer
UUID uuid.UUID UUID uuid.UUID
@ -86,174 +76,190 @@ type (
ByteArray []byte ByteArray []byte
) )
//ReadNBytes read N bytes from bytes.Reader const MaxVarIntLen = 5
func ReadNBytes(r DecodeReader, n int) (bs []byte, err error) { const MaxVarLongLen = 10
bs = make([]byte, n)
for i := 0; i < n; i++ {
bs[i], err = r.ReadByte()
if err != nil {
return
}
}
return
}
//Encode a Boolean //Encode a Boolean
func (b Boolean) Encode() []byte { func (b Boolean) WriteTo(w io.Writer) (n int64, err error) {
var nn int
if b { if b {
return []byte{0x01} nn, err = w.Write([]byte{0x01})
} }
return []byte{0x00} nn, err = w.Write([]byte{0x00})
return int64(nn), err
} }
//Decode a Boolean //Decode a Boolean
func (b *Boolean) Decode(r DecodeReader) error { func (b *Boolean) ReadFrom(r io.Reader) (n int64, err error) {
v, err := r.ReadByte() v, err := readByte(r)
if err != nil { if err != nil {
return err return 1, err
} }
*b = Boolean(v != 0) *b = v != 0
return nil return 1, nil
} }
// Encode a String // Encode a String
func (s String) Encode() (p []byte) { func (s String) WriteTo(w io.Writer) (int64, error) {
byteString := []byte(s) byteStr := []byte(s)
p = append(p, VarInt(len(byteString)).Encode()...) //len n1, err := VarInt(len(byteStr)).WriteTo(w)
p = append(p, byteString...) //data if err != nil {
return return n1, err
}
n2, err := w.Write(byteStr)
return n1 + int64(n2), err
} }
//Decode a String //Decode a String
func (s *String) Decode(r DecodeReader) error { func (s *String) ReadFrom(r io.Reader) (n int64, err error) {
var l VarInt //String length var l VarInt //String length
if err := l.Decode(r); err != nil {
return err
}
bs, err := ReadNBytes(r, int(l)) nn, err := l.ReadFrom(r)
if err != nil { if err != nil {
return err return nn, err
} }
n += nn
bs := make([]byte, l)
if _, err := io.ReadFull(r, bs); err != nil {
return n, err
}
n += int64(l)
*s = String(bs) *s = String(bs)
return nil return n, nil
}
// readByte read one byte from io.Reader
func readByte(r io.Reader) (byte, error) {
if r, ok := r.(io.ByteReader); ok {
return r.ReadByte()
}
var v [1]byte
_, err := io.ReadFull(r, v[:])
return v[0], err
} }
//Encode a Byte //Encode a Byte
func (b Byte) Encode() []byte { func (b Byte) WriteTo(w io.Writer) (n int64, err error) {
return []byte{byte(b)} nn, err := w.Write([]byte{byte(b)})
return int64(nn), err
} }
//Decode a Byte //Decode a Byte
func (b *Byte) Decode(r DecodeReader) error { func (b *Byte) ReadFrom(r io.Reader) (n int64, err error) {
v, err := r.ReadByte() v, err := readByte(r)
if err != nil { if err != nil {
return err return 0, err
} }
*b = Byte(v) *b = Byte(v)
return nil return 1, nil
} }
//Encode a UnsignedByte //Encode a UnsignedByte
func (ub UnsignedByte) Encode() []byte { func (u UnsignedByte) WriteTo(w io.Writer) (n int64, err error) {
return []byte{byte(ub)} nn, err := w.Write([]byte{byte(u)})
return int64(nn), err
} }
//Decode a UnsignedByte //Decode a UnsignedByte
func (ub *UnsignedByte) Decode(r DecodeReader) error { func (u *UnsignedByte) ReadFrom(r io.Reader) (n int64, err error) {
v, err := r.ReadByte() v, err := readByte(r)
if err != nil { if err != nil {
return err return 0, err
} }
*ub = UnsignedByte(v) *u = UnsignedByte(v)
return nil return 1, nil
} }
// Encode a Signed Short // Encode a Signed Short
func (s Short) Encode() []byte { func (s Short) WriteTo(w io.Writer) (int64, error) {
n := uint16(s) n := uint16(s)
return []byte{ nn, err := w.Write([]byte{byte(n >> 8), byte(n)})
byte(n >> 8), return int64(nn), err
byte(n),
}
} }
//Decode a Short //Decode a Short
func (s *Short) Decode(r DecodeReader) error { func (s *Short) ReadFrom(r io.Reader) (n int64, err error) {
bs, err := ReadNBytes(r, 2) var bs [2]byte
if err != nil { if nn, err := io.ReadFull(r, bs[:]); err != nil {
return err return int64(nn), err
} else {
n += int64(nn)
} }
*s = Short(int16(bs[0])<<8 | int16(bs[1])) *s = Short(int16(bs[0])<<8 | int16(bs[1]))
return nil return
} }
// Encode a Unsigned Short // Encode a Unsigned Short
func (us UnsignedShort) Encode() []byte { func (us UnsignedShort) WriteTo(w io.Writer) (int64, error) {
n := uint16(us) n := uint16(us)
return []byte{ nn, err := w.Write([]byte{byte(n >> 8), byte(n)})
byte(n >> 8), return int64(nn), err
byte(n),
}
} }
//Decode a UnsignedShort //Decode a UnsignedShort
func (us *UnsignedShort) Decode(r DecodeReader) error { func (us *UnsignedShort) ReadFrom(r io.Reader) (n int64, err error) {
bs, err := ReadNBytes(r, 2) var bs [2]byte
if err != nil { if nn, err := io.ReadFull(r, bs[:]); err != nil {
return err return int64(nn), err
} else {
n += int64(nn)
} }
*us = UnsignedShort(int16(bs[0])<<8 | int16(bs[1])) *us = UnsignedShort(int16(bs[0])<<8 | int16(bs[1]))
return nil return
} }
// Encode a Int // Encode a Int
func (i Int) Encode() []byte { func (i Int) WriteTo(w io.Writer) (int64, error) {
n := uint32(i) n := uint32(i)
return []byte{ nn, err := w.Write([]byte{byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)})
byte(n >> 24), byte(n >> 16), return int64(nn), err
byte(n >> 8), byte(n),
}
} }
//Decode a Int //Decode a Int
func (i *Int) Decode(r DecodeReader) error { func (i *Int) ReadFrom(r io.Reader) (n int64, err error) {
bs, err := ReadNBytes(r, 4) var bs [4]byte
if err != nil { if nn, err := io.ReadFull(r, bs[:]); err != nil {
return err return int64(nn), err
} else {
n += int64(nn)
} }
*i = Int(int32(bs[0])<<24 | int32(bs[1])<<16 | int32(bs[2])<<8 | int32(bs[3])) *i = Int(int32(bs[0])<<24 | int32(bs[1])<<16 | int32(bs[2])<<8 | int32(bs[3]))
return nil return
} }
// Encode a Long // Encode a Long
func (l Long) Encode() []byte { func (l Long) WriteTo(w io.Writer) (int64, error) {
n := uint64(l) n := uint64(l)
return []byte{ nn, err := w.Write([]byte{
byte(n >> 56), byte(n >> 48), byte(n >> 40), byte(n >> 32), byte(n >> 56), byte(n >> 48), byte(n >> 40), byte(n >> 32),
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n), byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
} })
return int64(nn), err
} }
//Decode a Long //Decode a Long
func (l *Long) Decode(r DecodeReader) error { func (l *Long) ReadFrom(r io.Reader) (n int64, err error) {
bs, err := ReadNBytes(r, 8) var bs [8]byte
if err != nil { if nn, err := io.ReadFull(r, bs[:]); err != nil {
return err return int64(nn), err
} else {
n += int64(nn)
} }
*l = Long(int64(bs[0])<<56 | int64(bs[1])<<48 | int64(bs[2])<<40 | int64(bs[3])<<32 | *l = Long(int64(bs[0])<<56 | int64(bs[1])<<48 | int64(bs[2])<<40 | int64(bs[3])<<32 |
int64(bs[4])<<24 | int64(bs[5])<<16 | int64(bs[6])<<8 | int64(bs[7])) int64(bs[4])<<24 | int64(bs[5])<<16 | int64(bs[6])<<8 | int64(bs[7]))
return nil return
} }
//Encode a VarInt //Encode a VarInt
func (v VarInt) Encode() (vi []byte) { func (v VarInt) WriteTo(w io.Writer) (n int64, err error) {
var vi = make([]byte, 0, MaxVarIntLen)
num := uint32(v) num := uint32(v)
for { for {
b := num & 0x7F b := num & 0x7F
@ -266,29 +272,28 @@ func (v VarInt) Encode() (vi []byte) {
break break
} }
} }
return nn, err := w.Write(vi)
return int64(nn), err
} }
//Decode a VarInt //Decode a VarInt
func (v *VarInt) Decode(r DecodeReader) error { func (v *VarInt) ReadFrom(r io.Reader) (n int64, err error) {
var n uint32 var V uint32
for i := 0; ; i++ { //读数据前的长度标记 for sec := byte(0x80); sec&0x80 != 0; n++ {
sec, err := r.ReadByte() if n > MaxVarIntLen {
return n, errors.New("VarInt is too big")
}
sec, err = readByte(r)
if err != nil { if err != nil {
return err return n, err
} }
n |= uint32(sec&0x7F) << uint32(7*i) V |= uint32(sec&0x7F) << uint32(7*n)
if i >= 5 {
return errors.New("VarInt is too big")
} else if sec&0x80 == 0 {
break
}
} }
*v = VarInt(n) *v = VarInt(V)
return nil return
} }
//Encode a VarLong //Encode a VarLong
@ -309,44 +314,44 @@ func (v VarLong) Encode() (vi []byte) {
} }
//Decode a VarLong //Decode a VarLong
func (v *VarLong) Decode(r DecodeReader) error { func (v *VarLong) ReadFrom(r io.Reader) (n int64, err error) {
var n uint64 var V uint64
for i := 0; ; i++ { //读数据前的长度标记 for sec := byte(0x80); sec&0x80 != 0; n++ {
sec, err := r.ReadByte() if n >= MaxVarLongLen {
return n, errors.New("VarLong is too big")
}
sec, err = readByte(r)
if err != nil { if err != nil {
return err return
} }
n |= uint64(sec&0x7F) << uint64(7*i) V |= uint64(sec&0x7F) << uint64(7*n)
if i >= 10 {
return errors.New("VarLong is too big")
} else if sec&0x80 == 0 {
break
}
} }
*v = VarLong(n) *v = VarLong(V)
return nil return
} }
//Encode a Position //Encode a Position
func (p Position) Encode() []byte { func (p Position) WriteTo(w io.Writer) (n int64, err error) {
b := make([]byte, 8) var b [8]byte
position := uint64(p.X&0x3FFFFFF)<<38 | uint64((p.Z&0x3FFFFFF)<<12) | uint64(p.Y&0xFFF) position := uint64(p.X&0x3FFFFFF)<<38 | uint64((p.Z&0x3FFFFFF)<<12) | uint64(p.Y&0xFFF)
for i := 7; i >= 0; i-- { for i := 7; i >= 0; i-- {
b[i] = byte(position) b[i] = byte(position)
position >>= 8 position >>= 8
} }
return b nn, err := w.Write(b[:])
return int64(nn), err
} }
// Decode a Position // Decode a Position
func (p *Position) Decode(r DecodeReader) error { func (p *Position) ReadFrom(r io.Reader) (n int64, err error) {
var v Long var v Long
if err := v.Decode(r); err != nil { nn, err := v.ReadFrom(r)
return err if err != nil {
return nn, err
} }
n += nn
x := int(v >> 38) x := int(v >> 38)
y := int(v & 0xFFF) y := int(v & 0xFFF)
@ -364,88 +369,111 @@ func (p *Position) Decode(r DecodeReader) error {
} }
p.X, p.Y, p.Z = x, y, z p.X, p.Y, p.Z = x, y, z
return nil return
} }
//Decodes an Angle // ToDeg convert Angle to Degree
func (b *Angle) Decode(r DecodeReader) error { func (a Angle) ToDeg() float64 {
v, err := r.ReadByte() return 360 * float64(a) / 256
if err != nil {
return err
} }
*b = Angle(v)
return nil // ToRad convert Angle to Radian
func (a Angle) ToRad() float64 {
return 2 * math.Pi * float64(a) / 256
}
func (a Angle) WriteTo(w io.Writer) (int64, error) {
return Byte(a).WriteTo(w)
}
func (a *Angle) ReadFrom(r io.Reader) (int64, error) {
return (*Byte)(a).ReadFrom(r)
} }
//Encode a Float //Encode a Float
func (f Float) Encode() []byte { func (f Float) WriteTo(w io.Writer) (n int64, err error) {
return Int(math.Float32bits(float32(f))).Encode() return Int(math.Float32bits(float32(f))).WriteTo(w)
} }
// Decode a Float // Decode a Float
func (f *Float) Decode(r DecodeReader) error { func (f *Float) ReadFrom(r io.Reader) (n int64, err error) {
var v Int var v Int
if err := v.Decode(r); err != nil {
return err n, err = v.ReadFrom(r)
if err != nil {
return
} }
*f = Float(math.Float32frombits(uint32(v))) *f = Float(math.Float32frombits(uint32(v)))
return nil return
} }
//Encode a Double //Encode a Double
func (d Double) Encode() []byte { func (d Double) WriteTo(w io.Writer) (n int64, err error) {
return Long(math.Float64bits(float64(d))).Encode() return Long(math.Float64bits(float64(d))).WriteTo(w)
} }
// Decode a Double // Decode a Double
func (d *Double) Decode(r DecodeReader) error { func (d *Double) ReadFrom(r io.Reader) (n int64, err error) {
var v Long var v Long
if err := v.Decode(r); err != nil { n, err = v.ReadFrom(r)
return err if err != nil {
return
} }
*d = Double(math.Float64frombits(uint64(v))) *d = Double(math.Float64frombits(uint64(v)))
return nil return
} }
// Encode a NBT // Encode a NBT
func (n NBT) Encode() []byte { func (n *NBT) WriteTo(w io.Writer) (int64, error) {
var buf bytes.Buffer var buf bytes.Buffer
if err := nbt.NewEncoder(&buf).Encode(n.V); err != nil { if err := nbt.NewEncoder(&buf).Encode(n.V); err != nil {
panic(err) panic(err)
} }
return buf.Bytes() return buf.WriteTo(w)
} }
// Decode a NBT // Decode a NBT
func (n NBT) Decode(r DecodeReader) error { func (n *NBT) ReadFrom(r io.Reader) (int64, error) {
return nbt.NewDecoder(r).Decode(n.V) // LimitReader is used to count reader length
lr := &io.LimitedReader{R: r, N: math.MaxInt64}
err := nbt.NewDecoder(lr).Decode(n.V)
return math.MaxInt64 - lr.N, err
} }
// Encode a ByteArray // Encode a ByteArray
func (b ByteArray) Encode() []byte { func (b ByteArray) WriteTo(w io.Writer) (n int64, err error) {
return append(VarInt(len(b)).Encode(), b...) n1, err := VarInt(len(b)).WriteTo(w)
if err != nil {
return n1, err
}
n2, err := w.Write(b)
return n1 + int64(n2), err
} }
// Decode a ByteArray // Decode a ByteArray
func (b *ByteArray) Decode(r DecodeReader) error { func (b *ByteArray) ReadFrom(r io.Reader) (n int64, err error) {
var Len VarInt var Len VarInt
if err := Len.Decode(r); err != nil { n1, err := Len.ReadFrom(r)
return err if err != nil {
return n1, err
} }
*b = make([]byte, Len) buf := bytes.NewBuffer(*b)
_, err := r.Read(*b) buf.Reset()
return err n2, err := io.CopyN(buf, r, int64(Len))
*b = buf.Bytes()
return n1 + n2, err
} }
// Encode a UUID // Encode a UUID
func (u UUID) Encode() []byte { func (u UUID) WriteTo(w io.Writer) (n int64, err error) {
return u[:] nn, err := w.Write(u[:])
return int64(nn), err
} }
// Decode a UUID // Decode a UUID
func (u *UUID) Decode(r DecodeReader) error { func (u *UUID) ReadFrom(r io.Reader) (n int64, err error) {
_, err := io.ReadFull(r, (*u)[:]) nn, err := io.ReadFull(r, (*u)[:])
return err return int64(nn), err
} }

View File

@ -1,51 +1,84 @@
package packet package packet
import ( import (
"io"
"reflect" "reflect"
) )
type Ary struct { type Ary struct {
Len Field Len Field // One of VarInt, VarLong, Int or Long
Ary interface{} Ary interface{} // FieldEncoder, FieldDecoder or both (Field)
} }
func (a Ary) Encode() (data []byte) { func (a Ary) WriteTo(r io.Writer) (n int64, err error) {
length := int(reflect.ValueOf(a.Len).Int()) length := int(reflect.ValueOf(a.Len).Int())
array := reflect.ValueOf(a.Ary).Elem() array := reflect.ValueOf(a.Ary).Elem()
for i := 0; i < length; i++ { for i := 0; i < length; i++ {
elem := array.Index(i) elem := array.Index(i)
data = append(data, elem.Interface().(FieldEncoder).Encode()...) nn, err := elem.Interface().(FieldEncoder).WriteTo(r)
n += nn
if err != nil {
return n, err
}
}
return n, nil
}
func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
length := int(reflect.ValueOf(a.Len).Int())
array := reflect.ValueOf(a.Ary).Elem()
for i := 0; i < length; i++ {
elem := array.Index(i)
nn, err := elem.Interface().(FieldDecoder).ReadFrom(r)
n += nn
if err != nil {
return n, err
}
}
return n, err
}
type Opt struct {
Has *Boolean
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
}
func (o Opt) WriteTo(w io.Writer) (int64, error) {
if *o.Has {
return o.Field.(FieldEncoder).WriteTo(w)
}
return 0, nil
}
func (o Opt) ReadFrom(r io.Reader) (int64, error) {
if *o.Has {
return o.Field.(FieldDecoder).ReadFrom(r)
}
return 0, nil
}
type Tuple []interface{} // FieldEncoder, FieldDecoder or both (Field)
// WriteTo write Tuple to io.Writer, panic when any of filed don't implement FieldEncoder
func (t Tuple) WriteTo(w io.Writer) (n int64, err error) {
for _, v := range t {
nn, err := v.(FieldEncoder).WriteTo(w)
if err != nil {
return n, err
}
n += nn
} }
return return
} }
func (a Ary) Decode(r DecodeReader) error { // ReadFrom read Tuple from io.Reader, panic when any of field don't implement FieldDecoder
length := int(reflect.ValueOf(a.Len).Int()) func (t Tuple) ReadFrom(r io.Reader) (n int64, err error) {
array := reflect.ValueOf(a.Ary).Elem() for _, v := range t {
for i := 0; i < length; i++ { nn, err := v.(FieldDecoder).ReadFrom(r)
elem := array.Index(i) if err != nil {
if err := elem.Interface().(FieldDecoder).Decode(r); err != nil { return n, err
return err
} }
n += nn
} }
return nil return
}
type Opt struct {
Has func() bool
Field interface{}
}
func (o Opt) Encode() []byte {
if o.Has() {
return nil
}
return o.Field.(FieldEncoder).Encode()
}
func (o Opt) Decode(r DecodeReader) error {
if o.Has() {
return nil
}
return o.Field.(FieldDecoder).Decode(r)
} }

View File

@ -2,8 +2,8 @@
package ptypes package ptypes
import ( import (
"bytes" "io"
"fmt" "math"
"github.com/Tnze/go-mc/bot/world/entity" "github.com/Tnze/go-mc/bot/world/entity"
"github.com/Tnze/go-mc/nbt" "github.com/Tnze/go-mc/nbt"
@ -17,96 +17,53 @@ type ChunkData struct {
PrimaryBitMask pk.VarInt PrimaryBitMask pk.VarInt
Heightmaps struct{} Heightmaps struct{}
Biomes biomesData Biomes biomesData
Data chunkData Data pk.ByteArray
BlockEntities blockEntities BlockEntities blockEntities
} }
func (p *ChunkData) Decode(pkt pk.Packet) error { func (p *ChunkData) ReadFrom(r io.Reader) (int64, error) {
r := bytes.NewReader(pkt.Data) return pk.Tuple{
if err := p.X.Decode(r); err != nil { &p.X,
return fmt.Errorf("decode X: %v", err) &p.Z,
} &p.FullChunk,
if err := p.Z.Decode(r); err != nil { &p.PrimaryBitMask,
return fmt.Errorf("decode Z: %v", err) &pk.NBT{V: &p.Heightmaps},
} pk.Opt{Has: &p.FullChunk, Field: &p.Biomes},
if err := p.FullChunk.Decode(r); err != nil { &p.Data,
return fmt.Errorf("full chunk: %v", err) &p.BlockEntities,
} }.ReadFrom(r)
if err := p.PrimaryBitMask.Decode(r); err != nil {
return fmt.Errorf("bit mask: %v", err)
}
if err := (pk.NBT{V: &p.Heightmaps}).Decode(r); err != nil {
return fmt.Errorf("heightmaps: %v", err)
}
// Biomes data is only present for full chunks.
if p.FullChunk {
if err := p.Biomes.Decode(r); err != nil {
return fmt.Errorf("heightmaps: %v", err)
}
}
if err := p.Data.Decode(r); err != nil {
return fmt.Errorf("data: %v", err)
}
if err := p.BlockEntities.Decode(r); err != nil {
return fmt.Errorf("block entities: %v", err)
}
return nil
} }
type biomesData struct { type biomesData struct {
data []pk.VarInt data []pk.VarInt
} }
func (b *biomesData) Decode(r pk.DecodeReader) error { func (b *biomesData) ReadFrom(r io.Reader) (int64, error) {
var BiomesDataNums pk.VarInt // Number of Biomes Data var n pk.VarInt // Number of Biomes Data
if err := BiomesDataNums.Decode(r); err != nil { return pk.Tuple{
return err &n, pk.Ary{Len: &n, Ary: []pk.VarInt{}},
} }.ReadFrom(r)
b.data = make([]pk.VarInt, BiomesDataNums)
for i := 0; i < int(BiomesDataNums); i++ {
var d pk.VarInt
if err := d.Decode(r); err != nil {
return err
}
b.data[i] = d
} }
return nil
}
type chunkData []byte
type blockEntities []entity.BlockEntity type blockEntities []entity.BlockEntity
// Decode implement net.packet.FieldDecoder // Decode implement net.packet.FieldDecoder
func (c *chunkData) Decode(r pk.DecodeReader) error { func (b *blockEntities) ReadFrom(r io.Reader) (n int64, err error) {
var sz pk.VarInt
if err := sz.Decode(r); err != nil {
return err
}
*c = make([]byte, sz)
if _, err := r.Read(*c); err != nil {
return err
}
return nil
}
// Decode implement net.packet.FieldDecoder
func (b *blockEntities) Decode(r pk.DecodeReader) error {
var sz pk.VarInt // Number of BlockEntities var sz pk.VarInt // Number of BlockEntities
if err := sz.Decode(r); err != nil { if nn, err := sz.ReadFrom(r); err != nil {
return err return nn, err
} else {
n += nn
} }
*b = make(blockEntities, sz) *b = make(blockEntities, sz)
decoder := nbt.NewDecoder(r) lr := &io.LimitedReader{R: r, N: math.MaxInt64}
d := nbt.NewDecoder(lr)
for i := 0; i < int(sz); i++ { for i := 0; i < int(sz); i++ {
if err := decoder.Decode(&(*b)[i]); err != nil { if err := d.Decode(&(*b)[i]); err != nil {
return err return math.MaxInt64 - lr.N, err
} }
} }
return nil return math.MaxInt64 - lr.N, nil
} }
// TileEntityData describes a change to a tile entity. // TileEntityData describes a change to a tile entity.
@ -116,13 +73,10 @@ type TileEntityData struct {
Data entity.BlockEntity Data entity.BlockEntity
} }
func (p *TileEntityData) Decode(pkt pk.Packet) error { func (p *TileEntityData) ReadFrom(r io.Reader) (int64, error) {
r := bytes.NewReader(pkt.Data) return pk.Tuple{
if err := p.Pos.Decode(r); err != nil { &p.Pos,
return fmt.Errorf("position: %v", err) &p.Action,
} &pk.NBT{V: &p.Data},
if err := p.Action.Decode(r); err != nil { }.ReadFrom(r)
return fmt.Errorf("action: %v", err)
}
return nbt.NewDecoder(r).Decode(&p.Data)
} }

View File

@ -2,8 +2,8 @@
package ptypes package ptypes
import ( import (
"bytes"
"errors" "errors"
"io"
"github.com/Tnze/go-mc/bot/world/entity" "github.com/Tnze/go-mc/bot/world/entity"
"github.com/Tnze/go-mc/chat" "github.com/Tnze/go-mc/chat"
@ -35,24 +35,16 @@ type WindowItems struct {
Slots []entity.Slot Slots []entity.Slot
} }
func (p *WindowItems) Decode(pkt pk.Packet) error { func (p *WindowItems) ReadFrom(r io.Reader) (int64, error) {
r := bytes.NewReader(pkt.Data)
if err := p.WindowID.Decode(r); err != nil {
return err
}
var count pk.Short var count pk.Short
if err := count.Decode(r); err != nil { return pk.Tuple{
return err &p.WindowID,
} &count,
&pk.Ary{
p.Slots = make([]entity.Slot, int(count)) Len: &count,
for i := 0; i < int(count); i++ { Ary: []entity.Slot{},
if err := p.Slots[i].Decode(r); err != nil && !errors.Is(err, nbt.ErrEND) { },
return err }.ReadFrom(r)
}
}
return nil
} }
// OpenWindow is a clientbound packet which opens an inventory. // OpenWindow is a clientbound packet which opens an inventory.

View File

@ -59,17 +59,18 @@ func (p *UpdateHealth) Decode(pkt pk.Packet) error {
// PluginData encodes the custom data encoded in a plugin message. // PluginData encodes the custom data encoded in a plugin message.
type PluginData []byte type PluginData []byte
func (p PluginData) Encode() []byte { func (p PluginData) WriteTo(w io.Writer) (int64, error) {
return []byte(p) n, err := w.Write(p)
return int64(n), err
} }
func (p *PluginData) Decode(r pk.DecodeReader) error { func (p *PluginData) ReadFrom(r io.Reader) (int64, error) {
d, err := io.ReadAll(r) d, err := io.ReadAll(r)
if err != nil { if err != nil {
return err return int64(len(d)), err
} }
*p = d *p = d
return nil return int64(len(d)), nil
} }
// PluginMessage represents a packet with a customized payload. // PluginMessage represents a packet with a customized payload.