コード例 #1
0
    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")
コード例 #2
0
    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")
コード例 #3
0
ファイル: heavenlyhaven.py プロジェクト: wolskiCN/bemaniutils
    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")
コード例 #4
0
    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')
コード例 #5
0
ファイル: limelight.py プロジェクト: Subject38/bemaniutils
    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
コード例 #6
0
    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
コード例 #7
0
ファイル: core.py プロジェクト: wolskiCN/bemaniutils
    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
コード例 #8
0
ファイル: test_protocol.py プロジェクト: wolskiCN/bemaniutils
    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)
コード例 #9
0
    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")
コード例 #10
0
    def verify_player_rb5_player_start(self, refid: str) -> None:
        call = self.call_node()

        player = Node.void('player')
        player.set_attribute('method', 'rb5_player_start')
        player.add_child(Node.string('rid', refid))
        player.add_child(Node.u8_array('ga', [127, 0, 0, 1]))
        player.add_child(Node.u16('gp', 10573))
        player.add_child(Node.u8_array('la', [16, 0, 0, 0]))
        player.add_child(
            Node.u8_array(
                'pnid',
                [39, 16, 0, 0, 0, 23, 62, 60, 39, 127, 0, 0, 1, 23, 62, 60]))

        call.add_child(player)

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/player/plyid")
        self.assert_path(resp, "response/player/start_time")
        self.assert_path(resp, "response/player/event_ctrl")
        self.assert_path(resp, "response/player/item_lock_ctrl")
        self.assert_path(resp, "response/player/mycourse_ctrl")
コード例 #11
0
ファイル: lapistoria.py プロジェクト: wolskiCN/bemaniutils
    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")
コード例 #12
0
ファイル: sunnypark.py プロジェクト: vangar/bemaniutils
    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}\'')
コード例 #13
0
    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")
コード例 #14
0
ファイル: heavenlyhaven.py プロジェクト: wolskiCN/bemaniutils
    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")
コード例 #15
0
ファイル: eclale.py プロジェクト: wolskiCN/bemaniutils
    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")
コード例 #16
0
ファイル: reflecbeat.py プロジェクト: wolskiCN/bemaniutils
    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
コード例 #17
0
    def verify_player24_buy(self, ref_id: str, item: Dict[str, int]) -> None:
        call = self.call_node()

        # Construct node
        player24 = Node.void('player24')
        call.add_child(player24)
        player24.set_attribute('method', 'buy')
        player24.add_child(Node.s32('play_id', 0))
        player24.add_child(Node.string('ref_id', ref_id))
        player24.add_child(Node.u16('id', item['id']))
        player24.add_child(Node.u8('type', item['type']))
        player24.add_child(Node.u16('param', item['param']))
        player24.add_child(Node.s32('lumina', item['points']))
        player24.add_child(Node.u16('price', item['price']))

        # Swap with server
        resp = self.exchange('', call)
        self.assert_path(resp, "response/player24/@status")
コード例 #18
0
    def verify_game_save(self, location: str, refid: str, packet: int,
                         block: int, blaster_energy: int,
                         appealcards: List[int]) -> None:
        call = self.call_node()

        game = Node.void('game_2')
        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.u8('hispeed', 52))
        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))
        game.add_child(Node.void('item'))
        appealcard = Node.void('appealcard')
        game.add_child(appealcard)
        for card in appealcards:
            info = Node.void('info')
            info.add_child(Node.u32('id', card))
            info.add_child(Node.u32('count', 0))
            appealcard.add_child(info)
        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))

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/game_2")
コード例 #19
0
ファイル: test_protocol.py プロジェクト: wolskiCN/bemaniutils
    def test_packet1(self) -> Node:
        root = Node.void('test')
        root.set_attribute('test', 'test string value')

        # Regular nodes
        root.add_child(Node.void('void_node'))
        root.add_child(Node.s8('s8_node', -1))
        root.add_child(Node.u8('u8_node', 245))
        root.add_child(Node.s16('s16_node', -8000))
        root.add_child(Node.u16('u16_node', 65000))
        root.add_child(Node.s32('s32_node', -2000000000))
        root.add_child(Node.u32('u32_node', 4000000000))
        root.add_child(Node.s64('s64_node', -1234567890000))
        root.add_child(Node.u64('u64_node', 1234567890000))
        root.add_child(Node.binary('bin_node', b'DEADBEEF'))
        root.add_child(Node.string('str_node', 'this is a string!'))
        root.add_child(Node.ipv4('ip4_node', '192.168.1.24'))
        root.add_child(Node.time('time_node', 1234567890))
        root.add_child(Node.float('float_node', 2.5))
        root.add_child(Node.fouru8('4u8_node', [0x20, 0x21, 0x22, 0x23]))
        root.add_child(Node.bool('bool_true_node', True))
        root.add_child(Node.bool('bool_false_node', False))

        # Array nodes
        root.add_child(Node.s8_array('s8_array_node', [-1, -2, 3, 4, -5]))
        root.add_child(Node.u8_array('u8_array_node', [245, 2, 0, 255, 1]))
        root.add_child(Node.s16_array('s16_array_node', [-8000, 8000]))
        root.add_child(Node.u16_array('u16_array_node', [65000, 1, 2, 65535]))
        root.add_child(Node.s32_array('s32_array_node', [-2000000000, -1]))
        root.add_child(Node.u32_array('u32_array_node', [4000000000, 0, 1, 2]))
        root.add_child(
            Node.s64_array('s64_array_node', [-1234567890000, -1, 1, 1337]))
        root.add_child(
            Node.u64_array('u64_array_node', [1234567890000, 123, 456, 7890]))
        root.add_child(
            Node.time_array('time_array_node', [1234567890, 98765432]))
        root.add_child(
            Node.float_array('float_array_node', [2.5, 0.0, 5.0, 20.5]))
        root.add_child(
            Node.bool_array('bool_array_node', [False, True, True, False]))

        # XML escaping
        escape = Node.string(
            'escape_test',
            '\r\n<testing> & \'thing\' "thing" \r\nthing on new line\r\n    ')
        escape.set_attribute('test',
                             '<testing> & \'thing\' "thing" \r\n thing')
        root.add_child(escape)

        # Unicode
        unicode_node = Node.string('unicode', '今日は')
        unicode_node.set_attribute('unicode_attr', 'わたし')
        root.add_child(unicode_node)

        self.assertLoopback(root)
