From c306e992c44d9895b6a7b1155c9993eee4071b2c Mon Sep 17 00:00:00 2001 From: Ryan Walters Date: Sat, 22 Nov 2025 21:14:24 -0600 Subject: [PATCH] fix(game): resolve race condition in render dirty flag using bitwise OR The render dirty flag was being reset instead of accumulated, causing the game to become stuck and unplayable in web builds. Changed from assignment to bitwise OR to preserve all dirty state updates. Also adds game layout component and updates Justfile to build frontend. --- Justfile | 3 ++- pacman/src/game.rs | 2 +- web/pages/index/+Layout.tsx | 9 +++++++++ web/pages/index/+Page.tsx | 9 ++------- 4 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 web/pages/index/+Layout.tsx diff --git a/Justfile b/Justfile index 704b093..eac895c 100644 --- a/Justfile +++ b/Justfile @@ -36,7 +36,8 @@ samply: # Build the project for Emscripten web *args: - bun run pacman/web.build.ts {{args}}; + bun run pacman/web.build.ts {{args}} + bun run --cwd web build caddy file-server --root web/dist/client # Fix linting errors & formatting diff --git a/pacman/src/game.rs b/pacman/src/game.rs index d78aa43..cfcf0ca 100644 --- a/pacman/src/game.rs +++ b/pacman/src/game.rs @@ -521,7 +521,7 @@ impl Game { stage_system.in_set(GameplaySet::Respond), ( (|mut dirty: ResMut, score: Res, stage: Res| { - dirty.0 = score.is_changed() || stage.is_changed(); + dirty.0 |= score.is_changed() || stage.is_changed(); }), dirty_render_system.run_if(|dirty: Res| dirty.0.not()), combined_render_system, diff --git a/web/pages/index/+Layout.tsx b/web/pages/index/+Layout.tsx new file mode 100644 index 0000000..06b253d --- /dev/null +++ b/web/pages/index/+Layout.tsx @@ -0,0 +1,9 @@ +import "../../layouts/tailwind.css"; + +export default function GameLayout({ children }: { children: React.ReactNode }) { + return ( +
+
{children}
+
+ ); +} diff --git a/web/pages/index/+Page.tsx b/web/pages/index/+Page.tsx index 3aec5be..c262fd9 100644 --- a/web/pages/index/+Page.tsx +++ b/web/pages/index/+Page.tsx @@ -2,32 +2,27 @@ import { useEffect } from "react"; export default function Page() { useEffect(() => { - // Only setup Module if not already configured (prevents double-initialization on hot reload) if (!(window as any).Module) { const canvas = document.getElementById("canvas"); - // Simple Module configuration matching the original working approach (window as any).Module = { canvas: canvas, locateFile: (path: string) => { - // Return absolute paths for all resources return path.startsWith("/") ? path : `/${path}`; }, preRun: [], }; - // Load the Emscripten script const script = document.createElement("script"); script.src = "/pacman.js"; - script.async = false; // Load synchronously to ensure Module is configured first + script.async = false; document.body.appendChild(script); - // Cleanup function (runs when component unmounts) return () => { script.remove(); }; } - }, []); // Empty dependency array = run once on mount + }, []); return (