def handle_demodata_get_hitchart_request(self, request: Node) -> Node: demodata = Node.void('demodata') data = Node.void('data') demodata.add_child(data) # Not sure what this is, maybe date? data.add_child(Node.string('update', time.strftime("%d/%m/%Y"))) # No idea which songs are licensed or regular, so only return hit chart # for all songs on regular mode. hitchart_lic = Node.void('hitchart_lic') data.add_child(hitchart_lic) hitchart_lic.set_attribute('count', '0') songs = self.data.local.music.get_hit_chart(self.game, self.version, 10) hitchart_org = Node.void('hitchart_org') data.add_child(hitchart_org) hitchart_org.set_attribute('count', str(len(songs))) rank = 1 for song in songs: rankdata = Node.void('rankdata') hitchart_org.add_child(rankdata) rankdata.add_child(Node.s32('music_id', song[0])) rankdata.add_child(Node.s16('rank', rank)) rankdata.add_child(Node.s16('prev', rank)) rank = rank + 1 return demodata
def verify_info_rb5_info_read_shop_ranking(self, loc: str) -> None: call = self.call_node() info = Node.void('info') call.add_child(info) info.set_attribute('method', 'rb5_info_read_shop_ranking') # Arbitrarily chosen based on the song IDs we send in the # score section below. info.add_child(Node.s16('min', 1)) info.add_child(Node.s16('max', 10)) info.add_child(Node.string('lid', loc)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/info/shop_score/time") self.assert_path(resp, "response/info/shop_score/data/rank") self.assert_path(resp, "response/info/shop_score/data/music_id") self.assert_path(resp, "response/info/shop_score/data/note_grade") self.assert_path(resp, "response/info/shop_score/data/clear_type") self.assert_path(resp, "response/info/shop_score/data/user_id") self.assert_path(resp, "response/info/shop_score/data/icon_id") self.assert_path(resp, "response/info/shop_score/data/score") self.assert_path(resp, "response/info/shop_score/data/time") self.assert_path(resp, "response/info/shop_score/data/name")
def verify_player22_write(self, ref_id: str, scores: List[Dict[str, Any]]) -> None: call = self.call_node() # Construct node player22 = Node.void('player22') call.add_child(player22) player22.set_attribute('method', 'write') player22.add_child(Node.string('ref_id', value=ref_id)) # Add required children config = Node.void('config') player22.add_child(config) config.add_child(Node.s16('chara', value=1543)) # Add requested scores for score in scores: stage = Node.void('stage') player22.add_child(stage) stage.add_child(Node.s16('no', score['id'])) stage.add_child(Node.u8('sheet', score['chart'])) stage.add_child(Node.u16('clearmedal', score['medal'])) stage.add_child(Node.s32('nscore', score['score'])) # Swap with server resp = self.exchange('', call) self.assert_path(resp, "response/player22/@status")
def verify_player24_update_ranking(self, ref_id: str, loc: str) -> None: call = self.call_node() # Construct node player24 = Node.void('player24') call.add_child(player24) player24.set_attribute('method', 'update_ranking') player24.add_child(Node.s16('pref', 51)) player24.add_child(Node.string('location_id', loc)) player24.add_child(Node.string('ref_id', ref_id)) player24.add_child(Node.string('name', self.NAME)) player24.add_child(Node.s16('chara_num', 1)) player24.add_child(Node.s16('course_id', 12345)) player24.add_child(Node.s32('total_score', 86000)) player24.add_child(Node.s16('music_num', 1375)) player24.add_child(Node.u8('sheet_num', 2)) player24.add_child(Node.u8('clear_type', 7)) player24.add_child(Node.u8('clear_rank', 5)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/player24/all_ranking/name") self.assert_path(resp, "response/player24/all_ranking/chara_num") self.assert_path(resp, "response/player24/all_ranking/total_score") self.assert_path(resp, "response/player24/all_ranking/clear_type") self.assert_path(resp, "response/player24/all_ranking/clear_rank") self.assert_path(resp, "response/player24/all_ranking/player_count") self.assert_path(resp, "response/player24/all_ranking/player_rank")
def verify_lobby_entry(self, location: str, extid: int) -> int: call = self.call_node() lobby = Node.void('lobby') lobby.set_attribute('method', 'entry') e = Node.void('e') lobby.add_child(e) e.add_child(Node.s32('eid', 0)) e.add_child(Node.u16('mid', 79)) e.add_child(Node.u8('ng', 0)) e.add_child(Node.s32('uid', extid)) e.add_child(Node.s32('uattr', 0)) e.add_child(Node.string('pn', self.NAME)) e.add_child(Node.s16('mg', 255)) e.add_child(Node.s32('mopt', 0)) e.add_child(Node.s32('tid', 0)) e.add_child(Node.string('tn', '')) e.add_child(Node.s32('topt', 0)) e.add_child(Node.string('lid', location)) e.add_child(Node.string('sn', '')) e.add_child(Node.u8('pref', 51)) e.add_child(Node.s8('stg', 4)) e.add_child(Node.s8('pside', 0)) e.add_child(Node.s16('eatime', 30)) e.add_child(Node.u8_array('ga', [127, 0, 0, 1])) e.add_child(Node.u16('gp', 10007)) e.add_child(Node.u8_array('la', [16, 0, 0, 0])) e.add_child(Node.u8('ver', 5)) lobby.add_child(Node.s32_array('friend', [])) call.add_child(lobby) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/lobby/interval") self.assert_path(resp, "response/lobby/interval_p") self.assert_path(resp, "response/lobby/eid") self.assert_path(resp, "response/lobby/e/eid") self.assert_path(resp, "response/lobby/e/mid") self.assert_path(resp, "response/lobby/e/ng") self.assert_path(resp, "response/lobby/e/uid") self.assert_path(resp, "response/lobby/e/uattr") self.assert_path(resp, "response/lobby/e/pn") self.assert_path(resp, "response/lobby/e/mg") self.assert_path(resp, "response/lobby/e/mopt") self.assert_path(resp, "response/lobby/e/tid") self.assert_path(resp, "response/lobby/e/tn") self.assert_path(resp, "response/lobby/e/topt") self.assert_path(resp, "response/lobby/e/lid") self.assert_path(resp, "response/lobby/e/sn") self.assert_path(resp, "response/lobby/e/pref") self.assert_path(resp, "response/lobby/e/stg") self.assert_path(resp, "response/lobby/e/pside") self.assert_path(resp, "response/lobby/e/eatime") self.assert_path(resp, "response/lobby/e/ga") self.assert_path(resp, "response/lobby/e/gp") self.assert_path(resp, "response/lobby/e/la") self.assert_path(resp, "response/lobby/e/ver") return resp.child_value('lobby/eid')
def verify_playerdata_set(self, ref_id: str, scores: List[Dict[str, Any]]) -> None: call = self.call_node() # Construct node playerdata = Node.void('playerdata') call.add_child(playerdata) playerdata.set_attribute('method', 'set') playerdata.set_attribute('ref_id', ref_id) playerdata.set_attribute('shop_name', '') # Add required children playerdata.add_child(Node.s16('chara', 1543)) # Add requested scores for score in scores: stage = Node.void('stage') playerdata.add_child(stage) stage.add_child(Node.s16('no', score['id'])) stage.add_child(Node.u8('sheet', score['chart'])) stage.add_child( Node.u16('n_data', (score['medal'] << (4 * score['chart'])))) stage.add_child(Node.s32('score', score['score'])) # Swap with server resp = self.exchange('pnm20/playerdata', call) # Verify nodes that cause crashes if they don't exist self.assert_path(resp, "response/playerdata/name") name = resp.child('playerdata').child('name').value if name != self.NAME: raise Exception( f'Invalid name \'{name}\' returned for Ref ID \'{ref_id}\'')
def verify_game_play_e(self, location: str, refid: str) -> None: call = self.call_node() game = Node.void('game_3') call.add_child(game) game.set_attribute('ver', '0') game.set_attribute('method', 'play_e') game.add_child(Node.string('dataid', refid)) game.add_child(Node.s8('mode', 2)) game.add_child(Node.s16('track_num', 3)) game.add_child(Node.s32('s_coin', 0)) game.add_child(Node.s32('s_paseli', 0)) game.add_child(Node.s16('blaster_count', 0)) game.add_child(Node.s16('blaster_cartridge', 0)) game.add_child(Node.string('locid', location)) game.add_child(Node.u16('drop_frame', 396)) game.add_child(Node.u16('drop_frame_max', 396)) game.add_child(Node.u16('drop_count', 1)) game.add_child(Node.string('etc', 'StoryID:0,StoryPrg:0,PrgPrm:0')) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game_3")
def verify_player_rb5_player_read(self, refid: str, cardid: str, location: str) -> None: call = self.call_node() player = Node.void('player') player.set_attribute('method', 'rb5_player_read') player.add_child(Node.string('rid', refid)) player.add_child(Node.string('lid', location)) player.add_child(Node.s16('ver', 0)) player.add_child(Node.string('card_id', cardid)) player.add_child(Node.s16('card_type', 1)) call.add_child(player) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/player/pdata/account/usrid") self.assert_path(resp, "response/player/pdata/account/tpc") self.assert_path(resp, "response/player/pdata/account/dpc") self.assert_path(resp, "response/player/pdata/account/crd") self.assert_path(resp, "response/player/pdata/account/brd") self.assert_path(resp, "response/player/pdata/account/tdc") self.assert_path(resp, "response/player/pdata/account/intrvld") self.assert_path(resp, "response/player/pdata/account/ver") self.assert_path(resp, "response/player/pdata/account/pst") self.assert_path(resp, "response/player/pdata/account/st") self.assert_path(resp, "response/player/pdata/account/succeed") self.assert_path(resp, "response/player/pdata/account/opc") self.assert_path(resp, "response/player/pdata/account/lpc") self.assert_path(resp, "response/player/pdata/account/cpc") self.assert_path(resp, "response/player/pdata/base/name") self.assert_path(resp, "response/player/pdata/base/mg") self.assert_path(resp, "response/player/pdata/base/ap") self.assert_path(resp, "response/player/pdata/base/cmnt") self.assert_path(resp, "response/player/pdata/base/uattr") self.assert_path(resp, "response/player/pdata/base/money") self.assert_path(resp, "response/player/pdata/base/tbs") self.assert_path(resp, "response/player/pdata/base/tbgs") self.assert_path(resp, "response/player/pdata/base/mlog") self.assert_path(resp, "response/player/pdata/base/class") self.assert_path(resp, "response/player/pdata/base/class_ar") self.assert_path(resp, "response/player/pdata/rival") self.assert_path(resp, "response/player/pdata/config") self.assert_path(resp, "response/player/pdata/custom") self.assert_path(resp, "response/player/pdata/released") self.assert_path(resp, "response/player/pdata/announce") self.assert_path(resp, "response/player/pdata/dojo") self.assert_path(resp, "response/player/pdata/player_param") self.assert_path(resp, "response/player/pdata/shop_score") self.assert_path(resp, "response/player/pdata/minigame") self.assert_path(resp, "response/player/pdata/derby/is_open") self.assert_path(resp, "response/player/pdata/mylist/list/idx") self.assert_path(resp, "response/player/pdata/mylist/list/mlst") if resp.child_value('player/pdata/base/name') != self.NAME: raise Exception( f'Invalid name {resp.child_value("player/pdata/base/name")} returned on profile read!' )
def handle_lobby_entry_request(self, request: Node) -> Node: root = Node.void('lobby') root.add_child(Node.s32('interval', 120)) root.add_child(Node.s32('interval_p', 120)) # Create a lobby entry for this user extid = request.child_value('e/uid') userid = self.data.remote.user.from_extid(self.game, self.version, extid) if userid is not None: profile = self.get_profile(userid) self.data.local.lobby.put_lobby( self.game, self.version, userid, { 'mid': request.child_value('e/mid'), 'ng': request.child_value('e/ng'), 'mopt': request.child_value('e/mopt'), 'tid': request.child_value('e/tid'), 'tn': request.child_value('e/tn'), 'topt': request.child_value('e/topt'), 'lid': request.child_value('e/lid'), 'sn': request.child_value('e/sn'), 'pref': request.child_value('e/pref'), 'stg': request.child_value('e/stg'), 'pside': request.child_value('e/pside'), 'eatime': request.child_value('e/eatime'), 'ga': request.child_value('e/ga'), 'gp': request.child_value('e/gp'), 'la': request.child_value('e/la'), }) lobby = self.data.local.lobby.get_lobby( self.game, self.version, userid, ) root.add_child(Node.s32('eid', lobby.get_int('id'))) e = Node.void('e') root.add_child(e) e.add_child(Node.s32('eid', lobby.get_int('id'))) e.add_child(Node.u16('mid', lobby.get_int('mid'))) e.add_child(Node.u8('ng', lobby.get_int('ng'))) e.add_child(Node.s32('uid', profile.get_int('extid'))) e.add_child(Node.string('pn', profile.get_str('name'))) e.add_child(Node.s32('uattr', profile.get_int('uattr'))) e.add_child(Node.s32('mopt', lobby.get_int('mopt'))) e.add_child(Node.s16('mg', profile.get_int('mg'))) e.add_child(Node.s32('tid', lobby.get_int('tid'))) e.add_child(Node.string('tn', lobby.get_str('tn'))) e.add_child(Node.s32('topt', lobby.get_int('topt'))) e.add_child(Node.string('lid', lobby.get_str('lid'))) e.add_child(Node.string('sn', lobby.get_str('sn'))) e.add_child(Node.u8('pref', lobby.get_int('pref'))) e.add_child(Node.s8('stg', lobby.get_int('stg'))) e.add_child(Node.s8('pside', lobby.get_int('pside'))) e.add_child(Node.s16('eatime', lobby.get_int('eatime'))) e.add_child(Node.u8_array('ga', lobby.get_int_array('ga', 4))) e.add_child(Node.u16('gp', lobby.get_int('gp'))) e.add_child(Node.u8_array('la', lobby.get_int_array('la', 4))) return root
def handle_lobby_rb5_lobby_read_request(self, request: Node) -> Node: root = Node.void('lobby') root.add_child(Node.s32('interval', 120)) root.add_child(Node.s32('interval_p', 120)) # Look up all lobbies matching the criteria specified ver = request.child_value('var') mg = request.child_value('m_grade') # noqa: F841 extid = request.child_value('uid') limit = request.child_value('max') userid = self.data.remote.user.from_extid(self.game, self.version, extid) if userid is not None: lobbies = self.data.local.lobby.get_all_lobbies( self.game, self.version) for (user, lobby) in lobbies: if limit <= 0: break if user == userid: # If we have our own lobby, don't return it continue if ver != lobby.get_int('ver'): # Don't return lobby data for different versions continue profile = self.get_profile(user) info = self.data.local.lobby.get_play_session_info( self.game, self.version, userid) if profile is None or info is None: # No profile info, don't return this lobby return root e = Node.void('e') root.add_child(e) e.add_child(Node.s32('eid', lobby.get_int('id'))) e.add_child(Node.u16('mid', lobby.get_int('mid'))) e.add_child(Node.u8('ng', lobby.get_int('ng'))) e.add_child(Node.s32('uid', profile.get_int('extid'))) e.add_child(Node.s32('uattr', profile.get_int('uattr'))) e.add_child(Node.string('pn', profile.get_str('name'))) e.add_child(Node.s32('plyid', info.get_int('id'))) e.add_child(Node.s16('mg', profile.get_int('mg'))) e.add_child(Node.s32('mopt', lobby.get_int('mopt'))) e.add_child(Node.string('lid', lobby.get_str('lid'))) e.add_child(Node.string('sn', lobby.get_str('sn'))) e.add_child(Node.u8('pref', lobby.get_int('pref'))) e.add_child(Node.s8('stg', lobby.get_int('stg'))) e.add_child(Node.s8('pside', lobby.get_int('pside'))) e.add_child(Node.s16('eatime', lobby.get_int('eatime'))) e.add_child(Node.u8_array('ga', lobby.get_int_array('ga', 4))) e.add_child(Node.u16('gp', lobby.get_int('gp'))) e.add_child(Node.u8_array('la', lobby.get_int_array('la', 4))) e.add_child(Node.u8('ver', lobby.get_int('ver'))) limit = limit - 1 return root
def handle_info_rb5_info_read_shop_ranking_request(self, request: Node) -> Node: start_music_id = request.child_value('min') end_music_id = request.child_value('max') root = Node.void('info') shop_score = Node.void('shop_score') root.add_child(shop_score) shop_score.add_child(Node.s32('time', Time.now())) profiles: Dict[UserID, ValidatedDict] = {} for songid in range(start_music_id, end_music_id + 1): allscores = self.data.local.music.get_all_scores( self.game, self.music_version, songid=songid, ) for ng in [ self.CHART_TYPE_BASIC, self.CHART_TYPE_MEDIUM, self.CHART_TYPE_HARD, self.CHART_TYPE_SPECIAL, ]: scores = sorted( [score for score in allscores if score[1].chart == ng], key=lambda score: score[1].points, reverse=True, ) for i in range(len(scores)): userid, score = scores[i] if userid not in profiles: profiles[userid] = self.get_any_profile(userid) profile = profiles[userid] data = Node.void('data') shop_score.add_child(data) data.add_child(Node.s32('rank', i + 1)) data.add_child(Node.s16('music_id', songid)) data.add_child(Node.s8('note_grade', score.chart)) data.add_child( Node.s8( 'clear_type', self._db_to_game_clear_type( score.data.get_int('clear_type')))) data.add_child( Node.s32('user_id', profile.get_int('extid'))) data.add_child( Node.s16( 'icon_id', profile.get_dict('config').get_int('icon_id'))) data.add_child(Node.s32('score', score.points)) data.add_child(Node.s32('time', score.timestamp)) data.add_child(Node.string('name', profile.get_str('name'))) return root
def format_conversion(self, userid: UserID, profile: ValidatedDict) -> Node: # Circular import, ugh from bemani.backend.popn.lapistoria import PopnMusicLapistoria root = Node.void('playerdata') root.add_child(Node.string('name', profile.get_str('name', 'なし'))) root.add_child(Node.s16('chara', profile.get_int('chara', -1))) root.add_child(Node.s32('option', profile.get_int('option', 0))) root.add_child(Node.s8('result', 1)) scores = self.data.remote.music.get_scores(self.game, self.version, userid) for score in scores: if score.id > self.GAME_MAX_MUSIC_ID: continue # Skip any scores for chart types we don't support if score.chart not in [ self.CHART_TYPE_EASY, self.CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER, self.CHART_TYPE_EX, ]: continue points = score.points medal = score.data.get_int('medal') music = Node.void('music') root.add_child(music) music.add_child(Node.s16('music_num', score.id)) music.add_child(Node.u8('sheet_num', { self.CHART_TYPE_EASY: PopnMusicLapistoria.GAME_CHART_TYPE_EASY, self.CHART_TYPE_NORMAL: PopnMusicLapistoria.GAME_CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER: PopnMusicLapistoria.GAME_CHART_TYPE_HYPER, self.CHART_TYPE_EX: PopnMusicLapistoria.GAME_CHART_TYPE_EX, }[score.chart])) music.add_child(Node.s16('cnt', score.plays)) music.add_child(Node.s32('score', 0)) music.add_child(Node.u8('clear_type', 0)) music.add_child(Node.s32('old_score', points)) music.add_child(Node.u8('old_clear_type', { self.PLAY_MEDAL_CIRCLE_FAILED: PopnMusicLapistoria.GAME_PLAY_MEDAL_CIRCLE_FAILED, self.PLAY_MEDAL_DIAMOND_FAILED: PopnMusicLapistoria.GAME_PLAY_MEDAL_DIAMOND_FAILED, self.PLAY_MEDAL_STAR_FAILED: PopnMusicLapistoria.GAME_PLAY_MEDAL_STAR_FAILED, self.PLAY_MEDAL_EASY_CLEAR: PopnMusicLapistoria.GAME_PLAY_MEDAL_EASY_CLEAR, self.PLAY_MEDAL_CIRCLE_CLEARED: PopnMusicLapistoria.GAME_PLAY_MEDAL_CIRCLE_CLEARED, self.PLAY_MEDAL_DIAMOND_CLEARED: PopnMusicLapistoria.GAME_PLAY_MEDAL_DIAMOND_CLEARED, self.PLAY_MEDAL_STAR_CLEARED: PopnMusicLapistoria.GAME_PLAY_MEDAL_STAR_CLEARED, self.PLAY_MEDAL_CIRCLE_FULL_COMBO: PopnMusicLapistoria.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO, self.PLAY_MEDAL_DIAMOND_FULL_COMBO: PopnMusicLapistoria.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO, self.PLAY_MEDAL_STAR_FULL_COMBO: PopnMusicLapistoria.GAME_PLAY_MEDAL_STAR_FULL_COMBO, self.PLAY_MEDAL_PERFECT: PopnMusicLapistoria.GAME_PLAY_MEDAL_PERFECT, }[medal])) return root
def handle_player_rb5_player_read_rival_ranking_data_5_request( self, request: Node) -> Node: extid = request.child_value('uid') userid = self.data.remote.user.from_extid(self.game, self.version, extid) root = Node.void('player') rival_data = Node.void('rival_data') root.add_child(rival_data) if userid is not None: links = self.data.local.user.get_links(self.game, self.version, userid) for link in links: if link.type != 'rival': continue rprofile = self.get_profile(link.other_userid) if rprofile is None: continue rl = Node.void('rl') rival_data.add_child(rl) rl.add_child(Node.s32('uid', rprofile.get_int('extid'))) rl.add_child(Node.string('nm', rprofile.get_str('name'))) rl.add_child( Node.s16('ic', rprofile.get_dict('config').get_int('icon_id'))) scores = self.data.remote.music.get_scores( self.game, self.music_version, link.other_userid) scores_by_musicid: Dict[int, List[Score]] = {} for score in scores: if score.id not in scores_by_musicid: scores_by_musicid[score.id] = [None, None, None, None] scores_by_musicid[score.id][score.chart] = score for (mid, scores) in scores_by_musicid.items(): points = [ score.points << 32 if score is not None else 0 for score in scores ] timestamps = [ score.timestamp if score is not None else 0 for score in scores ] sl = Node.void('sl') rl.add_child(sl) sl.add_child(Node.s16('mid', mid)) # Score, but shifted left 32 bits for no reason sl.add_child(Node.u64_array('m', points)) # Timestamp of the clear sl.add_child(Node.u64_array('t', timestamps)) return root
def handle_player_rb5_player_read_score_5_request(self, request: Node) -> Node: refid = request.child_value('rid') userid = self.data.remote.user.from_refid(self.game, self.version, refid) if userid is None: scores: List[Score] = [] else: scores = self.data.remote.music.get_scores(self.game, self.music_version, userid) root = Node.void('player') pdata = Node.void('pdata') root.add_child(pdata) record = Node.void('record') pdata.add_child(record) for score in scores: rec = Node.void('rec') record.add_child(rec) rec.add_child(Node.s16('mid', score.id)) rec.add_child(Node.s8('ntgrd', score.chart)) rec.add_child(Node.s32('pc', score.plays)) rec.add_child( Node.s8( 'ct', self._db_to_game_clear_type( score.data.get_int('clear_type')))) rec.add_child( Node.s16('ar', score.data.get_int('achievement_rate'))) rec.add_child(Node.s16('scr', score.points)) rec.add_child(Node.s16('ms', score.data.get_int('miss_count'))) rec.add_child( Node.s16( 'param', self._db_to_game_combo_type( score.data.get_int('combo_type')) + score.data.get_int('param'), )) rec.add_child(Node.s32('bscrt', score.timestamp)) rec.add_child( Node.s32('bart', score.data.get_int('best_achievement_rate_time'))) rec.add_child( Node.s32('bctt', score.data.get_int('best_clear_type_time'))) rec.add_child( Node.s32('bmst', score.data.get_int('best_miss_count_time'))) rec.add_child( Node.s32('time', score.data.get_int('last_played_time'))) rec.add_child(Node.s32('k_flag', score.data.get_int('kflag'))) return root
def handle_lobby_check_request(self, request: Node) -> Node: root = Node.void('lobby') data = Node.void('data') root.add_child(data) data.add_child(Node.s16('interval', 0)) data.add_child(Node.s16('entry_timeout', 0)) entrant_nr = Node.u32('entrant_nr', 0) entrant_nr.set_attribute('time', '0') data.add_child(entrant_nr) return root
def handle_player23_read_score_request(self, request: Node) -> Node: refid = request.child_value('ref_id') root = Node.void('player23') userid = self.data.remote.user.from_refid(self.game, self.version, refid) if userid is not None: scores = self.data.remote.music.get_scores(self.game, self.version, userid) else: scores = [] for score in scores: # Skip any scores for chart types we don't support if score.chart not in [ self.CHART_TYPE_EASY, self.CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER, self.CHART_TYPE_EX, ]: continue points = score.points medal = score.data.get_int('medal') music = Node.void('music') root.add_child(music) music.add_child(Node.s16('music_num', score.id)) music.add_child(Node.u8('sheet_num', { self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER, self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX, }[score.chart])) music.add_child(Node.s32('score', points)) music.add_child(Node.u8('clear_type', { self.PLAY_MEDAL_CIRCLE_FAILED: self.GAME_PLAY_MEDAL_CIRCLE_FAILED, self.PLAY_MEDAL_DIAMOND_FAILED: self.GAME_PLAY_MEDAL_DIAMOND_FAILED, self.PLAY_MEDAL_STAR_FAILED: self.GAME_PLAY_MEDAL_STAR_FAILED, self.PLAY_MEDAL_EASY_CLEAR: self.GAME_PLAY_MEDAL_EASY_CLEAR, self.PLAY_MEDAL_CIRCLE_CLEARED: self.GAME_PLAY_MEDAL_CIRCLE_CLEARED, self.PLAY_MEDAL_DIAMOND_CLEARED: self.GAME_PLAY_MEDAL_DIAMOND_CLEARED, self.PLAY_MEDAL_STAR_CLEARED: self.GAME_PLAY_MEDAL_STAR_CLEARED, self.PLAY_MEDAL_CIRCLE_FULL_COMBO: self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO, self.PLAY_MEDAL_DIAMOND_FULL_COMBO: self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO, self.PLAY_MEDAL_STAR_FULL_COMBO: self.GAME_PLAY_MEDAL_STAR_FULL_COMBO, self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT, }[medal])) music.add_child(Node.s16('cnt', score.plays)) return root
def verify_player_rb4readscore(self, refid: str, location: str) -> List[Dict[str, int]]: call = self.call_node() player = Node.void('player') call.add_child(player) player.set_attribute('method', 'rb4readscore') player.add_child(Node.string('rid', refid)) player.add_child(Node.string('lid', location)) player.add_child(Node.s16('ver', 1)) # Swap with server resp = self.exchange('', call) scores = [] for child in resp.child('player/pdata/record').children: if child.name != 'rec': continue score = { 'id': child.child_value('mid'), 'chart': child.child_value('ntgrd'), 'clear_type': child.child_value('ct'), 'combo_type': child.child_value('param'), 'achievement_rate': child.child_value('ar'), 'score': child.child_value('scr'), 'miss_count': child.child_value('ms'), } scores.append(score) return scores
def _add_event_info(self, root: Node) -> None: event_ctrl = Node.void('event_ctrl') root.add_child(event_ctrl) # Contains zero or more nodes like: # <data> # <type __type="s32">any</type> # <index __type="s32">any</phase> # <value __type="s32">any</phase> # <value2 __type="s32">any</phase> # <start_time __type="s32">any</phase> # <end_time __type="s32">any</phase> # </data> item_lock_ctrl = Node.void('item_lock_ctrl') root.add_child(item_lock_ctrl) # Contains zero or more nodes like: # <item> # <type __type="u8">any</type> # <id __type="u16">any</id> # <param __type="u16">0-3</param> # </item> mycourse_ctrl = Node.void('mycourse_ctrl') root.add_child(mycourse_ctrl) songs = { song.id for song in self.data.local.music.get_all_songs( self.game, self.music_version) } for song in songs: data = Node.void('data') mycourse_ctrl.add_child(data) data.add_child(Node.s16('mycourse_id', 1)) data.add_child(Node.s32('type', 0)) data.add_child(Node.s32('music_id', song))
def verify_pcb24_boot(self, loc: str) -> None: call = self.call_node() # Construct node pcb24 = Node.void('pcb24') call.add_child(pcb24) pcb24.set_attribute('method', 'boot') pcb24.add_child(Node.string('loc_id', loc)) pcb24.add_child(Node.u8('loc_type', 0)) pcb24.add_child(Node.string('loc_name', '')) pcb24.add_child(Node.string('country', 'US')) pcb24.add_child(Node.string('region', '.')) pcb24.add_child(Node.s16('pref', 51)) pcb24.add_child(Node.string('customer', '')) pcb24.add_child(Node.string('company', '')) pcb24.add_child(Node.ipv4('gip', '127.0.0.1')) pcb24.add_child(Node.u16('gp', 10011)) pcb24.add_child(Node.string('rom_number', 'M39-JB-G01')) pcb24.add_child(Node.u64('c_drive', 10028228608)) pcb24.add_child(Node.u64('d_drive', 47945170944)) pcb24.add_child(Node.u64('e_drive', 10394677248)) pcb24.add_child(Node.string('etc', '')) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/pcb24/@status")
def handle_player_rb5_player_read_rival_score_5_request( self, request: Node) -> Node: extid = request.child_value('uid') songid = request.child_value('music_id') chart = request.child_value('note_grade') userid = self.data.remote.user.from_extid(self.game, self.version, extid) if userid is None: score = None profile = None else: score = self.data.remote.music.get_score(self.game, self.music_version, userid, songid, chart) profile = self.get_any_profile(userid) root = Node.void('player') if score is not None and profile is not None: player_select_score = Node.void('player_select_score') root.add_child(player_select_score) player_select_score.add_child(Node.s32('user_id', extid)) player_select_score.add_child( Node.string('name', profile.get_str('name'))) player_select_score.add_child(Node.s32('m_score', score.points)) player_select_score.add_child( Node.s32('m_scoreTime', score.timestamp)) player_select_score.add_child( Node.s16('m_iconID', profile.get_dict('config').get_int('icon_id'))) return root
def handle_lobby_report_request(self, request: Node) -> Node: root = Node.void('lobby') data = Node.void('data') root.add_child(data) refresh_intr = Node.s16('refresh_intr', 3) data.add_child(refresh_intr) return root
def verify_eacoin_consume(self, sessid: str, balance: int, amount: int) -> None: call = self.call_node() # Construct node eacoin = Node.void('eacoin') call.add_child(eacoin) eacoin.set_attribute('method', 'consume') eacoin.add_child(Node.string('sessid', sessid)) eacoin.add_child(Node.s16('sequence', 0)) eacoin.add_child(Node.s32('payment', amount)) eacoin.add_child(Node.s32('service', 0)) eacoin.add_child(Node.string('itemtype', '0')) eacoin.add_child(Node.string('detail', '/eacoin/start_pt1')) # Swap with server resp = self.exchange('core/eacoin', call) # Verify that response is correct self.assert_path(resp, "response/eacoin/balance") newbalance = resp.child('eacoin').child_value('balance') if balance - amount != newbalance: raise Exception( "Expected to get back balance {} but got {}".format( balance - amount, newbalance))
def verify_game_play_e(self, location: str, refid: str, play_id: int) -> None: call = self.call_node() game = Node.void('game') call.add_child(game) game.set_attribute('ver', '0') game.set_attribute('method', 'sv4_play_e') game.add_child(Node.string('refid', refid)) game.add_child(Node.u32('play_id', play_id)) game.add_child(Node.s8('start_type', 1)) game.add_child(Node.s8('mode', 2)) game.add_child(Node.s16('track_num', 3)) game.add_child(Node.s32('s_coin', 0)) game.add_child(Node.s32('s_paseli', 247)) game.add_child(Node.u32('print_card', 0)) game.add_child(Node.u32('print_result', 0)) game.add_child(Node.u32('blaster_num', 0)) game.add_child(Node.u32('today_cnt', 1)) game.add_child(Node.u32('play_chain', 1)) game.add_child(Node.u32('week_play_cnt', 0)) game.add_child(Node.u32('week_chain', 0)) game.add_child(Node.string('locid', location)) game.add_child(Node.u16('drop_frame', 16169)) game.add_child(Node.u16('drop_frame_max', 11984)) game.add_child(Node.u16('drop_count', 6)) game.add_child(Node.string('etc', 'play_t:605')) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game")
def handle_pcbinfo_get_request(self, request: Node) -> Node: shop_id = ID.parse_machine_id(request.child_value('lid')) machine = self.get_machine_by_id(shop_id) if machine is not None: machine_name = machine.name close = machine.data.get_bool('close') hour = machine.data.get_int('hour') minute = machine.data.get_int('minute') pref = machine.data.get_int('pref', 51) else: machine_name = '' close = False hour = 0 minute = 0 pref = 51 root = Node.void('pcbinfo') info = Node.void('info') root.add_child(info) info.add_child(Node.string('name', machine_name)) info.add_child(Node.s16('pref', pref)) info.add_child(Node.bool('close', close)) info.add_child(Node.u8('hour', hour)) info.add_child(Node.u8('min', minute)) return root
def verify_gameend_final( self, ref_id: str, jid: int, ) -> None: call = self.call_node() # Construct node gameend = Node.void('gameend') call.add_child(gameend) gameend.set_attribute('method', 'final') gameend.add_child(Node.s32('retry', 0)) pcbinfo = Node.void('pcbinfo') gameend.add_child(pcbinfo) pcbinfo.set_attribute('client_data_version', '0') data = Node.void('data') gameend.add_child(data) player = Node.void('player') data.add_child(player) player.add_child(Node.string('refid', ref_id)) player.add_child(Node.s32('jid', jid)) jbox = Node.void('jbox') player.add_child(jbox) jbox.add_child(Node.s32('point', 0)) emblem = Node.void('emblem') jbox.add_child(emblem) emblem.add_child(Node.u8('type', 0)) emblem.add_child(Node.s16('index', 0)) # Swap with server resp = self.exchange('', call) self.assert_path(resp, "response/gameend/@status")
def format_conversion(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('playerdata') root.add_child(Node.string('name', profile.get_str('name', 'なし'))) root.add_child(Node.s16('chara', profile.get_int('chara', -1))) root.add_child(Node.s32('option', profile.get_int('option', 0))) root.add_child(Node.u8('version', 0)) root.add_child(Node.u8('kind', 0)) root.add_child(Node.u8('season', 0)) clear_medal = [0] * self.GAME_MAX_MUSIC_ID scores = self.data.remote.music.get_scores(self.game, self.version, userid) for score in scores: if score.id > self.GAME_MAX_MUSIC_ID: continue # Skip any scores for chart types we don't support if score.chart not in [ self.CHART_TYPE_EASY, self.CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER, self.CHART_TYPE_EX, ]: continue clear_medal[score.id] = clear_medal[ score.id] | self.__format_medal_for_score(score) root.add_child(Node.u16_array('clear_medal', clear_medal)) return root
def verify_game_save(self, location: str, refid: str, packet: int, block: int, blaster_energy: int) -> None: call = self.call_node() game = Node.void('game') call.add_child(game) game.set_attribute('method', 'sv4_save') game.set_attribute('ver', '0') game.add_child(Node.string('refid', refid)) game.add_child(Node.string('locid', location)) game.add_child(Node.u8('headphone', 0)) game.add_child(Node.u16('appeal_id', 1001)) game.add_child(Node.u16('comment_id', 0)) game.add_child(Node.s32('music_id', 29)) game.add_child(Node.u8('music_type', 1)) game.add_child(Node.u8('sort_type', 1)) game.add_child(Node.u8('narrow_down', 0)) game.add_child(Node.u8('gauge_option', 0)) game.add_child(Node.u8('ars_option', 0)) game.add_child(Node.u8('notes_option', 0)) game.add_child(Node.u8('early_late_disp', 0)) game.add_child(Node.s32('draw_adjust', 0)) game.add_child(Node.u8('eff_c_left', 0)) game.add_child(Node.u8('eff_c_right', 1)) game.add_child(Node.u32('earned_gamecoin_packet', packet)) game.add_child(Node.u32('earned_gamecoin_block', block)) item = Node.void('item') game.add_child(item) game.add_child(Node.s16('skill_name_id', 0)) game.add_child(Node.s16('skill_base_id', 0)) game.add_child(Node.s16('skill_name', 0)) game.add_child(Node.s32('earned_blaster_energy', blaster_energy)) game.add_child(Node.u32('blaster_count', 0)) printn = Node.void('print') game.add_child(printn) printn.add_child(Node.s32('count', 0)) ea_shop = Node.void('ea_shop') game.add_child(ea_shop) ea_shop.add_child(Node.s32('used_packet_booster', 0)) ea_shop.add_child(Node.s32('used_block_booster', 0)) game.add_child(Node.s8('start_option', 1)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game")
def verify_player23_write( self, ref_id: str, medal: Optional[Dict[str, int]] = None, item: Optional[Dict[str, int]] = None, character: Optional[Dict[str, int]] = None, ) -> None: call = self.call_node() # Construct node player23 = Node.void('player23') call.add_child(player23) player23.set_attribute('method', 'write') player23.add_child(Node.string('ref_id', ref_id)) # Add required children config = Node.void('config') player23.add_child(config) config.add_child(Node.s16('chara', 1543)) if medal is not None: medalnode = Node.void('medal') player23.add_child(medalnode) medalnode.add_child(Node.s16('medal_id', medal['id'])) medalnode.add_child(Node.s16('level', medal['level'])) medalnode.add_child(Node.s32('exp', medal['exp'])) medalnode.add_child(Node.s32('set_count', 0)) medalnode.add_child(Node.s32('get_count', 0)) if item is not None: itemnode = Node.void('item') player23.add_child(itemnode) itemnode.add_child(Node.u8('type', item['type'])) itemnode.add_child(Node.u16('id', item['id'])) itemnode.add_child(Node.u16('param', item['param'])) itemnode.add_child(Node.bool('is_new', False)) if character is not None: chara_param = Node.void('chara_param') player23.add_child(chara_param) chara_param.add_child(Node.u16('chara_id', character['id'])) chara_param.add_child( Node.u16('friendship', character['friendship'])) # Swap with server resp = self.exchange('', call) self.assert_path(resp, "response/player23/@status")
def format_conversion(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('player23') root.add_child(Node.string('name', profile.get_str('name', 'なし'))) root.add_child(Node.s16('chara', profile.get_int('chara', -1))) root.add_child(Node.s8('result', 1)) scores = self.data.remote.music.get_scores(self.game, self.version, userid) for score in scores: # Skip any scores for chart types we don't support if score.chart not in [ self.CHART_TYPE_EASY, self.CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER, self.CHART_TYPE_EX, ]: continue points = score.points medal = score.data.get_int('medal') music = Node.void('music') root.add_child(music) music.add_child(Node.s16('music_num', score.id)) music.add_child(Node.u8('sheet_num', { self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY, self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL, self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER, self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX, }[score.chart])) music.add_child(Node.s32('score', points)) music.add_child(Node.u8('clear_type', { self.PLAY_MEDAL_CIRCLE_FAILED: self.GAME_PLAY_MEDAL_CIRCLE_FAILED, self.PLAY_MEDAL_DIAMOND_FAILED: self.GAME_PLAY_MEDAL_DIAMOND_FAILED, self.PLAY_MEDAL_STAR_FAILED: self.GAME_PLAY_MEDAL_STAR_FAILED, self.PLAY_MEDAL_EASY_CLEAR: self.GAME_PLAY_MEDAL_EASY_CLEAR, self.PLAY_MEDAL_CIRCLE_CLEARED: self.GAME_PLAY_MEDAL_CIRCLE_CLEARED, self.PLAY_MEDAL_DIAMOND_CLEARED: self.GAME_PLAY_MEDAL_DIAMOND_CLEARED, self.PLAY_MEDAL_STAR_CLEARED: self.GAME_PLAY_MEDAL_STAR_CLEARED, self.PLAY_MEDAL_CIRCLE_FULL_COMBO: self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO, self.PLAY_MEDAL_DIAMOND_FULL_COMBO: self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO, self.PLAY_MEDAL_STAR_FULL_COMBO: self.GAME_PLAY_MEDAL_STAR_FULL_COMBO, self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT, }[medal])) music.add_child(Node.s16('cnt', score.plays)) return root
def handle_lobby_refresh_request(self, request: Node) -> Node: root = Node.void('lobby') data = Node.void('data') root.add_child(data) refresh_intr = Node.s16('refresh_intr', 3) data.add_child(refresh_intr) start = Node.bool('start', True) data.add_child(start) return root