コード例 #20
0
    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
コード例 #21
0
ファイル: common.py プロジェクト: vangar/bemaniutils
    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
コード例 #22
0
    def verify_jbrbcollabo_save(self, refid: str) -> None:
        call = self.call_node()

        jbrbcollabo = Node.void('jbrbcollabo')
        jbrbcollabo.set_attribute('method', 'save')
        jbrbcollabo.add_child(Node.string('ref_id', refid))
        jbrbcollabo.add_child(Node.u16('cre_count', 0))
        call.add_child(jbrbcollabo)

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/jbrbcollabo")
コード例 #23
0
ファイル: ddrx2.py プロジェクト: vangar/bemaniutils
    def handle_game_hiscore_request(self, request: Node) -> Node:
        # This is almost identical to X3 and above, except X3 added a 'code' field
        # that isn't present here. In the interest of correctness, keep a separate
        # implementation here.
        records = self.data.remote.music.get_all_records(self.game, self.music_version)

        sortedrecords: Dict[int, Dict[int, Tuple[UserID, Score]]] = {}
        missing_profiles = []
        for (userid, score) in records:
            if score.id not in sortedrecords:
                sortedrecords[score.id] = {}
            sortedrecords[score.id][score.chart] = (userid, score)
            missing_profiles.append(userid)
        users = {userid: profile for (userid, profile) in self.get_any_profiles(missing_profiles)}

        game = Node.void('game')
        for song in sortedrecords:
            music = Node.void('music')
            game.add_child(music)
            music.set_attribute('reclink_num', str(song))

            for chart in sortedrecords[song]:
                userid, score = sortedrecords[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.string('name', users[userid].get_str('name')))
                typenode.add_child(Node.u32('score', score.points))
                typenode.add_child(Node.u16('area', users[userid].get_int('area', 51)))
                typenode.add_child(Node.u8('rank', gamerank))
                typenode.add_child(Node.u8('combo_type', combo_type))

        return game
コード例 #24
0
    def verify_player_start(self, refid: str) -> None:
        call = self.call_node()

        player = Node.void('player')
        player.set_attribute('method', 'start')
        player.add_child(Node.string('rid', refid))
        player.add_child(Node.u8_array('ga', [127, 0, 0, 1]))
        player.add_child(Node.u16('gp', 10573))
        player.add_child(Node.u8_array('la', [16, 0, 0, 0]))
        call.add_child(player)

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/player/plyid")
        self.assert_path(resp, "response/player/start_time")
        self.assert_path(resp, "response/player/event_ctrl")
        self.assert_path(resp, "response/player/item_lock_ctrl")
        self.assert_path(resp, "response/player/lincle_link_4")
        self.assert_path(resp, "response/player/jbrbcollabo")
        self.assert_path(resp, "response/player/tricolettepark")
