aboutsummaryrefslogtreecommitdiff
path: root/assets/src/network/channel/messages
diff options
context:
space:
mode:
Diffstat (limited to 'assets/src/network/channel/messages')
-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);
+ }
+}