コード例 #1
0
    def __handle_ghostload(self, userid: Optional[UserID], requestdata: Node,
                           response: Node) -> None:
        ghostid = requestdata.child_value('ghostid')
        ghost = self.data.local.music.get_score_by_key(self.game,
                                                       self.music_version,
                                                       ghostid)
        if ghost is None:
            return

        userid, score = ghost
        profile = self.get_profile(userid)
        if profile is None:
            return

        if 'ghost' not in score.data:
            return

        ghostdata = Node.void('ghostdata')
        response.add_child(ghostdata)
        ghostdata.add_child(Node.s32('code', profile.get_int('extid')))
        ghostdata.add_child(Node.u32('mcode', score.id))
        ghostdata.add_child(
            Node.u8('notetype', self.db_to_game_chart(score.chart)))
        ghostdata.add_child(Node.s32('ghostsize', len(score.data['ghost'])))
        ghostdata.add_child(Node.string('ghost', score.data['ghost']))
コード例 #2
0
ファイル: reflecbeat.py プロジェクト: wolskiCN/bemaniutils
    def __add_event_info(self, request: Node) -> None:
        events: Dict[int, int] = {}

        for (eventid, phase) in events.items():
            data = Node.void('data')
            request.add_child(data)
            data.add_child(Node.s32('type', -1))
            data.add_child(Node.s32('value', -1))
コード例 #3
0
    def _add_event_info(self, root: Node) -> None:
        event_ctrl = Node.void('event_ctrl')
        root.add_child(event_ctrl)
        # Contains zero or more nodes like:
        # <data>
        #     <type __type="s32">any</type>
        #     <index __type="s32">any</phase>
        #     <value __type="s32">any</phase>
        #     <value2 __type="s32">any</phase>
        #     <start_time __type="s32">any</phase>
        #     <end_time __type="s32">any</phase>
        # </data>

        item_lock_ctrl = Node.void('item_lock_ctrl')
        root.add_child(item_lock_ctrl)
コード例 #4
0
    def _add_event_info(self, root: Node) -> None:
        event_ctrl = Node.void('event_ctrl')
        root.add_child(event_ctrl)
        # Contains zero or more nodes like:
        # <data>
        #     <type __type="s32">any</type>
        #     <index __type="s32">any</phase>
        #     <value __type="s32">any</phase>
        #     <value2 __type="s32">any</phase>
        #     <start_time __type="s32">any</phase>
        #     <end_time __type="s32">any</phase>
        # </data>

        item_lock_ctrl = Node.void('item_lock_ctrl')
        root.add_child(item_lock_ctrl)
        # Contains zero or more nodes like:
        # <item>
        #     <type __type="u8">any</type>
        #     <id __type="u16">any</id>
        #     <param __type="u16">0-3</param>
        # </item>

        mycourse_ctrl = Node.void('mycourse_ctrl')
        root.add_child(mycourse_ctrl)
        songs = {
            song.id
            for song in self.data.local.music.get_all_songs(
                self.game, self.music_version)
        }
        for song in songs:
            data = Node.void('data')
            mycourse_ctrl.add_child(data)
            data.add_child(Node.s16('mycourse_id', 1))
            data.add_child(Node.s32('type', 0))
            data.add_child(Node.s32('music_id', song))
コード例 #5
0
ファイル: ddrace.py プロジェクト: wolskiCN/bemaniutils
    def __handle_usernew(self, userid: Optional[UserID], requestdata: Node, response: Node) -> None:
        if userid is None:
            raise Exception('Expecting valid UserID to create new profile!')

        machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
        self.put_profile(userid, ValidatedDict({
            'lid': machine.id,
        }))
        profile = self.get_profile(userid)

        response.add_child(Node.string('seq', ID.format_extid(profile.get_int('extid'))))
        response.add_child(Node.s32('code', profile.get_int('extid')))
        response.add_child(Node.string('shoparea', ''))
