diff --git a/bot/basic/basic.go b/bot/basic/basic.go index c251824..3eb4745 100644 --- a/bot/basic/basic.go +++ b/bot/basic/basic.go @@ -18,9 +18,9 @@ type Player struct { func NewPlayer(c *bot.Client, settings Settings) *Player { b := &Player{c: c, Settings: settings} c.Events.AddListener( - bot.PacketHandler{Priority: 0, ID: packetid.ClientboundLogin, F: b.handleJoinGamePacket}, + bot.PacketHandler{Priority: 0, ID: packetid.ClientboundLogin, F: b.handleLoginPacket}, bot.PacketHandler{Priority: 0, ID: packetid.ClientboundKeepAlive, F: b.handleKeepAlivePacket}, - bot.PacketHandler{Priority: 0, ID: packetid.ClientboundPlayerPosition, F: b.handlePlayerPositionAndLook}, + bot.PacketHandler{Priority: 0, ID: packetid.ClientboundPlayerPosition, F: b.handlePlayerPosition}, ) return b } diff --git a/bot/basic/info.go b/bot/basic/info.go index ab84f0f..b549157 100644 --- a/bot/basic/info.go +++ b/bot/basic/info.go @@ -39,7 +39,7 @@ type ServInfo struct { Brand string } -func (p *Player) handleJoinGamePacket(packet pk.Packet) error { +func (p *Player) handleLoginPacket(packet pk.Packet) error { var WorldCount pk.VarInt var WorldNames = make([]pk.Identifier, 0) err := packet.Scan( @@ -89,7 +89,8 @@ func (p *Player) handleJoinGamePacket(packet pk.Packet) error { pk.Boolean(p.Settings.ChatColors), pk.UnsignedByte(p.Settings.DisplayedSkinParts), pk.VarInt(p.Settings.MainHand), - pk.Boolean(p.Settings.DisableTextFiltering), + pk.Boolean(p.Settings.EnableTextFiltering), + pk.Boolean(p.Settings.AllowListing), )) if err != nil { return Error{err} diff --git a/bot/basic/keepalive.go b/bot/basic/keepalive.go index 5580f67..53df512 100644 --- a/bot/basic/keepalive.go +++ b/bot/basic/keepalive.go @@ -21,7 +21,7 @@ func (p Player) handleKeepAlivePacket(packet pk.Packet) error { return nil } -func (p *Player) handlePlayerPositionAndLook(packet pk.Packet) error { +func (p *Player) handlePlayerPosition(packet pk.Packet) error { var ( X, Y, Z pk.Double Yaw, Pitch pk.Float @@ -48,7 +48,6 @@ func (p *Player) handlePlayerPositionAndLook(packet pk.Packet) error { packetid.ServerboundMoveVehicle, X, Y-1.62, Z, Yaw, Pitch, - pk.Boolean(true), )) if err != nil { return Error{err} diff --git a/bot/basic/settings.go b/bot/basic/settings.go index d72a92e..54b20ec 100644 --- a/bot/basic/settings.go +++ b/bot/basic/settings.go @@ -9,17 +9,17 @@ type Settings struct { DisplayedSkinParts uint8 //皮肤显示 MainHand int //主手 - // Disables filtering of text on signs and written book titles. - // Currently always true in vanilla client (i.e. the filtering is disabled) - DisableTextFiltering bool + // Enables filtering of text on signs and written book titles. + // Currently, always false (i.e. the filtering is disabled) + EnableTextFiltering bool + AllowListing bool - Brand string // The brand string presented to the server. + // The brand string presented to the server. + Brand string } -/* - Used by Settings.DisplayedSkinParts. - For each bits set if shows match part. -*/ +// Used by Settings.DisplayedSkinParts. +// For each bit set if shows match part. const ( _ = 1 << iota Jacket diff --git a/bot/pinglist.go b/bot/pinglist.go index c4478dc..e613397 100644 --- a/bot/pinglist.go +++ b/bot/pinglist.go @@ -28,7 +28,7 @@ func PingAndList(addr string) ([]byte, time.Duration, error) { return pingAndList(addr, conn) } -// PingAndListTimeout PingAndLIstTimeout is the version of PingAndList with max request time. +// PingAndListTimeout is the version of PingAndList with max request time. func PingAndListTimeout(addr string, timeout time.Duration) ([]byte, time.Duration, error) { deadLine := time.Now().Add(timeout) diff --git a/bot/screen/screen.go b/bot/screen/screen.go index d4c5555..e22b66d 100644 --- a/bot/screen/screen.go +++ b/bot/screen/screen.go @@ -12,14 +12,19 @@ import ( ) type Manager struct { + c *bot.Client + Screens map[int]Container Inventory Inventory Cursor Slot events EventsListener + // The last received State ID from server + stateID int32 } func NewManager(c *bot.Client, e EventsListener) *Manager { m := &Manager{ + c: c, Screens: make(map[int]Container), events: e, } @@ -33,6 +38,18 @@ func NewManager(c *bot.Client, e EventsListener) *Manager { return m } +//func (m *Manager) ContainerClick(id int, slot int16, button byte, mode int32) error { +// return m.c.Conn.WritePacket(pk.Marshal( +// packetid.ServerboundContainerClick, +// pk.UnsignedByte(id), +// pk.VarInt(m.stateID), +// pk.Short(slot), +// pk.Byte(button), +// pk.VarInt(mode), +// pk.VarInt() +// )) +//} + func (m *Manager) onOpenScreen(p pk.Packet) error { var ( ContainerID pk.VarInt @@ -72,6 +89,7 @@ func (m *Manager) onSetContentPacket(p pk.Packet) error { ); err != nil { return Error{err} } + m.stateID = int32(StateID) // copy the slot data to container container, ok := m.Screens[int(ContainerID)] if !ok { @@ -113,19 +131,21 @@ func (m *Manager) onCloseScreen(p pk.Packet) error { func (m *Manager) onSetSlot(p pk.Packet) (err error) { var ( ContainerID pk.Byte + StateID pk.VarInt SlotID pk.Short - ItemStack Slot + SlotData Slot ) - if err := p.Scan(&ContainerID, &SlotID, &ItemStack); err != nil { + if err := p.Scan(&ContainerID, &StateID, &SlotID, &SlotData); err != nil { return Error{err} } + m.stateID = int32(StateID) if ContainerID == -1 && SlotID == -1 { - m.Cursor = ItemStack + m.Cursor = SlotData } else if ContainerID == -2 { - err = m.Inventory.onSetSlot(int(SlotID), ItemStack) + err = m.Inventory.onSetSlot(int(SlotID), SlotData) } else if c, ok := m.Screens[int(ContainerID)]; ok { - err = c.onSetSlot(int(SlotID), ItemStack) + err = c.onSetSlot(int(SlotID), SlotData) } if m.events.SetSlot != nil { diff --git a/data/item/item.go b/data/item/item.go index d2469a4..c584d12 100644 --- a/data/item/item.go +++ b/data/item/item.go @@ -13,6 +13,10 @@ type Item struct { StackSize uint } +func (i Item) String() string { + return i.DisplayName +} + var ( Stone = Item{ ID: 1, diff --git a/examples/autofish/autofish.go b/examples/autofish/autofish.go index e33d34e..2524679 100644 --- a/examples/autofish/autofish.go +++ b/examples/autofish/autofish.go @@ -1,17 +1,17 @@ package main import ( - "github.com/Tnze/go-mc/bot/basic" - "github.com/Tnze/go-mc/data/packetid" - pk "github.com/Tnze/go-mc/net/packet" "log" "time" "github.com/google/uuid" "github.com/Tnze/go-mc/bot" + "github.com/Tnze/go-mc/bot/basic" "github.com/Tnze/go-mc/chat" _ "github.com/Tnze/go-mc/data/lang/en-us" + "github.com/Tnze/go-mc/data/packetid" + pk "github.com/Tnze/go-mc/net/packet" "github.com/mattn/go-colorable" ) diff --git a/examples/daze/daze.go b/examples/daze/daze.go index 3afe372..8662bd2 100644 --- a/examples/daze/daze.go +++ b/examples/daze/daze.go @@ -9,6 +9,7 @@ import ( "time" "github.com/google/uuid" + "github.com/mattn/go-colorable" "github.com/Tnze/go-mc/bot" "github.com/Tnze/go-mc/bot/basic" @@ -25,6 +26,7 @@ var screenManager *screen.Manager func main() { flag.Parse() + log.SetOutput(colorable.NewColorableStdout()) client = bot.NewClient() client.Auth.Name = "Daze" player = basic.NewPlayer(client, basic.DefaultSettings) @@ -86,7 +88,7 @@ func onGameStart() error { } func onChatMsg(c chat.Message, _ byte, _ uuid.UUID) error { - log.Println("Chat:", c.ClearString()) // output chat message without any format code (like color or bold) + log.Println("Chat:", c) // output chat message without any format code (like color or bold) return nil } @@ -98,14 +100,12 @@ func onScreenSlotChange(id, index int) error { } else { container, ok := screenManager.Screens[id] if ok { - // Currently only inventory container is supported + // Currently, only inventory container is supported switch container.(type) { case *screen.Inventory: slot := container.(*screen.Inventory).Slots[index] itemInfo := item.ByID[item.ID(slot.ID)] - if slot.ID != 0 { - log.Printf("Slot: Screen[%d].Slot[%d]: [%v] * %d | NBT: %v", id, index, itemInfo.DisplayName, slot.Count, slot.NBT) - } + log.Printf("Slot: Screen[%d].Slot[%d]: [%v] * %d | NBT: %v", id, index, itemInfo, slot.Count, slot.NBT) } } } diff --git a/nbt/rawmsg.go b/nbt/rawmsg.go index 072dcf6..6d55e78 100644 --- a/nbt/rawmsg.go +++ b/nbt/rawmsg.go @@ -43,9 +43,12 @@ func (m *RawMessage) Decode(tagType byte, r DecoderReader) error { // String convert the data into the SNBT(Stringified NBT) format. // The output is valid for using in in-game command. +// Expect two exceptions: +// - Empty string "" if there is only an TagEnd in the NBT (aka: []byte{0}). +// - "" if the content is not valid NBT data. func (m RawMessage) String() string { if m.Type == TagEnd { - return "TagEnd" + return "" } var snbt StringifiedMessage var sb strings.Builder @@ -53,7 +56,7 @@ func (m RawMessage) String() string { d := NewDecoder(r) err := snbt.encode(d, &sb, m.Type) if err != nil { - return "Invalid" + return "" } return sb.String() }