configuration protocol support draft

This commit is contained in:
Tnze
2023-11-19 02:10:15 +08:00
parent 61916db07a
commit 006f958f43
9 changed files with 184 additions and 106 deletions

67
bot/configuration.go Normal file
View File

@ -0,0 +1,67 @@
package bot
import (
"github.com/Tnze/go-mc/data/packetid"
"github.com/Tnze/go-mc/nbt"
"github.com/Tnze/go-mc/net"
pk "github.com/Tnze/go-mc/net/packet"
)
func (c *Client) joinConfiguration(conn *net.Conn) error {
receiving := "config custom payload"
for {
var p pk.Packet
if err := conn.ReadPacket(&p); err != nil {
return LoginErr{receiving, err}
}
switch packetid.ClientboundPacketID(p.ID) {
case packetid.ClientboundConfigCustomPayload:
var channel pk.Identifier
var data pk.PluginMessageData
err := p.Scan(&channel, &data)
if err != nil {
return LoginErr{"custom payload", err}
}
// TODO: Provide configuration custom data handling interface
case packetid.ClientboundConfigDisconnect:
case packetid.ClientboundConfigFinishConfiguration:
err := conn.WritePacket(pk.Marshal(
packetid.ServerboundConfigFinishConfiguration,
))
if err != nil {
return LoginErr{"finish config", err}
}
return nil
case packetid.ClientboundConfigKeepAlive:
var keepAliveID pk.Long
err := p.Scan(&keepAliveID)
if err != nil {
return LoginErr{"keep alive", err}
}
// send it back
err = conn.WritePacket(pk.Marshal(
packetid.ServerboundConfigKeepAlive,
keepAliveID,
))
if err != nil {
return LoginErr{"keep alive", err}
}
case packetid.ClientboundConfigPing:
case packetid.ClientboundConfigRegistryData:
var registryCodec nbt.RawMessage
err := p.Scan(pk.NBT(&registryCodec))
if err != nil {
return LoginErr{"registry data", err}
}
// TODO: Handle registries
case packetid.ClientboundConfigResourcePack:
case packetid.ClientboundConfigUpdateEnabledFeatures:
case packetid.ClientboundConfigUpdateTags:
}
}
}

View File

@ -15,12 +15,106 @@ import (
"net/http"
"strings"
"github.com/google/uuid"
"github.com/Tnze/go-mc/chat"
"github.com/Tnze/go-mc/data/packetid"
"github.com/Tnze/go-mc/net"
"github.com/Tnze/go-mc/net/CFB8"
pk "github.com/Tnze/go-mc/net/packet"
)
func (c *Client) joinLogin(conn *net.Conn) error {
var err error
if c.Auth.UUID != "" {
c.UUID, err = uuid.Parse(c.Auth.UUID)
if err != nil {
return LoginErr{"login start", err}
}
}
err = conn.WritePacket(pk.Marshal(
packetid.ServerboundLoginStart,
pk.String(c.Auth.Name),
pk.UUID(c.UUID),
))
if err != nil {
return LoginErr{"login start", err}
}
receiving := "encrypt start"
for {
// Receive Packet
var p pk.Packet
if err = conn.ReadPacket(&p); err != nil {
return LoginErr{receiving, err}
}
// Handle Packet
switch packetid.ClientboundPacketID(p.ID) {
case packetid.ClientboundLoginDisconnect: // LoginDisconnect
var reason chat.Message
err = p.Scan(&reason)
if err != nil {
return LoginErr{"disconnect", err}
}
return LoginErr{"disconnect", DisconnectErr(reason)}
case packetid.ClientboundLoginEncryptionRequest: // Encryption Request
if err := handleEncryptionRequest(conn, c, p); err != nil {
return LoginErr{"encryption", err}
}
receiving = "set compression"
case packetid.ClientboundLoginSuccess: // Login Success
err := p.Scan(
(*pk.UUID)(&c.UUID),
(*pk.String)(&c.Name),
)
if err != nil {
return LoginErr{"login success", err}
}
err = conn.WritePacket(pk.Marshal(packetid.ServerboundLoginAcknowledged))
if err != nil {
return LoginErr{"login success", err}
}
return nil
case packetid.ClientboundLoginCompression: // Set Compression
var threshold pk.VarInt
if err := p.Scan(&threshold); err != nil {
return LoginErr{"compression", err}
}
conn.SetThreshold(int(threshold))
receiving = "login success"
case packetid.ClientboundLoginPluginRequest: // Login Plugin Request
var (
msgid pk.VarInt
channel pk.Identifier
data pk.PluginMessageData
)
if err := p.Scan(&msgid, &channel, &data); err != nil {
return LoginErr{"Login Plugin", err}
}
var PluginMessageData pk.Option[pk.PluginMessageData, *pk.PluginMessageData]
if handler, ok := c.LoginPlugin[string(channel)]; ok {
PluginMessageData.Has = true
PluginMessageData.Val, err = handler(data)
if err != nil {
return LoginErr{"Login Plugin", err}
}
}
if err := conn.WritePacket(pk.Marshal(
packetid.ServerboundLoginPluginResponse,
msgid, PluginMessageData,
)); err != nil {
return LoginErr{"login Plugin", err}
}
}
}
}
// Auth includes an account
type Auth struct {
Name string
@ -196,7 +290,7 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte) (erp p
return erp, err
}
return pk.Marshal(
packetid.LoginEncryptionResponse,
packetid.ServerboundLoginEncryptionResponse,
pk.ByteArray(cryptPK),
pk.ByteArray(verifyT),
), nil

