예제 #1
0
    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', 'dialog#{}'.format(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
예제 #2
0
 def handle_game_ranking_request(self, request: Node) -> Node:
     # Ranking request, unknown what its for
     return Node.void('game')
예제 #3
0
 def handle_game_lock_request(self, request: Node) -> Node:
     game = Node.void('game')
     game.set_attribute('now_login', '0')
     return game
예제 #4
0
 def handle_logger_report_request(self, request: Node) -> Node:
     # Handle this by returning nothing, game doesn't care
     root = Node.void('logger')
     return root
예제 #5
0
    def handle_game_shop_request(self, request: Node) -> Node:
        self.update_machine_name(request.attribute('name'))

        game = Node.void('game')
        game.set_attribute('stop', '0')
        return game
예제 #6
0
    def format_conversion(self, userid: UserID,
                          profile: ValidatedDict) -> Node:
        root = Node.void('player23')
        root.add_child(Node.string('name', profile.get_str('name', 'なし')))
        root.add_child(Node.s16('chara', profile.get_int('chara', -1)))
        root.add_child(Node.s8('result', 1))

        scores = self.data.remote.music.get_scores(self.game, self.version,
                                                   userid)
        for score in scores:
            # Skip any scores for chart types we don't support
            if score.chart not in [
                    self.CHART_TYPE_EASY,
                    self.CHART_TYPE_NORMAL,
                    self.CHART_TYPE_HYPER,
                    self.CHART_TYPE_EX,
            ]:
                continue

            points = score.points
            medal = score.data.get_int('medal')

            music = Node.void('music')
            root.add_child(music)
            music.add_child(Node.s16('music_num', score.id))
            music.add_child(
                Node.u8(
                    'sheet_num', {
                        self.CHART_TYPE_EASY: self.GAME_CHART_TYPE_EASY,
                        self.CHART_TYPE_NORMAL: self.GAME_CHART_TYPE_NORMAL,
                        self.CHART_TYPE_HYPER: self.GAME_CHART_TYPE_HYPER,
                        self.CHART_TYPE_EX: self.GAME_CHART_TYPE_EX,
                    }[score.chart]))
            music.add_child(Node.s32('score', points))
            music.add_child(
                Node.u8(
                    'clear_type', {
                        self.PLAY_MEDAL_CIRCLE_FAILED:
                        self.GAME_PLAY_MEDAL_CIRCLE_FAILED,
                        self.PLAY_MEDAL_DIAMOND_FAILED:
                        self.GAME_PLAY_MEDAL_DIAMOND_FAILED,
                        self.PLAY_MEDAL_STAR_FAILED:
                        self.GAME_PLAY_MEDAL_STAR_FAILED,
                        self.PLAY_MEDAL_EASY_CLEAR:
                        self.GAME_PLAY_MEDAL_EASY_CLEAR,
                        self.PLAY_MEDAL_CIRCLE_CLEARED:
                        self.GAME_PLAY_MEDAL_CIRCLE_CLEARED,
                        self.PLAY_MEDAL_DIAMOND_CLEARED:
                        self.GAME_PLAY_MEDAL_DIAMOND_CLEARED,
                        self.PLAY_MEDAL_STAR_CLEARED:
                        self.GAME_PLAY_MEDAL_STAR_CLEARED,
                        self.PLAY_MEDAL_CIRCLE_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO,
                        self.PLAY_MEDAL_DIAMOND_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO,
                        self.PLAY_MEDAL_STAR_FULL_COMBO:
                        self.GAME_PLAY_MEDAL_STAR_FULL_COMBO,
                        self.PLAY_MEDAL_PERFECT: self.GAME_PLAY_MEDAL_PERFECT,
                    }[medal]))
            music.add_child(Node.s16('cnt', score.plays))

        return root
