From 4e23ad63a23cb70d7be2aac1d144e345acc67379 Mon Sep 17 00:00:00 2001 From: Tnze Date: Fri, 6 Jan 2023 20:01:05 +0800 Subject: [PATCH] support multi handler for same packetID and handler priority. --- bot/client.go | 5 +++-- bot/event.go | 46 +++++++++++++++++++--------------------------- bot/ingame.go | 18 +++++++----------- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/bot/client.go b/bot/client.go index e754702..2c32b44 100644 --- a/bot/client.go +++ b/bot/client.go @@ -1,10 +1,11 @@ package bot import ( + "github.com/google/uuid" + "github.com/Tnze/go-mc/data/packetid" "github.com/Tnze/go-mc/net" "github.com/Tnze/go-mc/yggdrasil/user" - "github.com/google/uuid" ) // Client is used to access Minecraft server @@ -34,7 +35,7 @@ func (c *Client) Close() error { func NewClient() *Client { return &Client{ Auth: Auth{Name: "Steve"}, - Events: Events{handlers: make(map[packetid.ClientboundPacketID]*handlerHeap)}, + Events: Events{handlers: make([][]PacketHandler, packetid.ClientboundPacketIDGuard)}, } } diff --git a/bot/event.go b/bot/event.go index 393a795..5f5a3ad 100644 --- a/bot/event.go +++ b/bot/event.go @@ -1,24 +1,29 @@ package bot import ( + "sort" + "strconv" + "github.com/Tnze/go-mc/data/packetid" pk "github.com/Tnze/go-mc/net/packet" ) type Events struct { - generic *handlerHeap // for every packet - handlers map[packetid.ClientboundPacketID]*handlerHeap // for specific packet id only + generic []PacketHandler // for every packet + handlers [][]PacketHandler // for specific packet id only } func (e *Events) AddListener(listeners ...PacketHandler) { for _, l := range listeners { - var s *handlerHeap - var ok bool - if s, ok = e.handlers[l.ID]; !ok { - s = &handlerHeap{l} - e.handlers[l.ID] = s + // panic if l.ID is invalid + if l.ID < 0 || int(l.ID) >= len(e.handlers) { + panic("Invalid packet ID (" + strconv.Itoa(int(l.ID)) + ")") + } + if s := e.handlers[l.ID]; s == nil { + e.handlers[l.ID] = []PacketHandler{l} } else { - s.Push(l) + e.handlers[l.ID] = append(s, l) + sortPacketHandlers(e.handlers[l.ID]) } } } @@ -26,13 +31,8 @@ func (e *Events) AddListener(listeners ...PacketHandler) { // AddGeneric adds listeners like AddListener, but the packet ID is ignored. // Generic listener is always called before specific packet listener. func (e *Events) AddGeneric(listeners ...PacketHandler) { - for _, l := range listeners { - if e.generic == nil { - e.generic = &handlerHeap{l} - } else { - e.generic.Push(l) - } - } + e.generic = append(e.generic, listeners...) + sortPacketHandlers(e.generic) } type ( @@ -44,16 +44,8 @@ type ( } ) -// handlerHeap is PriorityQueue -type handlerHeap []PacketHandler - -func (h handlerHeap) Len() int { return len(h) } -func (h handlerHeap) Less(i, j int) bool { return h[i].Priority < h[j].Priority } -func (h handlerHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } -func (h *handlerHeap) Push(x interface{}) { *h = append(*h, x.(PacketHandler)) } -func (h *handlerHeap) Pop() interface{} { - old := *h - n := len(old) - *h = old[0 : n-1] - return old[n-1] +func sortPacketHandlers(slice []PacketHandler) { + sort.SliceStable(slice, func(i, j int) bool { + return slice[i].Priority > slice[j].Priority + }) } diff --git a/bot/ingame.go b/bot/ingame.go index e416bf4..011050b 100644 --- a/bot/ingame.go +++ b/bot/ingame.go @@ -40,19 +40,15 @@ func (d PacketHandlerError) Unwrap() error { func (c *Client) handlePacket(p pk.Packet) (err error) { packetID := packetid.ClientboundPacketID(p.ID) - if c.Events.generic != nil { - for _, handler := range *c.Events.generic { - if err = handler.F(p); err != nil { - return PacketHandlerError{ID: packetID, Err: err} - } + for _, handler := range c.Events.generic { + if err = handler.F(p); err != nil { + return PacketHandlerError{ID: packetID, Err: err} } } - if listeners := c.Events.handlers[packetID]; listeners != nil { - for _, handler := range *listeners { - err = handler.F(p) - if err != nil { - return PacketHandlerError{ID: packetID, Err: err} - } + for _, handler := range c.Events.handlers[packetID] { + err = handler.F(p) + if err != nil { + return PacketHandlerError{ID: packetID, Err: err} } } return