View File

@ -10,10 +10,7 @@ import (
"net"
"strconv"
"github.com/google/uuid"
"github.com/Tnze/go-mc/chat"
"github.com/Tnze/go-mc/data/packetid"
mcnet "github.com/Tnze/go-mc/net"
pk "github.com/Tnze/go-mc/net/packet"
"github.com/Tnze/go-mc/net/queue"
@ -22,7 +19,7 @@ import (
// ProtocolVersion is the protocol version number of minecraft net protocol
const (
ProtocolVersion = 763
ProtocolVersion = 764
DefaultPort = mcnet.DefaultPort
)
@ -110,90 +107,18 @@ func (c *Client) join(addr string, options JoinOptions) error {
if err != nil {
return LoginErr{"handshake", err}
}
// Login Start
c.UUID, err = uuid.Parse(c.Auth.UUID)
PlayerUUID := pk.Option[pk.UUID, *pk.UUID]{
Has: err == nil,
Val: pk.UUID(c.UUID),
if err := c.joinLogin(conn); err != nil {
return err
}
err = conn.WritePacket(pk.Marshal(
packetid.LoginStart,
pk.String(c.Auth.Name),
PlayerUUID,
))
if err != nil {
return LoginErr{"login start", err}
}
receiving := "encrypt start"
for {
// Receive Packet
var p pk.Packet
if err = conn.ReadPacket(&p); err != nil {
return LoginErr{receiving, err}
}
// Handle Packet
switch p.ID {
case packetid.LoginDisconnect: // LoginDisconnect
var reason chat.Message
err = p.Scan(&reason)
if err != nil {
return LoginErr{"disconnect", err}
}
return LoginErr{"disconnect", DisconnectErr(reason)}
case packetid.LoginEncryptionRequest: // Encryption Request
if err := handleEncryptionRequest(conn, c, p); err != nil {
return LoginErr{"encryption", err}
}
receiving = "set compression"
case packetid.LoginSuccess: // Login Success
err := p.Scan(
(*pk.UUID)(&c.UUID),
(*pk.String)(&c.Name),
)
if err != nil {
return LoginErr{"login success", err}
}
c.Conn = warpConn(conn, options.QueueRead, options.QueueWrite)
return nil
case packetid.LoginCompression: // Set Compression
var threshold pk.VarInt
if err := p.Scan(&threshold); err != nil {
return LoginErr{"compression", err}
}
conn.SetThreshold(int(threshold))
receiving = "login success"
case packetid.LoginPluginRequest: // Login Plugin Request
var (
msgid pk.VarInt
channel pk.Identifier
data pk.PluginMessageData
)
if err := p.Scan(&msgid, &channel, &data); err != nil {
return LoginErr{"Login Plugin", err}
}
var PluginMessageData pk.Option[pk.PluginMessageData, *pk.PluginMessageData]
if handler, ok := c.LoginPlugin[string(channel)]; ok {
PluginMessageData.Has = true
PluginMessageData.Val, err = handler(data)
if err != nil {
return LoginErr{"Login Plugin", err}
}
}
if err := conn.WritePacket(pk.Marshal(
packetid.LoginPluginResponse,
msgid, PluginMessageData,
)); err != nil {
return LoginErr{"login Plugin", err}
}
}
// Configuration
if err := c.joinConfiguration(conn); err != nil {
return err
}
c.Conn = warpConn(conn, options.QueueRead, options.QueueWrite)
return nil
}
type LoginErr struct {

View File

@ -94,7 +94,7 @@ func pingAndList(ctx context.Context, addr string, conn *mcnet.Conn) (data []byt
// LIST
// 请求服务器状态
err = conn.WritePacket(pk.Marshal(
packetid.StatusRequest,
packetid.ServerboundStatusRequest,
))
if err != nil {
return nil, 0, fmt.Errorf("bot: send list packect fail: %v", err)
@ -114,7 +114,7 @@ func pingAndList(ctx context.Context, addr string, conn *mcnet.Conn) (data []byt
// PING
startTime := time.Now()
err = conn.WritePacket(pk.Marshal(
packetid.StatusPingRequest,
packetid.ServerboundStatusPingRequest,
pk.Long(startTime.Unix()),
))
if err != nil {