Updated 1.21.6

This commit is contained in:
2025-06-16 12:46:46 +08:00
parent 539b4a3a7f
commit f67c9e3052
290 changed files with 22178 additions and 18088 deletions

View File

@ -1,163 +0,0 @@
package basic
import (
"github.com/Tnze/go-mc/bot"
"github.com/Tnze/go-mc/chat"
"github.com/Tnze/go-mc/data/packetid"
pk "github.com/Tnze/go-mc/net/packet"
)
// EventsListener is a collection of event handlers.
// Fill the fields with your handler functions and pass it to [NewPlayer] to create the Player manager.
// For the event you don't want to handle, just leave it nil.
type EventsListener struct {
// GameStart event is called when the login process is completed and the player is ready to play.
//
// If you want to do some action when the bot joined the server like sending a chat message,
// this event is the right place to do it.
GameStart func() error
// Disconnect event is called before the server disconnects your client.
// When the server willfully disconnects the client, it will send a ClientboundDisconnect packet and tell you why.
// On vanilla client, the reason is displayed in the disconnect screen.
//
// This information may be very useful for debugging, and generally you should record it into the log.
//
// If the connection is disconnected due to network reasons or the client's initiative,
// this event will not be triggered.
Disconnect func(reason chat.Message) error
// HealthChange event is called when the player's health or food changed.
HealthChange func(health float32, foodLevel int32, foodSaturation float32) error
// Death event is a special case of HealthChange.
// It will be called after HealthChange handler called (if it isn't nil)
// when the player's health is less than or equal to 0.
//
// Typically, you should call [Player.Respawn] in this handler.
Death func() error
// Teleported event is called when the server think the player position in the client side is wrong,
// and send a ClientboundPlayerPosition packet to correct the client.
//
// Typically, you need to do two things in this handler:
// - Update the player's position and rotation you tracked to the correct position.
// - Call [Player.AcceptTeleportation] to send a teleport confirmation packet to the server.
//
// Before you confirm the teleportation, the server will not accept any player motion packets.
//
// The position coordinates and rotation are absolute or relative depends on the flags.
// The flag byte is a bitfield, specifies whether each coordinate value is absolute or relative.
// For more information, see https://wiki.vg/Protocol#Synchronize_Player_Position
Teleported func(x, y, z float64, yaw, pitch float32, flags byte, teleportID int32) 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(p *Player) {
if e.GameStart != nil {
attachJoinGameHandler(p.c, e.GameStart)
}
if e.Disconnect != nil {
attachDisconnect(p.c, e.Disconnect)
}
if e.HealthChange != nil || e.Death != nil {
attachUpdateHealth(p.c, e.HealthChange, e.Death)
}
if e.Teleported != nil {
attachPlayerPosition(p.c, e.Teleported)
}
}
func attachJoinGameHandler(c *bot.Client, handler func() error) {
c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundLogin,
F: func(_ pk.Packet) error {
return handler()
},
})
}
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(chat.Message(reason))
},
})
}
func attachUpdateHealth(c *bot.Client, healthChangeHandler func(health float32, food int32, saturation 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 saturation pk.Float
if err := p.Scan(&health, &food, &saturation); err != nil {
return Error{err}
}
var healthChangeErr, deathErr error
if healthChangeHandler != nil {
healthChangeErr = healthChangeHandler(float32(health), int32(food), float32(saturation))
}
if deathHandler != nil && health <= 0 {
deathErr = deathHandler()
}
if healthChangeErr != nil || deathErr != nil {
return updateHealthError{healthChangeErr, deathErr}
}
return nil
},
})
}
func attachPlayerPosition(c *bot.Client, handler func(x, y, z float64, yaw, pitch float32, flag byte, teleportID int32) error) {
c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundPlayerPosition,
F: func(p pk.Packet) error {
var (
X, Y, Z pk.Double
Yaw, Pitch pk.Float
Flags pk.Byte
TeleportID pk.VarInt
)
if err := p.Scan(&X, &Y, &Z, &Yaw, &Pitch, &Flags, &TeleportID); err != nil {
return Error{err}
}
return handler(float64(X), float64(Y), float64(Z), float32(Yaw), float32(Pitch), byte(Flags), int32(TeleportID))
},
})
}
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
}
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"
}
}