Enhance support of screens
This commit is contained in:
7
bot/screen/events.go
Normal file
7
bot/screen/events.go
Normal file
@ -0,0 +1,7 @@
|
||||
package screen
|
||||
|
||||
type EventsListener struct {
|
||||
Open func(id int) error
|
||||
SetSlot func(id, index int) error
|
||||
Close func(id int) error
|
||||
}
|
@ -1,16 +1,29 @@
|
||||
package screen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Tnze/go-mc/data/item"
|
||||
"github.com/Tnze/go-mc/nbt"
|
||||
)
|
||||
import "errors"
|
||||
|
||||
type Inventory struct {
|
||||
Slots [46]Slot
|
||||
}
|
||||
|
||||
func (inv Inventory) SetSlot(i int, id int32, count byte, NBT nbt.RawMessage) {
|
||||
// TODO: accept inv data
|
||||
fmt.Printf("Inventory[%d] = minecraft:%v * %d\n", i, item.ByID[item.ID(id)].Name, count)
|
||||
func (inv *Inventory) onClose() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (inv *Inventory) onSetSlot(i int, s Slot) error {
|
||||
if i < 0 || i >= len(inv.Slots) {
|
||||
return errors.New("slot index out of bounds")
|
||||
}
|
||||
inv.Slots[i] = s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (inv *Inventory) CraftingOutput() *Slot { return &inv.Slots[0] }
|
||||
func (inv *Inventory) CraftingInput() []Slot { return inv.Slots[1 : 1+4] }
|
||||
|
||||
// Armor returns to the armor section of the Inventory.
|
||||
// The length is 4, which are head, chest, legs and feet.
|
||||
func (inv *Inventory) Armor() []Slot { return inv.Slots[5 : 5+4] }
|
||||
func (inv *Inventory) Main() []Slot { return inv.Slots[9 : 9+3*9] }
|
||||
func (inv *Inventory) Hotbar() []Slot { return inv.Slots[36 : 36+9] }
|
||||
func (inv *Inventory) Offhand() *Slot { return &inv.Slots[45] }
|
||||
|
@ -1,6 +1,7 @@
|
||||
package screen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
@ -11,15 +12,23 @@ import (
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
Screens map[byte]Container
|
||||
Screens map[int]Container
|
||||
Inventory Inventory
|
||||
Cursor Slot
|
||||
events EventsListener
|
||||
}
|
||||
|
||||
func NewManager(c *bot.Client) *Manager {
|
||||
m := &Manager{Screens: make(map[byte]Container)}
|
||||
m.Screens[0] = &Inventory{}
|
||||
func NewManager(c *bot.Client, e EventsListener) *Manager {
|
||||
m := &Manager{
|
||||
Screens: make(map[int]Container),
|
||||
events: e,
|
||||
}
|
||||
m.Screens[0] = &m.Inventory
|
||||
c.Events.AddListener(
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.OpenWindow, F: m.onOpenScreen},
|
||||
bot.PacketHandler{Priority: 64, ID: packetid.WindowItems, F: m.onSetContentPacket},
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.OpenWindow, F: m.onOpenScreen},
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.WindowItems, F: m.onSetContentPacket},
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.CloseWindowClientbound, F: m.onCloseScreen},
|
||||
bot.PacketHandler{Priority: 0, ID: packetid.SetSlot, F: m.onSetSlot},
|
||||
)
|
||||
return m
|
||||
}
|
||||
@ -33,7 +42,14 @@ func (m *Manager) onOpenScreen(p pk.Packet) error {
|
||||
if err := p.Scan(&ContainerID, &Type, &Title); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
//if c, ok := m.Screens[byte(ContainerID)]; ok {
|
||||
// TODO: Create the specified container
|
||||
//}
|
||||
if m.events.Open != nil {
|
||||
if err := m.events.Open(int(ContainerID)); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -41,7 +57,7 @@ func (m *Manager) onSetContentPacket(p pk.Packet) error {
|
||||
var (
|
||||
ContainerID pk.UnsignedByte
|
||||
Count pk.Short
|
||||
SlotData []slot
|
||||
SlotData []Slot
|
||||
)
|
||||
if err := p.Scan(
|
||||
&ContainerID,
|
||||
@ -51,32 +67,93 @@ func (m *Manager) onSetContentPacket(p pk.Packet) error {
|
||||
}); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
container := m.Screens[byte(ContainerID)]
|
||||
// copy the slot data to container
|
||||
container, ok := m.Screens[int(ContainerID)]
|
||||
if !ok {
|
||||
return Error{errors.New("setting content of non-exist container")}
|
||||
}
|
||||
for i, v := range SlotData {
|
||||
container.SetSlot(i, int32(v.id), byte(v.count), v.nbt)
|
||||
err := container.onSetSlot(i, v)
|
||||
if err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
if m.events.SetSlot != nil {
|
||||
if err := m.events.SetSlot(int(ContainerID), i); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type slot struct {
|
||||
present pk.Boolean
|
||||
id pk.VarInt
|
||||
count pk.Byte
|
||||
nbt nbt.RawMessage
|
||||
func (m *Manager) onCloseScreen(p pk.Packet) error {
|
||||
var ContainerID pk.UnsignedByte
|
||||
if err := p.Scan(&ContainerID); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
if c, ok := m.Screens[int(ContainerID)]; ok {
|
||||
delete(m.Screens, int(ContainerID))
|
||||
if err := c.onClose(); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
if m.events.Close != nil {
|
||||
if err := m.events.Close(int(ContainerID)); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *slot) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
func (m *Manager) onSetSlot(p pk.Packet) (err error) {
|
||||
var (
|
||||
ContainerID pk.Byte
|
||||
SlotID pk.Short
|
||||
ItemStack Slot
|
||||
)
|
||||
if err := p.Scan(&ContainerID, &SlotID, &ItemStack); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
|
||||
if ContainerID == -1 && SlotID == -1 {
|
||||
m.Cursor = ItemStack
|
||||
} else if ContainerID == -2 {
|
||||
err = m.Inventory.onSetSlot(int(SlotID), ItemStack)
|
||||
} else if c, ok := m.Screens[int(ContainerID)]; ok {
|
||||
err = c.onSetSlot(int(SlotID), ItemStack)
|
||||
}
|
||||
|
||||
if m.events.Close != nil {
|
||||
if err := m.events.Close(int(ContainerID)); err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Slot struct {
|
||||
ID pk.VarInt
|
||||
Count pk.Byte
|
||||
NBT nbt.RawMessage
|
||||
}
|
||||
|
||||
func (s *Slot) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var present pk.Boolean
|
||||
return pk.Tuple{
|
||||
&s.present, pk.Opt{Has: &s.present,
|
||||
&present, pk.Opt{Has: &present,
|
||||
Field: pk.Tuple{
|
||||
&s.id, &s.count, pk.NBT(&s.nbt),
|
||||
&s.ID, &s.Count, pk.NBT(&s.NBT),
|
||||
},
|
||||
},
|
||||
}.ReadFrom(r)
|
||||
}
|
||||
|
||||
type Container interface {
|
||||
SetSlot(i int, id int32, count byte, NBT nbt.RawMessage)
|
||||
onSetSlot(i int, s Slot) error
|
||||
onClose() error
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
|
@ -1,29 +0,0 @@
|
||||
package screen
|
||||
|
||||
type Info struct {
|
||||
Name string
|
||||
Start, End int // Player inventory
|
||||
Slots int
|
||||
}
|
||||
|
||||
func (i Info) PlayerInvStart() int {
|
||||
return i.Start
|
||||
}
|
||||
|
||||
func (i Info) PlayerInvEnd() int {
|
||||
return i.End
|
||||
}
|
||||
|
||||
func (i Info) HotbarIdx(place int) int {
|
||||
return i.End - (8 - place)
|
||||
}
|
||||
|
||||
var ByType = map[int]Info{
|
||||
-1: {Name: "inventory", Start: 9, End: 44, Slots: 46},
|
||||
0: {Name: "generic_9x1", Start: 1 * 9, End: 1*9 + 35, Slots: 1*9 + 36},
|
||||
1: {Name: "generic_9x2", Start: 2 * 9, End: 2*9 + 35, Slots: 2*9 + 36},
|
||||
2: {Name: "generic_9x3", Start: 3 * 9, End: 3*9 + 35, Slots: 3*9 + 36},
|
||||
3: {Name: "generic_9x4", Start: 4 * 9, End: 4*9 + 35, Slots: 4*9 + 36},
|
||||
4: {Name: "generic_9x5", Start: 5 * 9, End: 5*9 + 35, Slots: 5*9 + 36},
|
||||
5: {Name: "generic_9x6", Start: 6 * 9, End: 6*9 + 35, Slots: 6*9 + 36},
|
||||
}
|
@ -11,15 +11,15 @@ package chat
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
en_us "github.com/Tnze/go-mc/data/lang/en-us"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
en_us "github.com/Tnze/go-mc/data/lang/en-us"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
)
|
||||
|
||||
//Message is a message sent by other
|
||||
// Message is a message sent by other
|
||||
type Message jsonChat
|
||||
|
||||
type jsonChat struct {
|
||||
@ -50,7 +50,7 @@ func (m *Message) UnmarshalJSON(jsonMsg []byte) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//Decode for a ChatMsg packet
|
||||
// ReadFrom decode Message in a ChatMsg packet
|
||||
func (m *Message) ReadFrom(r io.Reader) (int64, error) {
|
||||
var Len pk.VarInt
|
||||
if n, err := Len.ReadFrom(r); err != nil {
|
||||
@ -61,7 +61,7 @@ func (m *Message) ReadFrom(r io.Reader) (int64, error) {
|
||||
return int64(Len) - lr.N, err
|
||||
}
|
||||
|
||||
//Encode for a ChatMsg packet
|
||||
// WriteTo encode Message into a ChatMsg packet
|
||||
func (m Message) WriteTo(w io.Writer) (int64, error) {
|
||||
code, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
@ -174,7 +174,7 @@ func (m Message) ClearString() string {
|
||||
|
||||
if m.Extra != nil {
|
||||
for i := range m.Extra {
|
||||
msg.WriteString(Message(m.Extra[i]).ClearString())
|
||||
msg.WriteString(m.Extra[i].ClearString())
|
||||
}
|
||||
}
|
||||
return msg.String()
|
||||
@ -225,7 +225,7 @@ func (m Message) String() string {
|
||||
|
||||
if m.Extra != nil {
|
||||
for i := range m.Extra {
|
||||
msg.WriteString(Message(m.Extra[i]).String())
|
||||
msg.WriteString(m.Extra[i].String())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
var address = flag.String("address", "127.0.0.1", "The server address")
|
||||
var client *bot.Client
|
||||
var player *basic.Player
|
||||
var screenManager *screen.Manager
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
@ -32,7 +33,11 @@ func main() {
|
||||
Disconnect: onDisconnect,
|
||||
Death: onDeath,
|
||||
}.Attach(client)
|
||||
_ = screen.NewManager(client)
|
||||
screenManager = screen.NewManager(client, screen.EventsListener{
|
||||
Open: nil,
|
||||
SetSlot: onScreenSlotChange,
|
||||
Close: nil,
|
||||
})
|
||||
|
||||
//Login
|
||||
err := client.JoinServer(*address)
|
||||
@ -84,6 +89,18 @@ func onChatMsg(c chat.Message, _ byte, _ uuid.UUID) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func onScreenSlotChange(id, index int) error {
|
||||
if id == -2 {
|
||||
log.Printf("Slot change: inventory: %v", screenManager.Inventory.Slots[index])
|
||||
} else if id == -1 && index == -1 {
|
||||
log.Printf("Slot change: cursor: %v", screenManager.Cursor)
|
||||
} else {
|
||||
container := screenManager.Screens[id]
|
||||
log.Printf("Slot change: Screen[%d].Slot[%d]: %T", id, index, container)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DisconnectErr struct {
|
||||
Reason chat.Message
|
||||
}
|
||||
|
Reference in New Issue
Block a user