From 2fe0cd17e14473f0d7ffd5a1f5f100bd2419b018 Mon Sep 17 00:00:00 2001 From: Himbeer Date: Sat, 7 Dec 2024 13:57:39 +0100 Subject: Implement inventory plugin API This change adds an API to retrieve a read-only copy of the current inventory and listen for and modify inventory actions. Closes #90. --- plugin_inv.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ process.go | 11 +++++++++++ 2 files changed, 56 insertions(+) create mode 100644 plugin_inv.go diff --git a/plugin_inv.go b/plugin_inv.go new file mode 100644 index 0000000..6a8ffa5 --- /dev/null +++ b/plugin_inv.go @@ -0,0 +1,45 @@ +package proxy + +import ( + "bytes" + "sync" + + "github.com/HimbeerserverDE/mt" +) + +var ( + onInvAction []func(*ClientConn, string) string + onInvActionMu sync.RWMutex +) + +// Inv returns a copy of the current server-provided inventory of the client +// or nil if the client is not connected to a server. +func (cc *ClientConn) Inv() mt.Inv { + sc := cc.server() + if sc == nil { + return nil + } + + var ret mt.Inv + + sb := &bytes.Buffer{} + sc.inv.Serialize(sb) + ret.Deserialize(sb) + + return ret +} + +// RegisterOnInvAction registers a handler that is called +// when a client attempts to perform an inventory action. +// The returned string overrides the original action. +// Later handlers will receive the modified action. +// Handlers are called in registration order. +// If the final action string is empty, the action is not forwarded +// to the upstream server. +// You may use the mt package to interact with the action strings. +func RegisterOnInvAction(handler func(*ClientConn, string) string) { + onInvActionMu.Lock() + defer onInvActionMu.Unlock() + + onInvAction = append(onInvAction, handler) +} diff --git a/process.go b/process.go index 1d8263f..b7623b5 100644 --- a/process.go +++ b/process.go @@ -484,6 +484,17 @@ func (cc *ClientConn) process(pkt mt.Pkt) { case *mt.ToSrvCltInfo: // Store for any future hops (need to send it to the new server). cc.cltInfo = cmd + case *mt.ToSrvInvAction: + onInvActionMu.RLock() + defer onInvActionMu.RUnlock() + + for _, handler := range onInvAction { + cmd.Action = handler(cc, cmd.Action) + } + + if cmd.Action == "" { + return + } case *mt.ToSrvInvFields: if handleOnPlayerReceiveFields(cc, cmd) { return -- cgit v1.2.3