예제 #7
0
    def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
        root = Node.void('player23')

        # Mark this as a current profile
        root.add_child(Node.s8('result', 0))

        # Account stuff
        account = Node.void('account')
        root.add_child(account)
        account.add_child(
            Node.string('g_pm_id', self.format_extid(
                profile.get_int('extid'))))  # Eclale formats on its own
        account.add_child(Node.string('name', profile.get_str('name', 'なし')))
        account.add_child(Node.s8('tutorial', profile.get_int('tutorial')))
        account.add_child(Node.s16('area_id', profile.get_int('area_id')))
        account.add_child(Node.s16('lumina', profile.get_int('lumina', 300)))
        account.add_child(Node.s16('read_news', profile.get_int('read_news')))
        account.add_child(
            Node.bool('welcom_pack', profile.get_bool('welcom_pack')))
        account.add_child(
            Node.s16_array('medal_set', profile.get_int_array('medal_set', 4)))
        account.add_child(
            Node.s16_array('nice',
                           profile.get_int_array('nice', 30, [-1] * 30)))
        account.add_child(
            Node.s16_array(
                'favorite_chara',
                profile.get_int_array('favorite_chara', 20, [-1] * 20)))
        account.add_child(
            Node.s16_array('special_area',
                           profile.get_int_array('special_area', 8)))
        account.add_child(
            Node.s16_array(
                'chocolate_charalist',
                profile.get_int_array('chocolate_charalist', 5, [-1] * 5)))
        account.add_child(
            Node.s16_array('teacher_setting',
                           profile.get_int_array('teacher_setting', 10)))

        # Stuff we never change
        account.add_child(Node.s8('staff', 0))
        account.add_child(Node.s16('item_type', 0))
        account.add_child(Node.s16('item_id', 0))
        account.add_child(Node.s8('is_conv', 0))
        account.add_child(Node.bool('meteor_flg', True))
        account.add_child(Node.s16_array('license_data', [-1] * 20))

        # Add statistics 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))

        # TODO: Hook up rivals for Pop'n music?
        account.add_child(Node.u8('active_fr_num', 0))

        # player statistics
        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.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))

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

        # Set up last information
        config = Node.void('config')
        root.add_child(config)
        config.add_child(Node.u8('mode', profile.get_int('mode')))
        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')))
        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('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('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')))

        # Player options
        option = Node.void('option')
        option_dict = profile.get_dict('option')
        root.add_child(option)
        option.add_child(Node.s16('hispeed', option_dict.get_int('hispeed')))
        option.add_child(Node.u8('popkun', option_dict.get_int('popkun')))
        option.add_child(Node.bool('hidden', option_dict.get_bool('hidden')))
        option.add_child(
            Node.s16('hidden_rate', option_dict.get_int('hidden_rate')))
        option.add_child(Node.bool('sudden', option_dict.get_bool('sudden')))
        option.add_child(
            Node.s16('sudden_rate', option_dict.get_int('sudden_rate')))
        option.add_child(Node.s8('randmir', option_dict.get_int('randmir')))
        option.add_child(
            Node.s8('gauge_type', option_dict.get_int('gauge_type')))
        option.add_child(Node.u8('ojama_0', option_dict.get_int('ojama_0')))
        option.add_child(Node.u8('ojama_1', option_dict.get_int('ojama_1')))
        option.add_child(
            Node.bool('forever_0', option_dict.get_bool('forever_0')))
        option.add_child(
            Node.bool('forever_1', option_dict.get_bool('forever_1')))
        option.add_child(
            Node.bool('full_setting', option_dict.get_bool('full_setting')))
        option.add_child(Node.u8('judge', option_dict.get_int('judge')))

        # Unknown custom category stuff?
        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 achievements
        achievements = self.data.local.user.get_achievements(
            self.game, self.version, userid)
        for achievement in achievements:
            if achievement.type[:5] == 'item_':
                itemtype = int(achievement.type[5:])
                param = achievement.data.get_int('param')
                is_new = achievement.data.get_bool('is_new')

                item = Node.void('item')
                root.add_child(item)
                # Type is the type of unlock/item. Type 0 is song unlock in Eclale.
                # In this case, the id is the song ID according to the game. Unclear
                # what the param is supposed to be, but i've seen 8 and 0. Might be
                # what chart is available?
                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', is_new))

            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 == 'medal':
                level = achievement.data.get_int('level')
                exp = achievement.data.get_int('exp')
                set_count = achievement.data.get_int('set_count')
                get_count = achievement.data.get_int('get_count')

                medal = Node.void('medal')
                root.add_child(medal)
                medal.add_child(Node.s16('medal_id', achievement.id))
                medal.add_child(Node.s16('level', level))
                medal.add_child(Node.s32('exp', exp))
                medal.add_child(Node.s32('set_count', set_count))
                medal.add_child(Node.s32('get_count', get_count))

        # Unknown customizations
        customize = Node.void('customize')
        root.add_child(customize)
        customize.add_child(
            Node.u16('effect_left', profile.get_int('effect_left')))
        customize.add_child(
            Node.u16('effect_center', profile.get_int('effect_center')))
        customize.add_child(
            Node.u16('effect_right', profile.get_int('effect_right')))
        customize.add_child(Node.u16('hukidashi',
                                     profile.get_int('hukidashi')))
        customize.add_child(Node.u16('comment_1',
                                     profile.get_int('comment_1')))
        customize.add_child(Node.u16('comment_2',
                                     profile.get_int('comment_2')))

        # NetVS section
        netvs = Node.void('netvs')
        root.add_child(netvs)
        netvs.add_child(Node.s16_array('record', [0] * 6))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.string('dialog', ''))
        netvs.add_child(Node.s8_array('ojama_condition', [0] * 74))
        netvs.add_child(Node.s8_array('set_ojama', [0] * 3))
        netvs.add_child(Node.s8_array('set_recommend', [0] * 3))
        netvs.add_child(Node.u32('netvs_play_cnt', 0))

        # Event stuff
        event = Node.void('event')
        root.add_child(event)
        event.add_child(
            Node.s16('enemy_medal', profile.get_int('event_enemy_medal')))
        event.add_child(Node.s16('hp', profile.get_int('event_hp')))

        # Stamp stuff
        stamp = Node.void('stamp')
        root.add_child(stamp)
        stamp.add_child(Node.s16('stamp_id', profile.get_int('stamp_id')))
        stamp.add_child(Node.s16('cnt', profile.get_int('stamp_cnt')))

        return root
