update 1.19.2 bot basic events

This commit is contained in:
Tnze
2022-11-26 01:30:08 +08:00
parent 822d76a4b1
commit 6a3589ad61

View File

@ -1,134 +1,178 @@
package basic package basic
import ( import (
"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/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 ChatMsg func(c *PlayerMessage) error
SystemMsg func(c chat.Message, pos byte) 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.
// 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(c *bot.Client) {
c.Events.AddListener(
bot.PacketHandler{Priority: 64, ID: packetid.ClientboundLogin, F: e.onJoinGame},
bot.PacketHandler{Priority: 64, ID: packetid.ClientboundSystemChat, F: e.onSystemMsg},
bot.PacketHandler{Priority: 64, ID: packetid.ClientboundPlayerChat, F: e.onPlayerMsg},
bot.PacketHandler{Priority: 64, ID: packetid.ClientboundDisconnect, F: e.onDisconnect},
bot.PacketHandler{Priority: 64, ID: packetid.ClientboundSetHealth, F: e.onUpdateHealth},
)
}
func (e *EventsListener) onJoinGame(_ pk.Packet) error {
if e.GameStart != nil { if e.GameStart != nil {
return e.GameStart() attachJoinGameHandler(c, e.GameStart)
}
if e.ChatMsg != nil {
attachPlayerMsg(c, e.ChatMsg)
}
if e.SystemMsg != nil {
attachSystemMsg(c, e.SystemMsg)
}
if e.Disconnect != nil {
attachDisconnect(c, e.Disconnect)
}
if e.HealthChange != nil || e.Death != nil {
attachUpdateHealth(c, e.HealthChange, e.Death)
} }
return nil
} }
func (e *EventsListener) onDisconnect(p pk.Packet) error { func attachJoinGameHandler(c *bot.Client, handler func() error) {
if e.Disconnect != nil { c.Events.AddListener(bot.PacketHandler{
var reason chat.Message Priority: 64, ID: packetid.ClientboundLogin,
if err := p.Scan(&reason); err != nil { F: func(_ pk.Packet) error {
return Error{err} return handler()
} },
return e.Disconnect(reason) })
}
return nil
} }
type PlayerMessage struct { type PlayerMessage struct {
SignedMessage chat.Message
Unsigned bool
UnsignedMessage chat.Message
Position int32
Sender uuid.UUID
SenderDisplayName chat.Message
HasSenderTeam bool
SenderTeamName chat.Message
TimeStamp time.Time
} }
func (e *EventsListener) onPlayerMsg(p pk.Packet) error { func (p *PlayerMessage) ReadFrom(r io.Reader) (n int64, err error) {
if e.ChatMsg != nil { // SignedMessageHeader
var message PlayerMessage // MessageSignature
var senderDisplayName pk.String // SignedMessageBody
var senderTeamName pk.String // Optional<Component>
var timeStamp pk.Long // FilterMask
var salt pk.Long panic("implement me")
var signature pk.ByteArray }
if err := p.Scan(&message.SignedMessage,
(*pk.Boolean)(&message.Unsigned), type ChatType struct {
pk.Opt{ ID int32
Has: &message.Unsigned, Name chat.Message
Field: &message.UnsignedMessage, TargetName *chat.Message
}, }
(*pk.VarInt)(&message.Position),
(*pk.UUID)(&message.Sender), func (c *ChatType) ReadFrom(r io.Reader) (n int64, err error) {
&senderDisplayName, var hasTargetName pk.Boolean
(*pk.Boolean)(&message.HasSenderTeam), n1, err := (*pk.VarInt)(&c.ID).ReadFrom(r)
pk.Opt{ if err != nil {
Has: &message.HasSenderTeam, return n1, err
Field: &senderTeamName,
},
&timeStamp,
&salt,
&signature); err != nil {
return Error{err}
}
if err := message.SenderDisplayName.UnmarshalJSON([]byte(senderDisplayName)); err != nil {
return Error{err}
}
if err := message.SenderTeamName.UnmarshalJSON([]byte(senderDisplayName)); err != nil {
return Error{err}
}
return e.ChatMsg(&message)
} }
return nil n2, err := c.Name.ReadFrom(r)
} if err != nil {
func (e *EventsListener) onSystemMsg(p pk.Packet) error { return n1 + n2, err
if e.SystemMsg != nil {
var msg chat.Message
var pos pk.VarInt
if err := p.Scan(&msg, &pos); err != nil {
return Error{err}
}
return e.SystemMsg(msg, byte(pos))
} }
return nil 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 (e *EventsListener) onUpdateHealth(p pk.Packet) error { func attachPlayerMsg(c *bot.Client, handler func(c *PlayerMessage) error) {
if e.ChatMsg != nil { c.Events.AddListener(bot.PacketHandler{
var health pk.Float Priority: 64, ID: packetid.ClientboundPlayerChat,
var food pk.VarInt F: func(p pk.Packet) error {
var foodSaturation pk.Float var message PlayerMessage
var chatType ChatType
if err := p.Scan(&health, &food, &foodSaturation); err != nil { if err := p.Scan(&message, &chatType); err != nil {
return Error{err} return Error{err}
}
if e.HealthChange != nil {
if err := e.HealthChange(float32(health)); err != nil {
return err
} }
} return handler(&message)
if e.Death != nil && health <= 0 { },
if err := e.Death(); err != nil { })
return err }
func attachSystemMsg(c *bot.Client, handler func(c chat.Message, overlay bool) error) {
c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundSystemChat,
F: func(p pk.Packet) error {
var msg chat.Message
var pos pk.Boolean
if err := p.Scan(&msg, &pos); err != nil {
return Error{err}
} }
} return handler(msg, bool(pos))
},
})
}
func attachDisconnect(c *bot.Client, handler func(reason chat.Message) error) {
c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundDisconnect,
F: func(p pk.Packet) error {
var reason chat.Message
if err := p.Scan(&reason); err != nil {
return Error{err}
}
return handler(reason)
},
})
}
func attachUpdateHealth(c *bot.Client, healthChangeHandler func(health float32) error, deathHandler func() error) {
c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundSetHealth,
F: func(p pk.Packet) error {
var health pk.Float
var food pk.VarInt
var foodSaturation pk.Float
if err := p.Scan(&health, &food, &foodSaturation); err != nil {
return Error{err}
}
var healthChangeErr, deathErr error
if healthChangeHandler != nil {
healthChangeErr = healthChangeHandler(float32(health))
}
if deathHandler != nil && health <= 0 {
healthChangeErr = deathHandler()
}
return updateHealthError{healthChangeErr, deathErr}
},
})
}
type updateHealthError struct {
healthChangeErr, deathErr error
}
func (u updateHealthError) Unwrap() error {
if u.healthChangeErr != nil {
return u.healthChangeErr
}
if u.deathErr != nil {
return u.deathErr
} }
return nil return nil
} }
func (u updateHealthError) Error() string {
switch {
case u.healthChangeErr != nil && u.deathErr != nil:
return "[" + u.healthChangeErr.Error() + ", " + u.deathErr.Error() + "]"
case u.healthChangeErr != nil:
return u.healthChangeErr.Error()
case u.deathErr != nil:
return u.deathErr.Error()
default:
return "nil"
}
}