update 1.19.2 bot, chat support
This commit is contained in:
@ -20,7 +20,7 @@
|
|||||||
// - HealthChange
|
// - HealthChange
|
||||||
// - Death
|
// - Death
|
||||||
//
|
//
|
||||||
// You must manully attach the [EventsListener] to the [Client] as needed.
|
// You must manually attach the [EventsListener] to the [Client] as needed.
|
||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -38,22 +38,23 @@ type Player struct {
|
|||||||
isSpawn bool
|
isSpawn bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer(c *bot.Client, settings Settings) *Player {
|
func NewPlayer(c *bot.Client, settings Settings, events EventsListener) *Player {
|
||||||
b := &Player{c: c, Settings: settings}
|
p := &Player{c: c, Settings: settings}
|
||||||
c.Events.AddListener(
|
c.Events.AddListener(
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundLogin, F: b.handleLoginPacket},
|
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundLogin, F: p.handleLoginPacket},
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundKeepAlive, F: b.handleKeepAlivePacket},
|
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundKeepAlive, F: p.handleKeepAlivePacket},
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundPlayerPosition, F: b.handlePlayerPosition},
|
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundPlayerPosition, F: p.handlePlayerPosition},
|
||||||
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundRespawn, F: b.handleRespawnPacket},
|
bot.PacketHandler{Priority: 0, ID: packetid.ClientboundRespawn, F: p.handleRespawnPacket},
|
||||||
)
|
)
|
||||||
return b
|
events.attach(p)
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Respawn() error {
|
func (p *Player) Respawn() error {
|
||||||
const PerformRespawn = 0
|
const PerformRespawn = 0
|
||||||
|
|
||||||
err := p.c.Conn.WritePacket(pk.Marshal(
|
err := p.c.Conn.WritePacket(pk.Marshal(
|
||||||
packetid.ServerboundClientCommand,
|
int32(packetid.ServerboundClientCommand),
|
||||||
pk.VarInt(PerformRespawn),
|
pk.VarInt(PerformRespawn),
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -5,35 +5,30 @@ import (
|
|||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
"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"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EventsListener struct {
|
type EventsListener struct {
|
||||||
GameStart func() error
|
GameStart func() error
|
||||||
ChatMsg func(c *PlayerMessage) error
|
|
||||||
SystemMsg func(c chat.Message, overlay bool) error
|
SystemMsg func(c chat.Message, overlay bool) error
|
||||||
Disconnect func(reason chat.Message) error
|
Disconnect func(reason chat.Message) error
|
||||||
HealthChange func(health float32) error
|
HealthChange func(health float32) error
|
||||||
Death func() error
|
Death func() error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach your event listener to the client.
|
// attach your event listener to the client.
|
||||||
// The functions are copied when attaching, and modify on [EventListener] doesn't affect after that.
|
// The functions are copied when attaching, and modify on [EventListener] doesn't affect after that.
|
||||||
func (e EventsListener) Attach(c *bot.Client) {
|
func (e EventsListener) attach(p *Player) {
|
||||||
if e.GameStart != nil {
|
if e.GameStart != nil {
|
||||||
attachJoinGameHandler(c, e.GameStart)
|
attachJoinGameHandler(p.c, e.GameStart)
|
||||||
}
|
|
||||||
if e.ChatMsg != nil {
|
|
||||||
attachPlayerMsg(c, e.ChatMsg)
|
|
||||||
}
|
}
|
||||||
if e.SystemMsg != nil {
|
if e.SystemMsg != nil {
|
||||||
attachSystemMsg(c, e.SystemMsg)
|
attachSystemMsg(p.c, e.SystemMsg)
|
||||||
}
|
}
|
||||||
if e.Disconnect != nil {
|
if e.Disconnect != nil {
|
||||||
attachDisconnect(c, e.Disconnect)
|
attachDisconnect(p.c, e.Disconnect)
|
||||||
}
|
}
|
||||||
if e.HealthChange != nil || e.Death != nil {
|
if e.HealthChange != nil || e.Death != nil {
|
||||||
attachUpdateHealth(c, e.HealthChange, e.Death)
|
attachUpdateHealth(p.c, e.HealthChange, e.Death)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,60 +41,6 @@ func attachJoinGameHandler(c *bot.Client, handler func() error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlayerMessage struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PlayerMessage) ReadFrom(r io.Reader) (n int64, err error) {
|
|
||||||
// SignedMessageHeader
|
|
||||||
// MessageSignature
|
|
||||||
// SignedMessageBody
|
|
||||||
// Optional<Component>
|
|
||||||
// FilterMask
|
|
||||||
panic("implement me")
|
|
||||||
}
|
|
||||||
|
|
||||||
type ChatType struct {
|
|
||||||
ID int32
|
|
||||||
Name chat.Message
|
|
||||||
TargetName *chat.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChatType) ReadFrom(r io.Reader) (n int64, err error) {
|
|
||||||
var hasTargetName pk.Boolean
|
|
||||||
n1, err := (*pk.VarInt)(&c.ID).ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return n1, err
|
|
||||||
}
|
|
||||||
n2, err := c.Name.ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return n1 + n2, err
|
|
||||||
}
|
|
||||||
n3, err := hasTargetName.ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return n1 + n2 + n3, err
|
|
||||||
}
|
|
||||||
if hasTargetName {
|
|
||||||
c.TargetName = new(chat.Message)
|
|
||||||
n4, err := c.TargetName.ReadFrom(r)
|
|
||||||
return n1 + n2 + n3 + n4, err
|
|
||||||
}
|
|
||||||
return n1 + n2 + n3, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func attachPlayerMsg(c *bot.Client, handler func(c *PlayerMessage) error) {
|
|
||||||
c.Events.AddListener(bot.PacketHandler{
|
|
||||||
Priority: 64, ID: packetid.ClientboundPlayerChat,
|
|
||||||
F: func(p pk.Packet) error {
|
|
||||||
var message PlayerMessage
|
|
||||||
var chatType ChatType
|
|
||||||
if err := p.Scan(&message, &chatType); err != nil {
|
|
||||||
return Error{err}
|
|
||||||
}
|
|
||||||
return handler(&message)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func attachSystemMsg(c *bot.Client, handler func(c chat.Message, overlay bool) error) {
|
func attachSystemMsg(c *bot.Client, handler func(c chat.Message, overlay bool) error) {
|
||||||
c.Events.AddListener(bot.PacketHandler{
|
c.Events.AddListener(bot.PacketHandler{
|
||||||
Priority: 64, ID: packetid.ClientboundSystemChat,
|
Priority: 64, ID: packetid.ClientboundSystemChat,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Tnze/go-mc/chat"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
@ -46,9 +47,14 @@ type Dimension struct {
|
|||||||
MonsterSpawnBlockLightLimit int32 `nbt:"monster_spawn_block_light_limit"`
|
MonsterSpawnBlockLightLimit int32 `nbt:"monster_spawn_block_light_limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChatType struct {
|
||||||
|
Chat chat.Decoration `nbt:"chat"`
|
||||||
|
Narration chat.Decoration `nbt:"narration"`
|
||||||
|
}
|
||||||
|
|
||||||
type RegistryCodec struct {
|
type RegistryCodec struct {
|
||||||
// What is Below? (wiki.vg)
|
// What is Below? (wiki.vg)
|
||||||
ChatType Registry[nbt.RawMessage] `nbt:"minecraft:chat_type"`
|
ChatType Registry[ChatType] `nbt:"minecraft:chat_type"`
|
||||||
DimensionType Registry[Dimension] `nbt:"minecraft:dimension_type"`
|
DimensionType Registry[Dimension] `nbt:"minecraft:dimension_type"`
|
||||||
WorldGenBiome Registry[nbt.RawMessage] `nbt:"minecraft:worldgen/biome"`
|
WorldGenBiome Registry[nbt.RawMessage] `nbt:"minecraft:worldgen/biome"`
|
||||||
}
|
}
|
||||||
@ -71,6 +77,18 @@ func (r *Registry[E]) Find(name string) *E {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Registry[E]) FindByID(id int32) *E {
|
||||||
|
if id >= 0 && id < int32(len(r.Value)) && r.Value[id].ID == id {
|
||||||
|
return &r.Value[id].Element
|
||||||
|
}
|
||||||
|
for i := range r.Value {
|
||||||
|
if r.Value[i].ID == id {
|
||||||
|
return &r.Value[i].Element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type PlayerInfo struct {
|
type PlayerInfo struct {
|
||||||
EID int32 // The player's Entity ID (EID).
|
EID int32 // The player's Entity ID (EID).
|
||||||
Hardcore bool // Is hardcore
|
Hardcore bool // Is hardcore
|
||||||
@ -106,7 +124,7 @@ func (p *Player) handleLoginPacket(packet pk.Packet) error {
|
|||||||
return Error{err}
|
return Error{err}
|
||||||
}
|
}
|
||||||
err = p.c.Conn.WritePacket(pk.Marshal( //PluginMessage packet
|
err = p.c.Conn.WritePacket(pk.Marshal( //PluginMessage packet
|
||||||
packetid.ServerboundCustomPayload,
|
int32(packetid.ServerboundCustomPayload),
|
||||||
pk.Identifier("minecraft:brand"),
|
pk.Identifier("minecraft:brand"),
|
||||||
pk.String(p.Settings.Brand),
|
pk.String(p.Settings.Brand),
|
||||||
))
|
))
|
||||||
@ -115,7 +133,7 @@ func (p *Player) handleLoginPacket(packet pk.Packet) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = p.c.Conn.WritePacket(pk.Marshal(
|
err = p.c.Conn.WritePacket(pk.Marshal(
|
||||||
packetid.ServerboundClientInformation, // Client settings
|
int32(packetid.ServerboundClientInformation), // Client settings
|
||||||
pk.String(p.Settings.Locale),
|
pk.String(p.Settings.Locale),
|
||||||
pk.Byte(p.Settings.ViewDistance),
|
pk.Byte(p.Settings.ViewDistance),
|
||||||
pk.VarInt(p.Settings.ChatMode),
|
pk.VarInt(p.Settings.ChatMode),
|
||||||
|
@ -12,7 +12,7 @@ func (p Player) handleKeepAlivePacket(packet pk.Packet) error {
|
|||||||
}
|
}
|
||||||
// Response
|
// Response
|
||||||
err := p.c.Conn.WritePacket(pk.Packet{
|
err := p.c.Conn.WritePacket(pk.Packet{
|
||||||
ID: packetid.ServerboundKeepAlive,
|
ID: int32(packetid.ServerboundKeepAlive),
|
||||||
Data: packet.Data,
|
Data: packet.Data,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
168
bot/chat/chat.go
Normal file
168
bot/chat/chat.go
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package chat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/bot"
|
||||||
|
"github.com/Tnze/go-mc/bot/basic"
|
||||||
|
"github.com/Tnze/go-mc/chat"
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Chat struct {
|
||||||
|
c *bot.Client
|
||||||
|
p *basic.Player
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewChat(c *bot.Client, p *basic.Player, events EventsHandler) *Chat {
|
||||||
|
attachPlayerMsg(c, p, events.PlayerChatMessage)
|
||||||
|
return &Chat{c, p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func attachPlayerMsg(c *bot.Client, p *basic.Player, handler func(msg chat.Message) error) {
|
||||||
|
c.Events.AddListener(bot.PacketHandler{
|
||||||
|
Priority: 64, ID: packetid.ClientboundPlayerChat,
|
||||||
|
F: func(packet pk.Packet) error {
|
||||||
|
var message PlayerMessage
|
||||||
|
if err := packet.Scan(&message); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var content chat.Message
|
||||||
|
if message.content.formatted != nil {
|
||||||
|
content = *message.content.formatted
|
||||||
|
} else {
|
||||||
|
content = chat.Text(message.content.plainMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
ct := p.WorldInfo.RegistryCodec.ChatType.FindByID(message.chatType.ID)
|
||||||
|
if ct == nil {
|
||||||
|
return fmt.Errorf("chat type %d not found", message.chatType.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := (*chat.Type)(&message.chatType).Decorate(content, &ct.Chat)
|
||||||
|
return handler(msg)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlayerMessage struct {
|
||||||
|
// SignedMessageHeader
|
||||||
|
signature []byte
|
||||||
|
sender uuid.UUID
|
||||||
|
// MessageSignature
|
||||||
|
msgSignature []byte
|
||||||
|
// SignedMessageBody
|
||||||
|
content msgContent
|
||||||
|
timestamp time.Time
|
||||||
|
salt int64
|
||||||
|
prevMessages []prevMsg
|
||||||
|
// Optional<Component>
|
||||||
|
unsignedContent *chat.Message
|
||||||
|
// FilterMask
|
||||||
|
filterType int32
|
||||||
|
filterSet pk.BitSet
|
||||||
|
// ChatType
|
||||||
|
chatType chatType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PlayerMessage) String() string {
|
||||||
|
return p.content.plainMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PlayerMessage) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
var hasMsgSign, hasUnsignedContent pk.Boolean
|
||||||
|
var timestamp pk.Long
|
||||||
|
var unsignedContent chat.Message
|
||||||
|
n, err = pk.Tuple{
|
||||||
|
&hasMsgSign, pk.Opt{Has: &hasMsgSign,
|
||||||
|
Field: (*pk.ByteArray)(&p.signature),
|
||||||
|
},
|
||||||
|
(*pk.UUID)(&p.sender),
|
||||||
|
(*pk.ByteArray)(&p.msgSignature),
|
||||||
|
&p.content,
|
||||||
|
×tamp,
|
||||||
|
(*pk.Long)(&p.salt),
|
||||||
|
pk.Array(&p.prevMessages),
|
||||||
|
&hasUnsignedContent, pk.Opt{Has: &hasUnsignedContent,
|
||||||
|
Field: &unsignedContent,
|
||||||
|
},
|
||||||
|
(*pk.VarInt)(&p.filterType),
|
||||||
|
pk.Opt{
|
||||||
|
Has: func() bool { return p.filterType == 2 },
|
||||||
|
Field: &p.filterSet,
|
||||||
|
},
|
||||||
|
&p.chatType,
|
||||||
|
}.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.timestamp = time.UnixMilli(int64(timestamp))
|
||||||
|
if hasUnsignedContent {
|
||||||
|
p.unsignedContent = &unsignedContent
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type msgContent struct {
|
||||||
|
plainMsg string
|
||||||
|
formatted *chat.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *msgContent) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
var hasFormatted pk.Boolean
|
||||||
|
n1, err := (*pk.String)(&m.plainMsg).ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n1, err
|
||||||
|
}
|
||||||
|
n2, err := hasFormatted.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n1 + n2, err
|
||||||
|
}
|
||||||
|
if hasFormatted {
|
||||||
|
m.formatted = new(chat.Message)
|
||||||
|
n3, err := m.formatted.ReadFrom(r)
|
||||||
|
return n1 + n2 + n3, err
|
||||||
|
}
|
||||||
|
return n1 + n2, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type prevMsg struct {
|
||||||
|
sender uuid.UUID
|
||||||
|
signature []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prevMsg) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
return pk.Tuple{
|
||||||
|
(*pk.UUID)(&p.sender),
|
||||||
|
(*pk.ByteArray)(&p.signature),
|
||||||
|
}.ReadFrom(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
type chatType chat.Type
|
||||||
|
|
||||||
|
func (c *chatType) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
|
var hasTargetName pk.Boolean
|
||||||
|
n1, err := (*pk.VarInt)(&c.ID).ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n1, err
|
||||||
|
}
|
||||||
|
n2, err := c.SenderName.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n1 + n2, err
|
||||||
|
}
|
||||||
|
n3, err := hasTargetName.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n1 + n2 + n3, err
|
||||||
|
}
|
||||||
|
if hasTargetName {
|
||||||
|
c.TargetName = new(chat.Message)
|
||||||
|
n4, err := c.TargetName.ReadFrom(r)
|
||||||
|
return n1 + n2 + n3 + n4, err
|
||||||
|
}
|
||||||
|
return n1 + n2 + n3, nil
|
||||||
|
}
|
7
bot/chat/events.go
Normal file
7
bot/chat/events.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package chat
|
||||||
|
|
||||||
|
import "github.com/Tnze/go-mc/chat"
|
||||||
|
|
||||||
|
type EventsHandler struct {
|
||||||
|
PlayerChatMessage func(msg chat.Message) error
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
"github.com/Tnze/go-mc/net"
|
"github.com/Tnze/go-mc/net"
|
||||||
"github.com/Tnze/go-mc/yggdrasil/user"
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -33,7 +34,7 @@ func (c *Client) Close() error {
|
|||||||
func NewClient() *Client {
|
func NewClient() *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
Auth: Auth{Name: "Steve"},
|
Auth: Auth{Name: "Steve"},
|
||||||
Events: Events{handlers: make(map[int32]*handlerHeap)},
|
Events: Events{handlers: make(map[packetid.ClientboundPacketID]*handlerHeap)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package bot
|
package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Events struct {
|
type Events struct {
|
||||||
generic *handlerHeap // for every packet
|
generic *handlerHeap // for every packet
|
||||||
handlers map[int32]*handlerHeap // for specific packet id only
|
handlers map[packetid.ClientboundPacketID]*handlerHeap // for specific packet id only
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Events) AddListener(listeners ...PacketHandler) {
|
func (e *Events) AddListener(listeners ...PacketHandler) {
|
||||||
@ -36,7 +37,7 @@ func (e *Events) AddGeneric(listeners ...PacketHandler) {
|
|||||||
|
|
||||||
type PacketHandlerFunc func(p pk.Packet) error
|
type PacketHandlerFunc func(p pk.Packet) error
|
||||||
type PacketHandler struct {
|
type PacketHandler struct {
|
||||||
ID int32
|
ID packetid.ClientboundPacketID
|
||||||
Priority int
|
Priority int
|
||||||
F func(p pk.Packet) error
|
F func(p pk.Packet) error
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package bot
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,12 +26,12 @@ func (c *Client) HandleGame() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PacketHandlerError struct {
|
type PacketHandlerError struct {
|
||||||
ID int32
|
ID packetid.ClientboundPacketID
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d PacketHandlerError) Error() string {
|
func (d PacketHandlerError) Error() string {
|
||||||
return fmt.Sprintf("handle packet 0x%X error: %v", d.ID, d.Err)
|
return fmt.Sprintf("handle packet %v error: %v", d.ID, d.Err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d PacketHandlerError) Unwrap() error {
|
func (d PacketHandlerError) Unwrap() error {
|
||||||
@ -37,18 +39,19 @@ func (d PacketHandlerError) Unwrap() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) handlePacket(p pk.Packet) (err error) {
|
func (c *Client) handlePacket(p pk.Packet) (err error) {
|
||||||
|
packetID := packetid.ClientboundPacketID(p.ID)
|
||||||
if c.Events.generic != nil {
|
if c.Events.generic != nil {
|
||||||
for _, handler := range *c.Events.generic {
|
for _, handler := range *c.Events.generic {
|
||||||
if err = handler.F(p); err != nil {
|
if err = handler.F(p); err != nil {
|
||||||
return PacketHandlerError{ID: p.ID, Err: err}
|
return PacketHandlerError{ID: packetID, Err: err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if listeners := c.Events.handlers[p.ID]; listeners != nil {
|
if listeners := c.Events.handlers[packetID]; listeners != nil {
|
||||||
for _, handler := range *listeners {
|
for _, handler := range *listeners {
|
||||||
err = handler.F(p)
|
err = handler.F(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PacketHandlerError{ID: p.ID, Err: err}
|
return PacketHandlerError{ID: packetID, Err: err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
chat/decoration.go
Normal file
51
chat/decoration.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package chat
|
||||||
|
|
||||||
|
type Decoration struct {
|
||||||
|
TranslationKey string `nbt:"translation_key"`
|
||||||
|
Parameters []string `nbt:"parameters"`
|
||||||
|
Style struct {
|
||||||
|
Bold bool `nbt:"bold"`
|
||||||
|
Italic bool `nbt:"italic"`
|
||||||
|
UnderLined bool `nbt:"underlined"`
|
||||||
|
StrikeThrough bool `nbt:"strikethrough"`
|
||||||
|
Obfuscated bool `nbt:"obfuscated"`
|
||||||
|
Color string `nbt:"color"`
|
||||||
|
Insertion string `nbt:"insertion"`
|
||||||
|
Font string `nbt:"font"`
|
||||||
|
} `nbt:"style"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
ID int32
|
||||||
|
SenderName Message
|
||||||
|
TargetName *Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) Decorate(content Message, d *Decoration) (msg Message) {
|
||||||
|
with := make([]Message, len(d.Parameters))
|
||||||
|
for i, para := range d.Parameters {
|
||||||
|
switch para {
|
||||||
|
case "sender":
|
||||||
|
with[i] = t.SenderName
|
||||||
|
case "target":
|
||||||
|
with[i] = *t.TargetName
|
||||||
|
case "content":
|
||||||
|
with[i] = content
|
||||||
|
default:
|
||||||
|
with[i] = Text("<nil>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Message{
|
||||||
|
Translate: d.TranslationKey,
|
||||||
|
With: with,
|
||||||
|
|
||||||
|
Bold: d.Style.Bold,
|
||||||
|
Italic: d.Style.Italic,
|
||||||
|
UnderLined: d.Style.UnderLined,
|
||||||
|
StrikeThrough: d.Style.StrikeThrough,
|
||||||
|
Obfuscated: d.Style.Obfuscated,
|
||||||
|
Font: d.Style.Font,
|
||||||
|
Color: d.Style.Color,
|
||||||
|
Insertion: d.Style.Insertion,
|
||||||
|
}
|
||||||
|
}
|
@ -22,10 +22,8 @@ import (
|
|||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Type int32
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Chat Type = iota
|
Chat = iota
|
||||||
System
|
System
|
||||||
GameInfo
|
GameInfo
|
||||||
SayCommand
|
SayCommand
|
||||||
@ -77,7 +75,7 @@ type Message struct {
|
|||||||
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"`
|
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"`
|
||||||
|
|
||||||
Translate string `json:"translate,omitempty"`
|
Translate string `json:"translate,omitempty"`
|
||||||
With []json.RawMessage `json:"with,omitempty"`
|
With []Message `json:"with,omitempty"`
|
||||||
Extra []Message `json:"extra,omitempty"`
|
Extra []Message `json:"extra,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +97,7 @@ type translateMsg struct {
|
|||||||
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"`
|
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"`
|
||||||
|
|
||||||
Translate string `json:"translate"`
|
Translate string `json:"translate"`
|
||||||
With []json.RawMessage `json:"with,omitempty"`
|
With []Message `json:"with,omitempty"`
|
||||||
Extra []Message `json:"extra,omitempty"`
|
Extra []Message `json:"extra,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,10 +178,7 @@ func Text(str string) Message {
|
|||||||
|
|
||||||
func TranslateMsg(key string, with ...Message) (m Message) {
|
func TranslateMsg(key string, with ...Message) (m Message) {
|
||||||
m.Translate = key
|
m.Translate = key
|
||||||
m.With = make([]json.RawMessage, len(with))
|
m.With = with
|
||||||
for i, v := range with {
|
|
||||||
m.With[i], _ = json.Marshal(v)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,9 +245,7 @@ func (m Message) ClearString() string {
|
|||||||
if m.Translate != "" {
|
if m.Translate != "" {
|
||||||
args := make([]interface{}, len(m.With))
|
args := make([]interface{}, len(m.With))
|
||||||
for i, v := range m.With {
|
for i, v := range m.With {
|
||||||
var arg Message
|
args[i] = v.ClearString()
|
||||||
_ = arg.UnmarshalJSON(v) //ignore error
|
|
||||||
args[i] = arg.ClearString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...)
|
_, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...)
|
||||||
@ -297,9 +290,7 @@ func (m Message) String() string {
|
|||||||
if m.Translate != "" {
|
if m.Translate != "" {
|
||||||
args := make([]interface{}, len(m.With))
|
args := make([]interface{}, len(m.With))
|
||||||
for i, v := range m.With {
|
for i, v := range m.With {
|
||||||
var arg Message
|
args[i] = v
|
||||||
_ = arg.UnmarshalJSON(v) //ignore error
|
|
||||||
args[i] = arg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...)
|
_, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...)
|
||||||
|
130
data/packetid/clientboundpacketid_string.go
Normal file
130
data/packetid/clientboundpacketid_string.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// Code generated by "stringer -type ClientboundPacketID"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package packetid
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[ClientboundAddEntity-0]
|
||||||
|
_ = x[ClientboundAddExperienceOrb-1]
|
||||||
|
_ = x[ClientboundAddPlayer-2]
|
||||||
|
_ = x[ClientboundAnimate-3]
|
||||||
|
_ = x[ClientboundAwardStats-4]
|
||||||
|
_ = x[ClientboundBlockChangedAck-5]
|
||||||
|
_ = x[ClientboundBlockDestruction-6]
|
||||||
|
_ = x[ClientboundBlockEntityData-7]
|
||||||
|
_ = x[ClientboundBlockEvent-8]
|
||||||
|
_ = x[ClientboundBlockUpdate-9]
|
||||||
|
_ = x[ClientboundBossEvent-10]
|
||||||
|
_ = x[ClientboundChangeDifficulty-11]
|
||||||
|
_ = x[ClientboundChatPreview-12]
|
||||||
|
_ = x[ClientboundClearTitles-13]
|
||||||
|
_ = x[ClientboundCommandSuggestions-14]
|
||||||
|
_ = x[ClientboundCommands-15]
|
||||||
|
_ = x[ClientboundContainerClose-16]
|
||||||
|
_ = x[ClientboundContainerSetContent-17]
|
||||||
|
_ = x[ClientboundContainerSetData-18]
|
||||||
|
_ = x[ClientboundContainerSetSlot-19]
|
||||||
|
_ = x[ClientboundCooldown-20]
|
||||||
|
_ = x[ClientboundCustomChatCompletions-21]
|
||||||
|
_ = x[ClientboundCustomPayload-22]
|
||||||
|
_ = x[ClientboundCustomSound-23]
|
||||||
|
_ = x[ClientboundDeleteChat-24]
|
||||||
|
_ = x[ClientboundDisconnect-25]
|
||||||
|
_ = x[ClientboundEntityEvent-26]
|
||||||
|
_ = x[ClientboundExplode-27]
|
||||||
|
_ = x[ClientboundForgetLevelChunk-28]
|
||||||
|
_ = x[ClientboundGameEvent-29]
|
||||||
|
_ = x[ClientboundHorseScreenOpen-30]
|
||||||
|
_ = x[ClientboundInitializeBorder-31]
|
||||||
|
_ = x[ClientboundKeepAlive-32]
|
||||||
|
_ = x[ClientboundLevelChunkWithLight-33]
|
||||||
|
_ = x[ClientboundLevelEvent-34]
|
||||||
|
_ = x[ClientboundLevelParticles-35]
|
||||||
|
_ = x[ClientboundLightUpdate-36]
|
||||||
|
_ = x[ClientboundLogin-37]
|
||||||
|
_ = x[ClientboundMapItemData-38]
|
||||||
|
_ = x[ClientboundMerchantOffers-39]
|
||||||
|
_ = x[ClientboundMoveEntityPos-40]
|
||||||
|
_ = x[ClientboundMoveEntityPosRot-41]
|
||||||
|
_ = x[ClientboundMoveEntityRot-42]
|
||||||
|
_ = x[ClientboundMoveVehicle-43]
|
||||||
|
_ = x[ClientboundOpenBook-44]
|
||||||
|
_ = x[ClientboundOpenScreen-45]
|
||||||
|
_ = x[ClientboundOpenSignEditor-46]
|
||||||
|
_ = x[ClientboundPing-47]
|
||||||
|
_ = x[ClientboundPlaceGhostRecipe-48]
|
||||||
|
_ = x[ClientboundPlayerAbilities-49]
|
||||||
|
_ = x[ClientboundPlayerChatHeader-50]
|
||||||
|
_ = x[ClientboundPlayerChat-51]
|
||||||
|
_ = x[ClientboundPlayerCombatEnd-52]
|
||||||
|
_ = x[ClientboundPlayerCombatEnter-53]
|
||||||
|
_ = x[ClientboundPlayerCombatKill-54]
|
||||||
|
_ = x[ClientboundPlayerInfo-55]
|
||||||
|
_ = x[ClientboundPlayerLookAt-56]
|
||||||
|
_ = x[ClientboundPlayerPosition-57]
|
||||||
|
_ = x[ClientboundRecipe-58]
|
||||||
|
_ = x[ClientboundRemoveEntities-59]
|
||||||
|
_ = x[ClientboundRemoveMobEffect-60]
|
||||||
|
_ = x[ClientboundResourcePack-61]
|
||||||
|
_ = x[ClientboundRespawn-62]
|
||||||
|
_ = x[ClientboundRotateHead-63]
|
||||||
|
_ = x[ClientboundSectionBlocksUpdate-64]
|
||||||
|
_ = x[ClientboundSelectAdvancementsTab-65]
|
||||||
|
_ = x[ClientboundServerData-66]
|
||||||
|
_ = x[ClientboundSetActionBarText-67]
|
||||||
|
_ = x[ClientboundSetBorderCenter-68]
|
||||||
|
_ = x[ClientboundSetBorderLerpSize-69]
|
||||||
|
_ = x[ClientboundSetBorderSize-70]
|
||||||
|
_ = x[ClientboundSetBorderWarningDelay-71]
|
||||||
|
_ = x[ClientboundSetBorderWarningDistance-72]
|
||||||
|
_ = x[ClientboundSetCamera-73]
|
||||||
|
_ = x[ClientboundSetCarriedItem-74]
|
||||||
|
_ = x[ClientboundSetChunkCacheCenter-75]
|
||||||
|
_ = x[ClientboundSetChunkCacheRadius-76]
|
||||||
|
_ = x[ClientboundSetDefaultSpawnPosition-77]
|
||||||
|
_ = x[ClientboundSetDisplayChatPreview-78]
|
||||||
|
_ = x[ClientboundSetDisplayObjective-79]
|
||||||
|
_ = x[ClientboundSetEntityData-80]
|
||||||
|
_ = x[ClientboundSetEntityLink-81]
|
||||||
|
_ = x[ClientboundSetEntityMotion-82]
|
||||||
|
_ = x[ClientboundSetEquipment-83]
|
||||||
|
_ = x[ClientboundSetExperience-84]
|
||||||
|
_ = x[ClientboundSetHealth-85]
|
||||||
|
_ = x[ClientboundSetObjective-86]
|
||||||
|
_ = x[ClientboundSetPassengers-87]
|
||||||
|
_ = x[ClientboundSetPlayerTeam-88]
|
||||||
|
_ = x[ClientboundSetScore-89]
|
||||||
|
_ = x[ClientboundSetSimulationDistance-90]
|
||||||
|
_ = x[ClientboundSetSubtitleText-91]
|
||||||
|
_ = x[ClientboundSetTime-92]
|
||||||
|
_ = x[ClientboundSetTitleText-93]
|
||||||
|
_ = x[ClientboundSetTitlesAnimation-94]
|
||||||
|
_ = x[ClientboundSoundEntity-95]
|
||||||
|
_ = x[ClientboundSound-96]
|
||||||
|
_ = x[ClientboundStopSound-97]
|
||||||
|
_ = x[ClientboundSystemChat-98]
|
||||||
|
_ = x[ClientboundTabList-99]
|
||||||
|
_ = x[ClientboundTagQuery-100]
|
||||||
|
_ = x[ClientboundTakeItemEntity-101]
|
||||||
|
_ = x[ClientboundTeleportEntity-102]
|
||||||
|
_ = x[ClientboundUpdateAdvancements-103]
|
||||||
|
_ = x[ClientboundUpdateAttributes-104]
|
||||||
|
_ = x[ClientboundUpdateMobEffect-105]
|
||||||
|
_ = x[ClientboundUpdateRecipes-106]
|
||||||
|
_ = x[ClientboundUpdateTags-107]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _ClientboundPacketID_name = "ClientboundAddEntityClientboundAddExperienceOrbClientboundAddPlayerClientboundAnimateClientboundAwardStatsClientboundBlockChangedAckClientboundBlockDestructionClientboundBlockEntityDataClientboundBlockEventClientboundBlockUpdateClientboundBossEventClientboundChangeDifficultyClientboundChatPreviewClientboundClearTitlesClientboundCommandSuggestionsClientboundCommandsClientboundContainerCloseClientboundContainerSetContentClientboundContainerSetDataClientboundContainerSetSlotClientboundCooldownClientboundCustomChatCompletionsClientboundCustomPayloadClientboundCustomSoundClientboundDeleteChatClientboundDisconnectClientboundEntityEventClientboundExplodeClientboundForgetLevelChunkClientboundGameEventClientboundHorseScreenOpenClientboundInitializeBorderClientboundKeepAliveClientboundLevelChunkWithLightClientboundLevelEventClientboundLevelParticlesClientboundLightUpdateClientboundLoginClientboundMapItemDataClientboundMerchantOffersClientboundMoveEntityPosClientboundMoveEntityPosRotClientboundMoveEntityRotClientboundMoveVehicleClientboundOpenBookClientboundOpenScreenClientboundOpenSignEditorClientboundPingClientboundPlaceGhostRecipeClientboundPlayerAbilitiesClientboundPlayerChatHeaderClientboundPlayerChatClientboundPlayerCombatEndClientboundPlayerCombatEnterClientboundPlayerCombatKillClientboundPlayerInfoClientboundPlayerLookAtClientboundPlayerPositionClientboundRecipeClientboundRemoveEntitiesClientboundRemoveMobEffectClientboundResourcePackClientboundRespawnClientboundRotateHeadClientboundSectionBlocksUpdateClientboundSelectAdvancementsTabClientboundServerDataClientboundSetActionBarTextClientboundSetBorderCenterClientboundSetBorderLerpSizeClientboundSetBorderSizeClientboundSetBorderWarningDelayClientboundSetBorderWarningDistanceClientboundSetCameraClientboundSetCarriedItemClientboundSetChunkCacheCenterClientboundSetChunkCacheRadiusClientboundSetDefaultSpawnPositionClientboundSetDisplayChatPreviewClientboundSetDisplayObjectiveClientboundSetEntityDataClientboundSetEntityLinkClientboundSetEntityMotionClientboundSetEquipmentClientboundSetExperienceClientboundSetHealthClientboundSetObjectiveClientboundSetPassengersClientboundSetPlayerTeamClientboundSetScoreClientboundSetSimulationDistanceClientboundSetSubtitleTextClientboundSetTimeClientboundSetTitleTextClientboundSetTitlesAnimationClientboundSoundEntityClientboundSoundClientboundStopSoundClientboundSystemChatClientboundTabListClientboundTagQueryClientboundTakeItemEntityClientboundTeleportEntityClientboundUpdateAdvancementsClientboundUpdateAttributesClientboundUpdateMobEffectClientboundUpdateRecipesClientboundUpdateTags"
|
||||||
|
|
||||||
|
var _ClientboundPacketID_index = [...]uint16{0, 20, 47, 67, 85, 106, 132, 159, 185, 206, 228, 248, 275, 297, 319, 348, 367, 392, 422, 449, 476, 495, 527, 551, 573, 594, 615, 637, 655, 682, 702, 728, 755, 775, 805, 826, 851, 873, 889, 911, 936, 960, 987, 1011, 1033, 1052, 1073, 1098, 1113, 1140, 1166, 1193, 1214, 1240, 1268, 1295, 1316, 1339, 1364, 1381, 1406, 1432, 1455, 1473, 1494, 1524, 1556, 1577, 1604, 1630, 1658, 1682, 1714, 1749, 1769, 1794, 1824, 1854, 1888, 1920, 1950, 1974, 1998, 2024, 2047, 2071, 2091, 2114, 2138, 2162, 2181, 2213, 2239, 2257, 2280, 2309, 2331, 2347, 2367, 2388, 2406, 2425, 2450, 2475, 2504, 2531, 2557, 2581, 2602}
|
||||||
|
|
||||||
|
func (i ClientboundPacketID) String() string {
|
||||||
|
if i < 0 || i >= ClientboundPacketID(len(_ClientboundPacketID_index)-1) {
|
||||||
|
return "ClientboundPacketID(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _ClientboundPacketID_name[_ClientboundPacketID_index[i]:_ClientboundPacketID_index[i+1]]
|
||||||
|
}
|
@ -1,5 +1,11 @@
|
|||||||
package packetid
|
package packetid
|
||||||
|
|
||||||
|
//go:generate stringer -type ClientboundPacketID
|
||||||
|
//go:generate stringer -type ServerboundPacketID
|
||||||
|
|
||||||
|
type ClientboundPacketID int32
|
||||||
|
type ServerboundPacketID int32
|
||||||
|
|
||||||
// Login Clientbound
|
// Login Clientbound
|
||||||
const (
|
const (
|
||||||
LoginDisconnect = iota
|
LoginDisconnect = iota
|
||||||
@ -30,7 +36,7 @@ const (
|
|||||||
|
|
||||||
// Game Clientbound
|
// Game Clientbound
|
||||||
const (
|
const (
|
||||||
ClientboundAddEntity = iota
|
ClientboundAddEntity ClientboundPacketID = iota
|
||||||
ClientboundAddExperienceOrb
|
ClientboundAddExperienceOrb
|
||||||
ClientboundAddPlayer
|
ClientboundAddPlayer
|
||||||
ClientboundAnimate
|
ClientboundAnimate
|
||||||
@ -142,7 +148,7 @@ const (
|
|||||||
|
|
||||||
// Game Serverbound
|
// Game Serverbound
|
||||||
const (
|
const (
|
||||||
ServerboundAcceptTeleportation = iota
|
ServerboundAcceptTeleportation ServerboundPacketID = iota
|
||||||
ServerboundBlockEntityTagQuery
|
ServerboundBlockEntityTagQuery
|
||||||
ServerboundChangeDifficulty
|
ServerboundChangeDifficulty
|
||||||
ServerboundChatAck
|
ServerboundChatAck
|
||||||
|
73
data/packetid/serverboundpacketid_string.go
Normal file
73
data/packetid/serverboundpacketid_string.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Code generated by "stringer -type ServerboundPacketID"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package packetid
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[ServerboundAcceptTeleportation-0]
|
||||||
|
_ = x[ServerboundBlockEntityTagQuery-1]
|
||||||
|
_ = x[ServerboundChangeDifficulty-2]
|
||||||
|
_ = x[ServerboundChatAck-3]
|
||||||
|
_ = x[ServerboundChatCommand-4]
|
||||||
|
_ = x[ServerboundChat-5]
|
||||||
|
_ = x[ServerboundChatPreview-6]
|
||||||
|
_ = x[ServerboundClientCommand-7]
|
||||||
|
_ = x[ServerboundClientInformation-8]
|
||||||
|
_ = x[ServerboundCommandSuggestion-9]
|
||||||
|
_ = x[ServerboundContainerButtonClick-10]
|
||||||
|
_ = x[ServerboundContainerClick-11]
|
||||||
|
_ = x[ServerboundContainerClose-12]
|
||||||
|
_ = x[ServerboundCustomPayload-13]
|
||||||
|
_ = x[ServerboundEditBook-14]
|
||||||
|
_ = x[ServerboundEntityTagQuery-15]
|
||||||
|
_ = x[ServerboundInteract-16]
|
||||||
|
_ = x[ServerboundJigsawGenerate-17]
|
||||||
|
_ = x[ServerboundKeepAlive-18]
|
||||||
|
_ = x[ServerboundLockDifficulty-19]
|
||||||
|
_ = x[ServerboundMovePlayerPos-20]
|
||||||
|
_ = x[ServerboundMovePlayerPosRot-21]
|
||||||
|
_ = x[ServerboundMovePlayerRot-22]
|
||||||
|
_ = x[ServerboundMovePlayerStatusOnly-23]
|
||||||
|
_ = x[ServerboundMoveVehicle-24]
|
||||||
|
_ = x[ServerboundPaddleBoat-25]
|
||||||
|
_ = x[ServerboundPickItem-26]
|
||||||
|
_ = x[ServerboundPlaceRecipe-27]
|
||||||
|
_ = x[ServerboundPlayerAbilities-28]
|
||||||
|
_ = x[ServerboundPlayerAction-29]
|
||||||
|
_ = x[ServerboundPlayerCommand-30]
|
||||||
|
_ = x[ServerboundPlayerInput-31]
|
||||||
|
_ = x[ServerboundPong-32]
|
||||||
|
_ = x[ServerboundRecipeBookChangeSettings-33]
|
||||||
|
_ = x[ServerboundRecipeBookSeenRecipe-34]
|
||||||
|
_ = x[ServerboundRenameItem-35]
|
||||||
|
_ = x[ServerboundResourcePack-36]
|
||||||
|
_ = x[ServerboundSeenAdvancements-37]
|
||||||
|
_ = x[ServerboundSelectTrade-38]
|
||||||
|
_ = x[ServerboundSetBeacon-39]
|
||||||
|
_ = x[ServerboundSetCarriedItem-40]
|
||||||
|
_ = x[ServerboundSetCommandBlock-41]
|
||||||
|
_ = x[ServerboundSetCommandMinecart-42]
|
||||||
|
_ = x[ServerboundSetCreativeModeSlot-43]
|
||||||
|
_ = x[ServerboundSetJigsawBlock-44]
|
||||||
|
_ = x[ServerboundSetStructureBlock-45]
|
||||||
|
_ = x[ServerboundSignUpdate-46]
|
||||||
|
_ = x[ServerboundSwing-47]
|
||||||
|
_ = x[ServerboundTeleportToEntity-48]
|
||||||
|
_ = x[ServerboundUseItemOn-49]
|
||||||
|
_ = x[ServerboundUseItem-50]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _ServerboundPacketID_name = "ServerboundAcceptTeleportationServerboundBlockEntityTagQueryServerboundChangeDifficultyServerboundChatAckServerboundChatCommandServerboundChatServerboundChatPreviewServerboundClientCommandServerboundClientInformationServerboundCommandSuggestionServerboundContainerButtonClickServerboundContainerClickServerboundContainerCloseServerboundCustomPayloadServerboundEditBookServerboundEntityTagQueryServerboundInteractServerboundJigsawGenerateServerboundKeepAliveServerboundLockDifficultyServerboundMovePlayerPosServerboundMovePlayerPosRotServerboundMovePlayerRotServerboundMovePlayerStatusOnlyServerboundMoveVehicleServerboundPaddleBoatServerboundPickItemServerboundPlaceRecipeServerboundPlayerAbilitiesServerboundPlayerActionServerboundPlayerCommandServerboundPlayerInputServerboundPongServerboundRecipeBookChangeSettingsServerboundRecipeBookSeenRecipeServerboundRenameItemServerboundResourcePackServerboundSeenAdvancementsServerboundSelectTradeServerboundSetBeaconServerboundSetCarriedItemServerboundSetCommandBlockServerboundSetCommandMinecartServerboundSetCreativeModeSlotServerboundSetJigsawBlockServerboundSetStructureBlockServerboundSignUpdateServerboundSwingServerboundTeleportToEntityServerboundUseItemOnServerboundUseItem"
|
||||||
|
|
||||||
|
var _ServerboundPacketID_index = [...]uint16{0, 30, 60, 87, 105, 127, 142, 164, 188, 216, 244, 275, 300, 325, 349, 368, 393, 412, 437, 457, 482, 506, 533, 557, 588, 610, 631, 650, 672, 698, 721, 745, 767, 782, 817, 848, 869, 892, 919, 941, 961, 986, 1012, 1041, 1071, 1096, 1124, 1145, 1161, 1188, 1208, 1226}
|
||||||
|
|
||||||
|
func (i ServerboundPacketID) String() string {
|
||||||
|
if i < 0 || i >= ServerboundPacketID(len(_ServerboundPacketID_index)-1) {
|
||||||
|
return "ServerboundPacketID(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _ServerboundPacketID_name[_ServerboundPacketID_index[i]:_ServerboundPacketID_index[i+1]]
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
botchat "github.com/Tnze/go-mc/bot/chat"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ const timeout = 45
|
|||||||
var (
|
var (
|
||||||
c *bot.Client
|
c *bot.Client
|
||||||
p *basic.Player
|
p *basic.Player
|
||||||
|
bc *botchat.Chat
|
||||||
|
|
||||||
watch chan time.Time
|
watch chan time.Time
|
||||||
)
|
)
|
||||||
@ -26,16 +28,16 @@ var (
|
|||||||
func main() {
|
func main() {
|
||||||
//log.SetOutput(colorable.NewColorableStdout()) // optional for colorable output
|
//log.SetOutput(colorable.NewColorableStdout()) // optional for colorable output
|
||||||
c = bot.NewClient()
|
c = bot.NewClient()
|
||||||
p = basic.NewPlayer(c, basic.DefaultSettings)
|
p = basic.NewPlayer(c, basic.DefaultSettings, basic.EventsListener{
|
||||||
|
|
||||||
//Register event handlers
|
|
||||||
basic.EventsListener{
|
|
||||||
GameStart: onGameStart,
|
GameStart: onGameStart,
|
||||||
ChatMsg: onChatMsg,
|
|
||||||
SystemMsg: onSystemMsg,
|
SystemMsg: onSystemMsg,
|
||||||
Disconnect: onDisconnect,
|
Disconnect: onDisconnect,
|
||||||
Death: onDeath,
|
Death: onDeath,
|
||||||
}.Attach(c)
|
})
|
||||||
|
bc = botchat.NewChat(c, p, botchat.EventsHandler{PlayerChatMessage: onChatMsg})
|
||||||
|
|
||||||
|
//Register event handlers
|
||||||
|
|
||||||
c.Events.AddListener(soundListener)
|
c.Events.AddListener(soundListener)
|
||||||
|
|
||||||
//Login
|
//Login
|
||||||
@ -107,13 +109,13 @@ func onSound(id int, category int, x, y, z float64, volume, pitch float32) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onChatMsg(c *basic.PlayerMessage) error {
|
func onChatMsg(c chat.Message) error {
|
||||||
log.Println("Chat:", c.SignedMessage)
|
log.Println("Chat:", c)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSystemMsg(c chat.Message, pos byte) error {
|
func onSystemMsg(c chat.Message, overlay bool) error {
|
||||||
log.Printf("System: %v, Location: %v", c, pos)
|
log.Printf("System: %v, Overlay: %v", c, overlay)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/bot/basic"
|
"github.com/Tnze/go-mc/bot/basic"
|
||||||
|
botchat "github.com/Tnze/go-mc/bot/chat"
|
||||||
"github.com/Tnze/go-mc/bot/screen"
|
"github.com/Tnze/go-mc/bot/screen"
|
||||||
"github.com/Tnze/go-mc/bot/world"
|
"github.com/Tnze/go-mc/bot/world"
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
@ -27,6 +28,7 @@ var accessToken = flag.String("token", "", "AccessToken")
|
|||||||
|
|
||||||
var client *bot.Client
|
var client *bot.Client
|
||||||
var player *basic.Player
|
var player *basic.Player
|
||||||
|
var chatHandler *botchat.Chat
|
||||||
var worldManager *world.World
|
var worldManager *world.World
|
||||||
var screenManager *screen.Manager
|
var screenManager *screen.Manager
|
||||||
|
|
||||||
@ -39,15 +41,16 @@ func main() {
|
|||||||
UUID: *playerID,
|
UUID: *playerID,
|
||||||
AsTk: *accessToken,
|
AsTk: *accessToken,
|
||||||
}
|
}
|
||||||
player = basic.NewPlayer(client, basic.DefaultSettings)
|
player = basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{
|
||||||
basic.EventsListener{
|
|
||||||
GameStart: onGameStart,
|
GameStart: onGameStart,
|
||||||
ChatMsg: onChatMsg,
|
|
||||||
SystemMsg: onSystemMsg,
|
SystemMsg: onSystemMsg,
|
||||||
Disconnect: onDisconnect,
|
Disconnect: onDisconnect,
|
||||||
HealthChange: onHealthChange,
|
HealthChange: onHealthChange,
|
||||||
Death: onDeath,
|
Death: onDeath,
|
||||||
}.Attach(client)
|
})
|
||||||
|
chatHandler = botchat.NewChat(client, player, botchat.EventsHandler{
|
||||||
|
PlayerChatMessage: onPlayerMsg,
|
||||||
|
})
|
||||||
worldManager = world.NewWorld(client, player, world.EventsListener{
|
worldManager = world.NewWorld(client, player, world.EventsListener{
|
||||||
LoadChunk: onChunkLoad,
|
LoadChunk: onChunkLoad,
|
||||||
UnloadChunk: onChunkUnload,
|
UnloadChunk: onChunkUnload,
|
||||||
@ -103,13 +106,13 @@ 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 *basic.PlayerMessage) error {
|
func onPlayerMsg(msg chat.Message) error {
|
||||||
log.Println("Chat:", c.SignedMessage.String())
|
log.Printf("Player: %v", msg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSystemMsg(c chat.Message, pos byte) error {
|
func onSystemMsg(c chat.Message, overlay bool) error {
|
||||||
log.Printf("System: %v, Location: %v", c, pos)
|
log.Printf("System: %v, Overlay: %v", c, overlay)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ func main() {
|
|||||||
//log.SetOutput(colorable.NewColorableStdout())
|
//log.SetOutput(colorable.NewColorableStdout())
|
||||||
client = bot.NewClient()
|
client = bot.NewClient()
|
||||||
client.Auth.Name = "Daze"
|
client.Auth.Name = "Daze"
|
||||||
player = basic.NewPlayer(client, basic.DefaultSettings)
|
player = basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{})
|
||||||
client.Events.AddListener(bot.PacketHandler{
|
client.Events.AddListener(bot.PacketHandler{
|
||||||
ID: packetid.ClientboundCommands,
|
ID: packetid.ClientboundCommands,
|
||||||
Priority: 50,
|
Priority: 50,
|
||||||
|
@ -44,11 +44,10 @@ func newIndividual(id int, name string) (i *individual) {
|
|||||||
i.id = id
|
i.id = id
|
||||||
i.client = bot.NewClient()
|
i.client = bot.NewClient()
|
||||||
i.client.Auth.Name = name
|
i.client.Auth.Name = name
|
||||||
i.player = basic.NewPlayer(i.client, basic.DefaultSettings)
|
i.player = basic.NewPlayer(i.client, basic.DefaultSettings, basic.EventsListener{
|
||||||
basic.EventsListener{
|
|
||||||
GameStart: i.onGameStart,
|
GameStart: i.onGameStart,
|
||||||
Disconnect: onDisconnect,
|
Disconnect: onDisconnect,
|
||||||
}.Attach(i.client)
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,12 @@ 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 ~int32 | int](id ID, fields ...FieldEncoder) (pk Packet) {
|
||||||
var pb Builder
|
var pb Builder
|
||||||
for _, v := range fields {
|
for _, v := range fields {
|
||||||
pb.WriteField(v)
|
pb.WriteField(v)
|
||||||
}
|
}
|
||||||
return pb.Packet(id)
|
return pb.Packet(int32(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan decode the packet and fill data into fields
|
// Scan decode the packet and fill data into fields
|
||||||
|
@ -2,6 +2,7 @@ package packet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
@ -130,10 +131,10 @@ func (t Tuple) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
|
|
||||||
// ReadFrom read Tuple from io.Reader, panic when any of field don't implement FieldDecoder
|
// ReadFrom read Tuple from io.Reader, panic when any of field don't implement FieldDecoder
|
||||||
func (t Tuple) ReadFrom(r io.Reader) (n int64, err error) {
|
func (t Tuple) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
for _, v := range t {
|
for i, v := range t {
|
||||||
nn, err := v.(FieldDecoder).ReadFrom(r)
|
nn, err := v.(FieldDecoder).ReadFrom(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, fmt.Errorf("decode tuple[%d] error: %w", i, err)
|
||||||
}
|
}
|
||||||
n += nn
|
n += nn
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user