예제 #8
0
    def verify_iidx26music_arenacpu(self) -> None:
        call = self.call_node()
        IIDX26music = Node.void('IIDX26music')
        call.add_child(IIDX26music)
        IIDX26music.set_attribute('method', 'arenaCPU')
        music_list = Node.void('music_list')
        IIDX26music.add_child(music_list)
        music_list.add_child(Node.s32('index', 0))
        music_list.add_child(Node.s32('music_id', 26072))
        music_list.add_child(Node.s32('note_style', 0))
        music_list.add_child(Node.s32('note_grade', 2))
        music_list.add_child(Node.s32('total_notes', 1857))
        music_list_1 = Node.void('music_list')
        IIDX26music.add_child(music_list_1)
        music_list_1.add_child(Node.s32('index', 1))
        music_list_1.add_child(Node.s32('music_id', 25020))
        music_list_1.add_child(Node.s32('note_style', 0))
        music_list_1.add_child(Node.s32('note_grade', 0))
        music_list_1.add_child(Node.s32('total_notes', 483))
        music_list_2 = Node.void('music_list')
        IIDX26music.add_child(music_list_2)
        music_list_2.add_child(Node.s32('index', 2))
        music_list_2.add_child(Node.s32('music_id', 2000))
        music_list_2.add_child(Node.s32('note_style', 0))
        music_list_2.add_child(Node.s32('note_grade', 0))
        music_list_2.add_child(Node.s32('total_notes', 360))
        music_list_3 = Node.void('music_list')
        IIDX26music.add_child(music_list_3)
        music_list_3.add_child(Node.s32('index', 3))
        music_list_3.add_child(Node.s32('music_id', 19020))
        music_list_3.add_child(Node.s32('note_style', 0))
        music_list_3.add_child(Node.s32('note_grade', 0))
        music_list_3.add_child(Node.s32('total_notes', 404))
        cpu_list = Node.void('cpu_list')
        IIDX26music.add_child(cpu_list)
        cpu_list.add_child(Node.s32('index', 0))
        cpu_list.add_child(Node.s32('play_style', 0))
        cpu_list.add_child(Node.s32('arena_class', 0))
        cpu_list.add_child(Node.s32('grade_id', -1))
        cpu_list_1 = Node.void('cpu_list')
        IIDX26music.add_child(cpu_list_1)
        cpu_list_1.add_child(Node.s32('index', 1))
        cpu_list_1.add_child(Node.s32('play_style', 0))
        cpu_list_1.add_child(Node.s32('arena_class', 0))
        cpu_list_1.add_child(Node.s32('grade_id', 6))
        cpu_list_2 = Node.void('cpu_list')
        IIDX26music.add_child(cpu_list_2)
        cpu_list_2.add_child(Node.s32('index', 2))
        cpu_list_2.add_child(Node.s32('play_style', 0))
        cpu_list_2.add_child(Node.s32('arena_class', 0))
        cpu_list_2.add_child(Node.s32('grade_id', 6))
        cpu_list_3 = Node.void('cpu_list')
        IIDX26music.add_child(cpu_list_3)
        cpu_list_3.add_child(Node.s32('index', 3))
        cpu_list_3.add_child(Node.s32('play_style', 0))
        cpu_list_3.add_child(Node.s32('arena_class', 0))
        cpu_list_3.add_child(Node.s32('grade_id', 6))
        # Swap with server
        resp = self.exchange('', call)

        self.assert_path(
            resp, 'response/IIDX26music/cpu_score_list/score_list/score')
        self.assert_path(
            resp,
            'response/IIDX26music/cpu_score_list/score_list/enable_score')
        self.assert_path(
            resp, 'response/IIDX26music/cpu_score_list/score_list/ghost')
        self.assert_path(
            resp,
            'response/IIDX26music/cpu_score_list/score_list/enable_ghost')
예제 #9
0
    def verify_usergamedata_send(self, ref_id: str, msg_type: str) -> None:
        call = self.call_node()

        # Set up profile write
        profiledata = [
            b'ffffffff',
            b'IBBDAT00',
            b'1',
            b'0',
            b'0',
            b'0',
            b'0',
            b'0',
            b'e474c1b',
            b'0',
            b'0',
            b'ff',
            b'0',
            b'0',
            b'0',
            b'0',
            b'0',
            b'0',
            b'0',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'0.000000',
            b'',
            b'',
            b'',
            b'\x96\xa2\x90\xdd\x92\xe8',
            b'\x8d\x81\x8d`',
            b'',
            b'',
            b'',
        ]

        if msg_type == 'new':
            # New profile gets blank name, because we save over it at the end of the round.
            profiledata[27] = b''
        elif msg_type == 'existing':
            # Exiting profile gets our hardcoded name saved.
            profiledata[27] = self.NAME.encode('shift-jis')

        # Construct node
        playerdata = Node.void('playerdata')
        call.add_child(playerdata)
        playerdata.set_attribute('method', 'usergamedata_send')
        playerdata.add_child(Node.u32('retrycnt', 0))

        data = Node.void('data')
        playerdata.add_child(data)
        data.add_child(Node.string('eaid', ref_id))
        data.add_child(Node.string('gamekind', 'IBB'))
        data.add_child(Node.u32('datanum', 1))
        record = Node.void('record')
        data.add_child(record)
        d = Node.string('d', base64.b64encode(b','.join(profiledata)).decode('ascii'))
        record.add_child(d)
        d.add_child(Node.string('bin1', ''))

        # Swap with server
        resp = self.exchange('', call)
        self.assert_path(resp, "response/playerdata/result")
