about summary refs log tree commit diff
path: root/assets/src/network/channel/messages/handler.ts
diff options
context:
space:
mode:
authorMelonai <einebeere@gmail.com>2021-06-03 02:10:52 +0200
committerMelonai <einebeere@gmail.com>2021-06-03 02:10:52 +0200
commit1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8 (patch)
tree991147a82958413ed7a5c4a30ce6861bbdabb918 /assets/src/network/channel/messages/handler.ts
parent6f7ce856f784dce0952db2272a85ee70e6e1b159 (diff)
downloadrook-1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8.tar.zst
rook-1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8.zip
Dynamic event handling architecture
Diffstat (limited to 'assets/src/network/channel/messages/handler.ts')
-rw-r--r--assets/src/network/channel/messages/handler.ts93
1 files changed, 93 insertions, 0 deletions
diff --git a/assets/src/network/channel/messages/handler.ts b/assets/src/network/channel/messages/handler.ts
new file mode 100644
index 0000000..5cfe327
--- /dev/null
+++ b/assets/src/network/channel/messages/handler.ts
@@ -0,0 +1,93 @@
+import { getChannel } from "../connection";
+import type { AnyMessage } from "./messages";
+
+export type Handlers = {
+    [event: string]: EventHandler<unknown>;
+};
+
+type EventHandler<Message extends AnyMessage> = {
+    tokenHandler: TokenHandler<Message>;
+    directHandlers: Handler<Message>[];
+};
+
+export type TokenHandler<Message extends AnyMessage> = {
+    [token: string]: Handler<Message>;
+};
+
+export type Handler<Message extends AnyMessage> = (message?: Message) => void;
+
+export type UnregisterHandler = () => void;
+
+export function registerTokenHandler<Message extends AnyMessage>(
+    handlers: Handlers,
+    event: string,
+    token: string | null,
+    handler: Handler<Message>
+): UnregisterHandler {
+    let eventHandler = handlers[event];
+
+    // If this event did not yet have any handlers registered we have to register it
+    if (eventHandler === undefined) {
+        eventHandler = {
+            tokenHandler: {},
+            directHandlers: [],
+        };
+
+        handlers[event] = eventHandler;
+
+        registerNewEvent<Message>(eventHandler, event);
+    }
+
+    let unregister: UnregisterHandler;
+
+    if (token === null) {
+        const directHandlers = eventHandler.directHandlers;
+        directHandlers.push(handler);
+
+        unregister = () => {
+            const index = directHandlers.findIndex(h => h === handler);
+            directHandlers.splice(index, 1);
+        };
+    } else {
+        const tokenHandler = eventHandler.tokenHandler;
+        tokenHandler[token] = handler;
+
+        unregister = () => {
+            delete tokenHandler[token];
+        };
+    }
+
+    return unregister;
+}
+
+function registerNewEvent<Message extends AnyMessage>(
+    eventHandler: EventHandler<Message>,
+    event: string
+) {
+    const callback = (data: Message) => {
+        handleEvent<Message>(eventHandler, data);
+    };
+
+    getChannel().on(event, callback);
+}
+
+function handleEvent<Message extends AnyMessage>(
+    eventHandler: EventHandler<Message>,
+    message: Message
+) {
+    if (message["token"] !== undefined) {
+        const token = message["token"];
+
+        const handler: Handler<Message> = eventHandler.tokenHandler[token];
+
+        if (handler === undefined) {
+            throw new Error("Received message for an unknown token.");
+        }
+
+        handler(message);
+    }
+
+    for (const handler of eventHandler.directHandlers) {
+        handler(message);
+    }
+}