コード例 #6
0
    def _add_shop_score(self, root: Node) -> None:
        shop_score = Node.void('shop_score')
        root.add_child(shop_score)
        today = Node.void('today')
        shop_score.add_child(today)
        yesterday = Node.void('yesterday')
        shop_score.add_child(yesterday)

        all_profiles = self.data.local.user.get_all_profiles(self.game, self.version)
        all_attempts = self.data.local.music.get_all_attempts(self.game, self.version, timelimit=(Time.beginning_of_today() - Time.SECONDS_IN_DAY))
        machine = self.data.local.machine.get_machine(self.config['machine']['pcbid'])
        if machine.arcade is not None:
            lids = [
                machine.id for machine in self.data.local.machine.get_all_machines(machine.arcade)
            ]
        else:
            lids = [machine.id]

        relevant_profiles = [
            profile for profile in all_profiles
            if profile[1].get_int('lid', -1) in lids
        ]

        for (rootnode, timeoffset) in [
            (today, 0),
            (yesterday, Time.SECONDS_IN_DAY),
        ]:
            # Grab all attempts made in the relevant day
            relevant_attempts = [
                attempt for attempt in all_attempts
                if (
                    attempt[1].timestamp >= (Time.beginning_of_today() - timeoffset) and
                    attempt[1].timestamp <= (Time.end_of_today() - timeoffset)
                )
            ]

            # Calculate scores based on attempt
            scores_by_user: Dict[UserID, Dict[int, Dict[int, Attempt]]] = {}
            for (userid, attempt) in relevant_attempts:
                if userid not in scores_by_user:
                    scores_by_user[userid] = {}
                if attempt.id not in scores_by_user[userid]:
                    scores_by_user[userid][attempt.id] = {}
                if attempt.chart not in scores_by_user[userid][attempt.id]:
                    # No high score for this yet, just use this attempt
                    scores_by_user[userid][attempt.id][attempt.chart] = attempt
                else:
                    # If this attempt is better than the stored one, replace it
                    if scores_by_user[userid][attempt.id][attempt.chart].points < attempt.points:
                        scores_by_user[userid][attempt.id][attempt.chart] = attempt

            # Calculate points earned by user in the day
            points_by_user: Dict[UserID, int] = {}
            for userid in scores_by_user:
                points_by_user[userid] = 0
                for mid in scores_by_user[userid]:
                    for chart in scores_by_user[userid][mid]:
                        points_by_user[userid] = points_by_user[userid] + scores_by_user[userid][mid][chart].points

            # Output that day's earned points
            for (userid, profile) in relevant_profiles:
                data = Node.void('data')
                rootnode.add_child(data)
                data.add_child(Node.s16('day_id', int((Time.now() - timeoffset) / Time.SECONDS_IN_DAY)))
                data.add_child(Node.s32('user_id', profile.get_int('extid')))
                data.add_child(Node.s16('icon_id', profile.get_dict('config').get_int('icon_id')))
                data.add_child(Node.s16('point', min(points_by_user.get(userid, 0), 32767)))
                data.add_child(Node.s32('update_time', Time.now()))
                data.add_child(Node.string('name', profile.get_str('name')))

            rootnode.add_child(Node.s32('time', Time.beginning_of_today() - timeoffset))
コード例 #7
0
ファイル: eclale.py プロジェクト: vangar/bemaniutils
    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.music_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))
コード例 #8
0
 def __handle_inheritance(self, userid: Optional[UserID], requestdata: Node,
                          response: Node) -> None:
     response.add_child(Node.s32('InheritanceStatus', 0))
