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

View File

@ -62,34 +62,12 @@ type encryptionRequest struct {
VerifyToken []byte
}
func (e *encryptionRequest) Decode(r pk.DecodeReader) error {
var serverID pk.String
if err := serverID.Decode(r); err != nil {
return err
}
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
func (e *encryptionRequest) ReadFrom(r io.Reader) (int64, error) {
return pk.Tuple{
(*pk.String)(&e.ServerID),
(*pk.ByteArray)(&e.PublicKey),
(*pk.ByteArray)(&e.VerifyToken),
}.ReadFrom(r)
}
// 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)
return
}
var data []byte
data = append(data, pk.VarInt(int32(len(cryptPK))).Encode()...)
data = append(data, cryptPK...)
data = append(data, pk.VarInt(int32(len(verifyT))).Encode()...)
data = append(data, verifyT...)
erp = pk.Packet{
ID: 0x01,
Data: data,
}
return
return pk.Marshal(
0x01,
pk.ByteArray(cryptPK),
pk.ByteArray(verifyT),
), nil
}

View File

@ -3,6 +3,7 @@ package world
import (
"bytes"
"fmt"
"io"
"math"
"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
if err := nonAirBlockCount.Decode(data); err != nil {
if _, err := nonAirBlockCount.ReadFrom(data); err != nil {
return nil, fmt.Errorf("block count: %w", err)
}
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)
}
// 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 {
// read palettes
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)
}
palettes = make([]BlockStatus, length)
palettesIndex = make(map[BlockStatus]int, length)
for i := 0; i < int(length); i++ {
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)
}
palettes[i] = BlockStatus(v)
@ -74,7 +75,7 @@ func readSection(data pk.DecodeReader) (s Section, err error) {
// read data array
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)
}
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)
for i := 0; i < int(dataLen); i++ {
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)
}
dataArray[i] = uint64(v)

View File

