From 84ef3baa3335bc0700c7cf78264752012965bdc7 Mon Sep 17 00:00:00 2001 From: Usagi no Niku Date: Tue, 5 Dec 2023 11:59:10 +0000 Subject: [PATCH 1/2] depart leaving match logic in player.py --- app/objects/match.py | 45 +++++++++++++++++++++++++++++++++++++++++-- app/objects/player.py | 35 +++------------------------------ 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/app/objects/match.py b/app/objects/match.py index 69ac15a02..1149a0be5 100644 --- a/app/objects/match.py +++ b/app/objects/match.py @@ -7,7 +7,7 @@ from datetime import timedelta as timedelta from enum import IntEnum from enum import unique -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from typing import TypedDict import databases.core @@ -257,10 +257,19 @@ def __init__( self.tourney_clients: set[int] = set() # player ids + @property + def empty(self) -> bool: + return all(s.empty() for s in self.slots) + # TODO: handle user not found in session situation. @property # TODO: test cache speed def host(self) -> Player: - return app.state.sessions.players.get(id=self.host_id) or app.state.sessions.bot + player = app.state.sessions.players.get(id=self.host_id) + if not player: + player = self.find_next_host() + if not player: + player = app.state.sessions.bot + return player @property def url(self) -> str: @@ -451,6 +460,38 @@ async def await_submissions( # all scores retrieved, update the match. return scores, didnt_submit + + def terminate(self): + log(f"Match {self} finished.") + if self.starting is not None: + self.starting["start"].cancel() + for alert in self.starting["alerts"]: + alert.cancel() + self.starting = None + app.state.sessions.matches.remove(self) + lobby = app.state.sessions.channels.get_by_name("#lobby") + if lobby: + lobby.enqueue(app.packets.dispose_match(self.id)) + + + def find_next_host(self) -> Optional[Player]: + current_host_id = self.host_id + next_host = None + for slot in self.slots: + if slot.empty() or slot.player.id == current_host_id: + continue + next_host = slot.player + break + if not next_host: + # Normally, match is terminated rather than without next host. + log(f"An empty match was trying to find next host.") + self.terminate() + return + self.host_id = next_host.id + next_host.enqueue(app.packets.match_transfer_host()) + self.enqueue_state() # boardcast to all players in the match + return next_host + async def update_matchpoints(self, was_playing: Sequence[Slot]) -> None: """\ diff --git a/app/objects/player.py b/app/objects/player.py index 0ae25a78f..9159261a9 100644 --- a/app/objects/player.py +++ b/app/objects/player.py @@ -661,44 +661,15 @@ def leave_match(self) -> None: self.leave_channel(self.match.chat) - if all(s.empty() for s in self.match.slots): - # multi is now empty, chat has been removed. - # remove the multi from the channels list. - log(f"Match {self.match} finished.") - - # cancel any pending start timers - if self.match.starting is not None: - self.match.starting["start"].cancel() - for alert in self.match.starting["alerts"]: - alert.cancel() - - self.match.starting = None - - app.state.sessions.matches.remove(self.match) - - lobby = app.state.sessions.channels.get_by_name("#lobby") - if lobby: - lobby.enqueue(app.packets.dispose_match(self.match.id)) - + if self.match.empty: + self.match.terminate() else: # multi is not empty - if self is self.match.host: - # player was host, trasnfer to first occupied slot - for s in self.match.slots: - # add double check to ensure match player - if s.player is None or s.player.match is None: - continue - - self.match.host_id = s.player.id - self.match.host.enqueue(app.packets.match_transfer_host()) - break + self.match.find_next_host() if self in self.match._refs: self.match._refs.remove(self) self.match.chat.send_bot(f"{self.name} removed from match referees.") - # notify others of our deprature - self.match.enqueue_state() - self.match = None async def join_clan(self, clan: Clan) -> bool: From 4060a7c71abb64b22ffc1fb4394a9bf8476b6ecd Mon Sep 17 00:00:00 2001 From: Usagi no Niku Date: Tue, 5 Dec 2023 12:10:26 +0000 Subject: [PATCH 2/2] add #multiplayer to IGNORED_CHANNELS --- app/api/domains/cho.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/domains/cho.py b/app/api/domains/cho.py index f999aa27b..35e32e4a2 100644 --- a/app/api/domains/cho.py +++ b/app/api/domains/cho.py @@ -287,7 +287,7 @@ async def handle(self, player: Player) -> None: app.state.sessions.players.enqueue(app.packets.user_stats(player)) -IGNORED_CHANNELS = ["#highlight", "#userlog"] +IGNORED_CHANNELS = ["#highlight", "#userlog", "#multiplayer"] @register(ClientPackets.SEND_PUBLIC_MESSAGE)