From 10a4bd64d28f889f7d814bacdad50d735470efdc Mon Sep 17 00:00:00 2001 From: sepia Date: Mon, 21 Jul 2025 22:19:59 -0500 Subject: [PATCH] Huge refactor of web-socket-handler --- bun.lockb | Bin 135470 -> 137213 bytes index.html | 2 +- package.json | 1 + src/game/game-instance.test.ts | 14 +- src/game/game-instance.ts | 85 ++-------- src/index.ts | 37 ++--- src/messages.ts | 13 ++ src/view/board-renderer.ts | 19 +-- src/web-socket-handler.ts | 293 --------------------------------- src/web-socket-handler.tsx | 267 ++++++++++++++++++++++++++++++ tsconfig.json | 112 ++----------- 11 files changed, 333 insertions(+), 510 deletions(-) create mode 100644 src/messages.ts delete mode 100644 src/web-socket-handler.ts create mode 100644 src/web-socket-handler.tsx diff --git a/bun.lockb b/bun.lockb index ae867a03b17d9c27515fff5c24b1e09393286b05..fc8fa7bf0d3690bb30ae471e23c2237e774cac14 100755 GIT binary patch delta 27766 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
-
+