コード例 #25
0
ファイル: booth.py プロジェクト: wolskiCN/bemaniutils
    def verify_game_save(self, location: str, refid: str, packet: int,
                         block: int, exp: int) -> None:
        call = self.call_node()

        game = Node.void('game')
        call.add_child(game)
        game.set_attribute('method', 'save')
        game.set_attribute('refid', refid)
        game.set_attribute('locid', location)
        game.set_attribute('ver', '0')
        game.add_child(Node.u8('headphone', 0))
        game.add_child(Node.u8('hispeed', 16))
        game.add_child(Node.u16('appeal_id', 19))
        game.add_child(Node.u16('frame0', 0))
        game.add_child(Node.u16('frame1', 0))
        game.add_child(Node.u16('frame2', 0))
        game.add_child(Node.u16('frame3', 0))
        game.add_child(Node.u16('frame4', 0))
        last = Node.void('last')
        game.add_child(last)
        last.set_attribute('music_type', '1')
        last.set_attribute('music_id', '29')
        last.set_attribute('sort_type', '4')
        game.add_child(Node.u32('earned_gamecoin_packet', packet))
        game.add_child(Node.u32('earned_gamecoin_block', block))
        game.add_child(Node.u32('gain_exp', exp))
        game.add_child(Node.u32('m_user_cnt', 0))
        game.add_child(Node.bool_array('have_item', [False] * 512))
        game.add_child(Node.bool_array('have_note', [False] * 512))
        tracking = Node.void('tracking')
        game.add_child(tracking)
        m0 = Node.void('m0')
        tracking.add_child(m0)
        m0.add_child(Node.u8('type', 2))
        m0.add_child(Node.u32('id', 5))
        m0.add_child(Node.u32('score', 774566))
        tracking.add_child(Node.time('p_start', Time.now() - 300))
        tracking.add_child(Node.time('p_end', Time.now()))

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/game")
コード例 #26
0
ファイル: heavenlyhaven.py プロジェクト: wolskiCN/bemaniutils
    def verify_game_entry_s(self) -> int:
        call = self.call_node()

        game = Node.void('game')
        call.add_child(game)
        game.set_attribute('ver', '0')
        game.set_attribute('method', 'sv4_entry_s')
        game.add_child(Node.u8('c_ver', 174))
        game.add_child(Node.u8('p_num', 1))
        game.add_child(Node.u8('p_rest', 1))
        game.add_child(Node.u8('filter', 1))
        game.add_child(Node.u32('mid', 492))
        game.add_child(Node.u32('sec', 45))
        game.add_child(Node.u16('port', 10007))
        game.add_child(Node.fouru8('gip', [127, 0, 0, 1]))
        game.add_child(Node.fouru8('lip', [10, 0, 5, 73]))
        game.add_child(Node.u8('claim', 0))

        # Swap with server
        resp = self.exchange('', call)

        # Verify that response is correct
        self.assert_path(resp, "response/game/entry_id")
        return resp.child_value('game/entry_id')
コード例 #27
0
def parse_psmap(data: bytes, offset: str, rootname: str) -> Node:
    pe = pefile.PE(data=data, fast_load=True)
    root = Node.void(rootname)
    base = int(offset, 16)

    def virtual_to_physical(offset: int) -> int:
        for section in pe.sections:
            start = section.VirtualAddress + pe.OPTIONAL_HEADER.ImageBase
            end = start + section.SizeOfRawData

            if offset >= start and offset < end:
                return (offset - start) + section.PointerToRawData
        raise Exception(
            f'Couldn\'t find raw offset for virtual offset 0x{offset:08x}')

    if base >= pe.OPTIONAL_HEADER.ImageBase:
        # Assume this is virtual
        base = virtual_to_physical(base)

    def read_string(offset: int) -> str:
        # First, translate load offset in memory to disk offset
        offset = virtual_to_physical(offset)

        # Now, grab bytes until we're null-terminated
        bytestring = []
        while data[offset] != 0:
            bytestring.append(data[offset])
            offset = offset + 1

        # Its shift-jis encoded, so decode it now
        return bytes(bytestring).decode('shift_jisx0213')

    # For recursing into nodes
    saved_root: List[Node] = []
    saved_loc: List[int] = []

    while True:
        chunk = data[base:(base + 16)]
        base = base + 16

        (nodetype, mandatory, outoffset, width, nameptr,
         defaultptr) = struct.unpack('<BBHIII', chunk)

        if nodetype == 0xFF:
            # End of nodes, see if we should exit
            if len(saved_root) == 0:
                break
            else:
                root = saved_root.pop()
                oldbase = saved_loc.pop()
                if oldbase is not None:
                    base = oldbase
                continue

        # Grab name, get rid of parse numbers
        name = read_string(nameptr)
        try:
            if name.index('#') >= 0:
                name = name[:name.index('#')]
        except ValueError:
            pass

        if nodetype == 0x00:
            raise Exception(f'Invalid node type 0x{nodetype:02x}')
        elif nodetype == 0x01:
            # This is a void node, so we should handle by recursing
            node = Node.void(name)
            root.add_child(node)

            # Recurse here
            saved_root.append(root)

            if defaultptr != 0:
                saved_loc.append(base)
                base = virtual_to_physical(defaultptr)
            else:
                saved_loc.append(None)

            root = node
            continue
        elif nodetype == 0x02 or nodetype == 0x43:
            if nodetype < 0x40:
                elements = int(width / 1)
            else:
                elements = width
            if elements > 1:
                node = Node.s8_array(name, [-1] * elements)
            else:
                node = Node.s8(name, -1)
        elif nodetype == 0x03 or nodetype == 0x44:
            if nodetype < 0x40:
                elements = int(width / 1)
            else:
                elements = width
            if elements > 1:
                node = Node.u8_array(name, [0] * elements)
            else:
                node = Node.u8(name, 0)
        elif nodetype == 0x04 or nodetype == 0x45:
            if nodetype < 0x40:
                elements = int(width / 2)
            else:
                elements = width
            if elements > 1:
                node = Node.s16_array(name, [-1] * elements)
            else:
                node = Node.s16(name, -1)
        elif nodetype == 0x05 or nodetype == 0x46:
            if nodetype < 0x40:
                elements = int(width / 2)
            else:
                elements = width
            if elements > 1:
                node = Node.u16_array(name, [0] * elements)
            else:
                node = Node.u16(name, 0)
        elif nodetype == 0x06 or nodetype == 0x47:
            if nodetype < 0x40:
                elements = int(width / 4)
            else:
                elements = width
            if elements > 1:
                node = Node.s32_array(name, [-1] * elements)
            else:
                node = Node.s32(name, -1)
        elif nodetype == 0x07 or nodetype == 0x48:
            if nodetype < 0x40:
                elements = int(width / 4)
            else:
                elements = width
            if elements > 1:
                node = Node.u32_array(name, [0] * elements)
            else:
                node = Node.u32(name, 0)
        elif nodetype == 0x08 or nodetype == 0x49:
            if nodetype < 0x40:
                elements = int(width / 8)
            else:
                elements = width
            if elements > 1:
                node = Node.s64_array(name, [-1] * elements)
            else:
                node = Node.s64(name, -1)
        elif nodetype == 0x09 or nodetype == 0x4A:
            if nodetype < 0x40:
                elements = int(width / 8)
            else:
                elements = width
            if elements > 1:
                node = Node.u64_array(name, [0] * elements)
            else:
                node = Node.u64(name, 0)
        elif nodetype == 0x0A:
            node = Node.string(name, '')
        elif nodetype == 0x0D:
            node = Node.float(name, 0.0)
        elif nodetype == 0x32 or nodetype == 0x6D:
            if nodetype < 0x40:
                elements = int(width / 1)
            else:
                elements = width
            if elements > 1:
                node = Node.bool_array(name, [False] * elements)
            else:
                node = Node.bool(name, False)
        elif nodetype == 0x2F:
            # Special case, this is an attribute
            if name[-1] != '@':
                raise Exception(
                    f'Attribute name {name} expected to end with @')
            root.set_attribute(name[:-1], '')
            continue
        else:
            raise Exception(f'Unimplemented node type 0x{nodetype:02x}')

        # Append it
        root.add_child(node)

    return root