コード例 #9
0
    def __handle_rivalload(self, userid: Optional[UserID], requestdata: Node,
                           response: Node) -> None:
        data = Node.void('data')
        response.add_child(data)
        data.add_child(
            Node.s32('recordtype', requestdata.child_value('loadflag')))

        thismachine = self.data.local.machine.get_machine(
            self.config['machine']['pcbid'])
        machines_by_id: Dict[int, Optional[Machine]] = {
            thismachine.id: thismachine
        }

        loadkind = requestdata.child_value('loadflag')
        profiles_by_userid: Dict[UserID, ValidatedDict] = {}

        def get_machine(lid: int) -> Optional[Machine]:
            if lid not in machines_by_id:
                pcbid = self.data.local.machine.from_machine_id(lid)
                if pcbid is None:
                    machines_by_id[lid] = None
                    return None

                machine = self.data.local.machine.get_machine(pcbid)
                if machine is None:
                    machines_by_id[lid] = None
                    return None

                machines_by_id[lid] = machine
            return machines_by_id[lid]

        if loadkind == self.GAME_RIVAL_TYPE_WORLD:
            # Just load all scores for this network
            scores = self.data.remote.music.get_all_records(
                self.game, self.music_version)
        elif loadkind == self.GAME_RIVAL_TYPE_AREA:
            if thismachine.arcade is not None:
                match_arcade = thismachine.arcade
                match_machine = None
            else:
                match_arcade = None
                match_machine = thismachine.id

            # Load up all scores by any user registered on a machine in the same arcade
            profiles = self.data.local.user.get_all_profiles(
                self.game, self.version)
            userids: List[UserID] = []
            for userid, profiledata in profiles:
                profiles_by_userid[userid] = profiledata

                # If we have an arcade to match, see if this user's location matches the arcade.
                # If we don't, just match lid directly
                if match_arcade is not None:
                    theirmachine = get_machine(profiledata.get_int('lid'))
                    if theirmachine is not None and theirmachine.arcade == match_arcade:
                        userids.append(userid)
                elif match_machine is not None:
                    if profiledata.get_int('lid') == match_machine:
                        userids.append(userid)

            # Load all scores for users in the area
            scores = self.data.local.music.get_all_records(self.game,
                                                           self.music_version,
                                                           userlist=userids)
        elif loadkind == self.GAME_RIVAL_TYPE_MACHINE:
            # Load up all scores and filter them by those earned at this location
            scores = self.data.local.music.get_all_records(
                self.game, self.music_version, locationlist=[thismachine.id])
        elif loadkind in [
                self.GAME_RIVAL_TYPE_RIVAL1,
                self.GAME_RIVAL_TYPE_RIVAL2,
                self.GAME_RIVAL_TYPE_RIVAL3,
        ]:
            # Load up this user's highscores, format the way the below code expects it
            extid = requestdata.child_value('ddrcode')
            otherid = self.data.remote.user.from_extid(self.game, self.version,
                                                       extid)
            userscores = self.data.remote.music.get_scores(
                self.game, self.music_version, otherid)
            scores = [(otherid, score) for score in userscores]
        else:
            # Nothing here
            scores = []

        missing_users = [
            userid for (userid, _) in scores
            if userid not in profiles_by_userid
        ]
        for (userid, profile) in self.get_any_profiles(missing_users):
            profiles_by_userid[userid] = profile

        for userid, score in scores:
            if profiles_by_userid.get(userid) is None:
                raise Exception(
                    f'Logic error, couldn\'t find any profile for {userid}')
            profiledata = profiles_by_userid[userid]

            record = Node.void('record')
            data.add_child(record)
            record.add_child(Node.u32('mcode', score.id))
            record.add_child(
                Node.u8('notetype', self.db_to_game_chart(score.chart)))
            record.add_child(
                Node.u8('rank',
                        self.db_to_game_rank(score.data.get_int('rank'))))
            record.add_child(
                Node.u8('clearkind',
                        self.db_to_game_halo(score.data.get_int('halo'))))
            record.add_child(Node.u8('flagdata', 0))
            record.add_child(Node.string('name', profiledata.get_str('name')))
            record.add_child(Node.s32('area', profiledata.get_int('area', 58)))
            record.add_child(Node.s32('code', profiledata.get_int('extid')))
            record.add_child(Node.s32('score', score.points))
            record.add_child(Node.s32('ghostid', score.key))