예제 #10
0
    def verify_iidx26music_getrank(
            self, extid: int) -> Dict[int, Dict[int, Dict[str, int]]]:
        scores: Dict[int, Dict[int, Dict[str, int]]] = {}
        for cltype in [0, 1]:  # singles, doubles
            call = self.call_node()

            # Construct node
            IIDX26music = Node.void('IIDX26music')
            call.add_child(IIDX26music)
            IIDX26music.set_attribute('method', 'getrank')
            IIDX26music.set_attribute('iidxid', str(extid))
            IIDX26music.set_attribute('cltype', str(cltype))

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

            self.assert_path(resp, "response/IIDX26music/style")
            if int(resp.child('IIDX26music/style').attribute(
                    'type')) != cltype:
                raise Exception(
                    'Returned wrong clear type for IIDX26music.getrank!')

            for child in resp.child('IIDX26music').children:
                if child.name == 'm':
                    if child.value[0] != -1:
                        raise Exception(
                            'Got non-self score back when requesting only our scores!'
                        )

                    music_id = child.value[1]
                    normal_clear_status = child.value[2]
                    hyper_clear_status = child.value[3]
                    another_clear_status = child.value[4]
                    normal_ex_score = child.value[5]
                    hyper_ex_score = child.value[6]
                    another_ex_score = child.value[7]
                    normal_miss_count = child.value[8]
                    hyper_miss_count = child.value[9]
                    another_miss_count = child.value[10]

                    if cltype == 0:
                        normal = 0
                        hyper = 1
                        another = 2
                    else:
                        normal = 3
                        hyper = 4
                        another = 5

                    if music_id not in scores:
                        scores[music_id] = {}

                    scores[music_id][normal] = {
                        'clear_status': normal_clear_status,
                        'ex_score': normal_ex_score,
                        'miss_count': normal_miss_count,
                    }
                    scores[music_id][hyper] = {
                        'clear_status': hyper_clear_status,
                        'ex_score': hyper_ex_score,
                        'miss_count': hyper_miss_count,
                    }
                    scores[music_id][another] = {
                        'clear_status': another_clear_status,
                        'ex_score': another_ex_score,
                        'miss_count': another_miss_count,
                    }
                elif child.name == 'b':
                    music_id = child.value[0]
                    clear_status = child.value[1]

                    scores[music_id][6] = {
                        'clear_status': clear_status,
                        'ex_score': -1,
                        'miss_count': -1,
                    }

        return scores
예제 #11
0
    def verify_iidx26pc_save(
            self,
            extid: int,
            card: str,
            lid: str,
            expert_point: Optional[Dict[str, int]] = None) -> None:
        call = self.call_node()

        # Construct node
        IIDX26pc = Node.void('IIDX26pc')
        call.add_child(IIDX26pc)
        IIDX26pc.set_attribute('s_disp_judge', '1')
        IIDX26pc.set_attribute('mode', '6')
        IIDX26pc.set_attribute('pmode', '0')
        IIDX26pc.set_attribute('method', 'save')
        IIDX26pc.set_attribute('s_sorttype', '0')
        IIDX26pc.set_attribute('s_exscore', '0')
        IIDX26pc.set_attribute('d_notes', '0.000000')
        IIDX26pc.set_attribute('gpos', '0')
        IIDX26pc.set_attribute('s_gno', '8')
        IIDX26pc.set_attribute('s_hispeed', '5.771802')
        IIDX26pc.set_attribute('s_judge', '0')
        IIDX26pc.set_attribute('d_timing', '0')
        IIDX26pc.set_attribute('rtype', '0')
        IIDX26pc.set_attribute('d_graph_score', '0')
        IIDX26pc.set_attribute('d_lift', '60')
        IIDX26pc.set_attribute('s_pace', '0')
        IIDX26pc.set_attribute('d_exscore', '0')
        IIDX26pc.set_attribute('d_sdtype', '0')
        IIDX26pc.set_attribute('s_opstyle', '1')
        IIDX26pc.set_attribute('s_achi', '449')
        IIDX26pc.set_attribute('s_graph_score', '0')
        IIDX26pc.set_attribute('d_gno', '0')
        IIDX26pc.set_attribute('s_lift', '60')
        IIDX26pc.set_attribute('s_notes', '31.484070')
        IIDX26pc.set_attribute('d_tune', '0')
        IIDX26pc.set_attribute('d_sdlen', '0')
        IIDX26pc.set_attribute('d_achi', '4')
        IIDX26pc.set_attribute('d_opstyle', '0')
        IIDX26pc.set_attribute('sp_opt', '8208')
        IIDX26pc.set_attribute('iidxid', str(extid))
        IIDX26pc.set_attribute('lid', lid)
        IIDX26pc.set_attribute('s_judgeAdj', '0')
        IIDX26pc.set_attribute('s_tune', '3')
        IIDX26pc.set_attribute('s_sdtype', '1')
        IIDX26pc.set_attribute('s_gtype', '2')
        IIDX26pc.set_attribute('d_judge', '0')
        IIDX26pc.set_attribute('cid', card)
        IIDX26pc.set_attribute('cltype', '0')
        IIDX26pc.set_attribute('ctype', '1')
        IIDX26pc.set_attribute('bookkeep', '0')
        IIDX26pc.set_attribute('d_hispeed', '0.000000')
        IIDX26pc.set_attribute('d_pace', '0')
        IIDX26pc.set_attribute('d_judgeAdj', '0')
        IIDX26pc.set_attribute('s_timing', '1')
        IIDX26pc.set_attribute('d_disp_judge', '0')
        IIDX26pc.set_attribute('s_sdlen', '121')
        IIDX26pc.set_attribute('dp_opt2', '0')
        IIDX26pc.set_attribute('d_gtype', '0')
        IIDX26pc.set_attribute('d_sorttype', '0')
        IIDX26pc.set_attribute('dp_opt', '0')
        IIDX26pc.set_attribute('s_auto_scrach', '0')
        IIDX26pc.set_attribute('d_auto_scrach', '0')
        IIDX26pc.set_attribute('s_gauge_disp', '0')
        IIDX26pc.set_attribute('d_gauge_disp', '0')
        IIDX26pc.set_attribute('s_lane_brignt', '0')
        IIDX26pc.set_attribute('d_lane_brignt', '0')
        IIDX26pc.set_attribute('s_camera_layout', '0')
        IIDX26pc.set_attribute('d_camera_layout', '0')
        IIDX26pc.set_attribute('s_ghost_score', '0')
        IIDX26pc.set_attribute('d_ghost_score', '0')
        IIDX26pc.set_attribute('s_tsujigiri_disp', '0')
        IIDX26pc.set_attribute('d_tsujigiri_disp', '0')
        deller = Node.void('deller')
        IIDX26pc.add_child(deller)
        deller.set_attribute('deller', '150')

        if expert_point is not None:
            epnode = Node.void('expert_point')
            epnode.set_attribute('h_point', str(expert_point['h_point']))
            epnode.set_attribute('course_id', str(expert_point['course_id']))
            epnode.set_attribute('n_point', str(expert_point['n_point']))
            epnode.set_attribute('a_point', str(expert_point['a_point']))
            IIDX26pc.add_child(epnode)

        # Swap with server
        resp = self.exchange('', call)
        self.assert_path(resp, "response/IIDX26pc")
