Update to 1.16.3 + add a few new event callbacks.
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
# Go-MC
|
# Go-MC
|
||||||

|

|
||||||

|

|
||||||
[](https://godoc.org/github.com/Tnze/go-mc)
|
[](https://godoc.org/github.com/Tnze/go-mc)
|
||||||
[](https://goreportcard.com/report/github.com/Tnze/go-mc)
|
[](https://goreportcard.com/report/github.com/Tnze/go-mc)
|
||||||
[](https://travis-ci.org/Tnze/go-mc)
|
[](https://travis-ci.org/Tnze/go-mc)
|
||||||
|
@ -14,6 +14,7 @@ type Client struct {
|
|||||||
|
|
||||||
player.Player
|
player.Player
|
||||||
PlayInfo
|
PlayInfo
|
||||||
|
ServInfo
|
||||||
abilities PlayerAbilities
|
abilities PlayerAbilities
|
||||||
settings Settings
|
settings Settings
|
||||||
Wd world.World //the map data
|
Wd world.World //the map data
|
||||||
@ -58,7 +59,12 @@ type PlayInfo struct {
|
|||||||
WorldName string //当前世界的名字
|
WorldName string //当前世界的名字
|
||||||
IsDebug bool //调试
|
IsDebug bool //调试
|
||||||
IsFlat bool //超平坦世界
|
IsFlat bool //超平坦世界
|
||||||
// SpawnPosition Position //主世界出生点
|
SpawnPosition Position //主世界出生点
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServInfo contains information about the server implementation.
|
||||||
|
type ServInfo struct {
|
||||||
|
Brand string
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlayerAbilities defines what player can do.
|
// PlayerAbilities defines what player can do.
|
||||||
|
49
bot/event.go
49
bot/event.go
@ -8,7 +8,30 @@ import (
|
|||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type seenPacketFlags uint8
|
||||||
|
|
||||||
|
// Valid seenPacketFlags values.
|
||||||
|
const (
|
||||||
|
seenJoinGame seenPacketFlags = 1 << iota
|
||||||
|
seenServerDifficulty
|
||||||
|
seenPlayerAbilities
|
||||||
|
seenPlayerInventory
|
||||||
|
seenUpdateLight
|
||||||
|
seenChunkData
|
||||||
|
seenPlayerPositionAndLook
|
||||||
|
seenSpawnPos
|
||||||
|
|
||||||
|
// gameReadyMinPackets are the minimum set of packets that must be seen, for
|
||||||
|
// the GameReady callback to be invoked.
|
||||||
|
gameReadyMinPackets = seenJoinGame | seenChunkData | seenUpdateLight |
|
||||||
|
seenPlayerAbilities | seenPlayerInventory | seenServerDifficulty |
|
||||||
|
seenPlayerPositionAndLook | seenSpawnPos
|
||||||
|
)
|
||||||
|
|
||||||
type eventBroker struct {
|
type eventBroker struct {
|
||||||
|
seenPackets seenPacketFlags
|
||||||
|
isReady bool
|
||||||
|
|
||||||
GameStart func() error
|
GameStart func() error
|
||||||
ChatMsg func(msg chat.Message, pos byte, sender uuid.UUID) error
|
ChatMsg func(msg chat.Message, pos byte, sender uuid.UUID) error
|
||||||
Disconnect func(reason chat.Message) error
|
Disconnect func(reason chat.Message) error
|
||||||
@ -28,7 +51,29 @@ type eventBroker struct {
|
|||||||
WindowsItem func(id byte, slots []entity.Slot) error
|
WindowsItem func(id byte, slots []entity.Slot) error
|
||||||
WindowsItemChange func(id byte, slotID int, slot entity.Slot) error
|
WindowsItemChange func(id byte, slotID int, slot entity.Slot) error
|
||||||
|
|
||||||
// ReceivePacket will be called when new packet arrive.
|
// ServerDifficultyChange is called whenever the gamemode of the server changes.
|
||||||
// Default handler will run only if pass == false.
|
// At time of writing (1.16.3), difficulty values of 0, 1, 2, and 3 correspond
|
||||||
|
// to peaceful, easy, normal, and hard respectively.
|
||||||
|
ServerDifficultyChange func(difficulty int) error
|
||||||
|
|
||||||
|
// GameReady is called after the client has joined the server and successfully
|
||||||
|
// received player state. Additionally, the server has begun sending world
|
||||||
|
// state (such as lighting and chunk information).
|
||||||
|
//
|
||||||
|
// Use this callback as a signal as to when your bot should start 'doing'
|
||||||
|
// things.
|
||||||
|
GameReady func() error
|
||||||
|
|
||||||
|
// ReceivePacket will be called when new packets arrive.
|
||||||
|
// The default handler will run only if pass == false.
|
||||||
ReceivePacket func(p pk.Packet) (pass bool, err error)
|
ReceivePacket func(p pk.Packet) (pass bool, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *eventBroker) updateSeenPackets(f seenPacketFlags) error {
|
||||||
|
b.seenPackets |= f
|
||||||
|
if (^b.seenPackets)&gameReadyMinPackets == 0 && b.GameReady != nil && !b.isReady {
|
||||||
|
b.isReady = true
|
||||||
|
return b.GameReady()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -71,12 +71,33 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
if err == nil && c.Events.GameStart != nil {
|
if err == nil && c.Events.GameStart != nil {
|
||||||
err = c.Events.GameStart()
|
err = c.Events.GameStart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = c.conn.WritePacket(
|
||||||
|
//PluginMessage packet (serverbound) - sending minecraft brand.
|
||||||
|
pk.Marshal(
|
||||||
|
data.PluginMessageServerbound,
|
||||||
|
pk.Identifier("minecraft:brand"),
|
||||||
|
pk.String(c.settings.Brand),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenJoinGame); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.PluginMessageClientbound:
|
case data.PluginMessageClientbound:
|
||||||
err = handlePluginPacket(c, p)
|
err = handlePluginPacket(c, p)
|
||||||
case data.ServerDifficulty:
|
case data.ServerDifficulty:
|
||||||
err = handleServerDifficultyPacket(c, p)
|
err = handleServerDifficultyPacket(c, p)
|
||||||
|
if err == nil && c.Events.ServerDifficultyChange != nil {
|
||||||
|
err = c.Events.ServerDifficultyChange(c.Difficulty)
|
||||||
|
}
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenServerDifficulty); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.SpawnPosition:
|
case data.SpawnPosition:
|
||||||
err = handleSpawnPositionPacket(c, p)
|
err = handleSpawnPositionPacket(c, p)
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenSpawnPos); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.PlayerAbilitiesClientbound:
|
case data.PlayerAbilitiesClientbound:
|
||||||
err = handlePlayerAbilitiesPacket(c, p)
|
err = handlePlayerAbilitiesPacket(c, p)
|
||||||
_ = c.conn.WritePacket(
|
_ = c.conn.WritePacket(
|
||||||
@ -91,13 +112,24 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) {
|
|||||||
pk.VarInt(c.settings.MainHand),
|
pk.VarInt(c.settings.MainHand),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenPlayerAbilities); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.HeldItemChangeClientbound:
|
case data.HeldItemChangeClientbound:
|
||||||
err = handleHeldItemPacket(c, p)
|
err = handleHeldItemPacket(c, p)
|
||||||
|
case data.UpdateLight:
|
||||||
|
err = c.Events.updateSeenPackets(seenUpdateLight)
|
||||||
case data.ChunkData:
|
case data.ChunkData:
|
||||||
err = handleChunkDataPacket(c, p)
|
err = handleChunkDataPacket(c, p)
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenChunkData); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.PlayerPositionAndLookClientbound:
|
case data.PlayerPositionAndLookClientbound:
|
||||||
err = handlePlayerPositionAndLookPacket(c, p)
|
err = handlePlayerPositionAndLookPacket(c, p)
|
||||||
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
sendPlayerPositionAndLookPacket(c) // to confirm the position
|
||||||
|
if err2 := c.Events.updateSeenPackets(seenPlayerPositionAndLook); err == nil {
|
||||||
|
err = err2
|
||||||
|
}
|
||||||
case data.DeclareRecipes:
|
case data.DeclareRecipes:
|
||||||
// handleDeclareRecipesPacket(g, reader)
|
// handleDeclareRecipesPacket(g, reader)
|
||||||
case data.EntityLookAndRelativeMove:
|
case data.EntityLookAndRelativeMove:
|
||||||
@ -395,6 +427,16 @@ func handlePluginPacket(c *Client, p pk.Packet) error {
|
|||||||
if err := p.Scan(&Channel, &Data); err != nil {
|
if err := p.Scan(&Channel, &Data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch Channel {
|
||||||
|
case "minecraft:brand":
|
||||||
|
var brandRaw pk.String
|
||||||
|
if err := brandRaw.Decode(bytes.NewReader(Data)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.ServInfo.Brand = string(brandRaw)
|
||||||
|
}
|
||||||
|
|
||||||
if c.Events.PluginMessage != nil {
|
if c.Events.PluginMessage != nil {
|
||||||
return c.Events.PluginMessage(string(Channel), []byte(Data))
|
return c.Events.PluginMessage(string(Channel), []byte(Data))
|
||||||
}
|
}
|
||||||
@ -417,8 +459,8 @@ func handleSpawnPositionPacket(c *Client, p pk.Packet) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// c.SpawnPosition.X, c.SpawnPosition.Y, c.SpawnPosition.Z =
|
c.SpawnPosition.X, c.SpawnPosition.Y, c.SpawnPosition.Z =
|
||||||
// pos.X, pos.Y, pos.Z
|
pos.X, pos.Y, pos.Z
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,11 +640,7 @@ func handleKeepAlivePacket(c *Client, p pk.Packet) error {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleWindowItemsPacket(c *Client, p pk.Packet) (err error) {
|
func handleWindowItemsPacket(c *Client, p pk.Packet) error {
|
||||||
if c.Events.WindowsItem == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
r := bytes.NewReader(p.Data)
|
r := bytes.NewReader(p.Data)
|
||||||
var (
|
var (
|
||||||
windowID pk.Byte
|
windowID pk.Byte
|
||||||
@ -623,6 +661,14 @@ func handleWindowItemsPacket(c *Client, p pk.Packet) (err error) {
|
|||||||
slots = append(slots, slot)
|
slots = append(slots, slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if windowID == 0 { // Window ID 0 is the players' inventory.
|
||||||
|
if err := c.Events.updateSeenPackets(seenPlayerInventory); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.Events.WindowsItem == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return c.Events.WindowsItem(byte(windowID), slots)
|
return c.Events.WindowsItem(byte(windowID), slots)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolVersion , the protocol version number of minecraft net protocol
|
// ProtocolVersion , the protocol version number of minecraft net protocol
|
||||||
const ProtocolVersion = 751
|
const ProtocolVersion = 753
|
||||||
|
|
||||||
// JoinServer connect a Minecraft server for playing the game.
|
// JoinServer connect a Minecraft server for playing the game.
|
||||||
func (c *Client) JoinServer(addr string, port int) (err error) {
|
func (c *Client) JoinServer(addr string, port int) (err error) {
|
||||||
|
@ -9,6 +9,7 @@ type Settings struct {
|
|||||||
DisplayedSkinParts uint8 //皮肤显示
|
DisplayedSkinParts uint8 //皮肤显示
|
||||||
MainHand int //主手
|
MainHand int //主手
|
||||||
ReceiveMap bool //接收地图数据
|
ReceiveMap bool //接收地图数据
|
||||||
|
Brand string // The brand string presented to the server.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -33,4 +34,5 @@ var DefaultSettings = Settings{
|
|||||||
DisplayedSkinParts: Jacket | LeftSleeve | RightSleeve | LeftPantsLeg | RightPantsLeg | Hat,
|
DisplayedSkinParts: Jacket | LeftSleeve | RightSleeve | LeftPantsLeg | RightPantsLeg | Hat,
|
||||||
MainHand: 1,
|
MainHand: 1,
|
||||||
ReceiveMap: true,
|
ReceiveMap: true,
|
||||||
|
Brand: "vanilla",
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user