コード例 #28
0
ファイル: lapistoria.py プロジェクト: yungsun09/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('player22')

        # Result
        root.add_child(Node.s8('result', 0))

        # Set up account
        account = Node.void('account')
        root.add_child(account)
        account.add_child(Node.string('name', profile.get_str('name', 'なし')))
        account.add_child(
            Node.string('g_pm_id', ID.format_extid(profile.get_int('extid'))))
        account.add_child(Node.s8('tutorial', profile.get_int('tutorial', -1)))
        account.add_child(
            Node.s16('read_news', profile.get_int('read_news', 0)))
        account.add_child(Node.s8('staff', 0))
        account.add_child(Node.s8('is_conv', 0))
        account.add_child(Node.s16('item_type', 0))
        account.add_child(Node.s16('item_id', 0))
        account.add_child(
            Node.s16_array('license_data',
                           [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]))

        # Statistics section and scores section
        statistics = self.get_play_statistics(userid)
        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (last_play_date[0] == today_play_date[0]
                and last_play_date[1] == today_play_date[1]
                and last_play_date[2] == today_play_date[2]):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0
        account.add_child(Node.u8('active_fr_num',
                                  0))  # TODO: Hook up rivals code?
        account.add_child(
            Node.s16('total_play_cnt', statistics.get_int('total_plays', 0)))
        account.add_child(Node.s16('today_play_cnt', today_count))
        account.add_child(
            Node.s16('consecutive_days',
                     statistics.get_int('consecutive_days', 0)))
        account.add_child(
            Node.s16('total_days', statistics.get_int('total_days', 0)))
        account.add_child(Node.s16('interval_day', 0))

        # Add scores section
        last_played = [
            x[0] for x in self.data.local.music.get_last_played(
                self.game, self.version, userid, 5)
        ]
        most_played = [
            x[0] for x in self.data.local.music.get_most_played(
                self.game, self.version, userid, 10)
        ]
        while len(last_played) < 5:
            last_played.append(-1)
        while len(most_played) < 10:
            most_played.append(-1)

        account.add_child(Node.s16_array('my_best', most_played))
        account.add_child(Node.s16_array('latest_music', last_played))

        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.s16('cnt', score.plays))
            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.s32('old_score', 0))
            music.add_child(Node.u8('old_clear_type', 0))

        # Net VS section
        netvs = Node.void('netvs')
        root.add_child(netvs)
        netvs.add_child(Node.s32('rank_point', 0))
        netvs.add_child(Node.s16_array('record', [0, 0, 0, 0, 0, 0]))
        netvs.add_child(Node.u8('rank', 0))
        netvs.add_child(Node.s8('vs_rank_old', 0))
        netvs.add_child(Node.s8_array('ojama_condition', [0] * 74))
        netvs.add_child(Node.s8_array('set_ojama', [0, 0, 0]))
        netvs.add_child(Node.s8_array('set_recommend', [0, 0, 0]))
        netvs.add_child(Node.u32('netvs_play_cnt', 0))
        for dialog in [0, 1, 2, 3, 4, 5]:
            # TODO: Configure this, maybe?
            netvs.add_child(Node.string('dialog', f'dialog#{dialog}'))

        # Set up config
        config = Node.void('config')
        root.add_child(config)
        config.add_child(Node.u8('mode', profile.get_int('mode', 0)))
        config.add_child(Node.s16('chara', profile.get_int('chara', -1)))
        config.add_child(Node.s16('music', profile.get_int('music', -1)))
        config.add_child(Node.u8('sheet', profile.get_int('sheet', 0)))
        config.add_child(Node.s8('category', profile.get_int('category', 1)))
        config.add_child(
            Node.s8('sub_category', profile.get_int('sub_category', -1)))
        config.add_child(
            Node.s8('chara_category', profile.get_int('chara_category', -1)))
        config.add_child(Node.s16('story_id', profile.get_int('story_id', -1)))
        config.add_child(
            Node.s16('course_id', profile.get_int('course_id', -1)))
        config.add_child(
            Node.s8('course_folder', profile.get_int('course_folder', -1)))
        config.add_child(
            Node.s8('story_folder', profile.get_int('story_folder', -1)))
        config.add_child(
            Node.s8('ms_banner_disp', profile.get_int('ms_banner_disp')))
        config.add_child(
            Node.s8('ms_down_info', profile.get_int('ms_down_info')))
        config.add_child(
            Node.s8('ms_side_info', profile.get_int('ms_side_info')))
        config.add_child(
            Node.s8('ms_raise_type', profile.get_int('ms_raise_type')))
        config.add_child(Node.s8('ms_rnd_type',
                                 profile.get_int('ms_rnd_type')))

        # Set up option
        option_dict = profile.get_dict('option')
        option = Node.void('option')
        root.add_child(option)
        option.add_child(
            Node.s16('hispeed', option_dict.get_int('hispeed', 10)))
        option.add_child(Node.u8('popkun', option_dict.get_int('popkun', 0)))
        option.add_child(
            Node.bool('hidden', option_dict.get_bool('hidden', False)))
        option.add_child(
            Node.s16('hidden_rate', option_dict.get_int('hidden_rate', -1)))
        option.add_child(
            Node.bool('sudden', option_dict.get_bool('sudden', False)))
        option.add_child(
            Node.s16('sudden_rate', option_dict.get_int('sudden_rate', -1)))
        option.add_child(Node.s8('randmir', option_dict.get_int('randmir', 0)))
        option.add_child(
            Node.s8('gauge_type', option_dict.get_int('gauge_type', 0)))
        option.add_child(Node.u8('ojama_0', option_dict.get_int('ojama_0', 0)))
        option.add_child(Node.u8('ojama_1', option_dict.get_int('ojama_1', 0)))
        option.add_child(
            Node.bool('forever_0', option_dict.get_bool('forever_0', False)))
        option.add_child(
            Node.bool('forever_1', option_dict.get_bool('forever_1', False)))
        option.add_child(
            Node.bool('full_setting',
                      option_dict.get_bool('full_setting', False)))

        # Set up info
        info = Node.void('info')
        root.add_child(info)
        info.add_child(Node.u16('ep', profile.get_int('ep', 0)))
        info.add_child(Node.u16('ap', profile.get_int('ap', 0)))

        # Set up custom_cate
        custom_cate = Node.void('custom_cate')
        root.add_child(custom_cate)
        custom_cate.add_child(Node.s8('valid', 0))
        custom_cate.add_child(Node.s8('lv_min', -1))
        custom_cate.add_child(Node.s8('lv_max', -1))
        custom_cate.add_child(Node.s8('medal_min', -1))
        custom_cate.add_child(Node.s8('medal_max', -1))
        custom_cate.add_child(Node.s8('friend_no', -1))
        custom_cate.add_child(Node.s8('score_flg', -1))

        # Set up customize
        customize_dict = profile.get_dict('customize')
        customize = Node.void('customize')
        root.add_child(customize)
        customize.add_child(
            Node.u16('effect', customize_dict.get_int('effect')))
        customize.add_child(
            Node.u16('hukidashi', customize_dict.get_int('hukidashi')))
        customize.add_child(Node.u16('font', customize_dict.get_int('font')))
        customize.add_child(
            Node.u16('comment_1', customize_dict.get_int('comment_1')))
        customize.add_child(
            Node.u16('comment_2', customize_dict.get_int('comment_2')))

        # Set up achievements
        achievements = self.data.local.user.get_achievements(
            self.game, self.version, userid)
        for achievement in achievements:
            if achievement.type == 'item':
                itemtype = achievement.data.get_int('type')
                param = achievement.data.get_int('param')

                item = Node.void('item')
                root.add_child(item)
                item.add_child(Node.u8('type', itemtype))
                item.add_child(Node.u16('id', achievement.id))
                item.add_child(Node.u16('param', param))
                item.add_child(Node.bool('is_new', False))

            elif achievement.type == 'achievement':
                count = achievement.data.get_int('count')

                ach_node = Node.void('achievement')
                root.add_child(ach_node)
                ach_node.add_child(Node.u8('type', achievement.id))
                ach_node.add_child(Node.u32('count', count))

            elif achievement.type == 'chara':
                friendship = achievement.data.get_int('friendship')

                chara = Node.void('chara_param')
                root.add_child(chara)
                chara.add_child(Node.u16('chara_id', achievement.id))
                chara.add_child(Node.u16('friendship', friendship))

            elif achievement.type == 'story':
                chapter = achievement.data.get_int('chapter')
                gauge = achievement.data.get_int('gauge')
                cleared = achievement.data.get_bool('cleared')
                clear_chapter = achievement.data.get_int('clear_chapter')

                story = Node.void('story')
                root.add_child(story)
                story.add_child(Node.u32('story_id', achievement.id))
                story.add_child(Node.u32('chapter_id', chapter))
                story.add_child(Node.u16('gauge_point', gauge))
                story.add_child(Node.bool('is_cleared', cleared))
                story.add_child(Node.u32('clear_chapter', clear_chapter))

        return root
