Refactoring package go-mc/bot
This commit is contained in:
32
bot/basic/basic.go
Normal file
32
bot/basic/basic.go
Normal file
@ -0,0 +1,32 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
c *bot.Client
|
||||
Settings Settings
|
||||
|
||||
PlayerInfo
|
||||
WorldInfo
|
||||
}
|
||||
|
||||
func NewPlayer(c *bot.Client, settings Settings) *Player {
|
||||
b := &Player{c: c, Settings: settings}
|
||||
c.Events.AddListener(
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.Login, F: b.handleJoinGamePacket},
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.KeepAliveClientbound, F: b.handleKeepAlivePacket},
|
||||
)
|
||||
return b
|
||||
}
|
||||
|
||||
func (p *Player) Respawn() error {
|
||||
const PerformRespawn = 0
|
||||
return p.c.Conn.WritePacket(pk.Marshal(
|
||||
packetid.ClientCommand,
|
||||
pk.VarInt(PerformRespawn),
|
||||
))
|
||||
}
|
83
bot/basic/events.go
Normal file
83
bot/basic/events.go
Normal file
@ -0,0 +1,83 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type EventsListener struct {
|
||||
GameStart func() error
|
||||
ChatMsg func(c chat.Message, pos byte, uuid uuid.UUID) error
|
||||
Disconnect func(reason chat.Message) error
|
||||
HealthChange func(health float32) error
|
||||
Death func() error
|
||||
}
|
||||
|
||||
func (e EventsListener) Attach(c *bot.Client) {
|
||||
c.Events.AddListener(
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.Login, F: e.onJoinGame},
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.ChatClientbound, F: e.onChatMsg},
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.Disconnect, F: e.onDisconnect},
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.UpdateHealth, F: e.onUpdateHealth},
|
||||
)
|
||||
}
|
||||
|
||||
func (e *EventsListener) onJoinGame(_ pk.Packet) error {
|
||||
if e.GameStart != nil {
|
||||
return e.GameStart()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EventsListener) onDisconnect(p pk.Packet) error {
|
||||
if e.Disconnect != nil {
|
||||
var reason chat.Message
|
||||
if err := p.Scan(&reason); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.Disconnect(reason)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EventsListener) onChatMsg(p pk.Packet) error {
|
||||
if e.ChatMsg != nil {
|
||||
var msg chat.Message
|
||||
var pos pk.Byte
|
||||
var sender pk.UUID
|
||||
|
||||
if err := p.Scan(&msg, &pos, &sender); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.ChatMsg(msg, byte(pos), uuid.UUID(sender))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EventsListener) onUpdateHealth(p pk.Packet) error {
|
||||
if e.ChatMsg != nil {
|
||||
var health pk.Float
|
||||
var food pk.VarInt
|
||||
var foodSaturation pk.Float
|
||||
|
||||
if err := p.Scan(&health, &food, &foodSaturation); err != nil {
|
||||
return err
|
||||
}
|
||||
if e.HealthChange != nil {
|
||||
if err := e.HealthChange(float32(health)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if e.Death != nil && health <= 0 {
|
||||
if err := e.Death(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
79
bot/basic/info.go
Normal file
79
bot/basic/info.go
Normal file
@ -0,0 +1,79 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// WorldInfo content player info in server.
|
||||
type WorldInfo struct {
|
||||
DimensionCodec struct {
|
||||
DimensionType interface{} `nbt:"minecraft:dimension_type"`
|
||||
WorldgenBiome interface{} `nbt:"minecraft:worldgen/biome"`
|
||||
}
|
||||
Dimension interface{}
|
||||
WorldNames []string // Identifiers for all worlds on the server.
|
||||
WorldName string // Name of the world being spawned into.
|
||||
HashedSeed int64 // First 8 bytes of the SHA-256 hash of the world's seed. Used client side for biome noise
|
||||
MaxPlayers int32 // Was once used by the client to draw the player list, but now is ignored.
|
||||
ViewDistance int32 // Render distance (2-32).
|
||||
ReducedDebugInfo bool // If true, a Notchian client shows reduced information on the debug screen. For servers in development, this should almost always be false.
|
||||
EnableRespawnScreen bool // Set to false when the doImmediateRespawn gamerule is true.
|
||||
IsDebug bool // True if the world is a debug mode world; debug mode worlds cannot be modified and have predefined blocks.
|
||||
IsFlat bool // True if the world is a superflat world; flat worlds have different void fog and a horizon at y=0 instead of y=63.
|
||||
}
|
||||
|
||||
type PlayerInfo struct {
|
||||
EID int32 // The player's Entity ID (EID).
|
||||
Hardcore bool // Is hardcore
|
||||
Gamemode byte // Gamemode. 0: Survival, 1: Creative, 2: Adventure, 3: Spectator.
|
||||
PrevGamemode int8 // Previous Gamemode
|
||||
}
|
||||
|
||||
// ServInfo contains information about the server implementation.
|
||||
type ServInfo struct {
|
||||
Brand string
|
||||
}
|
||||
|
||||
func (p *Player) handleJoinGamePacket(packet pk.Packet) error {
|
||||
var WorldCount pk.VarInt
|
||||
var WorldNames = []pk.Identifier{}
|
||||
err := packet.Scan(
|
||||
(*pk.Int)(&p.EID),
|
||||
(*pk.Boolean)(&p.Hardcore),
|
||||
(*pk.UnsignedByte)(&p.Gamemode),
|
||||
(*pk.Byte)(&p.PrevGamemode),
|
||||
&WorldCount,
|
||||
pk.Ary{Len: &WorldCount, Ary: &WorldNames},
|
||||
&pk.NBT{V: new(interface{})},
|
||||
&pk.NBT{V: new(interface{})},
|
||||
(*pk.Identifier)(&p.WorldName),
|
||||
(*pk.Long)(&p.HashedSeed),
|
||||
(*pk.VarInt)(&p.MaxPlayers),
|
||||
(*pk.VarInt)(&p.ViewDistance),
|
||||
(*pk.Boolean)(&p.ReducedDebugInfo),
|
||||
(*pk.Boolean)(&p.EnableRespawnScreen),
|
||||
(*pk.Boolean)(&p.IsDebug),
|
||||
(*pk.Boolean)(&p.IsFlat),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This line should work "like" the following code but without copy things
|
||||
// p.WorldNames = make([]string, len(WorldNames))
|
||||
// for i, v := range WorldNames {
|
||||
// p.WorldNames[i] = string(v)
|
||||
// }
|
||||
p.WorldNames = *(*[]string)(unsafe.Pointer(&WorldNames))
|
||||
|
||||
return p.c.Conn.WritePacket(
|
||||
//PluginMessage packet (serverbound) - sending minecraft brand.
|
||||
pk.Marshal(
|
||||
packetid.CustomPayloadServerbound,
|
||||
pk.Identifier("minecraft:brand"),
|
||||
pk.String(p.Settings.Brand),
|
||||
),
|
||||
)
|
||||
}
|
18
bot/basic/keepalive.go
Normal file
18
bot/basic/keepalive.go
Normal file
@ -0,0 +1,18 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
func (p Player) handleKeepAlivePacket(packet pk.Packet) error {
|
||||
var KeepAliveID pk.Long
|
||||
if err := packet.Scan(&KeepAliveID); err != nil {
|
||||
return err
|
||||
}
|
||||
// Response
|
||||
return p.c.Conn.WritePacket(pk.Marshal(
|
||||
packetid.KeepAliveServerbound,
|
||||
KeepAliveID,
|
||||
))
|
||||
}
|
38
bot/basic/settings.go
Normal file
38
bot/basic/settings.go
Normal file
@ -0,0 +1,38 @@
|
||||
package basic
|
||||
|
||||
// Settings of client
|
||||
type Settings struct {
|
||||
Locale string //地区
|
||||
ViewDistance int //视距
|
||||
ChatMode int //聊天模式
|
||||
ChatColors bool //聊天颜色
|
||||
DisplayedSkinParts uint8 //皮肤显示
|
||||
MainHand int //主手
|
||||
ReceiveMap bool //接收地图数据
|
||||
Brand string // The brand string presented to the server.
|
||||
}
|
||||
|
||||
/*
|
||||
Used by Settings.DisplayedSkinParts.
|
||||
For each bits set if shows match part.
|
||||
*/
|
||||
const (
|
||||
_ = 1 << iota
|
||||
Jacket
|
||||
LeftSleeve
|
||||
RightSleeve
|
||||
LeftPantsLeg
|
||||
RightPantsLeg
|
||||
Hat
|
||||
)
|
||||
|
||||
//DefaultSettings are the default settings of client
|
||||
var DefaultSettings = Settings{
|
||||
Locale: "zh_CN", // ^_^
|
||||
ViewDistance: 15,
|
||||
ChatMode: 0,
|
||||
DisplayedSkinParts: Jacket | LeftSleeve | RightSleeve | LeftPantsLeg | RightPantsLeg | Hat,
|
||||
MainHand: 1,
|
||||
ReceiveMap: true,
|
||||
Brand: "vanilla",
|
||||
}
|
Reference in New Issue
Block a user