aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-11-17 17:03:18 +0100
committerHimbeer <himbeer@disroot.org>2024-11-17 17:21:02 +0100
commit7b69e587118c299d1601680ef70241283f30a009 (patch)
treef80204e2e750d82c53d2be34201ab81dbb6052f2
parent3b344731fff17f3c5255f278f8f14879e7610f7d (diff)
Allow plugins to handle player join and leave events
This includes the ability to kick a client on join for reasons other than banning. Closes #156.
-rw-r--r--client_conn.go4
-rw-r--r--plugin_join_leave.go82
-rw-r--r--process.go1
3 files changed, 87 insertions, 0 deletions
diff --git a/client_conn.go b/client_conn.go
index 9753147..1a16d94 100644
--- a/client_conn.go
+++ b/client_conn.go
@@ -123,6 +123,10 @@ func handleClt(cc *ClientConn) {
pkt, err := cc.Recv()
if err != nil {
if errors.Is(err, net.ErrClosed) {
+ if cc.state() == csActive {
+ handleLeave(cc)
+ }
+
if errors.Is(cc.WhyClosed(), rudp.ErrTimedOut) {
cc.Log("<->", "timeout")
} else {
diff --git a/plugin_join_leave.go b/plugin_join_leave.go
new file mode 100644
index 0000000..baa4ba3
--- /dev/null
+++ b/plugin_join_leave.go
@@ -0,0 +1,82 @@
+package proxy
+
+import "sync"
+
+var (
+ onJoin []func(*ClientConn) string
+ onJoinMu sync.Mutex
+ onJoinOnce sync.Once
+)
+
+var (
+ onLeave []func(*ClientConn)
+ onLeaveMu sync.Mutex
+ onLeaveOnce sync.Once
+)
+
+// RegisterOnJoin registers a handler that is called
+// when a client finishes connecting to the proxy (TOSERVER_CLIENT_READY packet)
+// but before it is connected to an upstream server.
+// If any handler returns a non-empty string, the client is kicked
+// with that message.
+// Handlers are run sequentially and block the client's connection
+// and packet handling procedure.
+func RegisterOnJoin(handler func(*ClientConn) string) {
+ initOnJoin()
+
+ onJoinMu.Lock()
+ defer onJoinMu.Unlock()
+
+ onJoin = append(onJoin, handler)
+}
+
+// RegisterOnLeave registers a handler that is called
+// when a client disconnects for any reason after reaching the ready stage.
+// Handlers are run sequentially.
+func RegisterOnLeave(handler func(*ClientConn)) {
+ initOnLeave()
+
+ onLeaveMu.Lock()
+ defer onLeaveMu.Unlock()
+
+ onLeave = append(onLeave, handler)
+}
+
+func handleJoin(cc *ClientConn) {
+ onJoinMu.Lock()
+ defer onJoinMu.Unlock()
+
+ for _, handler := range onJoin {
+ if msg := handler(cc); msg != "" {
+ cc.Kick(msg)
+ break
+ }
+ }
+}
+
+func handleLeave(cc *ClientConn) {
+ onLeaveMu.Lock()
+ defer onLeaveMu.Unlock()
+
+ for _, handler := range onLeave {
+ handler(cc)
+ }
+}
+
+func initOnJoin() {
+ onJoinOnce.Do(func() {
+ onJoinMu.Lock()
+ defer onJoinMu.Unlock()
+
+ onJoin = make([]func(*ClientConn) string, 0)
+ })
+}
+
+func initOnLeave() {
+ onLeaveOnce.Do(func() {
+ onLeaveMu.Lock()
+ defer onLeaveMu.Unlock()
+
+ onLeave = make([]func(*ClientConn), 0)
+ })
+}
diff --git a/process.go b/process.go
index 215e6cc..862f29d 100644
--- a/process.go
+++ b/process.go
@@ -435,6 +435,7 @@ func (cc *ClientConn) process(pkt mt.Pkt) {
cc.formspecVer = cmd.Formspec
cc.setState(csActive)
+ handleJoin(cc)
close(cc.initCh)
return