diff --git a/server/game.py b/server/game.py index 169f8ee..73ea5d2 100644 --- a/server/game.py +++ b/server/game.py @@ -782,9 +782,17 @@ class Game: for i, player in enumerate(self.players): if player.id == player_id: removed = self.players.pop(i) - # Adjust dealer_idx if needed after removal - if self.players and self.dealer_idx >= len(self.players): - self.dealer_idx = 0 + if self.players: + # Adjust dealer_idx if needed after removal + if self.dealer_idx >= len(self.players): + self.dealer_idx = 0 + # Adjust current_player_index after removal + if i < self.current_player_index: + # Removed player was before current: shift back + self.current_player_index -= 1 + elif self.current_player_index >= len(self.players): + # Removed player was at/after current and index is now OOB + self.current_player_index = 0 self._emit("player_left", player_id=player_id, reason=reason) return removed return None @@ -807,6 +815,8 @@ class Game: def current_player(self) -> Optional[Player]: """Get the player whose turn it currently is.""" if self.players: + if self.current_player_index >= len(self.players): + self.current_player_index = self.current_player_index % len(self.players) return self.players[self.current_player_index] return None diff --git a/server/main.py b/server/main.py index 83ffc05..19000a2 100644 --- a/server/main.py +++ b/server/main.py @@ -431,7 +431,7 @@ async def _close_all_websockets(): app = FastAPI( title="Golf Card Game", debug=config.DEBUG, - version="3.1.6", + version="3.2.0", lifespan=lifespan, ) @@ -943,7 +943,18 @@ if os.path.exists(client_path): return FileResponse(os.path.join(client_path, "index.html")) # Mount static files for everything else (JS, CSS, SVG, etc.) - app.mount("/", StaticFiles(directory=client_path), name="static") + # Wrap StaticFiles to reject WebSocket requests gracefully instead of + # crashing with AssertionError (starlette asserts scope["type"] == "http"). + static_files = StaticFiles(directory=client_path) + + async def safe_static_files(scope, receive, send): + if scope["type"] != "http": + if scope["type"] == "websocket": + await send({"type": "websocket.close", "code": 1000}) + return + await static_files(scope, receive, send) + + app.mount("/", safe_static_files, name="static") def run():