[Enhance] Link Play Rooms info & API for that

- Add an HTTP API endpoint for getting the information of rooms and players in Link Play
This commit is contained in:
Lost-MSth
2023-12-03 16:42:53 +08:00
parent 150686d9f8
commit f3c17cdde7
5 changed files with 129 additions and 40 deletions

View File

@@ -91,6 +91,7 @@ class TCPRouter:
'create_room',
'join_room',
'update_room',
'get_rooms',
}
def __init__(self, raw_data: 'dict | list'):
@@ -115,7 +116,11 @@ class TCPRouter:
self.clean_check()
if self.endpoint not in self.router:
return None
r = getattr(self, self.endpoint)()
try:
r = getattr(self, self.endpoint)()
except Exception as e:
logging.error(e)
return 999
if isinstance(r, int):
return {'code': r}
return {
@@ -257,3 +262,41 @@ class TCPRouter:
'player_id': r['player_id'],
'song_unlock': b64encode(room.song_unlock).decode('utf-8')
}
def get_rooms(self) -> dict:
# 获取房间列表与详细信息
offset = int(self.data.get('offset', 0))
if offset < 0:
offset = 0
limit = min(int(self.data.get('limit', 100)), 100)
if limit < 0:
limit = 100
n = 0
m = 0
rooms = []
f = False
f2 = False
for room in Store.room_id_dict.values():
if room.player_num == 0:
continue
if m < offset:
m += 1
continue
if f:
# 处理刚好有 limit 个房间的情况
f2 = True
break
n += 1
rooms.append(room.to_dict())
if n >= limit:
f = True
return {
'amount': n,
'offset': offset,
'limit': limit,
'has_more': f2,
'rooms': rooms
}

View File

@@ -49,6 +49,27 @@ class Player:
def name(self) -> str:
return self.player_name.decode('ascii').rstrip('\x00')
def to_dict(self) -> dict:
return {
'multiplay_player_id': self.player_id,
'name': self.name,
'is_online': self.online == 1,
'character_id': self.character_id,
'is_uncapped': self.is_uncapped == 1,
'last_song': {
'difficulty': self.last_difficulty,
'score': self.last_score,
'cleartype': self.last_cleartype,
},
'song': {
'difficulty': self.difficulty,
'score': self.score,
'cleartype': self.cleartype,
},
'player_state': self.player_state,
'last_timestamp': self.last_timestamp,
}
def set_player_name(self, player_name: str):
self.player_name = player_name.encode('ascii')
if len(self.player_name) > 16:
@@ -80,6 +101,32 @@ class Room:
self.command_queue = []
def to_dict(self) -> dict:
p = [i.to_dict() for i in self.players if i.player_id != 0]
for i in p:
i['is_host'] = i['player_id'] == self.host_id
return {
'room_id': self.room_id,
'room_code': self.room_code,
'state': self.state,
'song_idx': self.song_idx,
'last_song_idx': self.last_song_idx if not self.is_playing else 0xffff,
'host_id': self.host_id,
'players': p,
'round_switch': self.round_switch == 1,
'last_timestamp': self.timestamp,
'is_enterable': self.is_enterable,
'is_playing': self.is_playing,
}
@property
def is_enterable(self) -> bool:
return 0 < self.player_num < 4 and self.state == 2
@property
def is_playing(self) -> bool:
return self.state in (4, 5, 6, 7)
@property
def command_queue_length(self) -> int:
return len(self.command_queue)