def verify_game_save_m(self, location: str, refid: str, score: Dict[str, int]) -> None: call = self.call_node() game = Node.void('game_2') call.add_child(game) game.set_attribute('ver', '0') game.set_attribute('method', 'save_m') game.add_child(Node.string('refid', refid)) game.add_child(Node.string('dataid', refid)) game.add_child(Node.u32('music_id', score['id'])) game.add_child(Node.u32('music_type', score['chart'])) game.add_child(Node.u32('score', score['score'])) game.add_child(Node.u32('clear_type', score['clear_type'])) game.add_child(Node.u32('score_grade', score['grade'])) game.add_child(Node.u32('max_chain', 0)) game.add_child(Node.u32('critical', 0)) game.add_child(Node.u32('near', 0)) game.add_child(Node.u32('error', 0)) game.add_child(Node.u32('effective_rate', 100)) game.add_child(Node.u32('btn_rate', 0)) game.add_child(Node.u32('long_rate', 0)) game.add_child(Node.u32('vol_rate', 0)) game.add_child(Node.u8('mode', 0)) game.add_child(Node.u8('gauge_type', 0)) game.add_child(Node.u16('online_num', 0)) game.add_child(Node.u16('local_num', 0)) game.add_child(Node.string('locid', location)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game_2")
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 handle_game_3_load_request(self, request: Node) -> Node: refid = request.child_value('refid') root = self.get_profile_by_refid(refid) if root is not None: return root # Figure out if this user has an older profile or not userid = self.data.remote.user.from_refid(self.game, self.version, refid) if userid is not None: previous_game = self.previous_version() else: previous_game = None if previous_game is not None: profile = previous_game.get_profile(userid) else: profile = None if profile is not None: root = Node.void('game_3') root.add_child(Node.u8('result', 2)) root.add_child(Node.string('name', profile.get_str('name'))) return root else: root = Node.void('game_3') root.add_child(Node.u8('result', 1)) return root
def verify_player24_write_music(self, ref_id: str, score: Dict[str, Any]) -> None: call = self.call_node() # Construct node player24 = Node.void('player24') call.add_child(player24) player24.set_attribute('method', 'write_music') player24.add_child(Node.string('ref_id', ref_id)) player24.add_child(Node.string('data_id', ref_id)) player24.add_child(Node.string('name', self.NAME)) player24.add_child(Node.u8('stage', 0)) player24.add_child(Node.s16('music_num', score['id'])) player24.add_child(Node.u8('sheet_num', score['chart'])) player24.add_child(Node.u8('clear_type', score['medal'])) player24.add_child(Node.s32('score', score['score'])) player24.add_child(Node.s16('combo', 0)) player24.add_child(Node.s16('cool', 0)) player24.add_child(Node.s16('great', 0)) player24.add_child(Node.s16('good', 0)) player24.add_child(Node.s16('bad', 0)) # Swap with server resp = self.exchange('', call) self.assert_path(resp, "response/player24/@status")
def verify_game_shop(self, location: str) -> None: call = self.call_node() game = Node.void('game') call.add_child(game) game.set_attribute('method', 'sv4_shop') game.set_attribute('ver', '0') game.add_child(Node.string('locid', location)) game.add_child(Node.string('regcode', '.')) game.add_child(Node.string('locname', '')) game.add_child(Node.u8('loctype', 0)) game.add_child(Node.string('cstcode', '')) game.add_child(Node.string('cpycode', '')) game.add_child(Node.s32('latde', 0)) game.add_child(Node.s32('londe', 0)) game.add_child(Node.u8('accu', 0)) game.add_child(Node.string('linid', '.')) game.add_child(Node.u8('linclass', 0)) game.add_child(Node.ipv4('ipaddr', '0.0.0.0')) game.add_child(Node.string('hadid', '00010203040506070809')) game.add_child(Node.string('licid', '00010203040506070809')) game.add_child(Node.string('actid', self.pcbid)) game.add_child(Node.s8('appstate', 0)) game.add_child(Node.s8('c_need', 1)) game.add_child(Node.s8('c_credit', 2)) game.add_child(Node.s8('s_credit', 2)) game.add_child(Node.bool('free_p', True)) game.add_child(Node.bool('close', False)) game.add_child(Node.s32('close_t', 1380)) game.add_child(Node.u32('playc', 0)) game.add_child(Node.u32('playn', 0)) game.add_child(Node.u32('playe', 0)) game.add_child(Node.u32('test_m', 0)) game.add_child(Node.u32('service', 0)) game.add_child(Node.bool('paseli', True)) game.add_child(Node.u32('update', 0)) game.add_child(Node.string('shopname', '')) game.add_child(Node.bool('newpc', False)) game.add_child(Node.s32('s_paseli', 206)) game.add_child(Node.s32('monitor', 1)) game.add_child(Node.string('romnumber', 'KFC-JA-B01')) game.add_child(Node.string('etc', 'TaxMode:1,BasicRate:100/1,FirstFree:0')) setting = Node.void('setting') game.add_child(setting) setting.add_child(Node.s32('coin_slot', 0)) setting.add_child(Node.s32('game_start', 1)) setting.add_child(Node.string('schedule', '0,0,0,0,0,0,0')) setting.add_child(Node.string('reference', '1,1,1')) setting.add_child(Node.string('basic_rate', '100,100,100')) setting.add_child(Node.s32('tax_rate', 1)) setting.add_child(Node.string('time_service', '0,0,0')) setting.add_child(Node.string('service_value', '10,10,10')) setting.add_child(Node.string('service_limit', '10,10,10')) setting.add_child(Node.string('service_time', '07:00-11:00,07:00-11:00,07:00-11:00')) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game/nxt_time")
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 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 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 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_game_3_common_request(self, request: Node) -> Node: game = Node.void('game_3') limited = Node.void('music_limited') game.add_child(limited) # Song unlock config game_config = self.get_game_config() if game_config.get_bool('force_unlock_songs'): ids = set() songs = self.data.local.music.get_all_songs( self.game, self.version) for song in songs: if song.data.get_int('limited') in ( self.GAME_LIMITED_LOCKED, self.GAME_LIMITED_UNLOCKABLE): ids.add((song.id, song.chart)) for (songid, chart) in ids: info = Node.void('info') limited.add_child(info) info.add_child(Node.s32('music_id', songid)) info.add_child(Node.u8('music_type', chart)) info.add_child(Node.u8('limited', self.GAME_LIMITED_UNLOCKED)) # Event config event = Node.void('event') game.add_child(event) def enable_event(eid: int) -> None: evt = Node.void('info') event.add_child(evt) evt.add_child(Node.u32('event_id', eid)) if not game_config.get_bool('disable_matching'): enable_event(143) # Matching enabled event_ids = [ 1, # Extended pedal options 56, # Generator grafica icon <print 1 in musicdb> 83, # Paseli Light Start 86, # Generator grafica icon <print 2 in musicdb> 98, # Caption 2 notice (grs_grafica_caption_2.png) 105, # Makes the "Number of Layers" option visible in game settings 130, # Curator Rank 140, # Agetta Moratta (vmlink_phase 3 in musicdb) 141, # Coconatsu & Mukipara grafica effects 145, # MUKIPARA UNLOCKS 146, # MUKIPARA UNLOCKS 147, # MUKIPARA UNLOCKS 148, # MUKIPARA UNLOCKS 149, # MUKIPARA UNLOCKS 195, # Fictional Curator (foot pedal options) 211, # News 1 ] for evtid in event_ids: enable_event(evtid) # Mission stuff return game
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_facility_get_request(self, request: Node) -> Node: """ Handle a facility request. The only method of note is the 'get' request, which expects to return a bunch of information about the arcade this cabinet is in, as well as some settings for URLs and the name of the cab. """ machine = self.data.local.machine.get_machine(self.config['machine']['pcbid']) root = Node.void('facility') root.set_attribute('expire', '600') location = Node.void('location') location.add_child(Node.string('id', ID.format_machine_id(machine.id))) location.add_child(Node.string('country', 'US')) location.add_child(Node.string('region', '.')) location.add_child(Node.string('name', machine.name)) location.add_child(Node.u8('type', 0)) line = Node.void('line') line.add_child(Node.string('id', '.')) line.add_child(Node.u8('class', 0)) portfw = Node.void('portfw') portfw.add_child(Node.ipv4('globalip', self.config['client']['address'])) portfw.add_child(Node.u16('globalport', machine.port)) portfw.add_child(Node.u16('privateport', machine.port)) public = Node.void('public') public.add_child(Node.u8('flag', 1)) public.add_child(Node.string('name', '.')) public.add_child(Node.string('latitude', '0')) public.add_child(Node.string('longitude', '0')) share = Node.void('share') eacoin = Node.void('eacoin') eacoin.add_child(Node.s32('notchamount', 3000)) eacoin.add_child(Node.s32('notchcount', 3)) eacoin.add_child(Node.s32('supplylimit', 10000)) eapass = Node.void('eapass') eapass.add_child(Node.u16('valid', 365)) url = Node.void('url') url.add_child(Node.string('eapass', self.config['server']['uri'] or 'www.ea-pass.konami.net')) url.add_child(Node.string('arcadefan', self.config['server']['uri'] or 'www.konami.jp/am')) url.add_child(Node.string('konaminetdx', self.config['server']['uri'] or 'http://am.573.jp')) url.add_child(Node.string('konamiid', self.config['server']['uri'] or 'https://id.konami.net')) url.add_child(Node.string('eagate', self.config['server']['uri'] or 'http://eagate.573.jp')) share.add_child(eacoin) share.add_child(url) share.add_child(eapass) root.add_child(location) root.add_child(line) root.add_child(portfw) root.add_child(public) root.add_child(share) 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 test_game_packet6(self) -> Node: root = Node.void('response') facility = Node.void('facility') root.add_child(facility) location = Node.void('location') facility.add_child(location) location.add_child(Node.string('id', 'US-6')) location.add_child(Node.string('country', 'US')) location.add_child(Node.string('region', '.')) location.add_child(Node.string('name', '')) location.add_child(Node.u8('type', 0)) line = Node.void('line') facility.add_child(line) line.add_child(Node.string('id', '.')) line.add_child(Node.u8('class', 0)) portfw = Node.void('portfw') facility.add_child(portfw) portfw.add_child(Node.ipv4('globalip', '10.0.0.1')) portfw.add_child(Node.u16('globalport', 20000)) portfw.add_child(Node.u16('privateport', 20000)) public = Node.void('public') facility.add_child(public) public.add_child(Node.u8('flag', 1)) public.add_child(Node.string('name', '.')) public.add_child(Node.string('latitude', '0')) public.add_child(Node.string('longitude', '0')) share = Node.void('share') facility.add_child(share) eacoin = Node.void('eacoin') share.add_child(eacoin) eacoin.add_child(Node.s32('notchamount', 0)) eacoin.add_child(Node.s32('notchcount', 0)) eacoin.add_child(Node.s32('supplylimit', 1000000)) url = Node.void('url') share.add_child(url) url.add_child(Node.string('eapass', 'http://some.dummy.net/')) url.add_child(Node.string('arcadefan', 'http://some.dummy.net/')) url.add_child(Node.string('konaminetdx', 'http://some.dummy.net/')) url.add_child(Node.string('konamiid', 'http://some.dummy.net/')) url.add_child(Node.string('eagate', 'http://some.dummy.net/')) self.assertLoopback(root)
def handle_game_load_m_request(self, request: Node) -> Node: extid = intish(request.attribute('code')) refid = request.attribute('refid') if extid is not None: # Rival score loading userid = self.data.remote.user.from_extid(self.game, self.version, extid) else: # Self score loading 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.music_version, userid) else: scores = [] sortedscores: Dict[int, Dict[int, Score]] = {} for score in scores: if score.id not in sortedscores: sortedscores[score.id] = {} sortedscores[score.id][score.chart] = score game = Node.void('game') for song in sortedscores: music = Node.void('music') game.add_child(music) music.set_attribute('reclink', str(song)) for chart in sortedscores[song]: score = sortedscores[song][chart] try: gamechart = self.db_to_game_chart(chart) except KeyError: # Don't support this chart in this game continue gamerank = self.db_to_game_rank(score.data.get_int('rank')) combo_type = self.db_to_game_halo(score.data.get_int('halo')) typenode = Node.void('type') music.add_child(typenode) typenode.set_attribute('diff', str(gamechart)) typenode.add_child(Node.u32('score', score.points)) typenode.add_child(Node.u16('count', score.plays)) typenode.add_child(Node.u8('rank', gamerank)) typenode.add_child(Node.u8('combo_type', combo_type)) # The game optionally receives hard, life8, life4, risky, assist_clear, normal_clear # u8 values too, and saves music scores with these set, but the UI doesn't appear to # do anything with them, so we don't care. return game
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_3') call.add_child(game) game.set_attribute('method', '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.u32('earned_gamecoin_packet', packet)) game.add_child(Node.u32('earned_gamecoin_block', block)) item = Node.void('item') game.add_child(item) info = Node.void('info') item.add_child(info) info.add_child(Node.u32('id', 1)) info.add_child(Node.u32('type', 5)) info.add_child(Node.u32('param', 333333376)) info = Node.void('info') item.add_child(info) info.add_child(Node.u32('id', 0)) info.add_child(Node.u32('type', 5)) info.add_child(Node.u32('param', 600)) game.add_child( Node.s32_array( 'hidden_param', [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) game.add_child(Node.s16('skill_name_id', -1)) 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', 0)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game_3")
def handle_game_area_hiscore_request(self, request: Node) -> Node: shop_area = int(request.attribute('shop_area')) # First, get all users that are in the current shop's area area_users = { uid: prof for (uid, prof) in self.data.local.user.get_all_profiles(self.game, self.version) if prof.get_int('area', 51) == shop_area } # Second, look up records belonging only to those users records = self.data.local.music.get_all_records(self.game, self.music_version, userlist=list(area_users.keys())) # Now, do the same lazy thing as 'hiscore' because I don't want # to think about how to change this knowing that we only pulled # up area records. area_records: Dict[int, Dict[int, Tuple[UserID, Score]]] = {} for (userid, score) in records: if score.id not in area_records: area_records[score.id] = {} area_records[score.id][score.chart] = (userid, score) game = Node.void('game') for song in area_records: music = Node.void('music') game.add_child(music) music.set_attribute('reclink_num', str(song)) for chart in area_records[song]: userid, score = area_records[song][chart] if area_users[userid].get_int('area', 51) != shop_area: # Don't return this, this user isn't in this area continue try: gamechart = self.db_to_game_chart(chart) except KeyError: # Don't support this chart in this game continue gamerank = self.db_to_game_rank(score.data.get_int('rank')) combo_type = self.db_to_game_halo(score.data.get_int('halo')) typenode = Node.void('type') music.add_child(typenode) typenode.set_attribute('diff', str(gamechart)) typenode.add_child(Node.string('name', area_users[userid].get_str('name'))) typenode.add_child(Node.u32('score', score.points)) typenode.add_child(Node.u16('area', area_users[userid].get_int('area', 51))) typenode.add_child(Node.u8('rank', gamerank)) typenode.add_child(Node.u8('combo_type', combo_type)) typenode.add_child(Node.u32('code', area_users[userid].get_int('extid'))) return game
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 handle_shopinfo_regist_request(self, request: Node) -> Node: # Update the name of this cab for admin purposes self.update_machine_name(request.child_value('shop/name')) shopinfo = Node.void('shopinfo') data = Node.void('data') shopinfo.add_child(data) data.add_child(Node.u32('cabid', 1)) data.add_child(Node.string('locationid', 'nowhere')) data.add_child(Node.u8('is_send', 1)) data.add_child(Node.s32_array( 'white_music_list', [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ], )) data.add_child(Node.u8('tax_phase', 1)) lab = Node.void('lab') data.add_child(lab) lab.add_child(Node.bool('is_open', False)) vocaloid_event = Node.void('vocaloid_event') data.add_child(vocaloid_event) vocaloid_event.add_child(Node.u8('state', 0)) vocaloid_event.add_child(Node.s32('music_id', 0)) vocaloid_event2 = Node.void('vocaloid_event2') data.add_child(vocaloid_event2) vocaloid_event2.add_child(Node.u8('state', 0)) vocaloid_event2.add_child(Node.s32('music_id', 0)) # No obnoxious 30 second wait to play. matching_off = Node.void('matching_off') data.add_child(matching_off) matching_off.add_child(Node.bool('is_open', True)) tenka = Node.void('tenka') data.add_child(tenka) tenka.add_child(Node.bool('is_participant', False)) return shopinfo
def __handle_ghostload(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None: ghostid = requestdata.child_value('ghostid') ghost = self.data.local.music.get_score_by_key(self.game, self.music_version, ghostid) if ghost is None: return userid, score = ghost profile = self.get_profile(userid) if profile is None: return if 'ghost' not in score.data: return ghostdata = Node.void('ghostdata') response.add_child(ghostdata) ghostdata.add_child(Node.s32('code', profile.get_int('extid'))) ghostdata.add_child(Node.u32('mcode', score.id)) ghostdata.add_child( Node.u8('notetype', self.db_to_game_chart(score.chart))) ghostdata.add_child(Node.s32('ghostsize', len(score.data['ghost']))) ghostdata.add_child(Node.string('ghost', score.data['ghost']))
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 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_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_game_buy(self, refid: str, catalogtype: int, catalogid: int, currencytype: int, price: int, itemtype: int, itemid: int, param: int, success: bool) -> None: call = self.call_node() game = Node.void('game_2') call.add_child(game) game.set_attribute('ver', '0') game.set_attribute('method', 'buy') game.add_child(Node.string('refid', refid)) game.add_child(Node.u8('catalog_type', catalogtype)) game.add_child(Node.u32('catalog_id', catalogid)) game.add_child(Node.u32('earned_gamecoin_packet', 0)) game.add_child(Node.u32('earned_gamecoin_block', 0)) game.add_child(Node.u32('currency_type', currencytype)) game.add_child(Node.u32('price', price)) game.add_child(Node.u32('item_type', itemtype)) game.add_child(Node.u32('item_id', itemid)) game.add_child(Node.u32('param', param)) # Swap with server resp = self.exchange('', call) # Verify that response is correct self.assert_path(resp, "response/game_2/gamecoin_packet") self.assert_path(resp, "response/game_2/gamecoin_block") self.assert_path(resp, "response/game_2/result") if success: if resp.child_value('game_2/result') != 0: raise Exception('Failed to purchase!') else: if resp.child_value('game_2/result') == 0: raise Exception('Purchased when shouldn\'t have!')
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 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 handle_game_3_common_request(self, request: Node) -> Node: game = Node.void('game_3') limited = Node.void('music_limited') game.add_child(limited) # Song unlock config game_config = self.get_game_config() if game_config.get_bool('force_unlock_songs'): ids = set() songs = self.data.local.music.get_all_songs( self.game, self.version) for song in songs: if song.data.get_int('limited') in ( self.GAME_LIMITED_LOCKED, self.GAME_LIMITED_UNLOCKABLE): ids.add((song.id, song.chart)) for (songid, chart) in ids: info = Node.void('info') limited.add_child(info) info.add_child(Node.s32('music_id', songid)) info.add_child(Node.u8('music_type', chart)) info.add_child(Node.u8('limited', self.GAME_LIMITED_UNLOCKED)) # Event config event = Node.void('event') game.add_child(event) def enable_event(eid: int) -> None: evt = Node.void('info') event.add_child(evt) evt.add_child(Node.u32('event_id', eid)) if not game_config.get_bool('disable_matching'): enable_event(143) # Matching enabled enable_event(1) # Extended pedal options enable_event(83) # Light start enable_event(130) # Curator rank enable_event(195) # Fictional curator # Event 194 is continuation mode, but it doesn't seem to work on latest data. enable_event(98) # Mission mode for evtid in [145, 146, 147, 148, 149]: enable_event(evtid) # Mission stuff return game
def handle_lobby_read_request(self, request: Node) -> Node: root = Node.void('lobby') # Look up all lobbies matching the criteria specified 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 profile = self.get_profile(user) if profile is None: # No profile info, don't return this lobby continue 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('exp', profile.get_int('exp'))) e.add_child(Node.u8('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.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.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))) limit = limit - 1 return root
def verify_game_active(self) -> None: call = self.call_node() # Construct node game = Node.void('game') call.add_child(game) game.set_attribute('method', 'active') # Add what Pop'n 20 would add after full unlock game.set_attribute('method', 'active') game.add_child(Node.s8('event', 0)) game.add_child(Node.s8('card_use', 0)) game.add_child(Node.string('name', '')) game.add_child(Node.string('location_id', 'JP-1')) game.add_child(Node.string('shop_name_facility', '.')) game.add_child(Node.s8('pref', 50)) game.add_child(Node.string('shop_addr', '127.0.0.1 10000')) game.add_child(Node.string('shop_name', '')) game.add_child(Node.string('eacoin_price', '200,260,200,200')) game.add_child(Node.s8('eacoin_available', 1)) game.add_child(Node.s8('dipswitch', 0)) game.add_child(Node.u8('max_stage', 1)) game.add_child(Node.u8('difficult', 4)) game.add_child(Node.s8('free_play', 1)) game.add_child(Node.s8('event_mode', 0)) game.add_child(Node.s8('popn_card', 0)) game.add_child(Node.s16('close_time', -1)) game.add_child(Node.s32('game_phase', 2)) game.add_child(Node.s32('net_phase', 0)) game.add_child(Node.s32('event_phase', 0)) game.add_child(Node.s32('card_phase', 3)) game.add_child(Node.s32('ir_phase', 0)) game.add_child(Node.u8('coin_to_credit', 1)) game.add_child(Node.u8('credit_to_start', 2)) game.add_child(Node.s32('sound_attract', 100)) game.add_child(Node.s8('bookkeeping', 0)) game.add_child(Node.s8('set_clock', 0)) game.add_child(Node.s32('local_clock_sec', 80011)) game.add_child(Node.s32('revision_sec', 0)) game.add_child(Node.string('crash_log', '')) # Swap with server resp = self.exchange('pnm20/game', call) # Verify that response is correct self.assert_path(resp, "response/game/@status")
def handle_game_3_common_request(self, request: Node) -> Node: game = Node.void('game_3') limited = Node.void('music_limited') game.add_child(limited) # Song unlock config game_config = self.get_game_config() if game_config.get_bool('force_unlock_songs'): ids = set() songs = self.data.local.music.get_all_songs( self.game, self.music_version) for song in songs: if song.data.get_int('limited') in ( self.GAME_LIMITED_LOCKED, self.GAME_LIMITED_UNLOCKABLE): ids.add((song.id, song.chart)) for (songid, chart) in ids: info = Node.void('info') limited.add_child(info) info.add_child(Node.s32('music_id', songid)) info.add_child(Node.u8('music_type', chart)) info.add_child(Node.u8('limited', self.GAME_LIMITED_UNLOCKED)) # Event config event = Node.void('event') game.add_child(event) def enable_event(eid: int) -> None: evt = Node.void('info') event.add_child(evt) evt.add_child(Node.u32('event_id', eid)) # Allow PASELI light start enable_event(83) # If you want song unlock news to show up, enable one of the following: # 94 - 5/25/2016 unlocks # 95 - 4/27/2016 second unlocks # 89 - 4/27/2016 unlocks # 87 - 4/13/2016 unlocks # 82 - 3/23/2016 second unlocks # 80 - 3/23/2016 unlocks # 76 - 12/22/2016 unlocks return game