Add generic event
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
# Go-MC
|
# Go-MC
|
||||||

|

|
||||||

|

|
||||||
[](https://godoc.org/github.com/Tnze/go-mc)
|
[](https://godoc.org/github.com/Tnze/go-mc)
|
||||||
[](https://goreportcard.com/report/github.com/Tnze/go-mc)
|
[](https://goreportcard.com/report/github.com/Tnze/go-mc)
|
||||||
|
@ -12,6 +12,7 @@ type Player struct {
|
|||||||
|
|
||||||
PlayerInfo
|
PlayerInfo
|
||||||
WorldInfo
|
WorldInfo
|
||||||
|
isSpawn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer(c *bot.Client, settings Settings) *Player {
|
func NewPlayer(c *bot.Client, settings Settings) *Player {
|
||||||
@ -19,14 +20,33 @@ func NewPlayer(c *bot.Client, settings Settings) *Player {
|
|||||||
c.Events.AddListener(
|
c.Events.AddListener(
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.Login, F: b.handleJoinGamePacket},
|
bot.PacketHandler{Priority: 0, ID: packetid.Login, F: b.handleJoinGamePacket},
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.KeepAliveClientbound, F: b.handleKeepAlivePacket},
|
bot.PacketHandler{Priority: 0, ID: packetid.KeepAliveClientbound, F: b.handleKeepAlivePacket},
|
||||||
|
bot.PacketHandler{Priority: 0, ID: packetid.PositionClientbound, F: b.handlePlayerPositionAndLook},
|
||||||
)
|
)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Respawn() error {
|
func (p *Player) Respawn() error {
|
||||||
const PerformRespawn = 0
|
const PerformRespawn = 0
|
||||||
return p.c.Conn.WritePacket(pk.Marshal(
|
|
||||||
|
err := p.c.Conn.WritePacket(pk.Marshal(
|
||||||
packetid.ClientCommand,
|
packetid.ClientCommand,
|
||||||
pk.VarInt(PerformRespawn),
|
pk.VarInt(PerformRespawn),
|
||||||
))
|
))
|
||||||
|
if err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
return "bot/basic: " + e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e Error) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func (e *EventsListener) onDisconnect(p pk.Packet) error {
|
|||||||
if e.Disconnect != nil {
|
if e.Disconnect != nil {
|
||||||
var reason chat.Message
|
var reason chat.Message
|
||||||
if err := p.Scan(&reason); err != nil {
|
if err := p.Scan(&reason); err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
return e.Disconnect(reason)
|
return e.Disconnect(reason)
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ func (e *EventsListener) onChatMsg(p pk.Packet) error {
|
|||||||
var sender pk.UUID
|
var sender pk.UUID
|
||||||
|
|
||||||
if err := p.Scan(&msg, &pos, &sender); err != nil {
|
if err := p.Scan(&msg, &pos, &sender); err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.ChatMsg(msg, byte(pos), uuid.UUID(sender))
|
return e.ChatMsg(msg, byte(pos), uuid.UUID(sender))
|
||||||
@ -66,7 +66,7 @@ func (e *EventsListener) onUpdateHealth(p pk.Packet) error {
|
|||||||
var foodSaturation pk.Float
|
var foodSaturation pk.Float
|
||||||
|
|
||||||
if err := p.Scan(&health, &food, &foodSaturation); err != nil {
|
if err := p.Scan(&health, &food, &foodSaturation); err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
if e.HealthChange != nil {
|
if e.HealthChange != nil {
|
||||||
if err := e.HealthChange(float32(health)); err != nil {
|
if err := e.HealthChange(float32(health)); err != nil {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// WorldInfo content player info in server.
|
// WorldInfo content player info in server.
|
||||||
@ -38,7 +39,7 @@ type ServInfo struct {
|
|||||||
|
|
||||||
func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
||||||
var WorldCount pk.VarInt
|
var WorldCount pk.VarInt
|
||||||
var WorldNames = []pk.Identifier{}
|
var WorldNames = make([]pk.Identifier, 0)
|
||||||
err := packet.Scan(
|
err := packet.Scan(
|
||||||
(*pk.Int)(&p.EID),
|
(*pk.Int)(&p.EID),
|
||||||
(*pk.Boolean)(&p.Hardcore),
|
(*pk.Boolean)(&p.Hardcore),
|
||||||
@ -58,7 +59,7 @@ func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
|||||||
(*pk.Boolean)(&p.IsFlat),
|
(*pk.Boolean)(&p.IsFlat),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This line should work "like" the following code but without copy things
|
// This line should work "like" the following code but without copy things
|
||||||
@ -74,10 +75,10 @@ func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
|||||||
pk.String(p.Settings.Brand),
|
pk.String(p.Settings.Brand),
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.c.Conn.WritePacket(pk.Marshal(
|
err = p.c.Conn.WritePacket(pk.Marshal(
|
||||||
packetid.Settings, // Client settings
|
packetid.Settings, // Client settings
|
||||||
pk.String(p.Settings.Locale),
|
pk.String(p.Settings.Locale),
|
||||||
pk.Byte(p.Settings.ViewDistance),
|
pk.Byte(p.Settings.ViewDistance),
|
||||||
@ -86,4 +87,8 @@ func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
|||||||
pk.UnsignedByte(p.Settings.DisplayedSkinParts),
|
pk.UnsignedByte(p.Settings.DisplayedSkinParts),
|
||||||
pk.VarInt(p.Settings.MainHand),
|
pk.VarInt(p.Settings.MainHand),
|
||||||
))
|
))
|
||||||
|
if err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,59 @@ package basic
|
|||||||
import (
|
import (
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Player) handleKeepAlivePacket(packet pk.Packet) error {
|
func (p Player) handleKeepAlivePacket(packet pk.Packet) error {
|
||||||
var KeepAliveID pk.Long
|
var KeepAliveID pk.Long
|
||||||
if err := packet.Scan(&KeepAliveID); err != nil {
|
if err := packet.Scan(&KeepAliveID); err != nil {
|
||||||
return err
|
return Error{err}
|
||||||
}
|
}
|
||||||
// Response
|
// Response
|
||||||
return p.c.Conn.WritePacket(pk.Marshal(
|
err := p.c.Conn.WritePacket(pk.Packet{
|
||||||
packetid.KeepAliveServerbound,
|
ID: packetid.KeepAliveServerbound,
|
||||||
KeepAliveID,
|
Data: packet.Data,
|
||||||
))
|
})
|
||||||
|
if err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) handlePlayerPositionAndLook(packet pk.Packet) error {
|
||||||
|
var (
|
||||||
|
X, Y, Z pk.Double
|
||||||
|
Yaw, Pitch pk.Float
|
||||||
|
Flags pk.Byte
|
||||||
|
TeleportID pk.VarInt
|
||||||
|
)
|
||||||
|
if err := packet.Scan(&X, &Y, &Z, &Yaw, &Pitch, &Flags, &TeleportID); err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teleport Confirm
|
||||||
|
err := p.c.Conn.WritePacket(pk.Marshal(
|
||||||
|
packetid.TeleportConfirm,
|
||||||
|
TeleportID,
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.isSpawn {
|
||||||
|
// PlayerPositionAndRotation to confirm the spawn position
|
||||||
|
err = p.c.Conn.WritePacket(pk.Marshal(
|
||||||
|
packetid.PositionLook,
|
||||||
|
X, Y-1.62, Z,
|
||||||
|
Yaw, Pitch,
|
||||||
|
pk.Boolean(true),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return Error{err}
|
||||||
|
}
|
||||||
|
p.isSpawn = true
|
||||||
|
log.Print("Position confirmed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
15
bot/event.go
15
bot/event.go
@ -5,7 +5,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Events struct {
|
type Events struct {
|
||||||
handlers map[int32]*handlerHeap
|
generic *handlerHeap // for every packet
|
||||||
|
handlers map[int32]*handlerHeap // for specific packet id only
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) AddListener(listeners ...PacketHandler) {
|
func (e *Events) AddListener(listeners ...PacketHandler) {
|
||||||
@ -21,6 +22,18 @@ func (e *Events) AddListener(listeners ...PacketHandler) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddGeneric adds listeners like AddListener, but the packet ID is ignored.
|
||||||
|
// Generic listener is always called before specific packet listener.
|
||||||
|
func (e *Events) AddGeneric(listeners ...PacketHandler) {
|
||||||
|
for _, l := range listeners {
|
||||||
|
if e.generic == nil {
|
||||||
|
e.generic = &handlerHeap{l}
|
||||||
|
} else {
|
||||||
|
e.generic.Push(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type PacketHandlerFunc func(p pk.Packet) error
|
type PacketHandlerFunc func(p pk.Packet) error
|
||||||
type PacketHandler struct {
|
type PacketHandler struct {
|
||||||
ID int32
|
ID int32
|
||||||
|
@ -37,6 +37,13 @@ func (d PacketHandlerError) Unwrap() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) handlePacket(p pk.Packet) (err error) {
|
func (c *Client) handlePacket(p pk.Packet) (err error) {
|
||||||
|
if c.Events.generic != nil {
|
||||||
|
for _, handler := range *c.Events.generic {
|
||||||
|
if err = handler.F(p); err != nil {
|
||||||
|
return PacketHandlerError{ID: p.ID, Err: err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if listeners := c.Events.handlers[p.ID]; listeners != nil {
|
if listeners := c.Events.handlers[p.ID]; listeners != nil {
|
||||||
for _, handler := range *listeners {
|
for _, handler := range *listeners {
|
||||||
err = handler.F(p)
|
err = handler.F(p)
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
|
// Daze could join an offline-mode server as client.
|
||||||
|
// Just standing there and do nothing. Automatically reborn after five seconds of death.
|
||||||
|
//
|
||||||
|
// BUG(Tnze): Kick by Disconnect: Time Out
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
@ -20,6 +25,7 @@ var player *basic.Player
|
|||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
client = bot.NewClient()
|
client = bot.NewClient()
|
||||||
|
client.Auth.Name = "Daze"
|
||||||
player = basic.NewPlayer(client, basic.DefaultSettings)
|
player = basic.NewPlayer(client, basic.DefaultSettings)
|
||||||
basic.EventsListener{
|
basic.EventsListener{
|
||||||
GameStart: onGameStart,
|
GameStart: onGameStart,
|
||||||
@ -35,19 +41,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
log.Println("Login success")
|
log.Println("Login success")
|
||||||
|
|
||||||
//Register event handlers
|
|
||||||
|
|
||||||
//JoinGame
|
//JoinGame
|
||||||
for {
|
for {
|
||||||
if err = client.HandleGame(); err != nil {
|
if err = client.HandleGame(); err == nil {
|
||||||
var interErr *bot.PacketHandlerError
|
panic("HandleGame never return nil")
|
||||||
if errors.As(err, &interErr) {
|
}
|
||||||
log.Print("Internal bugs: ", interErr)
|
|
||||||
|
if err2 := new(bot.PacketHandlerError); errors.As(err, err2) {
|
||||||
|
if err := new(DisconnectErr); errors.As(err2, err) {
|
||||||
|
log.Print("Disconnect: ", err.Reason)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
log.Fatal(err)
|
// print and ignore the error
|
||||||
|
log.Print(err2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +64,14 @@ func main() {
|
|||||||
func onDeath() error {
|
func onDeath() error {
|
||||||
log.Println("Died and Respawned")
|
log.Println("Died and Respawned")
|
||||||
// If we exclude Respawn(...) then the player won't press the "Respawn" button upon death
|
// If we exclude Respawn(...) then the player won't press the "Respawn" button upon death
|
||||||
return player.Respawn()
|
go func() {
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
err := player.Respawn()
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onGameStart() error {
|
func onGameStart() error {
|
||||||
@ -63,12 +79,20 @@ func onGameStart() error {
|
|||||||
return nil //if err isn't nil, HandleGame() will return it.
|
return nil //if err isn't nil, HandleGame() will return it.
|
||||||
}
|
}
|
||||||
|
|
||||||
func onChatMsg(c chat.Message, pos byte, uuid uuid.UUID) error {
|
func onChatMsg(c chat.Message, _ byte, _ uuid.UUID) error {
|
||||||
log.Println("Chat:", c.ClearString()) // output chat message without any format code (like color or bold)
|
log.Println("Chat:", c.ClearString()) // output chat message without any format code (like color or bold)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onDisconnect(reason chat.Message) error {
|
type DisconnectErr struct {
|
||||||
log.Println("Disconnect:", reason)
|
Reason chat.Message
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
func (d DisconnectErr) Error() string {
|
||||||
|
return "disconnect: " + d.Reason.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func onDisconnect(reason chat.Message) error {
|
||||||
|
// return a error value so that we can stop main loop
|
||||||
|
return DisconnectErr{Reason: reason}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
//+build ignore
|
|
||||||
|
|
||||||
// gen_packetIDs.go generates the enumeration of packet IDs used on the wire.
|
// gen_packetIDs.go generates the enumeration of packet IDs used on the wire.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
@ -8,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/iancoleman/strcase"
|
"github.com/iancoleman/strcase"
|
||||||
@ -22,30 +21,30 @@ package packetid
|
|||||||
// Login state
|
// Login state
|
||||||
const (
|
const (
|
||||||
// Clientbound
|
// Clientbound
|
||||||
{{range $Name, $ID := .Login.Clientbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Login.Clientbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
// Serverbound
|
// Serverbound
|
||||||
{{range $Name, $ID := .Login.Serverbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Login.Serverbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ping state
|
// Ping state
|
||||||
const (
|
const (
|
||||||
// Clientbound
|
// Clientbound
|
||||||
{{range $Name, $ID := .Status.Clientbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Status.Clientbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
// Serverbound
|
// Serverbound
|
||||||
{{range $Name, $ID := .Status.Serverbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Status.Serverbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Play state
|
// Play state
|
||||||
const (
|
const (
|
||||||
// Clientbound
|
// Clientbound
|
||||||
{{range $Name, $ID := .Play.Clientbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Play.Clientbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
// Serverbound
|
// Serverbound
|
||||||
{{range $Name, $ID := .Play.Serverbound}} {{$Name}} = {{$ID}}
|
{{range $ID, $Name := .Play.Serverbound}} {{$Name}} = {{$ID | printf "%#x"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
@ -69,25 +68,21 @@ func unnest(input map[string]interface{}, keys ...string) (map[string]interface{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type duplexMappings struct {
|
type duplexMappings struct {
|
||||||
Clientbound map[string]string
|
Clientbound map[int32]string
|
||||||
Serverbound map[string]string
|
Serverbound map[int32]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *duplexMappings) EnsureUniqueNames() {
|
func (m *duplexMappings) EnsureUniqueNames() {
|
||||||
// Assemble a slice of keys to check across both maps, because we cannot
|
// Assemble a slice of keys to check across both maps, because we cannot
|
||||||
// mutate a map while iterating it.
|
// mutate a map while iterating it.
|
||||||
clientKeys := make([]string, 0, len(m.Clientbound))
|
clientBounds := make(map[string]int32)
|
||||||
for k, _ := range m.Clientbound {
|
for sk, sv := range m.Clientbound {
|
||||||
clientKeys = append(clientKeys, k)
|
clientBounds[sv] = sk
|
||||||
}
|
}
|
||||||
|
for sk, sv := range m.Serverbound {
|
||||||
for _, k := range clientKeys {
|
if ck, ok := clientBounds[sv]; ok {
|
||||||
if _, alsoServerKey := m.Serverbound[k]; alsoServerKey {
|
m.Clientbound[ck] = sv + "Clientbound"
|
||||||
cVal, sVal := m.Clientbound[k], m.Serverbound[k]
|
m.Serverbound[sk] = sv + "Serverbound"
|
||||||
delete(m.Clientbound, k)
|
|
||||||
delete(m.Serverbound, k)
|
|
||||||
m.Clientbound[k+"Clientbound"] = cVal
|
|
||||||
m.Serverbound[k+"Serverbound"] = sVal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,8 +91,8 @@ func (m *duplexMappings) EnsureUniqueNames() {
|
|||||||
// game state.
|
// game state.
|
||||||
func unpackMapping(data map[string]interface{}, gameState string) (duplexMappings, error) {
|
func unpackMapping(data map[string]interface{}, gameState string) (duplexMappings, error) {
|
||||||
out := duplexMappings{
|
out := duplexMappings{
|
||||||
Clientbound: make(map[string]string),
|
Clientbound: make(map[int32]string),
|
||||||
Serverbound: make(map[string]string),
|
Serverbound: make(map[int32]string),
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := unnest(data, gameState, "toClient", "types")
|
info, err := unnest(data, gameState, "toClient", "types")
|
||||||
@ -107,7 +102,7 @@ func unpackMapping(data map[string]interface{}, gameState string) (duplexMapping
|
|||||||
pType := info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
pType := info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
||||||
mappings := pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
mappings := pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
||||||
for k, v := range mappings {
|
for k, v := range mappings {
|
||||||
out.Clientbound[strcase.ToCamel(v.(string))] = k
|
out.Clientbound[mustAtoi(k)] = strcase.ToCamel(v.(string))
|
||||||
}
|
}
|
||||||
info, err = unnest(data, gameState, "toServer", "types")
|
info, err = unnest(data, gameState, "toServer", "types")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -116,12 +111,20 @@ func unpackMapping(data map[string]interface{}, gameState string) (duplexMapping
|
|||||||
pType = info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
pType = info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
||||||
mappings = pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
mappings = pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
||||||
for k, v := range mappings {
|
for k, v := range mappings {
|
||||||
out.Serverbound[strcase.ToCamel(v.(string))] = k
|
out.Serverbound[mustAtoi(k)] = strcase.ToCamel(v.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustAtoi(num string) int32 {
|
||||||
|
if n, err := strconv.ParseInt(num, 0, 32); err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
return int32(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type protocolIDs struct {
|
type protocolIDs struct {
|
||||||
Login duplexMappings
|
Login duplexMappings
|
||||||
Play duplexMappings
|
Play duplexMappings
|
||||||
@ -158,7 +161,7 @@ func downloadInfo() (*protocolIDs, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:generate go run $GOFILE
|
//go:generate go run $GOFILE
|
||||||
//go:generate go fmt packetid.go
|
//go:generate go fmt ../packetid.go
|
||||||
func main() {
|
func main() {
|
||||||
pIDs, err := downloadInfo()
|
pIDs, err := downloadInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -166,7 +169,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Create("packetid.go")
|
f, err := os.Create("../packetid.go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
@ -2,169 +2,175 @@
|
|||||||
|
|
||||||
package packetid
|
package packetid
|
||||||
|
|
||||||
// Valid PktID values.
|
// Login state
|
||||||
const (
|
const (
|
||||||
// Clientbound packets for connections in the login state.
|
// Clientbound
|
||||||
Compress = 0x03
|
Disconnect = 0x0
|
||||||
Disconnect = 0x00
|
EncryptionBeginClientbound = 0x1
|
||||||
EncryptionBeginClientbound = 0x01
|
Success = 0x2
|
||||||
LoginPluginRequest = 0x04
|
Compress = 0x3
|
||||||
Success = 0x02
|
LoginPluginRequest = 0x4
|
||||||
|
|
||||||
// Serverbound packets for connections in the login state
|
// Serverbound
|
||||||
EncryptionBeginServerbound = 0x01
|
LoginStart = 0x0
|
||||||
LoginPluginResponse = 0x02
|
EncryptionBeginServerbound = 0x1
|
||||||
LoginStart = 0x00
|
LoginPluginResponse = 0x2
|
||||||
|
)
|
||||||
|
|
||||||
// Clientbound packets for connections in the play state.
|
// Ping state
|
||||||
AbilitiesClientbound = 0x30
|
const (
|
||||||
AcknowledgePlayerDigging = 0x07
|
// Clientbound
|
||||||
Advancements = 0x57
|
ServerInfo = 0x0
|
||||||
Animation = 0x05
|
PingClientbound = 0x1
|
||||||
AttachEntity = 0x45
|
|
||||||
BlockAction = 0x0a
|
// Serverbound
|
||||||
BlockBreakAnimation = 0x08
|
PingStart = 0x0
|
||||||
BlockChange = 0x0b
|
PingServerbound = 0x1
|
||||||
BossBar = 0x0c
|
)
|
||||||
Camera = 0x3e
|
|
||||||
ChatClientbound = 0x0e
|
// Play state
|
||||||
CloseWindowClientbound = 0x12
|
const (
|
||||||
Collect = 0x55
|
// Clientbound
|
||||||
CombatEvent = 0x31
|
SpawnEntity = 0x0
|
||||||
CraftProgressBar = 0x14
|
SpawnEntityExperienceOrb = 0x1
|
||||||
CraftRecipeResponse = 0x2f
|
SpawnEntityLiving = 0x2
|
||||||
CustomPayloadClientbound = 0x17
|
SpawnEntityPainting = 0x3
|
||||||
|
NamedEntitySpawn = 0x4
|
||||||
|
Animation = 0x5
|
||||||
|
Statistics = 0x6
|
||||||
|
AcknowledgePlayerDigging = 0x7
|
||||||
|
BlockBreakAnimation = 0x8
|
||||||
|
TileEntityData = 0x9
|
||||||
|
BlockAction = 0xa
|
||||||
|
BlockChange = 0xb
|
||||||
|
BossBar = 0xc
|
||||||
|
Difficulty = 0xd
|
||||||
|
ChatClientbound = 0xe
|
||||||
|
TabCompleteClientbound = 0xf
|
||||||
DeclareCommands = 0x10
|
DeclareCommands = 0x10
|
||||||
DeclareRecipes = 0x5a
|
TransactionClientbound = 0x11
|
||||||
Difficulty = 0x0d
|
CloseWindowClientbound = 0x12
|
||||||
Entity = 0x2a
|
WindowItems = 0x13
|
||||||
EntityDestroy = 0x36
|
CraftProgressBar = 0x14
|
||||||
EntityEffect = 0x59
|
SetSlot = 0x15
|
||||||
EntityEquipment = 0x47
|
SetCooldown = 0x16
|
||||||
EntityHeadRotation = 0x3a
|
CustomPayloadClientbound = 0x17
|
||||||
EntityLook = 0x29
|
NamedSoundEffect = 0x18
|
||||||
EntityMetadata = 0x44
|
|
||||||
EntityMoveLook = 0x28
|
|
||||||
EntitySoundEffect = 0x50
|
|
||||||
EntityStatus = 0x1a
|
|
||||||
EntityTeleport = 0x56
|
|
||||||
EntityUpdateAttributes = 0x58
|
|
||||||
EntityVelocity = 0x46
|
|
||||||
Experience = 0x48
|
|
||||||
Explosion = 0x1b
|
|
||||||
FacePlayer = 0x33
|
|
||||||
GameStateChange = 0x1d
|
|
||||||
HeldItemSlotClientbound = 0x3f
|
|
||||||
KeepAliveClientbound = 0x1f
|
|
||||||
KickDisconnect = 0x19
|
KickDisconnect = 0x19
|
||||||
|
EntityStatus = 0x1a
|
||||||
|
Explosion = 0x1b
|
||||||
|
UnloadChunk = 0x1c
|
||||||
|
GameStateChange = 0x1d
|
||||||
|
OpenHorseWindow = 0x1e
|
||||||
|
KeepAliveClientbound = 0x1f
|
||||||
|
MapChunk = 0x20
|
||||||
|
WorldEvent = 0x21
|
||||||
|
WorldParticles = 0x22
|
||||||
|
UpdateLight = 0x23
|
||||||
Login = 0x24
|
Login = 0x24
|
||||||
Map = 0x25
|
Map = 0x25
|
||||||
MapChunk = 0x20
|
TradeList = 0x26
|
||||||
MultiBlockChange = 0x3b
|
|
||||||
NamedEntitySpawn = 0x04
|
|
||||||
NamedSoundEffect = 0x18
|
|
||||||
NbtQueryResponse = 0x54
|
|
||||||
OpenBook = 0x2c
|
|
||||||
OpenHorseWindow = 0x1e
|
|
||||||
OpenSignEntity = 0x2e
|
|
||||||
OpenWindow = 0x2d
|
|
||||||
PlayerInfo = 0x32
|
|
||||||
PlayerlistHeader = 0x53
|
|
||||||
PositionClientbound = 0x34
|
|
||||||
RelEntityMove = 0x27
|
RelEntityMove = 0x27
|
||||||
|
EntityMoveLook = 0x28
|
||||||
|
EntityLook = 0x29
|
||||||
|
Entity = 0x2a
|
||||||
|
VehicleMoveClientbound = 0x2b
|
||||||
|
OpenBook = 0x2c
|
||||||
|
OpenWindow = 0x2d
|
||||||
|
OpenSignEntity = 0x2e
|
||||||
|
CraftRecipeResponse = 0x2f
|
||||||
|
AbilitiesClientbound = 0x30
|
||||||
|
CombatEvent = 0x31
|
||||||
|
PlayerInfo = 0x32
|
||||||
|
FacePlayer = 0x33
|
||||||
|
PositionClientbound = 0x34
|
||||||
|
UnlockRecipes = 0x35
|
||||||
|
EntityDestroy = 0x36
|
||||||
RemoveEntityEffect = 0x37
|
RemoveEntityEffect = 0x37
|
||||||
ResourcePackSend = 0x38
|
ResourcePackSend = 0x38
|
||||||
Respawn = 0x39
|
Respawn = 0x39
|
||||||
ScoreboardDisplayObjective = 0x43
|
EntityHeadRotation = 0x3a
|
||||||
ScoreboardObjective = 0x4a
|
MultiBlockChange = 0x3b
|
||||||
ScoreboardScore = 0x4d
|
|
||||||
SelectAdvancementTab = 0x3c
|
SelectAdvancementTab = 0x3c
|
||||||
SetCooldown = 0x16
|
|
||||||
SetPassengers = 0x4b
|
|
||||||
SetSlot = 0x15
|
|
||||||
SoundEffect = 0x51
|
|
||||||
SpawnEntity = 0x00
|
|
||||||
SpawnEntityExperienceOrb = 0x01
|
|
||||||
SpawnEntityLiving = 0x02
|
|
||||||
SpawnEntityPainting = 0x03
|
|
||||||
SpawnPosition = 0x42
|
|
||||||
Statistics = 0x06
|
|
||||||
StopSound = 0x52
|
|
||||||
TabCompleteClientbound = 0x0f
|
|
||||||
Tags = 0x5b
|
|
||||||
Teams = 0x4c
|
|
||||||
TileEntityData = 0x09
|
|
||||||
Title = 0x4f
|
|
||||||
TradeList = 0x26
|
|
||||||
TransactionClientbound = 0x11
|
|
||||||
UnloadChunk = 0x1c
|
|
||||||
UnlockRecipes = 0x35
|
|
||||||
UpdateHealth = 0x49
|
|
||||||
UpdateLight = 0x23
|
|
||||||
UpdateTime = 0x4e
|
|
||||||
UpdateViewDistance = 0x41
|
|
||||||
UpdateViewPosition = 0x40
|
|
||||||
VehicleMoveClientbound = 0x2b
|
|
||||||
WindowItems = 0x13
|
|
||||||
WorldBorder = 0x3d
|
WorldBorder = 0x3d
|
||||||
WorldEvent = 0x21
|
Camera = 0x3e
|
||||||
WorldParticles = 0x22
|
HeldItemSlotClientbound = 0x3f
|
||||||
|
UpdateViewPosition = 0x40
|
||||||
|
UpdateViewDistance = 0x41
|
||||||
|
SpawnPosition = 0x42
|
||||||
|
ScoreboardDisplayObjective = 0x43
|
||||||
|
EntityMetadata = 0x44
|
||||||
|
AttachEntity = 0x45
|
||||||
|
EntityVelocity = 0x46
|
||||||
|
EntityEquipment = 0x47
|
||||||
|
Experience = 0x48
|
||||||
|
UpdateHealth = 0x49
|
||||||
|
ScoreboardObjective = 0x4a
|
||||||
|
SetPassengers = 0x4b
|
||||||
|
Teams = 0x4c
|
||||||
|
ScoreboardScore = 0x4d
|
||||||
|
UpdateTime = 0x4e
|
||||||
|
Title = 0x4f
|
||||||
|
EntitySoundEffect = 0x50
|
||||||
|
SoundEffect = 0x51
|
||||||
|
StopSound = 0x52
|
||||||
|
PlayerlistHeader = 0x53
|
||||||
|
NbtQueryResponse = 0x54
|
||||||
|
Collect = 0x55
|
||||||
|
EntityTeleport = 0x56
|
||||||
|
Advancements = 0x57
|
||||||
|
EntityUpdateAttributes = 0x58
|
||||||
|
EntityEffect = 0x59
|
||||||
|
DeclareRecipes = 0x5a
|
||||||
|
Tags = 0x5b
|
||||||
|
|
||||||
// Serverbound packets for connections in the play state.
|
// Serverbound
|
||||||
AbilitiesServerbound = 0x1a
|
TeleportConfirm = 0x0
|
||||||
AdvancementTab = 0x22
|
QueryBlockNbt = 0x1
|
||||||
ArmAnimation = 0x2c
|
SetDifficulty = 0x2
|
||||||
BlockDig = 0x1b
|
ChatServerbound = 0x3
|
||||||
BlockPlace = 0x2e
|
ClientCommand = 0x4
|
||||||
ChatServerbound = 0x03
|
Settings = 0x5
|
||||||
ClientCommand = 0x04
|
TabCompleteServerbound = 0x6
|
||||||
CloseWindowServerbound = 0x0a
|
TransactionServerbound = 0x7
|
||||||
CraftRecipeRequest = 0x19
|
EnchantItem = 0x8
|
||||||
CustomPayloadServerbound = 0x0b
|
WindowClick = 0x9
|
||||||
DisplayedRecipe = 0x1e
|
CloseWindowServerbound = 0xa
|
||||||
EditBook = 0x0c
|
CustomPayloadServerbound = 0xb
|
||||||
EnchantItem = 0x08
|
EditBook = 0xc
|
||||||
EntityAction = 0x1c
|
QueryEntityNbt = 0xd
|
||||||
Flying = 0x15
|
UseEntity = 0xe
|
||||||
GenerateStructure = 0x0f
|
GenerateStructure = 0xf
|
||||||
HeldItemSlotServerbound = 0x25
|
|
||||||
KeepAliveServerbound = 0x10
|
KeepAliveServerbound = 0x10
|
||||||
LockDifficulty = 0x11
|
LockDifficulty = 0x11
|
||||||
Look = 0x14
|
|
||||||
NameItem = 0x20
|
|
||||||
PickItem = 0x18
|
|
||||||
PositionLook = 0x13
|
|
||||||
PositionServerbound = 0x12
|
PositionServerbound = 0x12
|
||||||
QueryBlockNbt = 0x01
|
PositionLook = 0x13
|
||||||
QueryEntityNbt = 0x0d
|
Look = 0x14
|
||||||
|
Flying = 0x15
|
||||||
|
VehicleMoveServerbound = 0x16
|
||||||
|
SteerBoat = 0x17
|
||||||
|
PickItem = 0x18
|
||||||
|
CraftRecipeRequest = 0x19
|
||||||
|
AbilitiesServerbound = 0x1a
|
||||||
|
BlockDig = 0x1b
|
||||||
|
EntityAction = 0x1c
|
||||||
|
SteerVehicle = 0x1d
|
||||||
|
DisplayedRecipe = 0x1e
|
||||||
RecipeBook = 0x1f
|
RecipeBook = 0x1f
|
||||||
|
NameItem = 0x20
|
||||||
ResourcePackReceive = 0x21
|
ResourcePackReceive = 0x21
|
||||||
|
AdvancementTab = 0x22
|
||||||
SelectTrade = 0x23
|
SelectTrade = 0x23
|
||||||
SetBeaconEffect = 0x24
|
SetBeaconEffect = 0x24
|
||||||
SetCreativeSlot = 0x28
|
HeldItemSlotServerbound = 0x25
|
||||||
SetDifficulty = 0x02
|
|
||||||
Settings = 0x05
|
|
||||||
Spectate = 0x2d
|
|
||||||
SteerBoat = 0x17
|
|
||||||
SteerVehicle = 0x1d
|
|
||||||
TabCompleteServerbound = 0x06
|
|
||||||
TeleportConfirm = 0x00
|
|
||||||
TransactionServerbound = 0x07
|
|
||||||
UpdateCommandBlock = 0x26
|
UpdateCommandBlock = 0x26
|
||||||
UpdateCommandBlockMinecart = 0x27
|
UpdateCommandBlockMinecart = 0x27
|
||||||
|
SetCreativeSlot = 0x28
|
||||||
UpdateJigsawBlock = 0x29
|
UpdateJigsawBlock = 0x29
|
||||||
UpdateSign = 0x2b
|
|
||||||
UpdateStructureBlock = 0x2a
|
UpdateStructureBlock = 0x2a
|
||||||
UseEntity = 0x0e
|
UpdateSign = 0x2b
|
||||||
|
ArmAnimation = 0x2c
|
||||||
|
Spectate = 0x2d
|
||||||
|
BlockPlace = 0x2e
|
||||||
UseItem = 0x2f
|
UseItem = 0x2f
|
||||||
VehicleMoveServerbound = 0x16
|
|
||||||
WindowClick = 0x09
|
|
||||||
|
|
||||||
// Clientbound packets used to respond to ping/status requests.
|
|
||||||
PingClientbound = 0x01
|
|
||||||
ServerInfo = 0x00
|
|
||||||
|
|
||||||
// Serverbound packets used to ping or read server status.
|
|
||||||
PingServerbound = 0x01
|
|
||||||
PingStart = 0x00
|
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user