From 10058710fb7d39493c432dba7e6fc7111b2804a1 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Wed, 26 Nov 2025 17:11:20 +0530 Subject: [PATCH] Improve client matchmaking flow with ticket handling, auto-join, and mode distribution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### PlayerWebSocketHandler updates - Track `ticket` and `match_id` per player instance - Handle `matchmaker_ticket` messages and store ticket - Handle `matchmaker_matched` and automatically join created match - Enhance matchmaking debug output - Update join_matchmaking() to include mode-based string_properties + query ### Matchmaking simulation improvements - Evenly distribute players between "classic" and "blitz" modes - Randomize assignment order to simulate real queue behavior - Log player→mode mapping for visibility during tests Example: player_0 -> classic player_3 -> blitz player_5 -> classic Client test harness now accurately reflects multi-mode matchmaking behavior. --- game_flow.py | 22 +++++++++++++++++++--- match_making_flow.py | 19 ++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/game_flow.py b/game_flow.py index 3c9efb3..af5ee8f 100644 --- a/game_flow.py +++ b/game_flow.py @@ -96,7 +96,23 @@ class PlayerWebSocketHandler(WebSocketHandler): await handler.connect() return handler + def __init__(self, custom_id: str, label: str): + super().__init__(custom_id, label) + self.ticket = None + self.match_id = None + async def on_message(self, msg): + if "matchmaker_matched" in msg: + match_id = msg["matchmaker_matched"]["match_id"] + print(f"[{self.label}] ✅ Match found: {match_id}") + await self.join_match(match_id) + return + + if "matchmaker_ticket" in msg: + self.ticket = msg["matchmaker_ticket"]["ticket"] + print(f"[{self.label}] ✅ Received ticket: {self.ticket}") + return + if "match_data" not in msg: print(f"[{self.label}] {msg}") return @@ -124,9 +140,8 @@ class PlayerWebSocketHandler(WebSocketHandler): "matchmaker_add": { "min_count": 2, "max_count": 2, - "string_properties": { - "mode": mode - } + "string_properties": {"mode": mode}, + "query": f"+mode:{mode}" } })) print(f"[{self.label}] Searching match for mode={mode}...") @@ -151,6 +166,7 @@ class PlayerWebSocketHandler(WebSocketHandler): async def join_match(self, match_id: str): await self.ws.send(json.dumps({"match_join": {"match_id": match_id}})) print(f"[{self.label}] Joined match: {match_id}") + self.match_id = match_id # ---------- Gameplay ---------- async def send_move(self, match_id: str, row: int, col: int): diff --git a/match_making_flow.py b/match_making_flow.py index 545e478..4387939 100644 --- a/match_making_flow.py +++ b/match_making_flow.py @@ -1,8 +1,9 @@ import asyncio -from game_flow import PlayerWebSocketHandler +import random +from game_flow import PlayerWebSocketHandler, TEST_SCENARIOS -async def simulate_matchmaking(num_players: int = 6, mode: str = "classic"): +async def simulate_matchmaking(num_players: int = 6): print(f"\n🎮 Spawning {num_players} players...\n") # 1) Login + WebSocket connect @@ -21,12 +22,20 @@ async def simulate_matchmaking(num_players: int = 6, mode: str = "classic"): await asyncio.sleep(0.3) - # 3) Queue all players in matchmaking - print(f"\n🎯 Queuing players for mode={mode}...\n") + # ✅ 3) Split evenly between classic & blitz + half = num_players // 2 + assignments = ["classic"] * half + ["blitz"] * (num_players - half) + + # Optional — shuffle for realism + random.shuffle(assignments) + + print("\n🎯 Queuing players:") + for p, mode in zip(players, assignments): + print(f" - {p.label} -> {mode}") await asyncio.gather(*[ p.join_matchmaking(mode) - for p in players + for p, mode in zip(players, assignments) ]) print("\n✅ All players queued — waiting for matches...\n")