fix(multiplayer): handle user leave logic and improve room state updates

This commit is contained in:
MingxuanGame
2025-08-17 16:42:19 +00:00
parent 58fa355c80
commit 103ce7b2e5

View File

@@ -892,34 +892,21 @@ class MultiplayerHub(Hub[MultiplayerClientState]):
async def make_user_leave( async def make_user_leave(
self, self,
client: Client, client: Client | None,
room: ServerMultiplayerRoom, room: ServerMultiplayerRoom,
user: MultiplayerRoomUser, user: MultiplayerRoomUser,
kicked: bool = False, kicked: bool = False,
): ):
self.remove_from_group(client, self.group_id(room.room.room_id)) if client:
self.remove_from_group(client, self.group_id(room.room.room_id))
room.room.users.remove(user) room.room.users.remove(user)
if len(room.room.users) == 0: target_store = self.state.get(user.user_id)
await self.end_room(room) if target_store:
await self.update_room_state(room) target_store.room_id = 0
if (
len(room.room.users) != 0
and room.room.host
and room.room.host.user_id == user.user_id
):
next_host = room.room.users[0]
await self.set_host(room, next_host)
if kicked: redis = get_redis()
await self.call_noblock(client, "UserKicked", user) await redis.publish("chat:room:left", f"{room.room.channel_id}:{user.user_id}")
await self.broadcast_group_call(
self.group_id(room.room.room_id), "UserKicked", user
)
else:
await self.broadcast_group_call(
self.group_id(room.room.room_id), "UserLeft", user
)
async with AsyncSession(engine) as session: async with AsyncSession(engine) as session:
async with session.begin(): async with session.begin():
@@ -939,12 +926,28 @@ class MultiplayerHub(Hub[MultiplayerClientState]):
raise InvokeException("Room does not exist in database") raise InvokeException("Room does not exist in database")
db_room.participant_count -= 1 db_room.participant_count -= 1
target_store = self.state.get(user.user_id) if len(room.room.users) == 0:
if target_store: await self.end_room(room)
target_store.room_id = 0 return
await self.update_room_state(room)
if (
len(room.room.users) != 0
and room.room.host
and room.room.host.user_id == user.user_id
):
next_host = room.room.users[0]
await self.set_host(room, next_host)
redis = get_redis() if kicked:
await redis.publish("chat:room:left", f"{room.room.channel_id}:{user.user_id}") if client:
await self.call_noblock(client, "UserKicked", user)
await self.broadcast_group_call(
self.group_id(room.room.room_id), "UserKicked", user
)
else:
await self.broadcast_group_call(
self.group_id(room.room.room_id), "UserLeft", user
)
async def end_room(self, room: ServerMultiplayerRoom): async def end_room(self, room: ServerMultiplayerRoom):
assert room.room.host assert room.room.host
@@ -1005,8 +1008,6 @@ class MultiplayerHub(Hub[MultiplayerClientState]):
user.user_id, user.user_id,
) )
target_client = self.get_client_by_id(str(user.user_id)) target_client = self.get_client_by_id(str(user.user_id))
if target_client is None:
return
await self.make_user_leave(target_client, server_room, user, kicked=True) await self.make_user_leave(target_client, server_room, user, kicked=True)
logger.info( logger.info(
f"[MultiplayerHub] {user.user_id} was kicked from room {room.room_id}" f"[MultiplayerHub] {user.user_id} was kicked from room {room.room_id}"