예제 #12
0
    def verify_iidx26pc_get(self, ref_id: str, card_id: str,
                            lid: str) -> Dict[str, Any]:
        call = self.call_node()

        # Construct node
        IIDX26pc = Node.void('IIDX26pc')
        call.add_child(IIDX26pc)
        IIDX26pc.set_attribute('rid', ref_id)
        IIDX26pc.set_attribute('did', ref_id)
        IIDX26pc.set_attribute('pid', '51')
        IIDX26pc.set_attribute('lid', lid)
        IIDX26pc.set_attribute('cid', card_id)
        IIDX26pc.set_attribute('method', 'get')
        IIDX26pc.set_attribute('ctype', '1')

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

        # Verify that the response is correct
        self.assert_path(resp, "response/IIDX26pc/pcdata/@name")
        self.assert_path(resp, "response/IIDX26pc/pcdata/@pid")
        self.assert_path(resp, "response/IIDX26pc/pcdata/@id")
        self.assert_path(resp, "response/IIDX26pc/pcdata/@idstr")
        self.assert_path(resp, "response/IIDX26pc/deller")
        self.assert_path(resp, "response/IIDX26pc/secret/flg1")
        self.assert_path(resp, "response/IIDX26pc/secret/flg2")
        self.assert_path(resp, "response/IIDX26pc/secret/flg3")
        self.assert_path(resp, "response/IIDX26pc/achievements/trophy")
        self.assert_path(resp, "response/IIDX26pc/skin")
        self.assert_path(resp, "response/IIDX26pc/qprodata")
        self.assert_path(resp, "response/IIDX26pc/grade")
        self.assert_path(resp, "response/IIDX26pc/rlist")
        self.assert_path(resp, "response/IIDX26pc/step")
        self.assert_path(resp, "response/IIDX26pc/favorite/sp_mlist")
        self.assert_path(resp, "response/IIDX26pc/favorite/sp_clist")
        self.assert_path(resp, "response/IIDX26pc/favorite/dp_mlist")
        self.assert_path(resp, "response/IIDX26pc/favorite/dp_clist")
        self.assert_path(resp, "response/IIDX26pc/extra_favorite/sp_mlist")
        self.assert_path(resp, "response/IIDX26pc/extra_favorite/sp_clist")
        self.assert_path(resp, "response/IIDX26pc/extra_favorite/dp_mlist")
        self.assert_path(resp, "response/IIDX26pc/extra_favorite/dp_clist")

        name = resp.child('IIDX26pc/pcdata').attribute('name')
        if name != self.NAME:
            raise Exception(
                f'Invalid name \'{name}\' returned for Ref ID \'{ref_id}\'')

        expert_point: Dict[int, Dict[str, int]] = {}
        for child in resp.child('IIDX26pc/expert_point').children:
            if child.name == 'detail':
                expert_point[int(child.attribute('course_id'))] = {
                    'n_point': int(child.attribute('n_point')),
                    'h_point': int(child.attribute('h_point')),
                    'a_point': int(child.attribute('a_point')),
                }

        return {
            'extid': int(resp.child('IIDX26pc/pcdata').attribute('id')),
            'sp_dan': int(resp.child('IIDX26pc/grade').attribute('sgid')),
            'dp_dan': int(resp.child('IIDX26pc/grade').attribute('dgid')),
            'deller': int(resp.child('IIDX26pc/deller').attribute('deller')),
            'expert_point': expert_point,
        }
예제 #13
0
    def verify_player22_read(self, ref_id: str,
                             msg_type: str) -> Optional[Dict[str, Any]]:
        call = self.call_node()

        # Construct node
        player22 = Node.void('player22')
        call.add_child(player22)
        player22.set_attribute('method', 'read')

        player22.add_child(Node.string('ref_id', value=ref_id))
        player22.add_child(Node.string('shop_name', ''))
        player22.add_child(Node.s8('pref', 51))

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

        if msg_type == 'new':
            # Verify that response is correct
            self.assert_path(resp, "response/player22/@status")

            status = int(resp.child('player22').attribute('status'))
            if status != 109:
                raise Exception(
                    f'Reference ID \'{ref_id}\' returned invalid status \'{status}\''
                )

            # No score data
            return None
        elif msg_type == 'query':
            # Verify that the response is correct
            self.assert_path(resp, "response/player22/account/name")
            self.assert_path(resp, "response/player22/account/g_pm_id")
            self.assert_path(resp, "response/player22/account/my_best")
            self.assert_path(resp, "response/player22/account/latest_music")
            self.assert_path(resp, "response/player22/netvs")
            self.assert_path(resp, "response/player22/config")
            self.assert_path(resp, "response/player22/option")
            self.assert_path(resp, "response/player22/info")
            self.assert_path(resp, "response/player22/custom_cate")
            self.assert_path(resp, "response/player22/customize")

            name = resp.child('player22').child('account').child('name').value
            if name != self.NAME:
                raise Exception(
                    f'Invalid name \'{name}\' returned for Ref ID \'{ref_id}\''
                )

            # Extract and return score data
            medals: Dict[int, List[int]] = {}
            scores: Dict[int, List[int]] = {}
            for child in resp.child('player22').children:
                if child.name == 'music':
                    songid = child.child_value('music_num')
                    chart = child.child_value('sheet_num')
                    medal = child.child_value('clear_type')
                    points = child.child_value('score')

                    if songid not in medals:
                        medals[songid] = [0, 0, 0, 0]
                    medals[songid][chart] = medal
                    if songid not in scores:
                        scores[songid] = [0, 0, 0, 0]
                    scores[songid][chart] = points

            return {'medals': medals, 'scores': scores}

        else:
            raise Exception(f'Unrecognized message type \'{msg_type}\'')
