diff --git a/bot/event.go b/bot/event.go index a63593c..a34c280 100644 --- a/bot/event.go +++ b/bot/event.go @@ -18,6 +18,13 @@ type eventBroker struct { PluginMessage func(channel string, data []byte) error HeldItemChange func(slot int) error + // ExperienceChange will be called every time player's experience level updates. + // Parameters: + // bar - state of the experience bar from 0.0 to 1.0; + // level - current level; + // total - total amount of experience received from level 0. + ExperienceChange func(bar float32, level int32, total int32) error + WindowsItem func(id byte, slots []entity.Slot) error WindowsItemChange func(id byte, slotID int, slot entity.Slot) error diff --git a/bot/ingame.go b/bot/ingame.go index ec97122..5f96286 100644 --- a/bot/ingame.go +++ b/bot/ingame.go @@ -130,6 +130,8 @@ func (c *Client) handlePacket(p pk.Packet) (disconnect bool, err error) { err = handleSoundEffect(c, p) case data.NamedSoundEffect: err = handleNamedSoundEffect(c, p) + case data.SetExperience: + err = handleSetExperience(c, p) default: // fmt.Printf("ignore pack id %X\n", p.ID) } @@ -612,6 +614,26 @@ func handleWindowItemsPacket(c *Client, p pk.Packet) (err error) { return c.Events.WindowsItem(byte(windowID), slots) } +func handleSetExperience(c *Client, p pk.Packet) (err error) { + var ( + bar pk.Float + level pk.VarInt + total pk.VarInt + ) + + if err := p.Scan(&bar, &level, &total); err != nil { + return err + } + + c.Level = int32(level) + + if c.Events.ExperienceChange != nil { + return c.Events.ExperienceChange(float32(bar), int32(level), int32(total)) + } + + return nil +} + func sendPlayerPositionAndLookPacket(c *Client) { c.conn.WritePacket(pk.Marshal( data.PlayerPositionAndLookServerbound, diff --git a/bot/world/entity/player/player.go b/bot/world/entity/player/player.go index 54491c2..9a30332 100644 --- a/bot/world/entity/player/player.go +++ b/bot/world/entity/player/player.go @@ -16,4 +16,6 @@ type Player struct { Health float32 //血量 Food int32 //饱食度 FoodSaturation float32 //食物饱和度 + + Level int32 }