Implement generator and type for packet IDs
This commit is contained in:
@ -64,8 +64,8 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch p.ID {
|
switch data.PktID(p.ID) {
|
||||||
case data.JoinGame:
|
case data.Login:
|
||||||
err = handleJoinGamePacket(c, p)
|
err = handleJoinGamePacket(c, p)
|
||||||
|
|
||||||
if err == nil && c.Events.GameStart != nil {
|
if err == nil && c.Events.GameStart != nil {
|
||||||
@ -75,7 +75,7 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
_ = c.conn.WritePacket(
|
_ = c.conn.WritePacket(
|
||||||
//PluginMessage packet (serverbound) - sending minecraft brand.
|
//PluginMessage packet (serverbound) - sending minecraft brand.
|
||||||
pk.Marshal(
|
pk.Marshal(
|
||||||
data.PluginMessageServerbound,
|
data.CustomPayloadServerbound,
|
||||||
pk.Identifier("minecraft:brand"),
|
pk.Identifier("minecraft:brand"),
|
||||||
pk.String(c.settings.Brand),
|
pk.String(c.settings.Brand),
|
||||||
),
|
),
|
||||||
@ -83,9 +83,9 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
if err2 := c.Events.updateSeenPackets(seenJoinGame); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenJoinGame); err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
case data.PluginMessageClientbound:
|
case data.CustomPayloadClientbound:
|
||||||
err = handlePluginPacket(c, p)
|
err = handlePluginPacket(c, p)
|
||||||
case data.ServerDifficulty:
|
case data.Difficulty:
|
||||||
err = handleServerDifficultyPacket(c, p)
|
err = handleServerDifficultyPacket(c, p)
|
||||||
if err == nil && c.Events.ServerDifficultyChange != nil {
|
if err == nil && c.Events.ServerDifficultyChange != nil {
|
||||||
err = c.Events.ServerDifficultyChange(c.Difficulty)
|
err = c.Events.ServerDifficultyChange(c.Difficulty)
|
||||||
@ -98,12 +98,12 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
if err2 := c.Events.updateSeenPackets(seenSpawnPos); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenSpawnPos); err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
case data.PlayerAbilitiesClientbound:
|
case data.AbilitiesClientbound:
|
||||||
err = handlePlayerAbilitiesPacket(c, p)
|
err = handlePlayerAbilitiesPacket(c, p)
|
||||||
_ = c.conn.WritePacket(
|
_ = c.conn.WritePacket(
|
||||||
//ClientSettings packet (serverbound)
|
//ClientSettings packet (serverbound)
|
||||||
pk.Marshal(
|
pk.Marshal(
|
||||||
data.ClientSettings,
|
data.Settings,
|
||||||
pk.String(c.settings.Locale),
|
pk.String(c.settings.Locale),
|
||||||
pk.Byte(c.settings.ViewDistance),
|
pk.Byte(c.settings.ViewDistance),
|
||||||
pk.VarInt(c.settings.ChatMode),
|
pk.VarInt(c.settings.ChatMode),
|
||||||
@ -115,16 +115,16 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
if err2 := c.Events.updateSeenPackets(seenPlayerAbilities); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenPlayerAbilities); err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
case data.HeldItemChangeClientbound:
|
case data.HeldItemSlotClientbound:
|
||||||
err = handleHeldItemPacket(c, p)
|
err = handleHeldItemPacket(c, p)
|
||||||
case data.UpdateLight:
|
case data.UpdateLight:
|
||||||
err = c.Events.updateSeenPackets(seenUpdateLight)
|
err = c.Events.updateSeenPackets(seenUpdateLight)
|
||||||
case data.ChunkData:
|
case data.MapChunk:
|
||||||
err = handleChunkDataPacket(c, p)
|
err = handleChunkDataPacket(c, p)
|
||||||
if err2 := c.Events.updateSeenPackets(seenChunkData); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenChunkData); err == nil {
|
||||||
err = err2
|
err = err2
|
||||||
}
|
}
|
||||||
case data.PlayerPositionAndLookClientbound:
|
case data.PositionClientbound:
|
||||||
err = handlePlayerPositionAndLookPacket(c, p)
|
err = handlePlayerPositionAndLookPacket(c, p)
|
||||||
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
||||||
if err2 := c.Events.updateSeenPackets(seenPlayerPositionAndLook); err == nil {
|
if err2 := c.Events.updateSeenPackets(seenPlayerPositionAndLook); err == nil {
|
||||||
@ -132,29 +132,23 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
}
|
}
|
||||||
case data.DeclareRecipes:
|
case data.DeclareRecipes:
|
||||||
// handleDeclareRecipesPacket(g, reader)
|
// handleDeclareRecipesPacket(g, reader)
|
||||||
case data.EntityLookAndRelativeMove:
|
|
||||||
// err = handleEntityLookAndRelativeMove(g, reader)
|
|
||||||
case data.EntityHeadLook:
|
|
||||||
// handleEntityHeadLookPacket(g, reader)
|
|
||||||
case data.EntityRelativeMove:
|
|
||||||
// err = handleEntityRelativeMovePacket(g, reader)
|
|
||||||
case data.KeepAliveClientbound:
|
case data.KeepAliveClientbound:
|
||||||
err = handleKeepAlivePacket(c, p)
|
err = handleKeepAlivePacket(c, p)
|
||||||
case data.Entity:
|
case data.Entity:
|
||||||
//handleEntityPacket(g, reader)
|
//handleEntityPacket(g, reader)
|
||||||
case data.SpawnPlayer:
|
case data.NamedEntitySpawn:
|
||||||
// err = handleSpawnPlayerPacket(g, reader)
|
// err = handleSpawnPlayerPacket(g, reader)
|
||||||
case data.WindowItems:
|
case data.WindowItems:
|
||||||
err = handleWindowItemsPacket(c, p)
|
err = handleWindowItemsPacket(c, p)
|
||||||
case data.UpdateHealth:
|
case data.UpdateHealth:
|
||||||
err = handleUpdateHealthPacket(c, p)
|
err = handleUpdateHealthPacket(c, p)
|
||||||
case data.ChatMessageClientbound:
|
case data.ChatClientbound:
|
||||||
err = handleChatMessagePacket(c, p)
|
err = handleChatMessagePacket(c, p)
|
||||||
case data.BlockChange:
|
case data.BlockChange:
|
||||||
////err = handleBlockChangePacket(c, p)
|
////err = handleBlockChangePacket(c, p)
|
||||||
case data.MultiBlockChange:
|
case data.MultiBlockChange:
|
||||||
////err = handleMultiBlockChangePacket(c, p)
|
////err = handleMultiBlockChangePacket(c, p)
|
||||||
case data.DisconnectPlay:
|
case data.KickDisconnect:
|
||||||
err = handleDisconnectPacket(c, p)
|
err = handleDisconnectPacket(c, p)
|
||||||
disconnect = true
|
disconnect = true
|
||||||
case data.SetSlot:
|
case data.SetSlot:
|
||||||
@ -163,7 +157,7 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
err = handleSoundEffect(c, p)
|
err = handleSoundEffect(c, p)
|
||||||
case data.NamedSoundEffect:
|
case data.NamedSoundEffect:
|
||||||
err = handleNamedSoundEffect(c, p)
|
err = handleNamedSoundEffect(c, p)
|
||||||
case data.SetExperience:
|
case data.Experience:
|
||||||
err = handleSetExperience(c, p)
|
err = handleSetExperience(c, p)
|
||||||
default:
|
default:
|
||||||
// fmt.Printf("ignore pack id %X\n", p.ID)
|
// fmt.Printf("ignore pack id %X\n", p.ID)
|
||||||
@ -694,7 +688,7 @@ func handleSetExperience(c *Client, p pk.Packet) (err error) {
|
|||||||
|
|
||||||
func sendPlayerPositionAndLookPacket(c *Client) {
|
func sendPlayerPositionAndLookPacket(c *Client) {
|
||||||
c.conn.WritePacket(pk.Marshal(
|
c.conn.WritePacket(pk.Marshal(
|
||||||
data.PlayerPositionAndLookServerbound,
|
data.PositionLook,
|
||||||
pk.Double(c.X),
|
pk.Double(c.X),
|
||||||
pk.Double(c.Y),
|
pk.Double(c.Y),
|
||||||
pk.Double(c.Z),
|
pk.Double(c.Z),
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// It's just animation.
|
// It's just animation.
|
||||||
func (c *Client) SwingArm(hand int) error {
|
func (c *Client) SwingArm(hand int) error {
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.AnimationServerbound,
|
data.ArmAnimation,
|
||||||
pk.VarInt(hand),
|
pk.VarInt(hand),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ func (c *Client) SwingArm(hand int) error {
|
|||||||
// Respawn the player when it was dead.
|
// Respawn the player when it was dead.
|
||||||
func (c *Client) Respawn() error {
|
func (c *Client) Respawn() error {
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.ClientStatus,
|
data.ClientCommand,
|
||||||
pk.VarInt(0),
|
pk.VarInt(0),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ func (c *Client) Chat(msg string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.ChatMessageServerbound,
|
data.ChatServerbound,
|
||||||
pk.String(msg),
|
pk.String(msg),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ func (c *Client) Chat(msg string) error {
|
|||||||
// PluginMessage is used by mods and plugins to send their data.
|
// PluginMessage is used by mods and plugins to send their data.
|
||||||
func (c *Client) PluginMessage(channal string, msg []byte) error {
|
func (c *Client) PluginMessage(channal string, msg []byte) error {
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.PluginMessageServerbound,
|
data.CustomPayloadServerbound,
|
||||||
pk.Identifier(channal),
|
pk.Identifier(channal),
|
||||||
pluginMessageData(msg),
|
pluginMessageData(msg),
|
||||||
))
|
))
|
||||||
@ -103,7 +103,7 @@ func (c *Client) PluginMessage(channal string, msg []byte) error {
|
|||||||
// insideBlock is true when the player's head is inside of a block's collision.
|
// insideBlock is true when the player's head is inside of a block's collision.
|
||||||
func (c *Client) UseBlock(hand, locX, locY, locZ, face int, cursorX, cursorY, cursorZ float32, insideBlock bool) error {
|
func (c *Client) UseBlock(hand, locX, locY, locZ, face int, cursorX, cursorY, cursorZ float32, insideBlock bool) error {
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.PlayerBlockPlacement,
|
data.UseItem,
|
||||||
pk.VarInt(hand),
|
pk.VarInt(hand),
|
||||||
pk.Position{X: locX, Y: locY, Z: locZ},
|
pk.Position{X: locX, Y: locY, Z: locZ},
|
||||||
pk.VarInt(face),
|
pk.VarInt(face),
|
||||||
@ -120,7 +120,7 @@ func (c *Client) SelectItem(slot int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.HeldItemChangeServerbound,
|
data.HeldItemSlotServerbound,
|
||||||
pk.Short(slot),
|
pk.Short(slot),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ func (c *Client) PickItem(slot int) error {
|
|||||||
|
|
||||||
func (c *Client) playerAction(status, locX, locY, locZ, face int) error {
|
func (c *Client) playerAction(status, locX, locY, locZ, face int) error {
|
||||||
return c.conn.WritePacket(pk.Marshal(
|
return c.conn.WritePacket(pk.Marshal(
|
||||||
data.PlayerDigging,
|
data.BlockDig,
|
||||||
pk.VarInt(status),
|
pk.VarInt(status),
|
||||||
pk.Position{X: locX, Y: locY, Z: locZ},
|
pk.Position{X: locX, Y: locY, Z: locZ},
|
||||||
pk.Byte(face),
|
pk.Byte(face),
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package world
|
package world
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Tnze/go-mc/data"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newDirectSection(bpb int) Section {
|
func newDirectSection(bpb int) Section {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/uuid"
|
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
_ "github.com/Tnze/go-mc/data/lang/en-us"
|
_ "github.com/Tnze/go-mc/data/lang/en-us"
|
||||||
|
@ -2,9 +2,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/google/uuid"
|
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
_ "github.com/Tnze/go-mc/data/lang/en-us"
|
_ "github.com/Tnze/go-mc/data/lang/en-us"
|
||||||
|
@ -3,8 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Tnze/go-mc/yggdrasil"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/yggdrasil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var user = flag.String("user", "", "Can be an email address or player name for unmigrated accounts")
|
var user = flag.String("user", "", "Can be an email address or player name for unmigrated accounts")
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/data"
|
"github.com/Tnze/go-mc/data"
|
||||||
"github.com/Tnze/go-mc/net"
|
"github.com/Tnze/go-mc/net"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ProtocolVersion = 578
|
const ProtocolVersion = 578
|
||||||
@ -64,7 +65,7 @@ func handlePlaying(conn net.Conn, protocol int32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
joinGame(conn)
|
joinGame(conn)
|
||||||
conn.WritePacket(pk.Marshal(data.PlayerPositionAndLookClientbound,
|
conn.WritePacket(pk.Marshal(data.PositionClientbound,
|
||||||
// https://wiki.vg/Protocol#Player_Position_And_Look_.28clientbound.29
|
// https://wiki.vg/Protocol#Player_Position_And_Look_.28clientbound.29
|
||||||
pk.Double(0), pk.Double(0), pk.Double(0), // XYZ
|
pk.Double(0), pk.Double(0), pk.Double(0), // XYZ
|
||||||
pk.Float(0), pk.Float(0), // Yaw Pitch
|
pk.Float(0), pk.Float(0), // Yaw Pitch
|
||||||
@ -139,7 +140,7 @@ func loginSuccess(conn net.Conn, name string, uuid uuid.UUID) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func joinGame(conn net.Conn) error {
|
func joinGame(conn net.Conn) error {
|
||||||
return conn.WritePacket(pk.Marshal(data.JoinGame,
|
return conn.WritePacket(pk.Marshal(data.Login,
|
||||||
pk.Int(0), // EntityID
|
pk.Int(0), // EntityID
|
||||||
pk.UnsignedByte(1), // Gamemode
|
pk.UnsignedByte(1), // Gamemode
|
||||||
pk.Int(0), // Dimension
|
pk.Int(0), // Dimension
|
||||||
|
196
data/gen_packetIDs.go
Normal file
196
data/gen_packetIDs.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
// gen_packetIDs.go generates the enumeration of packet IDs used on the wire.
|
||||||
|
|
||||||
|
//+build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/iancoleman/strcase"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
protocolURL = "https://raw.githubusercontent.com/PrismarineJS/minecraft-data/master/data/pc/1.16.2/protocol.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// unnest is a utility function to unpack a value from a nested map, given
|
||||||
|
// an arbitrary set of keys to reach through.
|
||||||
|
func unnest(input map[string]interface{}, keys ...string) (map[string]interface{}, error) {
|
||||||
|
for _, k := range keys {
|
||||||
|
sub, ok := input[k]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("key %q not found", k)
|
||||||
|
}
|
||||||
|
next, ok := sub.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("key %q was %T, expected a string map", k, sub)
|
||||||
|
}
|
||||||
|
input = next
|
||||||
|
}
|
||||||
|
return input, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type duplexMappings struct {
|
||||||
|
Clientbound map[string]string
|
||||||
|
Serverbound map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *duplexMappings) EnsureUniqueNames() {
|
||||||
|
// Assemble a slice of keys to check across both maps, because we cannot
|
||||||
|
// mutate a map while iterating it.
|
||||||
|
clientKeys := make([]string, 0, len(m.Clientbound))
|
||||||
|
for k, _ := range m.Clientbound {
|
||||||
|
clientKeys = append(clientKeys, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k := range clientKeys {
|
||||||
|
if _, alsoServerKey := m.Serverbound[k]; alsoServerKey {
|
||||||
|
cVal, sVal := m.Clientbound[k], m.Serverbound[k]
|
||||||
|
delete(m.Clientbound, k)
|
||||||
|
delete(m.Serverbound, k)
|
||||||
|
m.Clientbound[k+"Clientbound"] = cVal
|
||||||
|
m.Serverbound[k+"Serverbound"] = sVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpackMapping returns the set of packet IDs and their names for a given
|
||||||
|
// game state.
|
||||||
|
func unpackMapping(data map[string]interface{}, gameState string) (duplexMappings, error) {
|
||||||
|
out := duplexMappings{
|
||||||
|
Clientbound: make(map[string]string),
|
||||||
|
Serverbound: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := unnest(data, gameState, "toClient", "types")
|
||||||
|
if err != nil {
|
||||||
|
return duplexMappings{}, err
|
||||||
|
}
|
||||||
|
pType := info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
||||||
|
mappings := pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
||||||
|
for k, v := range mappings {
|
||||||
|
out.Clientbound[strcase.ToCamel(v.(string))] = k
|
||||||
|
}
|
||||||
|
info, err = unnest(data, gameState, "toServer", "types")
|
||||||
|
if err != nil {
|
||||||
|
return duplexMappings{}, err
|
||||||
|
}
|
||||||
|
pType = info["packet"].([]interface{})[1].([]interface{})[0].(map[string]interface{})["type"]
|
||||||
|
mappings = pType.([]interface{})[1].(map[string]interface{})["mappings"].(map[string]interface{})
|
||||||
|
for k, v := range mappings {
|
||||||
|
out.Serverbound[strcase.ToCamel(v.(string))] = k
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type protocolIDs struct {
|
||||||
|
Login duplexMappings
|
||||||
|
Play duplexMappings
|
||||||
|
Status duplexMappings
|
||||||
|
// Handshake state has no packets
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p protocolIDs) MaxLen() int {
|
||||||
|
var max int
|
||||||
|
for _, m := range []duplexMappings{p.Login, p.Play, p.Status} {
|
||||||
|
for k, _ := range m.Clientbound {
|
||||||
|
if len(k) > max {
|
||||||
|
max = len(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k, _ := range m.Serverbound {
|
||||||
|
if len(k) > max {
|
||||||
|
max = len(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadInfo() (*protocolIDs, error) {
|
||||||
|
resp, err := http.Get(protocolURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
var data map[string]interface{}
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var out protocolIDs
|
||||||
|
if out.Login, err = unpackMapping(data, "login"); err != nil {
|
||||||
|
return nil, fmt.Errorf("login: %v", err)
|
||||||
|
}
|
||||||
|
out.Login.EnsureUniqueNames()
|
||||||
|
if out.Play, err = unpackMapping(data, "play"); err != nil {
|
||||||
|
return nil, fmt.Errorf("play: %v", err)
|
||||||
|
}
|
||||||
|
out.Play.EnsureUniqueNames()
|
||||||
|
if out.Status, err = unpackMapping(data, "status"); err != nil {
|
||||||
|
return nil, fmt.Errorf("play: %v", err)
|
||||||
|
}
|
||||||
|
out.Status.EnsureUniqueNames()
|
||||||
|
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pIDs, err := downloadInfo()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxLen := pIDs.MaxLen()
|
||||||
|
|
||||||
|
fmt.Println("package data")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("//go:generate bash -c \"go run gen_packetIDs.go > packetIDs.go\"")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("// This file is automatically generated by gen_packetIDs.go. DO NOT EDIT.")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("// PktID represents a packet ID used in the minecraft protocol.")
|
||||||
|
fmt.Println("type PktID int32")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("// Valid PktID values.")
|
||||||
|
fmt.Println("const (")
|
||||||
|
|
||||||
|
fmt.Println(" // Clientbound packets for connections in the login state.")
|
||||||
|
for k, v := range pIDs.Login.Clientbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println(" // Serverbound packets for connections in the login state.")
|
||||||
|
for k, v := range pIDs.Login.Serverbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println(" // Clientbound packets for connections in the play state.")
|
||||||
|
for k, v := range pIDs.Play.Clientbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println(" // Serverbound packets for connections in the play state.")
|
||||||
|
for k, v := range pIDs.Play.Serverbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println(" // Clientbound packets used to respond to ping/status requests.")
|
||||||
|
for k, v := range pIDs.Status.Clientbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println(" // Serverbound packets used to ping or read server status.")
|
||||||
|
for k, v := range pIDs.Status.Serverbound {
|
||||||
|
fmt.Printf(" %s%s PktID = %s\n", k, strings.Repeat(" ", maxLen-len(k)), v)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println(")")
|
||||||
|
}
|
@ -1,156 +1,173 @@
|
|||||||
package data
|
package data
|
||||||
|
|
||||||
// Clientbound packet IDs
|
//go:generate bash -c "go run gen_packetIDs.go > packetIDs.go"
|
||||||
|
|
||||||
|
// This file is automatically generated by gen_packetIDs.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
// PktID represents a packet ID used in the minecraft protocol.
|
||||||
|
type PktID int32
|
||||||
|
|
||||||
|
// Valid PktID values.
|
||||||
const (
|
const (
|
||||||
SpawnObject int32 = iota //0x00
|
// Clientbound packets for connections in the login state.
|
||||||
SpawnExperienceOrb
|
EncryptionBeginClientbound PktID = 0x01
|
||||||
SpawnLivingEntity
|
Success PktID = 0x02
|
||||||
SpawnPainting
|
Compress PktID = 0x03
|
||||||
SpawnPlayer
|
LoginPluginRequest PktID = 0x04
|
||||||
EntityAnimationClientbound
|
Disconnect PktID = 0x00
|
||||||
Statistics
|
// Serverbound packets for connections in the login state.
|
||||||
AcknowledgePlayerDigging
|
EncryptionBeginServerbound PktID = 0x01
|
||||||
BlockBreakAnimation
|
LoginPluginResponse PktID = 0x02
|
||||||
BlockEntityData
|
LoginStart PktID = 0x00
|
||||||
BlockAction
|
|
||||||
BlockChange
|
|
||||||
BossBar
|
|
||||||
ServerDifficulty
|
|
||||||
ChatMessageClientbound
|
|
||||||
TabComplete
|
|
||||||
|
|
||||||
DeclareCommands //0x10
|
// Clientbound packets for connections in the play state.
|
||||||
WindowConfirmationClientbound
|
EntityMetadata PktID = 0x44
|
||||||
CloseWindowClientbound
|
Teams PktID = 0x4c
|
||||||
WindowItems
|
BossBar PktID = 0x0c
|
||||||
WindowProperty
|
Map PktID = 0x25
|
||||||
SetSlot
|
Difficulty PktID = 0x0d
|
||||||
SetCooldown
|
Camera PktID = 0x3e
|
||||||
PluginMessageClientbound
|
WindowItems PktID = 0x13
|
||||||
NamedSoundEffect
|
ScoreboardObjective PktID = 0x4a
|
||||||
DisconnectPlay
|
RelEntityMove PktID = 0x27
|
||||||
EntityStatus
|
DeclareCommands PktID = 0x10
|
||||||
Explosion
|
CombatEvent PktID = 0x31
|
||||||
UnloadChunk
|
SpawnEntityPainting PktID = 0x03
|
||||||
ChangeGameState
|
EntityMoveLook PktID = 0x28
|
||||||
OpenHorseWindow
|
ScoreboardScore PktID = 0x4d
|
||||||
KeepAliveClientbound
|
Title PktID = 0x4f
|
||||||
|
CraftProgressBar PktID = 0x14
|
||||||
|
NamedEntitySpawn PktID = 0x04
|
||||||
|
ScoreboardDisplayObjective PktID = 0x43
|
||||||
|
WorldParticles PktID = 0x22
|
||||||
|
OpenWindow PktID = 0x2d
|
||||||
|
MultiBlockChange PktID = 0x3b
|
||||||
|
EntitySoundEffect PktID = 0x50
|
||||||
|
Tags PktID = 0x5b
|
||||||
|
EntityUpdateAttributes PktID = 0x58
|
||||||
|
NamedSoundEffect PktID = 0x18
|
||||||
|
GameStateChange PktID = 0x1d
|
||||||
|
PlayerInfo PktID = 0x32
|
||||||
|
Advancements PktID = 0x57
|
||||||
|
Explosion PktID = 0x1b
|
||||||
|
KeepAliveClientbound PktID = 0x1f
|
||||||
|
MapChunk PktID = 0x20
|
||||||
|
AttachEntity PktID = 0x45
|
||||||
|
TradeList PktID = 0x26
|
||||||
|
Respawn PktID = 0x39
|
||||||
|
EntityDestroy PktID = 0x36
|
||||||
|
Experience PktID = 0x48
|
||||||
|
EntityLook PktID = 0x29
|
||||||
|
OpenBook PktID = 0x2c
|
||||||
|
WorldEvent PktID = 0x21
|
||||||
|
DeclareRecipes PktID = 0x5a
|
||||||
|
UnlockRecipes PktID = 0x35
|
||||||
|
EntityEquipment PktID = 0x47
|
||||||
|
EntityVelocity PktID = 0x46
|
||||||
|
Animation PktID = 0x05
|
||||||
|
UpdateViewDistance PktID = 0x41
|
||||||
|
HeldItemSlotClientbound PktID = 0x3f
|
||||||
|
NbtQueryResponse PktID = 0x54
|
||||||
|
Entity PktID = 0x2a
|
||||||
|
UpdateViewPosition PktID = 0x40
|
||||||
|
AbilitiesClientbound PktID = 0x30
|
||||||
|
OpenSignEntity PktID = 0x2e
|
||||||
|
SetSlot PktID = 0x15
|
||||||
|
PlayerlistHeader PktID = 0x53
|
||||||
|
ResourcePackSend PktID = 0x38
|
||||||
|
SpawnEntityExperienceOrb PktID = 0x01
|
||||||
|
Collect PktID = 0x55
|
||||||
|
Statistics PktID = 0x06
|
||||||
|
TileEntityData PktID = 0x09
|
||||||
|
ChatClientbound PktID = 0x0e
|
||||||
|
WorldBorder PktID = 0x3d
|
||||||
|
UnloadChunk PktID = 0x1c
|
||||||
|
UpdateLight PktID = 0x23
|
||||||
|
UpdateHealth PktID = 0x49
|
||||||
|
RemoveEntityEffect PktID = 0x37
|
||||||
|
KickDisconnect PktID = 0x19
|
||||||
|
CustomPayloadClientbound PktID = 0x17
|
||||||
|
SpawnPosition PktID = 0x42
|
||||||
|
EntityStatus PktID = 0x1a
|
||||||
|
SpawnEntity PktID = 0x00
|
||||||
|
SetPassengers PktID = 0x4b
|
||||||
|
FacePlayer PktID = 0x33
|
||||||
|
TransactionClientbound PktID = 0x11
|
||||||
|
BlockAction PktID = 0x0a
|
||||||
|
BlockBreakAnimation PktID = 0x08
|
||||||
|
BlockChange PktID = 0x0b
|
||||||
|
Login PktID = 0x24
|
||||||
|
VehicleMoveClientbound PktID = 0x2b
|
||||||
|
CraftRecipeResponse PktID = 0x2f
|
||||||
|
SetCooldown PktID = 0x16
|
||||||
|
StopSound PktID = 0x52
|
||||||
|
EntityEffect PktID = 0x59
|
||||||
|
CloseWindowClientbound PktID = 0x12
|
||||||
|
AcknowledgePlayerDigging PktID = 0x07
|
||||||
|
SelectAdvancementTab PktID = 0x3c
|
||||||
|
EntityHeadRotation PktID = 0x3a
|
||||||
|
TabCompleteClientbound PktID = 0x0f
|
||||||
|
PositionClientbound PktID = 0x34
|
||||||
|
OpenHorseWindow PktID = 0x1e
|
||||||
|
UpdateTime PktID = 0x4e
|
||||||
|
SpawnEntityLiving PktID = 0x02
|
||||||
|
EntityTeleport PktID = 0x56
|
||||||
|
SoundEffect PktID = 0x51
|
||||||
|
// Serverbound packets for connections in the play state.
|
||||||
|
SetBeaconEffect PktID = 0x24
|
||||||
|
UpdateStructureBlock PktID = 0x2a
|
||||||
|
EnchantItem PktID = 0x08
|
||||||
|
Spectate PktID = 0x2d
|
||||||
|
ArmAnimation PktID = 0x2c
|
||||||
|
QueryEntityNbt PktID = 0x0d
|
||||||
|
Flying PktID = 0x15
|
||||||
|
ResourcePackReceive PktID = 0x21
|
||||||
|
BlockDig PktID = 0x1b
|
||||||
|
AbilitiesServerbound PktID = 0x1a
|
||||||
|
SelectTrade PktID = 0x23
|
||||||
|
UpdateJigsawBlock PktID = 0x29
|
||||||
|
SteerVehicle PktID = 0x1d
|
||||||
|
Settings PktID = 0x05
|
||||||
|
SteerBoat PktID = 0x17
|
||||||
|
UseItem PktID = 0x2f
|
||||||
|
TeleportConfirm PktID = 0x00
|
||||||
|
PickItem PktID = 0x18
|
||||||
|
CraftRecipeRequest PktID = 0x19
|
||||||
|
Look PktID = 0x14
|
||||||
|
TabCompleteServerbound PktID = 0x06
|
||||||
|
AdvancementTab PktID = 0x22
|
||||||
|
ClientCommand PktID = 0x04
|
||||||
|
EntityAction PktID = 0x1c
|
||||||
|
PositionServerbound PktID = 0x12
|
||||||
|
TransactionServerbound PktID = 0x07
|
||||||
|
UpdateSign PktID = 0x2b
|
||||||
|
QueryBlockNbt PktID = 0x01
|
||||||
|
PositionLook PktID = 0x13
|
||||||
|
HeldItemSlotServerbound PktID = 0x25
|
||||||
|
EditBook PktID = 0x0c
|
||||||
|
UpdateCommandBlock PktID = 0x26
|
||||||
|
UseEntity PktID = 0x0e
|
||||||
|
GenerateStructure PktID = 0x0f
|
||||||
|
NameItem PktID = 0x20
|
||||||
|
RecipeBook PktID = 0x1f
|
||||||
|
KeepAliveServerbound PktID = 0x10
|
||||||
|
CustomPayloadServerbound PktID = 0x0b
|
||||||
|
VehicleMoveServerbound PktID = 0x16
|
||||||
|
CloseWindowServerbound PktID = 0x0a
|
||||||
|
UpdateCommandBlockMinecart PktID = 0x27
|
||||||
|
WindowClick PktID = 0x09
|
||||||
|
ChatServerbound PktID = 0x03
|
||||||
|
SetCreativeSlot PktID = 0x28
|
||||||
|
DisplayedRecipe PktID = 0x1e
|
||||||
|
BlockPlace PktID = 0x2e
|
||||||
|
LockDifficulty PktID = 0x11
|
||||||
|
SetDifficulty PktID = 0x02
|
||||||
|
|
||||||
ChunkData //0x20
|
// Clientbound packets used to respond to ping/status requests.
|
||||||
Effect
|
ServerInfo PktID = 0x00
|
||||||
Particle
|
PingClientbound PktID = 0x01
|
||||||
UpdateLight
|
// Serverbound packets used to ping or read server status.
|
||||||
JoinGame
|
PingStart PktID = 0x00
|
||||||
MapData
|
PingServerbound PktID = 0x01
|
||||||
TradeList
|
|
||||||
EntityRelativeMove
|
|
||||||
EntityLookAndRelativeMove
|
|
||||||
EntityLook
|
|
||||||
Entity
|
|
||||||
VehicleMoveClientbound
|
|
||||||
OpenBook
|
|
||||||
OpenWindow
|
|
||||||
OpenSignEditor
|
|
||||||
CraftRecipeResponse
|
|
||||||
|
|
||||||
PlayerAbilitiesClientbound //0x30
|
|
||||||
CombatEvent
|
|
||||||
PlayerInfo
|
|
||||||
FacePlayer
|
|
||||||
PlayerPositionAndLookClientbound
|
|
||||||
UnlockRecipes
|
|
||||||
DestroyEntities
|
|
||||||
RemoveEntityEffect
|
|
||||||
ResourcePackSend
|
|
||||||
Respawn
|
|
||||||
EntityHeadLook
|
|
||||||
MultiBlockChange
|
|
||||||
SelectAdvancementTab
|
|
||||||
WorldBorder
|
|
||||||
Camera
|
|
||||||
HeldItemChangeClientbound
|
|
||||||
|
|
||||||
UpdateViewPosition //0x40
|
|
||||||
UpdateViewDistance
|
|
||||||
SpawnPosition
|
|
||||||
DisplayScoreboard
|
|
||||||
EntityMetadata
|
|
||||||
AttachEntity
|
|
||||||
EntityVelocity
|
|
||||||
EntityEquipment
|
|
||||||
SetExperience
|
|
||||||
UpdateHealth
|
|
||||||
ScoreboardObjective
|
|
||||||
SetPassengers
|
|
||||||
Teams
|
|
||||||
UpdateScore
|
|
||||||
TimeUpdate
|
|
||||||
Title
|
|
||||||
|
|
||||||
EntitySoundEffect //0x50
|
|
||||||
SoundEffect
|
|
||||||
StopSound
|
|
||||||
PlayerListHeaderAndFooter
|
|
||||||
NBTQueryResponse
|
|
||||||
CollectItem
|
|
||||||
EntityTeleport
|
|
||||||
Advancements
|
|
||||||
EntityProperties
|
|
||||||
EntityEffect
|
|
||||||
DeclareRecipes
|
|
||||||
Tags //0x5B
|
|
||||||
)
|
|
||||||
|
|
||||||
// Serverbound packet IDs
|
|
||||||
const (
|
|
||||||
TeleportConfirm int32 = iota //0x00
|
|
||||||
QueryBlockNBT
|
|
||||||
SetDifficulty
|
|
||||||
ChatMessageServerbound
|
|
||||||
ClientStatus
|
|
||||||
ClientSettings
|
|
||||||
TabCompleteServerbound
|
|
||||||
ConfirmTransactionServerbound
|
|
||||||
ClickWindowButton
|
|
||||||
ClickWindow
|
|
||||||
CloseWindowServerbound
|
|
||||||
PluginMessageServerbound
|
|
||||||
EditBook
|
|
||||||
QueryEntityNBT
|
|
||||||
UseEntity
|
|
||||||
GenerateStructure
|
|
||||||
|
|
||||||
KeepAliveServerbound //0x10
|
|
||||||
LockDifficulty
|
|
||||||
PlayerPosition
|
|
||||||
PlayerPositionAndLookServerbound
|
|
||||||
PlayerLook
|
|
||||||
Player
|
|
||||||
VehicleMoveServerbound
|
|
||||||
SteerBoat
|
|
||||||
PickItem
|
|
||||||
CraftRecipeRequest
|
|
||||||
PlayerAbilitiesServerbound
|
|
||||||
PlayerDigging
|
|
||||||
EntityAction
|
|
||||||
SteerVehicle
|
|
||||||
DisplayedRecipe
|
|
||||||
RecipeBookData
|
|
||||||
|
|
||||||
NameItem //0x20
|
|
||||||
ResourcePackStatus
|
|
||||||
AdvancementTab
|
|
||||||
SelectTrade
|
|
||||||
SetBeaconEffect
|
|
||||||
HeldItemChangeServerbound
|
|
||||||
UpdateCommandBlock
|
|
||||||
UpdateCommandBlockMinecart
|
|
||||||
CreativeInventoryAction
|
|
||||||
UpdateJigsawBlock
|
|
||||||
UpdateStructureBlock
|
|
||||||
UpdateSign
|
|
||||||
AnimationServerbound
|
|
||||||
Spectate
|
|
||||||
PlayerBlockPlacement
|
|
||||||
UseItem //0x2F
|
|
||||||
)
|
)
|
||||||
|
5
go.mod
5
go.mod
@ -2,4 +2,7 @@ module github.com/Tnze/go-mc
|
|||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/google/uuid v1.1.1
|
require (
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
|
github.com/iancoleman/strcase v0.1.1 // indirect
|
||||||
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -1,2 +1,4 @@
|
|||||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/iancoleman/strcase v0.1.1 h1:2I+LRClyCYB7JgZb9U0k75VHUiQe9RfknRqDyUfzp7k=
|
||||||
|
github.com/iancoleman/strcase v0.1.1/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
|
||||||
|
@ -5,6 +5,8 @@ import (
|
|||||||
"compress/zlib"
|
"compress/zlib"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Packet define a net data package
|
// Packet define a net data package
|
||||||
@ -14,8 +16,8 @@ type Packet struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Marshal generate Packet with the ID and Fields
|
//Marshal generate Packet with the ID and Fields
|
||||||
func Marshal(ID int32, fields ...FieldEncoder) (pk Packet) {
|
func Marshal(id data.PktID, fields ...FieldEncoder) (pk Packet) {
|
||||||
pk.ID = ID
|
pk.ID = int32(id)
|
||||||
|
|
||||||
for _, v := range fields {
|
for _, v := range fields {
|
||||||
pk.Data = append(pk.Data, v.Encode()...)
|
pk.Data = append(pk.Data, v.Encode()...)
|
||||||
|
Reference in New Issue
Block a user