예제 #14
0
    def handle_info22_request(self, request: Node) -> Optional[Node]:
        method = request.attribute('method')

        if method == 'common':
            # TODO: Hook these up to config so we can change this
            phases = {
                # Unknown event
                0: 0,
                # Unknown event
                1: 0,
                # Pop'n Aura, max 10 (remov all aura requirements)
                2: 10,
                # Story
                3: 1,
                # BEMANI ruins Discovery!
                4: 0,
                # Unknown event
                5: 0,
                # Unknown event
                6: 0,
                # Unknown event
                7: 0,
                # Unknown event
                8: 0,
                # Unknown event
                9: 0,
                # Unknown event
                10: 0,
                # Unknown event
                11: 0,
                # Unknown event
                12: 0,
                # Unknown event
                13: 0,
                # Unknown event
                14: 0,
                # Unknown event
                15: 0,
                # Unknown event
                16: 0,
                # Unknown event
                17: 0,
                # Unknown event
                18: 0,
                # Unknown event
                19: 0,
            }
            stories = list(range(173))

            root = Node.void('info22')
            for phaseid in phases:
                phase = Node.void('phase')
                root.add_child(phase)
                phase.add_child(Node.s16('event_id', phaseid))
                phase.add_child(Node.s16('phase', phases[phaseid]))

            for storyid in stories:
                story = Node.void('story')
                root.add_child(story)
                story.add_child(Node.u32('story_id', storyid))
                story.add_child(Node.bool('is_limited', False))
                story.add_child(Node.u64('limit_date', 0))

            return root

        # Invalid method
        return None
예제 #15
0
 def handle_player23_logout_request(self, request: Node) -> Node:
     return Node.void('player23')
예제 #16
0
    def verify_gameend_regist(
        self,
        ref_id: str,
        jid: int,
        scores: List[Dict[str, Any]],
        course: Dict[str, Any],
        league: Optional[Tuple[int, Tuple[int, int, int]]],
    ) -> None:
        call = self.call_node()

        # Construct node
        gameend = Node.void('gameend')
        call.add_child(gameend)
        gameend.set_attribute('method', 'regist')
        gameend.add_child(Node.s32('retry', 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))
        player.add_child(Node.string('name', self.NAME))
        result = Node.void('result')
        data.add_child(result)
        result.set_attribute('count', str(len(scores)))

        # Send scores
        scoreid = 0
        for score in scores:
            # Always played
            bits = 0x1
            if score['clear']:
                bits |= 0x2
            if score['fc']:
                bits |= 0x4
            if score['ex']:
                bits |= 0x8

            # Intentionally starting at 1 because that's what the game does
            scoreid = scoreid + 1
            tune = Node.void('tune')
            result.add_child(tune)
            tune.set_attribute('id', str(scoreid))
            tune.set_attribute('count', '0')
            tune.add_child(Node.s32('music', score['id']))
            player_1 = Node.void('player')
            tune.add_child(player_1)
            player_1.set_attribute('rank', '1')
            scorenode = Node.s32('score', score['score'])
            player_1.add_child(scorenode)
            scorenode.set_attribute('seq', str(score['chart']))
            scorenode.set_attribute('clear', str(bits))
            scorenode.set_attribute('combo', '69')
            player_1.add_child(
                Node.u8_array('mbar', [
                    239, 175, 170, 170, 190, 234, 187, 158, 153, 230, 170, 90,
                    102, 170, 85, 150, 150, 102, 85, 234, 171, 169, 157, 150,
                    170, 101, 230, 90, 214, 255
                ]))

        if len(course) > 0:
            coursenode = Node.void('course')
            player.add_child(coursenode)
            coursenode.add_child(Node.s32('course_id', course['course_id']))
            coursenode.add_child(Node.u8('rating', course['rating']))
            index = 0
            for coursescore in course['scores']:
                music = Node.void('music')
                coursenode.add_child(music)
                music.set_attribute('index', str(index))
                music.add_child(Node.s32('score', coursescore))
                index = index + 1

        if league is not None:
            leaguenode = Node.void('league')
            player.add_child(leaguenode)
            leaguenode.add_child(Node.s32('league_id', league[0]))
            leaguenode.add_child(Node.bool('is_first_play', False))
            leaguenode.add_child(Node.bool('is_checked', True))

            index = 0
            for leaguescore in league[1]:
                musicnode = Node.void('music')
                leaguenode.add_child(musicnode)
                musicnode.set_attribute('index', str(index))
                index = index + 1

                scorenode = Node.s32('score', leaguescore)
                musicnode.add_child(scorenode)
                scorenode.set_attribute('clear', '3')

        # Swap with server
        resp = self.exchange('', call)
        self.assert_path(resp, "response/gameend/data/player/session_id")
예제 #17
0
    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
예제 #18
0
 def handle_pcb23_error_request(self, request: Node) -> Node:
     return Node.void('pcb23')
