Refactoring package go-mc/bot
This commit is contained in:
15
net/conn.go
15
net/conn.go
@ -36,10 +36,7 @@ func (l Listener) Accept() (Conn, error) {
|
||||
//Conn is a minecraft Connection
|
||||
type Conn struct {
|
||||
Socket net.Conn
|
||||
Reader interface {
|
||||
io.ByteReader
|
||||
io.Reader
|
||||
}
|
||||
io.Reader
|
||||
io.Writer
|
||||
|
||||
threshold int
|
||||
@ -50,7 +47,7 @@ func DialMC(addr string) (*Conn, error) {
|
||||
conn, err := net.Dial("tcp", addr)
|
||||
return &Conn{
|
||||
Socket: conn,
|
||||
Reader: bufio.NewReader(conn),
|
||||
Reader: conn,
|
||||
Writer: conn,
|
||||
}, err
|
||||
}
|
||||
@ -60,7 +57,7 @@ func DialMCTimeout(addr string, timeout time.Duration) (*Conn, error) {
|
||||
conn, err := net.DialTimeout("tcp", addr, timeout)
|
||||
return &Conn{
|
||||
Socket: conn,
|
||||
Reader: bufio.NewReader(conn),
|
||||
Reader: conn,
|
||||
Writer: conn,
|
||||
}, err
|
||||
}
|
||||
@ -70,7 +67,7 @@ func DialMCTimeout(addr string, timeout time.Duration) (*Conn, error) {
|
||||
func WrapConn(conn net.Conn) *Conn {
|
||||
return &Conn{
|
||||
Socket: conn,
|
||||
Reader: bufio.NewReader(conn),
|
||||
Reader: conn,
|
||||
Writer: conn,
|
||||
}
|
||||
}
|
||||
@ -91,10 +88,10 @@ func (c *Conn) WritePacket(p pk.Packet) error {
|
||||
// SetCipher load the decode/encode stream to this Conn
|
||||
func (c *Conn) SetCipher(ecoStream, decoStream cipher.Stream) {
|
||||
//加密连接
|
||||
c.Reader = bufio.NewReader(cipher.StreamReader{ //Set receiver for AES
|
||||
c.Reader = cipher.StreamReader{ //Set receiver for AES
|
||||
S: decoStream,
|
||||
R: c.Socket,
|
||||
})
|
||||
}
|
||||
c.Writer = cipher.StreamWriter{
|
||||
S: ecoStream,
|
||||
W: c.Socket,
|
||||
|
BIN
net/packet/joingame_test.bin
Normal file
BIN
net/packet/joingame_test.bin
Normal file
Binary file not shown.
@ -3,8 +3,10 @@ package packet
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Packet define a net data package
|
||||
@ -25,8 +27,9 @@ func Marshal(id int32, fields ...FieldEncoder) (pk Packet) {
|
||||
//Scan decode the packet and fill data into fields
|
||||
func (p Packet) Scan(fields ...FieldDecoder) error {
|
||||
r := bytes.NewReader(p.Data)
|
||||
rr := io.TeeReader(r, hex.Dumper(os.Stdout))
|
||||
for _, v := range fields {
|
||||
_, err := v.ReadFrom(r)
|
||||
_, err := v.ReadFrom(rr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -82,25 +85,25 @@ func (p *Packet) UnPack(r io.Reader, threshold int) error {
|
||||
if length < 1 {
|
||||
return fmt.Errorf("packet length too short")
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(p.Data[:0])
|
||||
if _, err := io.CopyN(buf, r, int64(length)); err != nil {
|
||||
buf := make([]byte, length)
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return fmt.Errorf("read content of packet fail: %w", err)
|
||||
}
|
||||
buffer := bytes.NewBuffer(buf)
|
||||
|
||||
//解压数据
|
||||
if threshold > 0 {
|
||||
if err := unCompress(buf); err != nil {
|
||||
if err := unCompress(buffer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var packetID VarInt
|
||||
if _, err := packetID.ReadFrom(buf); err != nil {
|
||||
if _, err := packetID.ReadFrom(buffer); err != nil {
|
||||
return fmt.Errorf("read packet id fail: %v", err)
|
||||
}
|
||||
p.ID = int32(packetID)
|
||||
p.Data = buf.Bytes()
|
||||
p.Data = buffer.Bytes()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
package packet
|
||||
package packet_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"testing"
|
||||
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
var VarInts = []VarInt{0, 1, 2, 127, 128, 255, 2147483647, -1, -2147483648}
|
||||
var VarInts = []pk.VarInt{0, 1, 2, 127, 128, 255, 2147483647, -1, -2147483648}
|
||||
|
||||
var PackedVarInts = [][]byte{
|
||||
{0x00},
|
||||
@ -35,7 +38,7 @@ func TestPackVarInt(t *testing.T) {
|
||||
}
|
||||
func TestUnpackVarInt(t *testing.T) {
|
||||
for i, v := range PackedVarInts {
|
||||
var vi VarInt
|
||||
var vi pk.VarInt
|
||||
if _, err := vi.ReadFrom(bytes.NewReader(v)); err != nil {
|
||||
t.Errorf("unpack \"% x\" error: %v", v, err)
|
||||
}
|
||||
@ -46,7 +49,7 @@ func TestUnpackVarInt(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnpackVarInt_TooLongData(t *testing.T) {
|
||||
var vi VarInt
|
||||
var vi pk.VarInt
|
||||
var data = []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01}
|
||||
if _, err := vi.ReadFrom(bytes.NewReader(data)); err != nil {
|
||||
t.Logf("unpack \"% x\" error: %v", data, err)
|
||||
@ -55,7 +58,7 @@ func TestUnpackVarInt_TooLongData(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var VarLongs = []VarLong{0, 1, 2, 127, 128, 255, 2147483647, 9223372036854775807, -1, -2147483648, -9223372036854775808}
|
||||
var VarLongs = []pk.VarLong{0, 1, 2, 127, 128, 255, 2147483647, 9223372036854775807, -1, -2147483648, -9223372036854775808}
|
||||
|
||||
var PackedVarLongs = [][]byte{
|
||||
{0x00},
|
||||
@ -81,7 +84,7 @@ func TestPackVarLong(t *testing.T) {
|
||||
}
|
||||
func TestUnpackVarLong(t *testing.T) {
|
||||
for i, v := range PackedVarLongs {
|
||||
var vi VarLong
|
||||
var vi pk.VarLong
|
||||
if _, err := vi.ReadFrom(bytes.NewReader(v)); err != nil {
|
||||
t.Errorf("unpack \"% x\" error: %v", v, err)
|
||||
}
|
||||
@ -90,3 +93,46 @@ func TestUnpackVarLong(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed joingame_test.bin
|
||||
var joingame []byte
|
||||
|
||||
func TestJoinGamePacket(t *testing.T) {
|
||||
p := pk.Packet{ID: 0x24, Data: joingame}
|
||||
var (
|
||||
EID pk.Int
|
||||
Hardcore pk.Boolean
|
||||
Gamemode pk.UnsignedByte
|
||||
PreGamemode pk.Byte
|
||||
WorldCount pk.VarInt
|
||||
WorldNames = pk.Ary{Len: &WorldCount, Ary: &[]pk.String{}}
|
||||
DimensionCodec struct {
|
||||
DimensionType interface{} `nbt:"minecraft:dimension_type"`
|
||||
WorldgenBiome interface{} `nbt:"minecraft:worldgen/biome"`
|
||||
}
|
||||
Dimension interface{}
|
||||
WorldName pk.Identifier
|
||||
HashedSeed pk.Long
|
||||
MaxPlayers pk.VarInt
|
||||
ViewDistance pk.VarInt
|
||||
RDI, ERS, IsDebug, IsFlat pk.Boolean
|
||||
)
|
||||
err := p.Scan(
|
||||
&EID,
|
||||
&Hardcore,
|
||||
&Gamemode,
|
||||
&PreGamemode,
|
||||
&WorldCount,
|
||||
WorldNames,
|
||||
&pk.NBT{V: &DimensionCodec},
|
||||
&pk.NBT{V: &Dimension},
|
||||
&WorldName,
|
||||
&HashedSeed,
|
||||
&MaxPlayers,
|
||||
&ViewDistance,
|
||||
&RDI, &ERS, &IsDebug, &IsFlat,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type Ary struct {
|
||||
Len Field // One of VarInt, VarLong, Int or Long
|
||||
Ary interface{} // FieldEncoder, FieldDecoder or both (Field)
|
||||
Len Field // Pointer of VarInt, VarLong, Int or Long
|
||||
Ary interface{} // Slice of FieldEncoder, FieldDecoder or both (Field)
|
||||
}
|
||||
|
||||
func (a Ary) WriteTo(r io.Writer) (n int64, err error) {
|
||||
length := int(reflect.ValueOf(a.Len).Int())
|
||||
array := reflect.ValueOf(a.Ary).Elem()
|
||||
array := reflect.ValueOf(a.Ary)
|
||||
for i := 0; i < length; i++ {
|
||||
elem := array.Index(i)
|
||||
nn, err := elem.Interface().(FieldEncoder).WriteTo(r)
|
||||
@ -25,11 +25,15 @@ func (a Ary) WriteTo(r io.Writer) (n int64, err error) {
|
||||
}
|
||||
|
||||
func (a Ary) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
length := int(reflect.ValueOf(a.Len).Int())
|
||||
length := int(reflect.ValueOf(a.Len).Elem().Int())
|
||||
array := reflect.ValueOf(a.Ary).Elem()
|
||||
if array.Cap() < length {
|
||||
array = reflect.MakeSlice(array.Type(), length, length)
|
||||
a.Ary = array.Interface()
|
||||
}
|
||||
for i := 0; i < length; i++ {
|
||||
elem := array.Index(i)
|
||||
nn, err := elem.Interface().(FieldDecoder).ReadFrom(r)
|
||||
nn, err := elem.Addr().Interface().(FieldDecoder).ReadFrom(r)
|
||||
n += nn
|
||||
if err != nil {
|
||||
return n, err
|
||||
|
@ -1,82 +0,0 @@
|
||||
// Package ptypes implements encoding and decoding for high-level packets.
|
||||
package ptypes
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"github.com/Tnze/go-mc/bot/world/entity"
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// ChunkData is a client-bound packet which describes a chunk.
|
||||
type ChunkData struct {
|
||||
X, Z pk.Int
|
||||
FullChunk pk.Boolean
|
||||
PrimaryBitMask pk.VarInt
|
||||
Heightmaps struct{}
|
||||
Biomes biomesData
|
||||
Data pk.ByteArray
|
||||
BlockEntities blockEntities
|
||||
}
|
||||
|
||||
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) 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 blockEntities []entity.BlockEntity
|
||||
|
||||
// Decode implement net.packet.FieldDecoder
|
||||
func (b *blockEntities) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var sz pk.VarInt // Number of BlockEntities
|
||||
if nn, err := sz.ReadFrom(r); err != nil {
|
||||
return nn, err
|
||||
} else {
|
||||
n += nn
|
||||
}
|
||||
*b = make(blockEntities, sz)
|
||||
lr := &io.LimitedReader{R: r, N: math.MaxInt64}
|
||||
d := nbt.NewDecoder(lr)
|
||||
for i := 0; i < int(sz); i++ {
|
||||
if err := d.Decode(&(*b)[i]); err != nil {
|
||||
return math.MaxInt64 - lr.N, err
|
||||
}
|
||||
}
|
||||
return math.MaxInt64 - lr.N, nil
|
||||
}
|
||||
|
||||
// TileEntityData describes a change to a tile entity.
|
||||
type TileEntityData struct {
|
||||
Pos pk.Position
|
||||
Action pk.UnsignedByte
|
||||
Data entity.BlockEntity
|
||||
}
|
||||
|
||||
func (p *TileEntityData) ReadFrom(r io.Reader) (int64, error) {
|
||||
return pk.Tuple{
|
||||
&p.Pos,
|
||||
&p.Action,
|
||||
&pk.NBT{V: &p.Data},
|
||||
}.ReadFrom(r)
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package ptypes
|
||||
|
||||
import pk "github.com/Tnze/go-mc/net/packet"
|
||||
|
||||
// SpawnEntity is a client-bound packet used to spawn a non-mob entity.
|
||||
type SpawnEntity struct {
|
||||
ID pk.VarInt
|
||||
UUID pk.UUID
|
||||
Type pk.VarInt
|
||||
X, Y, Z pk.Double
|
||||
Pitch, Yaw pk.Angle
|
||||
Data pk.Int
|
||||
VelX, VelY, VelZ pk.Short
|
||||
}
|
||||
|
||||
func (p *SpawnEntity) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.UUID, &p.Type,
|
||||
&p.X, &p.Y, &p.Z, &p.Pitch, &p.Yaw,
|
||||
&p.Data, &p.VelX, &p.VelY, &p.VelZ)
|
||||
}
|
||||
|
||||
// SpawnPlayer is a client-bound packet used to describe a player entering
|
||||
// visible range.
|
||||
type SpawnPlayer struct {
|
||||
ID pk.VarInt
|
||||
UUID pk.UUID
|
||||
X, Y, Z pk.Double
|
||||
Yaw, Pitch pk.Angle
|
||||
}
|
||||
|
||||
func (p *SpawnPlayer) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.UUID, &p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch)
|
||||
}
|
||||
|
||||
// SpawnLivingEntity is a client-bound packet used to spawn a mob.
|
||||
type SpawnLivingEntity struct {
|
||||
ID pk.VarInt
|
||||
UUID pk.UUID
|
||||
Type pk.VarInt
|
||||
X, Y, Z pk.Double
|
||||
Yaw, Pitch pk.Angle
|
||||
HeadPitch pk.Angle
|
||||
VelX, VelY, VelZ pk.Short
|
||||
}
|
||||
|
||||
func (p *SpawnLivingEntity) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.UUID, &p.Type,
|
||||
&p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch,
|
||||
&p.HeadPitch, &p.VelX, &p.VelY, &p.VelZ)
|
||||
}
|
||||
|
||||
// EntityAnimationClientbound updates the animation state of an entity.
|
||||
type EntityAnimationClientbound struct {
|
||||
ID pk.VarInt
|
||||
Animation pk.UnsignedByte
|
||||
}
|
||||
|
||||
func (p *EntityAnimationClientbound) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.Animation)
|
||||
}
|
||||
|
||||
// EntityPosition is a clientbound packet used to update an entities position.
|
||||
type EntityPosition struct {
|
||||
ID pk.VarInt
|
||||
X, Y, Z pk.Short // Deltas
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p *EntityPosition) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.X, &p.Y, &p.Z, &p.OnGround)
|
||||
}
|
||||
|
||||
// EntityPosition is a clientbound packet used to update an entities position
|
||||
// and its rotation.
|
||||
type EntityPositionLook struct {
|
||||
ID pk.VarInt
|
||||
X, Y, Z pk.Short // Deltas
|
||||
Yaw, Pitch pk.Angle
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p *EntityPositionLook) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch, &p.OnGround)
|
||||
}
|
||||
|
||||
// EntityRotation is a clientbound packet used to update an entities rotation.
|
||||
type EntityRotation struct {
|
||||
ID pk.VarInt
|
||||
Yaw, Pitch pk.Angle
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p *EntityRotation) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.ID, &p.Yaw, &p.Pitch, &p.OnGround)
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
// Package ptypes implements encoding and decoding for high-level packets.
|
||||
package ptypes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/Tnze/go-mc/bot/world/entity"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// SetSlot is a clientbound packet which configures an inventory slot.
|
||||
// A window ID of -1 represents the cursor, and a window ID of 0 represents
|
||||
// the players inventory.
|
||||
type SetSlot struct {
|
||||
WindowID pk.Byte
|
||||
Slot pk.Short
|
||||
SlotData entity.Slot
|
||||
}
|
||||
|
||||
func (p *SetSlot) Decode(pkt pk.Packet) error {
|
||||
if err := pkt.Scan(&p.WindowID, &p.Slot, &p.SlotData); err != nil && !errors.Is(err, nbt.ErrEND) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WindowItems is a clientbound packet describing the contents of multiple
|
||||
// inventory slots in a window/inventory.
|
||||
type WindowItems struct {
|
||||
WindowID pk.Byte
|
||||
Slots []entity.Slot
|
||||
}
|
||||
|
||||
func (p *WindowItems) ReadFrom(r io.Reader) (int64, error) {
|
||||
var count pk.Short
|
||||
return pk.Tuple{
|
||||
&p.WindowID,
|
||||
&count,
|
||||
&pk.Ary{
|
||||
Len: &count,
|
||||
Ary: []entity.Slot{},
|
||||
},
|
||||
}.ReadFrom(r)
|
||||
}
|
||||
|
||||
// OpenWindow is a clientbound packet which opens an inventory.
|
||||
type OpenWindow struct {
|
||||
WindowID pk.VarInt
|
||||
WindowType pk.VarInt
|
||||
Title chat.Message
|
||||
}
|
||||
|
||||
func (p *OpenWindow) Decode(pkt pk.Packet) error {
|
||||
if err := pkt.Scan(&p.WindowID, &p.WindowType, &p.Title); err != nil && !errors.Is(err, nbt.ErrEND) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ConfirmTransaction struct {
|
||||
WindowID pk.Byte
|
||||
ActionID pk.Short
|
||||
Accepted pk.Boolean
|
||||
}
|
||||
|
||||
func (p *ConfirmTransaction) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.WindowID, &p.ActionID, &p.Accepted)
|
||||
}
|
||||
|
||||
func (p ConfirmTransaction) Encode() pk.Packet {
|
||||
return pk.Marshal(
|
||||
packetid.TransactionServerbound,
|
||||
p.WindowID,
|
||||
p.ActionID,
|
||||
p.Accepted,
|
||||
)
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
package ptypes
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// SoundEffect is a client-bound packet used to play a specific sound ID
|
||||
// on the client.
|
||||
type SoundEffect struct {
|
||||
Sound pk.VarInt
|
||||
Category pk.VarInt
|
||||
X, Y, Z pk.Int
|
||||
Volume, Pitch pk.Float
|
||||
}
|
||||
|
||||
func (p *SoundEffect) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.Sound, &p.Category, &p.X, &p.Y, &p.Z, &p.Volume, &p.Pitch)
|
||||
}
|
||||
|
||||
// NamedSoundEffect is a client-bound packet used to play a sound with the
|
||||
// specified name on the client.
|
||||
type NamedSoundEffect struct {
|
||||
Sound pk.String
|
||||
Category pk.VarInt
|
||||
X, Y, Z pk.Int
|
||||
Volume, Pitch pk.Float
|
||||
}
|
||||
|
||||
func (p *NamedSoundEffect) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.Sound, &p.Category, &p.X, &p.Y, &p.Z, &p.Volume, &p.Pitch)
|
||||
}
|
||||
|
||||
// ChatMessageClientbound represents a chat message forwarded by the server.
|
||||
type ChatMessageClientbound struct {
|
||||
S chat.Message
|
||||
Pos pk.Byte
|
||||
Sender pk.UUID
|
||||
}
|
||||
|
||||
func (p *ChatMessageClientbound) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.S, &p.Pos, &p.Sender)
|
||||
}
|
||||
|
||||
// UpdateHealth encodes player health/food information from the server.
|
||||
type UpdateHealth struct {
|
||||
Health pk.Float
|
||||
Food pk.VarInt
|
||||
FoodSaturation pk.Float
|
||||
}
|
||||
|
||||
func (p *UpdateHealth) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.Health, &p.Food, &p.FoodSaturation)
|
||||
}
|
||||
|
||||
// PluginData encodes the custom data encoded in a plugin message.
|
||||
type PluginData []byte
|
||||
|
||||
func (p PluginData) WriteTo(w io.Writer) (int64, error) {
|
||||
n, err := w.Write(p)
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
func (p *PluginData) ReadFrom(r io.Reader) (int64, error) {
|
||||
d, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return int64(len(d)), err
|
||||
}
|
||||
*p = d
|
||||
return int64(len(d)), nil
|
||||
}
|
||||
|
||||
// PluginMessage represents a packet with a customized payload.
|
||||
type PluginMessage struct {
|
||||
Channel pk.Identifier
|
||||
Data PluginData
|
||||
}
|
||||
|
||||
func (p *PluginMessage) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.Channel, &p.Data)
|
||||
}
|
||||
|
||||
func (p *PluginMessage) Encode() pk.Packet {
|
||||
return pk.Marshal(
|
||||
packetid.CustomPayloadServerbound,
|
||||
p.Channel,
|
||||
p.Data,
|
||||
)
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
// Package ptypes implements encoding and decoding for high-level packets.
|
||||
package ptypes
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// PositionAndLookClientbound describes the location and orientation of
|
||||
// the player.
|
||||
type PositionAndLookClientbound struct {
|
||||
X, Y, Z pk.Double
|
||||
Yaw, Pitch pk.Float
|
||||
Flags pk.Byte
|
||||
TeleportID pk.VarInt
|
||||
}
|
||||
|
||||
func (p *PositionAndLookClientbound) RelativeX() bool {
|
||||
return p.Flags&0x01 != 0
|
||||
}
|
||||
func (p *PositionAndLookClientbound) RelativeY() bool {
|
||||
return p.Flags&0x02 != 0
|
||||
}
|
||||
func (p *PositionAndLookClientbound) RelativeZ() bool {
|
||||
return p.Flags&0x04 != 0
|
||||
}
|
||||
func (p *PositionAndLookClientbound) RelativeYaw() bool {
|
||||
return p.Flags&0x08 != 0
|
||||
}
|
||||
func (p *PositionAndLookClientbound) RelativePitch() bool {
|
||||
return p.Flags&0x10 != 0
|
||||
}
|
||||
|
||||
func (p *PositionAndLookClientbound) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.X, &p.Y, &p.Z, &p.Yaw, &p.Pitch, &p.Flags, &p.TeleportID)
|
||||
}
|
||||
|
||||
// PositionAndLookServerbound describes the location and orientation of
|
||||
// the player.
|
||||
type PositionAndLookServerbound struct {
|
||||
X, Y, Z pk.Double
|
||||
Yaw, Pitch pk.Float
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p PositionAndLookServerbound) Encode() pk.Packet {
|
||||
return pk.Marshal(
|
||||
packetid.PositionLook,
|
||||
p.X, p.Y, p.Z,
|
||||
p.Yaw, p.Pitch,
|
||||
p.OnGround,
|
||||
)
|
||||
}
|
||||
|
||||
// Position describes the position of the player.
|
||||
type Position struct {
|
||||
X, Y, Z pk.Double
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p Position) Encode() pk.Packet {
|
||||
return pk.Marshal(
|
||||
packetid.PositionServerbound,
|
||||
p.X, p.Y, p.Z,
|
||||
p.OnGround,
|
||||
)
|
||||
}
|
||||
|
||||
// Look describes the rotation of the player.
|
||||
type Look struct {
|
||||
Yaw, Pitch pk.Float
|
||||
OnGround pk.Boolean
|
||||
}
|
||||
|
||||
func (p Look) Encode() pk.Packet {
|
||||
return pk.Marshal(
|
||||
packetid.Look,
|
||||
p.Yaw, p.Pitch,
|
||||
p.OnGround,
|
||||
)
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package ptypes
|
||||
|
||||
import (
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
// JoinGame encodes global/world information from the server.
|
||||
type JoinGame struct {
|
||||
PlayerEntity pk.Int
|
||||
Hardcore pk.Boolean
|
||||
Gamemode pk.UnsignedByte
|
||||
PrevGamemode pk.UnsignedByte
|
||||
WorldCount pk.VarInt
|
||||
WorldNames pk.Identifier
|
||||
//DimensionCodec pk.NBT
|
||||
Dimension pk.Int
|
||||
WorldName pk.Identifier
|
||||
HashedSeed pk.Long
|
||||
maxPlayers pk.VarInt // Now ignored
|
||||
ViewDistance pk.VarInt
|
||||
RDI pk.Boolean // Reduced Debug Info
|
||||
ERS pk.Boolean // Enable respawn screen
|
||||
IsDebug pk.Boolean
|
||||
IsFlat pk.Boolean
|
||||
}
|
||||
|
||||
func (p *JoinGame) Decode(pkt pk.Packet) error {
|
||||
return pkt.Scan(&p.PlayerEntity, &p.Hardcore, &p.Gamemode, &p.PrevGamemode,
|
||||
&p.WorldCount, &p.WorldNames, &p.Dimension,
|
||||
&p.WorldName, &p.HashedSeed, &p.maxPlayers, &p.ViewDistance,
|
||||
&p.RDI, &p.ERS, &p.IsDebug, &p.IsFlat)
|
||||
}
|
Reference in New Issue
Block a user