Documentation
¶
Index ¶
- Constants
- type Angle
- type Ary
- type Boolean
- type Builder
- type Byte
- type ByteArray
- type Chat
- type Double
- type Field
- type FieldDecoder
- type FieldEncoder
- type Float
- type Identifier
- type Int
- type Long
- type Opt
- type Packet
- type PluginMessageData
- type Position
- type Short
- type String
- type Tuple
- type UUID
- type UnsignedByte
- type UnsignedShort
- type VarInt
- type VarLong
Examples ¶
Constants ¶
const MaxVarIntLen = 5
const MaxVarLongLen = 10
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Ary ¶
type Ary struct {
Len interface{} // Value or Pointer of any integer type, only needed in ReadFrom
Ary interface{} // Slice or Pointer of Slice of FieldEncoder, FieldDecoder or both (Field)
}
Ary is used to send or receive the packet field like "Array of X" which has a count must be known from the context.
Typically, you must decode an integer representing the length. Then receive the corresponding amount of data according to the length. In this case, the field Len should be a pointer of integer type so the value can be updating when Packet.Scan() method is decoding the previous field. In some special cases, you might want to read an "Array of X" with a fix length. So it's allowed to directly set an integer type Len, but not a pointer.
Note that Ary DO NOT read or write the Len. You are controlling it manually.
func (Ary) ReadFrom ¶
Example ¶
package main
import (
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
var length pk.VarInt
var data []pk.String
var p pk.Packet // = conn.ReadPacket()
if err := p.Scan(
&length, // decode length first
pk.Ary{ // then decode Ary according to length
Len: &length,
Ary: &data,
},
); err != nil {
panic(err)
}
}
Output:
func (Ary) WriteTo ¶
Example ¶
package main
import (
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
data := []pk.Int{0, 1, 2, 3, 4, 5, 6}
// Len is completely ignored by WriteTo method.
// The length is inferred from the length of Ary.
pk.Marshal(
0x00,
// It's important to remember that
// typically the responsibility of
// sending the length field
// is on you.
pk.VarInt(len(data)),
pk.Ary{
Len: len(data), // this line can be removed
Ary: data,
},
)
}
Output:
type Boolean ¶
type Boolean bool
Boolean of True is encoded as 0x01, false as 0x00.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
func (*Builder) WriteField ¶
func (p *Builder) WriteField(fields ...FieldEncoder)
type ByteArray ¶
type ByteArray []byte
ByteArray is []byte with prefix VarInt as length
type Chat ¶
type Chat = String
Chat is encoded as a String with max length of 32767. Deprecated: Use chat.Message
type Double ¶
type Double float64
A Double is a double-precision 64-bit IEEE 754 floating point number
type Field ¶
type Field interface {
FieldEncoder
FieldDecoder
}
A Field is both FieldEncoder and FieldDecoder
type FieldDecoder ¶
type FieldDecoder io.ReaderFrom
A FieldDecoder can Decode from minecraft protocol
type FieldEncoder ¶
A FieldEncoder can be encode as minecraft protocol used.
type Identifier ¶
type Identifier = String
Identifier is encoded as a String with max length of 32767.
type Opt ¶
type Opt struct {
Has interface{} // Pointer of bool, or `func() bool`
Field interface{} // FieldEncoder, FieldDecoder or both (Field)
}
func (Opt) ReadFrom ¶
Example ¶
package main
import (
"fmt"
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
var has pk.Boolean
var data pk.String
p1 := pk.Packet{Data: []byte{
0x01, // pk.Boolean(true)
4, 'T', 'n', 'z', 'e', // pk.String
}}
if err := p1.Scan(
&has,
pk.Opt{
Has: &has, Field: &data,
},
); err != nil {
panic(err)
}
fmt.Println(data)
var data2 pk.String = "WILL NOT BE READ, WILL NOT BE COVERED"
p2 := pk.Packet{Data: []byte{
0x00, // pk.Boolean(false)
// empty
}}
if err := p2.Scan(
&has,
pk.Opt{
Has: &has, Field: &data2,
},
); err != nil {
panic(err)
}
fmt.Println(data2)
}
Output: Tnze WILL NOT BE READ, WILL NOT BE COVERED
Example (Func) ¶
package main
import (
"fmt"
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
// As an example, we define this packet as this:
// +------+-----------------+----------------------------------+
// | Name | Type | Notes |
// +------+-----------------+----------------------------------+
// | Flag | Unsigned Byte | Odd if the following is present. |
// +------+-----------------+----------------------------------+
// | User | Optional String | The player's name. |
// +------+-----------------+----------------------------------+
// So we need a function to decide if the User field is present.
var flag pk.Byte
var data pk.String
p := pk.Packet{Data: []byte{
0b_0010_0011, // pk.Byte(flag)
4, 'T', 'n', 'z', 'e', // pk.String
}}
if err := p.Scan(
&flag,
pk.Opt{
Has: func() bool {
return flag&1 != 0
},
Field: &data,
},
); err != nil {
panic(err)
}
fmt.Println(data)
}
Output: Tnze
type Packet ¶
Packet define a net data package
func Marshal ¶
func Marshal(id int32, fields ...FieldEncoder) (pk Packet)
Marshal generate Packet with the ID and Fields
Example (SetSlot) ¶
package main
import (
"fmt"
_ "embed"
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
for _, pf := range []struct {
WindowID byte
Slot int16
Present bool
ItemID int
ItemCount byte
NBT interface{}
}{
{WindowID: 0, Slot: 5, Present: false},
{WindowID: 0, Slot: 5, Present: true, ItemID: 0x01, ItemCount: 1, NBT: pk.Byte(0)},
{WindowID: 0, Slot: 5, Present: true, ItemID: 0x01, ItemCount: 1, NBT: pk.NBT(int32(0x12345678))},
} {
p := pk.Marshal(0x15,
pk.Byte(pf.WindowID),
pk.Short(pf.Slot),
pk.Boolean(pf.Present),
pk.Opt{Has: pf.Present, Field: pk.Tuple{
pk.VarInt(pf.ItemID),
pk.Byte(pf.ItemCount),
pf.NBT,
}},
)
fmt.Printf("%02X % 02X\n", p.ID, p.Data)
}
}
Output: 15 00 00 05 00 15 00 00 05 01 01 01 00 15 00 00 05 01 01 01 03 00 00 12 34 56 78
func (Packet) Scan ¶
func (p Packet) Scan(fields ...FieldDecoder) error
Scan decode the packet and fill data into fields
Example (JoinGame) ¶
package main
import (
"fmt"
_ "embed"
pk "github.com/Tnze/go-mc/net/packet"
)
//go:embed joingame_test.bin
var testJoinGameData []byte
func main() {
p := pk.Packet{ID: 0x24, Data: testJoinGameData}
var (
EID pk.Int
Hardcore pk.Boolean
Gamemode pk.UnsignedByte
PreGamemode pk.Byte
WorldCount pk.VarInt
WorldNames = make([]pk.Identifier, 0) // This cannot replace with "var WorldNames []pk.Identifier" because "nil" has no type information
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,
pk.Ary{
Len: &WorldCount,
Ary: &WorldNames,
},
pk.NBT(&DimensionCodec),
pk.NBT(&Dimension),
&WorldName,
&HashedSeed,
&MaxPlayers,
&ViewDistance,
&RDI, &ERS, &IsDebug, &IsFlat,
)
fmt.Print(err)
}
Output: <nil>
type PluginMessageData ¶
type PluginMessageData []byte
PluginMessageData is only used in LoginPlugin,and it will read all left bytes
type Position ¶
type Position struct {
X, Y, Z int
}
Position x as a 26-bit integer, followed by y as a 12-bit integer, followed by z as a 26-bit integer (all signed, two's complement)
type String ¶
type String string
String is sequence of Unicode scalar values
type Tuple ¶
type Tuple []interface{} // FieldEncoder, FieldDecoder or both (Field)
func (Tuple) ReadFrom ¶
ReadFrom read Tuple from io.Reader, panic when any of field don't implement FieldDecoder
Example ¶
package main
import (
pk "github.com/Tnze/go-mc/net/packet"
)
func main() {
// When you need to read an "Optional Array of X":
var has pk.Boolean
var arylen pk.Int
var ary []pk.String
var p pk.Packet // = conn.ReadPacket()
if err := p.Scan(
&has,
pk.Opt{
Has: &has,
Field: pk.Tuple{
&arylen,
pk.Ary{
Len: &arylen,
Ary: &ary,
},
},
},
); err != nil {
panic(err)
}
}
Output:
type UnsignedByte ¶
type UnsignedByte uint8
UnsignedByte is unsigned 8-bit integer
type UnsignedShort ¶
type UnsignedShort uint16
UnsignedShort is unsigned 16-bit integer
type VarInt ¶
type VarInt int32
VarInt is variable-length data encoding a two's complement signed 32-bit integer