예제 #19
0
    def __construct_common_info(self, root: Node) -> None:
        # Event phases
        phases = {
            # Unknown event (0-16)
            0: 16,
            # Unknown event (0-3)
            1: 3,
            # Unknown event (0-1)
            2: 1,
            # Unknown event (0-2)
            3: 2,
            # Unknown event (0-1)
            4: 1,
            # Unknown event (0-2)
            5: 2,
            # Unknown event (0-1)
            6: 1,
            # Unknown event (0-4)
            7: 4,
            # Unknown event (0-3)
            8: 3,
            # Unknown event (0-4)
            9: 4,
            # Unknown event (0-4)
            10: 4,
            # Unknown event (0-1)
            11: 1,
            # Possibly global event matching related? (0-1)
            12: 1,
            # Unknown event (0-4)
            13: 4,
        }

        for phaseid in phases:
            phase = Node.void('phase')
            root.add_child(phase)
            phase.add_child(Node.s16('event_id', phaseid))
            phase.add_child(Node.s16('phase', phases[phaseid]))

        for areaid in range(1, 50):
            area = Node.void('area')
            root.add_child(area)
            area.add_child(Node.s16('area_id', areaid))
            area.add_child(Node.u64('end_date', 0))
            area.add_child(Node.s16('medal_id', areaid))
            area.add_child(Node.bool('is_limit', False))

        # Calculate most popular characters
        profiles = self.data.remote.user.get_all_profiles(
            self.game, self.version)
        charas: Dict[int, int] = {}
        for (userid, profile) in profiles:
            chara = profile.get_int('chara', -1)
            if chara <= 0:
                continue
            if chara not in charas:
                charas[chara] = 1
            else:
                charas[chara] = charas[chara] + 1

        # Order a typle by most popular character to least popular character
        charamap = sorted(
            [(c, charas[c]) for c in charas],
            key=lambda c: c[1],
            reverse=True,
        )

        # Output the top 20 of them
        rank = 1
        for (charaid, usecount) in charamap[:20]:
            popular = Node.void('popular')
            root.add_child(popular)
            popular.add_child(Node.s16('rank', rank))
            popular.add_child(Node.s16('chara_num', charaid))
            rank = rank + 1

        # Output the hit chart
        for (songid, plays) in self.data.local.music.get_hit_chart(
                self.game, self.version, 500):
            popular_music = Node.void('popular_music')
            root.add_child(popular_music)
            popular_music.add_child(Node.s16('music_num', songid))

        # Output goods prices
        for goodsid in range(1, 421):
            if goodsid >= 1 and goodsid <= 80:
                price = 60
            elif goodsid >= 81 and goodsid <= 120:
                price = 250
            elif goodsid >= 121 and goodsid <= 142:
                price = 500
            elif goodsid >= 143 and goodsid <= 300:
                price = 100
            elif goodsid >= 301 and goodsid <= 420:
                price = 150
            else:
                raise Exception('Invalid goods ID!')
            goods = Node.void('goods')
            root.add_child(goods)
            goods.add_child(Node.s16('goods_id', goodsid))
            goods.add_child(Node.s32('price', price))
            goods.add_child(Node.s16('goods_type', 0))
예제 #20
0
 def handle_pcb23_dlstatus_request(self, request: Node) -> Node:
     return Node.void('pcb23')
예제 #21
0
 def handle_gameend_log_request(self, request: Node) -> Node:
     # Respond to request with nothing since we don't care about cardless players
     return Node.void('gameend')
예제 #22
0
 def handle_pcb23_write_request(self, request: Node) -> Node:
     # Update the name of this cab for admin purposes
     self.update_machine_name(request.child_value('pcb_setting/name'))
     return Node.void('pcb23')
예제 #23
0
파일: base.py 프로젝트: vangar/bemaniutils
 def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node:
     """
     Base handler for a profile. Given a userid and a profile dictionary,
     return a Node representing a profile. Should be overridden.
     """
     return Node.void('game')
예제 #24
0
 def handle_info23_common_request(self, request: Node) -> Node:
     info = Node.void('info23')
     self.__construct_common_info(info)
     return info
예제 #25
0
 def handle_game_message_request(self, request: Node) -> Node:
     return Node.void('game')
예제 #26
0
 def handle_lobby22_request(self, request: Node) -> Optional[Node]:
     # Stub out the entire lobby22 service (yes, its lobby22 in Pop'n 23)
     return Node.void('lobby22')
예제 #27
0
    def handle_game_friend_request(self, request: Node) -> Node:
        extid = intish(request.attribute('code'))
        userid = None
        friend = None

        if extid is not None:
            # Rival score loading
            userid = self.data.remote.user.from_extid(self.game, self.version, extid)
        if userid is not None:
            friend = self.get_profile(userid)
            play_stats = self.get_play_statistics(userid)

        if friend is None:
            # Return an empty node to tell the game we don't have a player here
            game = Node.void('game')
            return game

        game = Node.void('game')
        game.set_attribute('data', '1')
        game.add_child(Node.u32('code', friend.get_int('extid')))
        game.add_child(Node.string('name', friend.get_str('name')))
        game.add_child(Node.u8('area', friend.get_int('area', 51)))
        game.add_child(Node.u32('exp', play_stats.get_int('exp')))
        game.add_child(Node.u32('star', friend.get_int('star')))

        # Drill rankings
        if 'title' in friend:
            title = Node.void('title')
            game.add_child(title)
            titledict = friend.get_dict('title')
            if 't' in titledict:
                title.set_attribute('t', str(titledict.get_int('t')))
            if 's' in titledict:
                title.set_attribute('s', str(titledict.get_int('s')))
            if 'd' in titledict:
                title.set_attribute('d', str(titledict.get_int('d')))

        if 'title_gr' in friend:
            title_gr = Node.void('title_gr')
            game.add_child(title_gr)
            title_grdict = friend.get_dict('title_gr')
            if 't' in title_grdict:
                title_gr.set_attribute('t', str(title_grdict.get_int('t')))
            if 's' in title_grdict:
                title_gr.set_attribute('s', str(title_grdict.get_int('s')))
            if 'd' in title_grdict:
                title_gr.set_attribute('d', str(title_grdict.get_int('d')))

        # Groove gauge level-ups
        gr_s = Node.void('gr_s')
        game.add_child(gr_s)
        index = 1
        for entry in friend.get_int_array('gr_s', 5):
            gr_s.set_attribute('gr{}'.format(index), str(entry))
            index = index + 1

        gr_d = Node.void('gr_d')
        game.add_child(gr_d)
        index = 1
        for entry in friend.get_int_array('gr_d', 5):
            gr_d.set_attribute('gr{}'.format(index), str(entry))
            index = index + 1
        return game