コード例 #29
0
ファイル: saucer.py プロジェクト: yungsun09/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('gametop')
        data = Node.void('data')
        root.add_child(data)
        player = Node.void('player')
        data.add_child(player)

        # Player info and statistics
        info = Node.void('info')
        player.add_child(info)
        info.add_child(Node.s16('jubility', profile.get_int('jubility')))
        info.add_child(Node.s16('jubility_yday', profile.get_int('jubility_yday')))
        info.add_child(Node.s32('tune_cnt', profile.get_int('tune_cnt')))
        info.add_child(Node.s32('save_cnt', profile.get_int('save_cnt')))
        info.add_child(Node.s32('saved_cnt', profile.get_int('saved_cnt')))
        info.add_child(Node.s32('fc_cnt', profile.get_int('fc_cnt')))
        info.add_child(Node.s32('ex_cnt', profile.get_int('ex_cnt')))
        info.add_child(Node.s32('pf_cnt', profile.get_int('pf_cnt')))
        info.add_child(Node.s32('clear_cnt', profile.get_int('clear_cnt')))
        info.add_child(Node.s32('match_cnt', profile.get_int('match_cnt')))
        info.add_child(Node.s32('beat_cnt', profile.get_int('beat_cnt')))
        info.add_child(Node.s32('mynews_cnt', profile.get_int('mynews_cnt')))
        if 'total_best_score' in profile:
            info.add_child(Node.s32('total_best_score', profile.get_int('total_best_score')))

        # Looks to be set to true when there's an old profile, stops tutorial from
        # happening on first load.
        info.add_child(Node.bool('inherit', profile.get_bool('has_old_version')))

        # Not saved, but loaded
        info.add_child(Node.s32('mtg_entry_cnt', 123))
        info.add_child(Node.s32('mtg_hold_cnt', 456))
        info.add_child(Node.u8('mtg_result', 10))

        # Secret unlocks
        item = Node.void('item')
        player.add_child(item)
        item.add_child(Node.s32_array(
            'secret_list',
            profile.get_int_array(
                'secret_list',
                32,
                [-1] * 32,
            ),
        ))
        item.add_child(Node.s32_array(
            'title_list',
            profile.get_int_array(
                'title_list',
                96,
                [-1] * 96,
            ),
        ))
        item.add_child(Node.s16('theme_list', profile.get_int('theme_list', -1)))
        item.add_child(Node.s32_array('marker_list', profile.get_int_array('marker_list', 2, [-1] * 2)))
        item.add_child(Node.s32_array('parts_list', profile.get_int_array('parts_list', 96, [-1] * 96)))

        new = Node.void('new')
        item.add_child(new)
        new.add_child(Node.s32_array(
            'secret_list',
            profile.get_int_array(
                'secret_list_new',
                32,
                [-1] * 32,
            ),
        ))
        new.add_child(Node.s32_array(
            'title_list',
            profile.get_int_array(
                'title_list_new',
                96,
                [-1] * 96,
            ),
        ))
        new.add_child(Node.s16('theme_list', profile.get_int('theme_list_new', -1)))
        new.add_child(Node.s32_array('marker_list', profile.get_int_array('marker_list_new', 2, [-1] * 2)))

        # Last played data, for showing cursor and such
        lastdict = profile.get_dict('last')
        last = Node.void('last')
        player.add_child(last)
        last.add_child(Node.s32('music_id', lastdict.get_int('music_id')))
        last.add_child(Node.s8('marker', lastdict.get_int('marker')))
        last.add_child(Node.s16('title', lastdict.get_int('title')))
        last.add_child(Node.s8('theme', lastdict.get_int('theme')))
        last.add_child(Node.s8('sort', lastdict.get_int('sort')))
        last.add_child(Node.s8('rank_sort', lastdict.get_int('rank_sort')))
        last.add_child(Node.s8('combo_disp', lastdict.get_int('combo_disp')))
        last.add_child(Node.s8('seq_id', lastdict.get_int('seq_id')))
        last.add_child(Node.s16('parts', lastdict.get_int('parts')))
        last.add_child(Node.s8('category', lastdict.get_int('category')))
        last.add_child(Node.s64('play_time', lastdict.get_int('play_time')))
        last.add_child(Node.string('shopname', lastdict.get_str('shopname')))
        last.add_child(Node.string('areaname', lastdict.get_str('areaname')))

        # Miscelaneous crap
        player.add_child(Node.s32('session_id', 1))

        # Maybe hook this up? Unsure what it does, is it like IIDX dailies?
        today_music = Node.void('today_music')
        player.add_child(today_music)
        today_music.add_child(Node.s32('music_id', 0))

        # No news, ever.
        news = Node.void('news')
        player.add_child(news)
        news.add_child(Node.s16('checked', 0))

        # No rival support, yet.
        rivallist = Node.void('rivallist')
        player.add_child(rivallist)
        rivallist.set_attribute('count', '0')
        mylist = Node.void('mylist')
        player.add_child(mylist)
        mylist.set_attribute('count', '0')

        # No collaboration support yet.
        collabo = Node.void('collabo')
        player.add_child(collabo)
        collabo.add_child(Node.bool('success', False))
        collabo.add_child(Node.bool('completed', False))

        # Daily FC challenge.
        entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, 'fc_challenge')
        if entry is None:
            entry = ValidatedDict()

        # Figure out if we've played these songs
        start_time, end_time = self.data.local.network.get_schedule_duration('daily')
        today_attempts = self.data.local.music.get_all_attempts(self.game, self.version, userid, entry.get_int('today', -1), timelimit=start_time)

        challenge = Node.void('challenge')
        player.add_child(challenge)
        today = Node.void('today')
        challenge.add_child(today)
        today.add_child(Node.s32('music_id', entry.get_int('today', -1)))
        today.add_child(Node.u8('state', 0x40 if len(today_attempts) > 0 else 0x0))
        onlynow = Node.void('onlynow')
        challenge.add_child(onlynow)
        onlynow.add_child(Node.s32('magic_no', 0))
        onlynow.add_child(Node.s16('cycle', 0))

        # Bistro event
        bistro = Node.void('bistro')
        player.add_child(bistro)

        # Presumably these can affect the speed of the event
        info_1 = Node.void('info')
        bistro.add_child(info_1)
        info_1.add_child(Node.float('delicious_rate', 1.0))
        info_1.add_child(Node.float('favorite_rate', 1.0))
        bistro.add_child(Node.s32('carry_over', profile.get_int('bistro_carry_over')))

        # Your chef dude, I guess?
        chefdict = profile.get_dict('chef')
        chef = Node.void('chef')
        bistro.add_child(chef)
        chef.add_child(Node.s32('id', chefdict.get_int('id', 1)))
        chef.add_child(Node.u8('ability', chefdict.get_int('ability', 2)))
        chef.add_child(Node.u8('remain', chefdict.get_int('remain', 30)))
        chef.add_child(Node.u8('rate', chefdict.get_int('rate', 1)))

        # Routes, similar to story mode in Pop'n I guess?
        routes = [
            {
                'id': 50000284,
                'price': 20,
                'satisfaction': 10,
                'favorite': True,
            },
            {
                'id': 50000283,
                'price': 20,
                'satisfaction': 20,
                'favorite': False,
            },
            {
                'id': 50000282,
                'price': 30,
                'satisfaction': 10,
                'favorite': False,
            },
            {
                'id': 50000275,
                'price': 10,
                'satisfaction': 55,
                'favorite': False,
            },
            {
                'id': 50000274,
                'price': 40,
                'satisfaction': 40,
                'favorite': False,
            },
            {
                'id': 50000273,
                'price': 80,
                'satisfaction': 60,
                'favorite': False,
            },
            {
                'id': 50000272,
                'price': 70,
                'satisfaction': 60,
                'favorite': False,
            },
            {
                'id': 50000271,
                'price': 90,
                'satisfaction': 80,
                'favorite': False,
            },
            {
                'id': 50000270,
                'price': 90,
                'satisfaction': 20,
                'favorite': False,
            },
        ]
        for route_no in range(len(routes)):
            routedata = routes[route_no]
            route = Node.void('route')
            bistro.add_child(route)
            route.set_attribute('no', str(route_no))

            music = Node.void('music')
            route.add_child(music)
            music.add_child(Node.s32('id', routedata['id']))
            music.add_child(Node.u16('price', routedata['price']))
            music.add_child(Node.s32('price_s32', routedata['price']))

            # Look up any updated satisfaction stored by the game
            routesaved = self.data.local.user.get_achievement(self.game, self.version, userid, route_no + 1, 'route')
            if routesaved is None:
                routesaved = ValidatedDict()
            satisfaction = routesaved.get_int('satisfaction', routedata['satisfaction'])

            gourmates = Node.void('gourmates')
            route.add_child(gourmates)
            gourmates.add_child(Node.s32('id', route_no + 1))
            gourmates.add_child(Node.u8('favorite', 1 if routedata['favorite'] else 0))
            gourmates.add_child(Node.u16('satisfaction', satisfaction))
            gourmates.add_child(Node.s32('satisfaction_s32', satisfaction))

        # Sane defaults for unknown nodes
        only_now_music = Node.void('only_now_music')
        player.add_child(only_now_music)
        only_now_music.set_attribute('count', '0')
        requested_music = Node.void('requested_music')
        player.add_child(requested_music)
        requested_music.set_attribute('count', '0')
        kac_music = Node.void('kac_music')
        player.add_child(kac_music)
        kac_music.set_attribute('count', '0')
        history = Node.void('history')
        player.add_child(history)
        history.set_attribute('count', '0')

        # Basic profile info
        player.add_child(Node.string('name', profile.get_str('name', 'なし')))
        player.add_child(Node.s32('jid', profile.get_int('extid')))
        player.add_child(Node.string('refid', profile.get_str('refid')))

        # Miscelaneous history stuff
        data.add_child(Node.u8('termver', 16))
        data.add_child(Node.u32('season_etime', 0))
        data.add_child(Node.s32('bistro_last_music_id', 0))
        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.s32_array(
            'old_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.s32_array(
            'open_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,
            ],
        ))

        # Unsupported collaboration events with other games
        collabo_info = Node.void('collabo_info')
        data.add_child(collabo_info)

        # Unsupported marathon stuff
        run_run_marathon = Node.void('run_run_marathon')
        collabo_info.add_child(run_run_marathon)
        run_run_marathon.set_attribute('type', '1')
        run_run_marathon.add_child(Node.u8('state', 1))
        run_run_marathon.add_child(Node.bool('is_report_end', True))

        # Unsupported policy break stuff
        policy_break = Node.void('policy_break')
        collabo_info.add_child(policy_break)
        policy_break.set_attribute('type', '1')
        policy_break.add_child(Node.u8('state', 1))
        policy_break.add_child(Node.bool('is_report_end', False))

        # Unsupported vocaloid stuff
        vocaloid_event = Node.void('vocaloid_event')
        collabo_info.add_child(vocaloid_event)
        vocaloid_event.set_attribute('type', '1')
        vocaloid_event.add_child(Node.u8('state', 0))
        vocaloid_event.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))

        return root