@ -1,11 +1,10 @@
package entity
import (
"bytes"
"io"
"github.com/Tnze/go-mc/data/entity"
item "github.com/Tnze/go-mc/data/item"
"github.com/Tnze/go-mc/nbt"
pk "github.com/Tnze/go-mc/net/packet"
"github.com/google/uuid"
)
@ -49,53 +48,48 @@ type Slot struct {
Present bool
ItemID item.ID
Count int8
NBT interface{}
NBT pk.NBT
}
type SlotNBT struct {
data interface{}
}
//Decode implement packet.FieldDecoder interface
func (s *Slot) Decode(r pk.DecodeReader) error {
if err := (*pk.Boolean)(&s.Present).Decode(r); err != nil {
return err
func (s *Slot) ReadFrom(r io.Reader) (int64, error) {
var itemID pk.VarInt
n, err := pk.Tuple{
(*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
}
if s.Present {
var itemID pk.VarInt
if err := itemID.Decode(r); err != nil {
return err
}
s.ItemID = item.ID(itemID)
if err := (*pk.Byte)(&s.Count).Decode(r); err != nil {
return err
}
if err := nbt.NewDecoder(r).Decode(&s.NBT); err != nil {
return err
}
}
return nil
s.ItemID = item.ID(itemID)
return n, nil
}
func (s Slot) Encode() []byte {
if !s.Present {
return pk.Boolean(false).Encode()
}
var b bytes.Buffer
b.Write(pk.Boolean(true).Encode())
b.Write(pk.VarInt(s.ItemID).Encode())
b.Write(pk.Byte(s.Count).Encode())
if s.NBT != nil {
if err := nbt.NewEncoder(&b).Encode(s.NBT); err != nil {
panic(err)
}
} else {
if _, err := b.Write([]byte{nbt.TagEnd}); err != nil {
panic(err)
}
}
return b.Bytes()
func (s Slot) WriteTo(w io.Writer) (int64, error) {
return pk.Tuple{
pk.Boolean(s.Present),
pk.Opt{
Has: (*pk.Boolean)(&s.Present),
Field: pk.Tuple{
pk.VarInt(s.ItemID),
pk.Byte(s.Count),
s.NBT,
},
},
}.WriteTo(w)
}
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
func (m *Message) Decode(r pk.DecodeReader) error {
func (m *Message) ReadFrom(r io.Reader) (int64, error) {
var Len pk.VarInt
if err := Len.Decode(r); err != nil {
return err
if n, err := Len.ReadFrom(r); err != nil {
return n, err
}
return json.NewDecoder(io.LimitReader(r, int64(Len))).Decode(m)
lr := &io.LimitedReader{R: r, N: int64(Len)}
err := json.NewDecoder(lr).Decode(m)
return int64(Len) - lr.N, err
}
//Encode for a ChatMsg packet
func (m Message) Encode() []byte {
func (m Message) WriteTo(w io.Writer) (int64, error) {
code, err := json.Marshal(m)
if err != nil {
panic(err)
}
return pk.String(code).Encode()
return pk.String(code).WriteTo(w)
}
func (m *Message) Append(extraMsg ...Message) {

View File

@ -101,10 +101,11 @@ func TestChatMsgClearString(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
if err := msg.Decode(bytes.NewReader(codeMsg)); err != nil {
if _, err := msg.ReadFrom(&codeMsg); err != nil {
t.Errorf("decode message fail: %v", err)
}

View File

@ -65,7 +65,7 @@ func onPluginMessage(channel string, data []byte) error {
switch channel {
case "minecraft:brand":
var brand pk.String
if err := brand.Decode(bytes.NewReader(data)); err != nil {
if _, err := brand.ReadFrom(bytes.NewReader(data)); err != nil {
return err
}
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.
func (c *Conn) WritePacket(p pk.Packet) error {
_, err := c.Write(p.Pack(c.threshold))
return err
return p.Pack(c, c.threshold)
}
// SetCipher load the decode/encode stream to this Conn

View File

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

View File

@ -20,9 +20,15 @@ var PackedVarInts = [][]byte{
}
func TestPackVarInt(t *testing.T) {
var buf bytes.Buffer
for i, v := range VarInts {
p := v.Encode()
if !bytes.Equal(p, PackedVarInts[i]) {
buf.Reset()
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)
}
}
@ -30,7 +36,7 @@ func TestPackVarInt(t *testing.T) {
func TestUnpackVarInt(t *testing.T) {
for i, v := range PackedVarInts {
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)
}
if vi != VarInts[i] {
@ -42,7 +48,7 @@ func TestUnpackVarInt(t *testing.T) {
func TestUnpackVarInt_TooLongData(t *testing.T) {
var vi VarInt
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)
} else {
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) {
for i, v := range PackedVarLongs {
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)
}
if vi != VarLongs[i] {

View File

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

View File

@ -1,51 +1,84 @@
package packet
import (
"io"
"reflect"
)
type Ary struct {
Len Field
Ary interface{}
Len Field // One of VarInt, VarLong, Int or Long
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())
array := reflect.ValueOf(a.Ary).Elem()
for i := 0; i < length; 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
}
func (a Ary) Decode(r DecodeReader) error {
length := int(reflect.ValueOf(a.Len).Int())
array := reflect.ValueOf(a.Ary).Elem()
for i := 0; i < length; i++ {
elem := array.Index(i)
if err := elem.Interface().(FieldDecoder).Decode(r); err != nil {
return err
// ReadFrom read Tuple from io.Reader, panic when any of field don't implement FieldDecoder
func (t Tuple) ReadFrom(r io.Reader) (n int64, err error) {
for _, v := range t {
nn, err := v.(FieldDecoder).ReadFrom(r)
if err != nil {
return n, err
}
n += nn
}
return nil
}
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)
return
}

View File

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

View File

@ -2,8 +2,8 @@
package ptypes
import (
"bytes"
"errors"
"io"
"github.com/Tnze/go-mc/bot/world/entity"
"github.com/Tnze/go-mc/chat"
@ -35,24 +35,16 @@ type WindowItems struct {
Slots []entity.Slot
}
func (p *WindowItems) Decode(pkt pk.Packet) error {
r := bytes.NewReader(pkt.Data)
if err := p.WindowID.Decode(r); err != nil {
return err
}
func (p *WindowItems) ReadFrom(r io.Reader) (int64, error) {
var count pk.Short
if err := count.Decode(r); err != nil {
return err
}
p.Slots = make([]entity.Slot, int(count))
for i := 0; i < int(count); i++ {
if err := p.Slots[i].Decode(r); err != nil && !errors.Is(err, nbt.ErrEND) {
return err
}
}
return nil
return pk.Tuple{
&p.WindowID,
&count,
&pk.Ary{
Len: &count,
Ary: []entity.Slot{},
},
}.ReadFrom(r)
}
// 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.
type PluginData []byte
func (p PluginData) Encode() []byte {
return []byte(p)
func (p PluginData) WriteTo(w io.Writer) (int64, error) {
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)
if err != nil {
return err
return int64(len(d)), err
}
*p = d
return nil
return int64(len(d)), nil
}
// PluginMessage represents a packet with a customized payload.