예제 #28
0
 def handle_player23_start_request(self, request: Node) -> Node:
     root = Node.void('player23')
     root.add_child(Node.s32('play_id', 0))
     self.__construct_common_info(root)
     return root
예제 #29
0
 def handle_game_tax_info_request(self, request: Node) -> Node:
     game = Node.void('game')
     tax_info = Node.void('tax_info')
     game.add_child(tax_info)
     tax_info.set_attribute('tax_phase', '0')
     return game
예제 #30
0
    def handle_player22_request(self, request: Node) -> Optional[Node]:
        method = request.attribute('method')

        if method == 'read':
            refid = request.child_value('ref_id')
            # Pop'n Music 22 doesn't send a modelstring to load old profiles,
            # it just expects us to know. So always look for old profiles in
            # Pop'n 22 land.
            root = self.get_profile_by_refid(refid,
                                             self.OLD_PROFILE_FALLTHROUGH)
            if root is None:
                root = Node.void('player22')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'new':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            root = self.new_profile_by_refid(refid, name)
            if root is None:
                root = Node.void('player22')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'start':
            return Node.void('player22')

        elif method == 'logout':
            return Node.void('player22')

        elif method == 'write':
            refid = request.child_value('ref_id')

            root = Node.void('player22')
            if refid is None:
                return root

            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                return root

            oldprofile = self.get_profile(userid) or ValidatedDict()
            newprofile = self.unformat_profile(userid, request, oldprofile)

            if newprofile is not None:
                self.put_profile(userid, newprofile)

            return root

        elif method == 'conversion':
            refid = request.child_value('ref_id')
            name = request.child_value('name')
            chara = request.child_value('chara')
            root = self.new_profile_by_refid(refid, name, chara)
            if root is None:
                root = Node.void('playerdata')
                root.set_attribute('status', str(Status.NO_PROFILE))
            return root

        elif method == 'write_music':
            refid = request.child_value('ref_id')

            root = Node.void('player22')
            if refid is None:
                return root

            userid = self.data.remote.user.from_refid(self.game, self.version,
                                                      refid)
            if userid is None:
                return root

            songid = request.child_value('music_num')
            chart = {
                self.GAME_CHART_TYPE_EASY: self.CHART_TYPE_EASY,
                self.GAME_CHART_TYPE_NORMAL: self.CHART_TYPE_NORMAL,
                self.GAME_CHART_TYPE_HYPER: self.CHART_TYPE_HYPER,
                self.GAME_CHART_TYPE_EX: self.CHART_TYPE_EX,
            }[request.child_value('sheet_num')]
            medal = request.child_value('clearmedal')
            points = request.child_value('score')
            combo = request.child_value('combo')
            stats = {
                'cool': request.child_value('cool'),
                'great': request.child_value('great'),
                'good': request.child_value('good'),
                'bad': request.child_value('bad')
            }
            medal = {
                self.GAME_PLAY_MEDAL_CIRCLE_FAILED:
                self.PLAY_MEDAL_CIRCLE_FAILED,
                self.GAME_PLAY_MEDAL_DIAMOND_FAILED:
                self.PLAY_MEDAL_DIAMOND_FAILED,
                self.GAME_PLAY_MEDAL_STAR_FAILED: self.PLAY_MEDAL_STAR_FAILED,
                self.GAME_PLAY_MEDAL_EASY_CLEAR: self.PLAY_MEDAL_EASY_CLEAR,
                self.GAME_PLAY_MEDAL_CIRCLE_CLEARED:
                self.PLAY_MEDAL_CIRCLE_CLEARED,
                self.GAME_PLAY_MEDAL_DIAMOND_CLEARED:
                self.PLAY_MEDAL_DIAMOND_CLEARED,
                self.GAME_PLAY_MEDAL_STAR_CLEARED:
                self.PLAY_MEDAL_STAR_CLEARED,
                self.GAME_PLAY_MEDAL_CIRCLE_FULL_COMBO:
                self.PLAY_MEDAL_CIRCLE_FULL_COMBO,
                self.GAME_PLAY_MEDAL_DIAMOND_FULL_COMBO:
                self.PLAY_MEDAL_DIAMOND_FULL_COMBO,
                self.GAME_PLAY_MEDAL_STAR_FULL_COMBO:
                self.PLAY_MEDAL_STAR_FULL_COMBO,
                self.GAME_PLAY_MEDAL_PERFECT: self.PLAY_MEDAL_PERFECT,
            }[medal]
            self.update_score(userid,
                              songid,
                              chart,
                              points,
                              medal,
                              combo=combo,
                              stats=stats)
            return root

        # Invalid method
        return None