コード例 #30
0
ファイル: reflecbeat.py プロジェクト: wolskiCN/bemaniutils
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        statistics = self.get_play_statistics(userid)
        game_config = self.get_game_config()
        achievements = self.data.local.user.get_achievements(
            self.game, self.version, userid)
        scores = self.data.remote.music.get_scores(self.game, self.version,
                                                   userid)
        root = Node.void('player')
        pdata = Node.void('pdata')
        root.add_child(pdata)

        base = Node.void('base')
        pdata.add_child(base)
        base.add_child(Node.s32('uid', profile.get_int('extid')))
        base.add_child(Node.string('name', profile.get_str('name')))
        base.add_child(Node.s16('lv', profile.get_int('lvl')))
        base.add_child(Node.s32('exp', profile.get_int('exp')))
        base.add_child(Node.s16('mg', profile.get_int('mg')))
        base.add_child(Node.s16('ap', profile.get_int('ap')))
        base.add_child(Node.s32('flag', profile.get_int('flag')))

        last_play_date = statistics.get_int_array('last_play_date', 3)
        today_play_date = Time.todays_date()
        if (last_play_date[0] == today_play_date[0]
                and last_play_date[1] == today_play_date[1]
                and last_play_date[2] == today_play_date[2]):
            today_count = statistics.get_int('today_plays', 0)
        else:
            today_count = 0

        con = Node.void('con')
        pdata.add_child(con)
        con.add_child(Node.s32('day', today_count))
        con.add_child(Node.s32('cnt', statistics.get_int('total_plays')))
        con.add_child(
            Node.s32('last', statistics.get_int('last_play_timestamp')))
        con.add_child(Node.s32('now', Time.now()))

        team = Node.void('team')
        pdata.add_child(team)
        team.add_child(Node.s32('id', -1))
        team.add_child(Node.string('name', ''))

        custom = Node.void('custom')
        customdict = profile.get_dict('custom')
        pdata.add_child(custom)
        custom.add_child(Node.u8('bgm_m', customdict.get_int('bgm_m')))
        custom.add_child(Node.u8('st_f', customdict.get_int('st_f')))
        custom.add_child(Node.u8('st_bg', customdict.get_int('st_bg')))
        custom.add_child(Node.u8('st_bg_b', customdict.get_int('st_bg_b')))
        custom.add_child(Node.u8('eff_e', customdict.get_int('eff_e')))
        custom.add_child(Node.u8('se_s', customdict.get_int('se_s')))
        custom.add_child(Node.u8('se_s_v', customdict.get_int('se_s_v')))

        released = Node.void('released')
        pdata.add_child(released)

        for item in achievements:
            if item.type[:5] != 'item_':
                continue
            itemtype = int(item.type[5:])
            if game_config.get_bool('force_unlock_songs') and itemtype == 0:
                # Don't echo unlocks when we're force unlocking, we'll do it later
                continue

            info = Node.void('info')
            released.add_child(info)
            info.add_child(Node.u8('type', itemtype))
            info.add_child(Node.u16('id', item.id))

        if game_config.get_bool('force_unlock_songs'):
            songs = {
                song.id
                for song in self.data.local.music.get_all_songs(
                    self.game, self.version)
            }

            for songid in songs:
                info = Node.void('info')
                released.add_child(info)
                info.add_child(Node.u8('type', 0))
                info.add_child(Node.u16('id', songid))

        # Scores
        record = Node.void('record')
        pdata.add_child(record)

        for score in scores:
            rec = Node.void('rec')
            record.add_child(rec)
            rec.add_child(Node.u16('mid', score.id))
            rec.add_child(Node.u8('ng', score.chart))
            rec.add_child(
                Node.s32('win',
                         score.data.get_dict('stats').get_int('win')))
            rec.add_child(
                Node.s32('lose',
                         score.data.get_dict('stats').get_int('lose')))
            rec.add_child(
                Node.s32('draw',
                         score.data.get_dict('stats').get_int('draw')))
            rec.add_child(
                Node.u8(
                    'ct',
                    self.__db_to_game_clear_type(
                        score.data.get_int('clear_type'),
                        score.data.get_int('combo_type'))))
            rec.add_child(
                Node.s16('ar',
                         int(score.data.get_int('achievement_rate') / 10)))
            rec.add_child(Node.s16('bs', score.points))
            rec.add_child(Node.s16('mc', score.data.get_int('combo')))
            rec.add_child(Node.s16('bmc', score.data.get_int('miss_count')))

        # In original ReflecBeat, the entire battle log was returned for each battle.
        # We don't support storing all of that info, so don't return anything here.
        blog = Node.void('blog')
        pdata.add_child(blog)

        # Comment (seems unused?)
        pdata.add_child(Node.string('cmnt', ''))

        return root