コード例 #10
0
    def __handle_userload(self, userid: Optional[UserID], requestdata: Node,
                          response: Node) -> None:
        has_profile: bool = False
        achievements: List[Achievement] = []
        scores: List[Score] = []

        if userid is not None:
            has_profile = self.has_profile(userid)
            achievements = self.data.local.user.get_achievements(
                self.game, self.version, userid)
            scores = self.data.remote.music.get_scores(self.game,
                                                       self.music_version,
                                                       userid)

        # Place scores into an arrangement for easier distribution to Ace.
        scores_by_mcode: Dict[int, List[Optional[Score]]] = {}
        for score in scores:
            if score.id not in scores_by_mcode:
                scores_by_mcode[score.id] = [None] * 9

            scores_by_mcode[score.id][self.db_to_game_chart(
                score.chart)] = score

        # First, set new flag
        response.add_child(Node.bool('is_new', not has_profile))

        # Now, return the scores to Ace
        for mcode in scores_by_mcode:
            music = Node.void('music')
            response.add_child(music)
            music.add_child(Node.u32('mcode', mcode))

            scores_that_matter = scores_by_mcode[mcode]
            while scores_that_matter[-1] is None:
                scores_that_matter = scores_that_matter[:-1]

            for score in scores_that_matter:
                note = Node.void('note')
                music.add_child(note)

                if score is None:
                    note.add_child(Node.u16('count', 0))
                    note.add_child(Node.u8('rank', 0))
                    note.add_child(Node.u8('clearkind', 0))
                    note.add_child(Node.s32('score', 0))
                    note.add_child(Node.s32('ghostid', 0))
                else:
                    note.add_child(Node.u16('count', score.plays))
                    note.add_child(
                        Node.u8(
                            'rank',
                            self.db_to_game_rank(score.data.get_int('rank'))))
                    note.add_child(
                        Node.u8(
                            'clearkind',
                            self.db_to_game_halo(score.data.get_int('halo'))))
                    note.add_child(Node.s32('score', score.points))
                    note.add_child(Node.s32('ghostid', score.key))

        # Active event settings
        activeevents = [
            1,
            3,
            5,
            9,
            10,
            11,
            12,
            13,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26,
            27,
            28,
            29,
            30,
            31,
            32,
            33,
            34,
            35,
            36,
            37,
            38,
            39,
            40,
            41,
            42,
        ]

        # Event reward settings
        rewards = {
            '30': {
                999: 5,
            }
        }

        # Now handle event progress and activation.
        events = {
            ach.id: ach.data
            for ach in achievements if ach.type == '9999'
        }
        progress = [ach for ach in achievements if ach.type != '9999']

        # Make sure we always send a babylon's adventure save event or the game won't send progress
        babylon_included = False
        for evtprogress in progress:
            if evtprogress.id == 999 and evtprogress.type == '30':
                babylon_included = True
                break

        if not babylon_included:
            progress.append(
                Achievement(
                    999,
                    '30',
                    None,
                    {
                        'completed': False,
                        'progress': 0,
                    },
                ))

        for event in activeevents:
            # Get completion data
            playerstats = events.get(event, ValidatedDict({'completed':
                                                           False}))

            # Return the data
            eventdata = Node.void('eventdata')
            response.add_child(eventdata)
            eventdata.add_child(Node.u32('eventid', event))
            eventdata.add_child(Node.s32('eventtype', 9999))
            eventdata.add_child(Node.u32('eventno', 0))
            eventdata.add_child(Node.s64('condition', 0))
            eventdata.add_child(Node.u32('reward', 0))
            eventdata.add_child(
                Node.s32('comptime',
                         1 if playerstats.get_bool('completed') else 0))
            eventdata.add_child(Node.s64('savedata', 0))

        for evtprogress in progress:
            # Babylon's adventure progres and anything else the game sends
            eventdata = Node.void('eventdata')
            response.add_child(eventdata)
            eventdata.add_child(Node.u32('eventid', evtprogress.id))
            eventdata.add_child(Node.s32('eventtype', int(evtprogress.type)))
            eventdata.add_child(Node.u32('eventno', 0))
            eventdata.add_child(Node.s64('condition', 0))
            eventdata.add_child(
                Node.u32('reward',
                         rewards.get(evtprogress.type,
                                     {}).get(evtprogress.id)))
            eventdata.add_child(
                Node.s32('comptime',
                         1 if evtprogress.data.get_bool('completed') else 0))
            eventdata.add_child(
                Node.s64('savedata', evtprogress.data.get_int('progress')))