diff --git a/app/signalr/hub/multiplayer.py b/app/signalr/hub/multiplayer.py index 87eceb8..36c468d 100644 --- a/app/signalr/hub/multiplayer.py +++ b/app/signalr/hub/multiplayer.py @@ -336,12 +336,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): async def ChangeBeatmapAvailability( self, client: Client, beatmap_availability: BeatmapAvailability ): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -353,12 +348,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def AddPlaylistItem(self, client: Client, item: PlaylistItem): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) @@ -374,12 +364,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def EditPlaylistItem(self, client: Client, item: PlaylistItem): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) @@ -396,12 +381,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def RemovePlaylistItem(self, client: Client, item_id: int): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) @@ -417,7 +397,25 @@ class MultiplayerHub(Hub[MultiplayerClientState]): user, ) + async def change_db_settings(self, room: ServerMultiplayerRoom): + async with AsyncSession(engine) as session: + await session.execute( + update(Room) + .where(col(Room.id) == room.room.room_id) + .values( + name=room.room.settings.name, + type=room.room.settings.match_type, + queue_mode=room.room.settings.queue_mode, + auto_skip=room.room.settings.auto_skip, + auto_start_duration=int( + room.room.settings.auto_start_duration.total_seconds() + ), + host_id=room.room.host.user_id, + ) + ) + async def setting_changed(self, room: ServerMultiplayerRoom, beatmap_changed: bool): + await self.change_db_settings(room) await self.validate_styles(room) await self.unready_all_users(room, beatmap_changed) await self.broadcast_group_call( @@ -455,12 +453,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): async def ChangeUserStyle( self, client: Client, beatmap_id: int | None, ruleset_id: int | None ): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -583,12 +576,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def ChangeUserMods(self, client: Client, new_mods: list[APIMod]): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -645,7 +633,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): "Cannot ready up while all items have been played." ) case MultiplayerUserState.WAITING_FOR_LOAD: - raise InvokeException("Cannot change state from {old} to {new}") + raise InvokeException(f"Cannot change state from {old} to {new}") case MultiplayerUserState.LOADED: if old != MultiplayerUserState.WAITING_FOR_LOAD: raise InvokeException(f"Cannot change state from {old} to {new}") @@ -658,18 +646,13 @@ class MultiplayerHub(Hub[MultiplayerClientState]): if old != MultiplayerUserState.PLAYING: raise InvokeException(f"Cannot change state from {old} to {new}") case MultiplayerUserState.RESULTS: - raise InvokeException("Cannot change state from {old} to {new}") + raise InvokeException(f"Cannot change state from {old} to {new}") case MultiplayerUserState.SPECTATING: if old not in (MultiplayerUserState.IDLE, MultiplayerUserState.READY): raise InvokeException(f"Cannot change state from {old} to {new}") async def ChangeState(self, client: Client, state: MultiplayerUserState): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -795,18 +778,12 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def StartMatch(self, client: Client): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: raise InvokeException("You are not in this room") - if room.host is None or room.host.user_id != client.user_id: - raise InvokeException("You are not the host of this room") + self._ensure_host(client, server_room) # Check host state - host must be ready or spectating if room.host.state not in ( @@ -998,9 +975,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): store = self.get_or_create_state(client) if store.room_id == 0: return - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -1014,16 +989,9 @@ class MultiplayerHub(Hub[MultiplayerClientState]): logger.info(f"[MultiplayerHub] {client.user_id} left room {room.room_id}") async def KickUser(self, client: Client, user_id: int): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room - - if room.host is None or room.host.user_id != client.user_id: - raise InvokeException("You are not the host of this room") + self._ensure_host(client, server_room) if user_id == client.user_id: raise InvokeException("Can't kick self") @@ -1047,6 +1015,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): async def set_host(self, room: ServerMultiplayerRoom, user: MultiplayerRoomUser): room.room.host = user + await self.change_db_settings(room) await self.broadcast_group_call( self.group_id(room.room.room_id), "HostChanged", @@ -1054,16 +1023,9 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def TransferHost(self, client: Client, user_id: int): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room - - if room.host is None or room.host.user_id != client.user_id: - raise InvokeException("You are not the host of this room") + self._ensure_host(client, server_room) new_host = next((u for u in room.users if u.user_id == user_id), None) if new_host is None: @@ -1079,12 +1041,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): ) async def AbortGameplay(self, client: Client): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -1101,16 +1058,9 @@ class MultiplayerHub(Hub[MultiplayerClientState]): await self.update_room_state(server_room) async def AbortMatch(self, client: Client): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room - - if room.host is None or room.host.user_id != client.user_id: - raise InvokeException("You are not the host of this room") + self._ensure_host(client, server_room) if ( room.state != MultiplayerRoomState.PLAYING @@ -1175,12 +1125,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): await self.update_room_state(server_room) async def SendMatchRequest(self, client: Client, request: MatchRequest): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: @@ -1190,7 +1135,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): if room.host and room.host.user_id != user.user_id: raise InvokeException("You are not the host of this room") if room.state != MultiplayerRoomState.OPEN: - raise InvokeException("Cannot start a countdown during ongoing play") + raise InvokeException("Cannot start match countdown when not open") await server_room.start_countdown( MatchStartCountdown(time_remaining=request.duration), self.start_match, @@ -1215,12 +1160,7 @@ class MultiplayerHub(Hub[MultiplayerClientState]): await server_room.match_type_handler.handle_request(user, request) async def InvitePlayer(self, client: Client, user_id: int): - store = self.get_or_create_state(client) - if store.room_id == 0: - raise InvokeException("You are not in a room") - if store.room_id not in self.rooms: - raise InvokeException("Room does not exist") - server_room = self.rooms[store.room_id] + server_room = self._ensure_in_room(client) room = server_room.room user = next((u for u in room.users if u.user_id == client.user_id), None) if user is None: