Пример #1
0
def format_machine(machine: Machine) -> Dict[str, Any]:
    if machine.game is None:
        game = 'any game'
    elif machine.version is None:
        game = {
            GameConstants.BISHI_BASHI: 'BishiBashi',
            GameConstants.DDR: 'DDR',
            GameConstants.IIDX: 'IIDX',
            GameConstants.JUBEAT: 'Jubeat',
            GameConstants.MUSECA: 'MÚSECA',
            GameConstants.POPN_MUSIC: 'Pop\'n Music',
            GameConstants.REFLEC_BEAT: 'Reflec Beat',
            GameConstants.SDVX: 'SDVX',
        }.get(machine.game)
    elif machine.version > 0:
        game = [
            name for (game, version, name) in Base.all_games()
            if game == machine.game and version == machine.version
        ][0]
    elif machine.version < 0:
        game = [
            name for (game, version, name) in Base.all_games()
            if game == machine.game and version == -machine.version
        ][0] + ' or older'

    return {
        'pcbid': machine.pcbid,
        'name': machine.name,
        'description': machine.description,
        'port': machine.port,
        'game': game,
    }
Пример #2
0
def get_game_settings(arcade: Arcade) -> List[Dict[str, Any]]:
    game_lut: Dict[str, Dict[int, str]] = {}
    settings_lut: Dict[str, Dict[int, Dict[str, Any]]] = {}
    all_settings = []

    for (game, version, name) in Base.all_games():
        if game not in game_lut:
            game_lut[game] = {}
            settings_lut[game] = {}
        game_lut[game][version] = name
        settings_lut[game][version] = {}

    for (game, version, settings) in Base.all_settings():
        if not settings:
            continue

        # First, set up the basics
        game_settings: Dict[str, Any] = {
            'game': game,
            'version': version,
            'name': game_lut[game][version],
            'bools': [],
            'ints': [],
            'strs': [],
            'longstrs': [],
        }

        # Now, look up the current setting for each returned setting
        for setting_type, setting_unpacker in [
            ('bools', "get_bool"),
            ('ints', "get_int"),
            ('strs', "get_str"),
            ('longstrs', "get_str"),
        ]:
            for setting in settings.get(setting_type, []):
                if setting['category'] not in settings_lut[game][version]:
                    cached_setting = g.data.local.machine.get_settings(
                        arcade.id, game, version, setting['category'])
                    if cached_setting is None:
                        cached_setting = ValidatedDict()
                    settings_lut[game][version][
                        setting['category']] = cached_setting

                current_settings = settings_lut[game][version][
                    setting['category']]
                setting['value'] = getattr(current_settings, setting_unpacker)(
                    setting['setting'])
                game_settings[setting_type].append(setting)

        # Now, include it!
        all_settings.append(game_settings)

    return sorted(
        all_settings,
        key=lambda setting: (setting['game'], setting['version']),
    )
Пример #3
0
def viewmachines() -> Response:
    games: Dict[str, Dict[int, str]] = {}
    for (game, version, name) in Base.all_games():
        if game not in games:
            games[game] = {}
        games[game][version] = name

    return render_react(
        'Machines',
        'admin/machines.react.js',
        {
            'machines': [format_machine(machine) for machine in g.data.local.machine.get_all_machines()],
            'arcades': {arcade.id: arcade.name for arcade in g.data.local.machine.get_all_arcades()},
            'series': {
                GameConstants.BISHI_BASHI: 'BishiBashi',
                GameConstants.DDR: 'DDR',
                GameConstants.IIDX: 'IIDX',
                GameConstants.JUBEAT: 'Jubeat',
                GameConstants.MUSECA: 'MÚSECA',
                GameConstants.POPN_MUSIC: 'Pop\'n Music',
                GameConstants.REFLEC_BEAT: 'Reflec Beat',
                GameConstants.SDVX: 'SDVX',
            },
            'games': games,
            'enforcing': g.config['server']['enforce_pcbid'],
        },
        {
            'generatepcbid': url_for('admin_pages.generatepcbid'),
            'addpcbid': url_for('admin_pages.addpcbid'),
            'updatepcbid': url_for('admin_pages.updatepcbid'),
            'removepcbid': url_for('admin_pages.removepcbid'),
        },
    )
Пример #4
0
 def register_all(cls) -> None:
     for game in ['G15', 'H16', 'I17', 'J39', 'K39', 'L39', 'M39']:
         Base.register(game, PopnMusicFactory)
Пример #5
0
 def register_all(cls) -> None:
     for game in ['KFC']:
         Base.register(game, SoundVoltexFactory)
Пример #6
0
def get_game_settings(arcade: Arcade) -> List[Dict[str, Any]]:
    game_lut: Dict[str, Dict[int, str]] = {}
    settings_lut: Dict[str, Dict[int, Dict[str, Any]]] = {}
    all_settings = []

    for (game, version, name) in Base.all_games():
        if game not in game_lut:
            game_lut[game] = {}
            settings_lut[game] = {}
        game_lut[game][version] = name
        settings_lut[game][version] = {}

    for (game, version, settings) in Base.all_settings():
        if not settings:
            continue

        # First, set up the basics
        game_settings: Dict[str, Any] = {
            'game': game,
            'version': version,
            'name': game_lut[game][version],
            'bools': [],
            'ints': [],
        }

        # Now, look up the current setting for each returned setting
        for bool_setting in settings.get('bools', []):
            if bool_setting['category'] not in settings_lut[game][version]:
                cached_setting = g.data.local.machine.get_settings(
                    arcade.id, game, version, bool_setting['category'])
                if cached_setting is None:
                    cached_setting = ValidatedDict()
                settings_lut[game][version][
                    bool_setting['category']] = cached_setting

            current_settings = settings_lut[game][version][
                bool_setting['category']]
            bool_setting['value'] = current_settings.get_bool(
                bool_setting['setting'])
            game_settings['bools'].append(bool_setting)

        # Now, look up the current setting for each returned setting
        for int_setting in settings.get('ints', []):
            if int_setting['category'] not in settings_lut[game][version]:
                cached_setting = g.data.local.machine.get_settings(
                    arcade.id, game, version, int_setting['category'])
                if cached_setting is None:
                    cached_setting = ValidatedDict()
                settings_lut[game][version][
                    int_setting['category']] = cached_setting

            current_settings = settings_lut[game][version][
                int_setting['category']]
            int_setting['value'] = current_settings.get_int(
                int_setting['setting'])
            game_settings['ints'].append(int_setting)

        # Now, include it!
        all_settings.append(game_settings)

    return all_settings
Пример #7
0
 def register_all(cls) -> None:
     for game in ['IBB']:
         Base.register(game, BishiBashiFactory)
Пример #8
0
 def register_all(cls) -> None:
     for game in ['H44', 'I44', 'J44', 'K44', 'L44']:
         Base.register(game, JubeatFactory)
Пример #9
0
 def register_all(cls) -> None:
     for game in ['JDJ', 'JDZ', 'KDZ', 'LDJ']:
         Base.register(game, IIDXFactory)
Пример #10
0
    def handle(self, tree: Node) -> Optional[Node]:
        """
        Given a packet from a game, handle it and return a response.

        Parameters:
            tree - A Node representing the root of a tree. Expected to
                   come from an external game.

        Returns:
            A Node representing the root of a response tree, or None if
            we had a problem parsing or generating a response.
        """
        self.log("Received request:\n{}", tree)

        if tree.name != 'call':
            # Invalid request
            self.log("Invalid root node {}", tree.name)
            return None

        if len(tree.children) != 1:
            # Invalid request
            self.log("Invalid number of children for root node")
            return None

        modelstring = tree.attribute('model')
        model = Model.from_modelstring(modelstring)
        pcbid = tree.attribute('srcid')

        # If we are enforcing, bail out if we don't recognize thie ID
        pcb = self.__data.local.machine.get_machine(pcbid)
        if self.__config['server']['enforce_pcbid'] and pcb is None:
            self.log("Unrecognized PCBID {}", pcbid)
            raise UnrecognizedPCBIDException(
                pcbid, modelstring, self.__config['client']['address'])

        # If we don't have a Machine, but we aren't enforcing, we must create it
        if pcb is None:
            pcb = self.__data.local.machine.create_machine(pcbid)

        request = tree.children[0]

        config = copy.copy(self.__config)
        config['machine'] = {
            'pcbid': pcbid,
            'arcade': pcb.arcade,
        }

        # If the machine we looked up is in an arcade, override the global
        # paseli settings with the arcade paseli settings.
        if pcb.arcade is not None:
            arcade = self.__data.local.machine.get_arcade(pcb.arcade)
            if arcade is not None:
                config['paseli']['enabled'] = arcade.data.get_bool(
                    'paseli_enabled')
                config['paseli']['infinite'] = arcade.data.get_bool(
                    'paseli_infinite')
                if arcade.data.get_bool('mask_services_url'):
                    # Mask the address, no matter what the server settings are
                    config['server']['uri'] = None
        # If we don't have a server URI, we should add the default
        if 'uri' not in config['server']:
            config['server']['uri'] = None

        game = Base.create(self.__data, config, model)
        method = request.attribute('method')
        response = None

        # If we are enforcing, make sure the PCBID isn't specified to be
        # game-specific
        if self.__config['server']['enforce_pcbid'] and pcb.game is not None:
            if pcb.game != game.game:
                self.log(
                    "PCBID {} assigned to game {}, but connected from game {}",
                    pcbid, pcb.game, game.game)
                raise UnrecognizedPCBIDException(
                    pcbid, modelstring, self.__config['client']['address'])
            if pcb.version is not None:
                if pcb.version > 0 and pcb.version != game.version:
                    self.log(
                        "PCBID {} assigned to game {} version {}, but connected from game {} version {}",
                        pcbid,
                        pcb.game,
                        pcb.version,
                        game.game,
                        game.version,
                    )
                    raise UnrecognizedPCBIDException(
                        pcbid, modelstring, self.__config['client']['address'])
                if pcb.version < 0 and (-pcb.version) < game.version:
                    self.log(
                        "PCBID {} assigned to game {} maximum version {}, but connected from game {} version {}",
                        pcbid,
                        pcb.game,
                        -pcb.version,
                        game.game,
                        game.version,
                    )
                    raise UnrecognizedPCBIDException(
                        pcbid, modelstring, self.__config['client']['address'])

        # First, try to handle with specific service/method function
        try:
            handler = getattr(game, f'handle_{request.name}_{method}_request')
        except AttributeError:
            handler = None
        if handler is not None:
            response = handler(request)

        if response is None:
            # Now, try to pass it off to a generic service handler
            try:
                handler = getattr(game, f'handle_{request.name}_request')
            except AttributeError:
                handler = None
            if handler is not None:
                response = handler(request)

        if response is None:
            # Unrecognized handler
            self.log(f"Unrecognized service {request.name} method {method}")
            return None

        # Make sure we have a status value if one wasn't provided
        if 'status' not in response.attributes:
            response.set_attribute('status', str(Status.SUCCESS))

        root = Node.void('response')
        root.add_child(response)
        root.set_attribute('dstid', pcbid)

        self.log("Sending response:\n{}", root)

        return root
Пример #11
0
    def handle_cardmng_request(self, request: Node) -> Optional[Node]:
        """
        Handle a request for card management. This is independent of a game's profile handling,
        but still gives the game information as to whether or not a profile exists for a game.
        These methods handle looking up a card, handling binding a profile to a game version,
        returning whether a game profile exists or should be migrated, and creating a new account
        when no account is associated with a card.
        """
        method = request.attribute('method')

        if method == 'inquire':
            # Given a cardid, look up the dataid/refid (same thing in this system).
            # If the card doesn't exist or isn't allowed, return a status specifying this
            # instead of the results of the dataid/refid lookup.
            cardid = request.attribute('cardid')
            modelstring = request.attribute('model')
            userid = self.data.local.user.from_cardid(cardid)

            if userid is None:
                # This user doesn't exist, force system to create new account
                root = Node.void('cardmng')
                root.set_attribute('status', str(Status.NOT_REGISTERED))
                return root

            # Special handling for looking up whether the previous game's profile existed
            bound = self.has_profile(userid)
            expired = False
            if bound is False:
                if modelstring is not None:
                    model = Model.from_modelstring(modelstring)
                    oldgame = Base.create(self.data, self.config, model,
                                          self.model)
                    if oldgame is None:
                        bound = False
                    else:
                        bound = oldgame.has_profile(userid)
                        expired = True

            refid = self.data.local.user.get_refid(self.game, self.version,
                                                   userid)
            paseli_enabled = self.supports_paseli(
            ) and self.config['paseli']['enabled']

            root = Node.void('cardmng')
            root.set_attribute('refid', refid)
            root.set_attribute('dataid', refid)
            root.set_attribute('newflag', '1')  # Always seems to be set to 1
            root.set_attribute(
                'binded', '1' if bound else
                '0')  # Whether we've bound to this version of the game or not
            root.set_attribute(
                'expired', '1' if expired else '0')  # Whether we're expired
            root.set_attribute(
                'ecflag',
                '1' if paseli_enabled else '0')  # Whether to allow paseli
            root.set_attribute('useridflag', '1')
            root.set_attribute('extidflag', '1')
            return root

        elif method == 'authpass':
            # Given a dataid/refid previously found via inquire, verify the pin
            refid = request.attribute('refid')
            pin = request.attribute('pass')
            userid = self.data.local.user.from_refid(self.game, self.version,
                                                     refid)
            if userid is not None:
                valid = self.data.local.user.validate_pin(userid, pin)
            else:
                valid = False
            root = Node.void('cardmng')
            root.set_attribute(
                'status', str(Status.SUCCESS if valid else Status.INVALID_PIN))
            return root

        elif method == 'getrefid':
            # Given a cardid and a pin, register the card with the system and generate a new dataid/refid + extid
            cardid = request.attribute('cardid')
            pin = request.attribute('passwd')
            userid = self.data.local.user.create_account(cardid, pin)
            if userid is None:
                # This user can't be created
                root = Node.void('cardmng')
                root.set_attribute('status', str(Status.NOT_ALLOWED))
                return root

            refid = self.data.local.user.create_refid(self.game, self.version,
                                                      userid)
            root = Node.void('cardmng')
            root.set_attribute('dataid', refid)
            root.set_attribute('refid', refid)
            return root

        elif method == 'bindmodel':
            # Given a refid, bind the user's card to the current version of the game
            refid = request.attribute('refid')
            userid = self.data.local.user.from_refid(self.game, self.version,
                                                     refid)
            self.bind_profile(userid)
            root = Node.void('cardmng')
            root.set_attribute('dataid', refid)
            return root

        elif method == 'getkeepspan':
            # Unclear what this method does, return an arbitrary span
            root = Node.void('cardmng')
            root.set_attribute('keepspan', '30')
            return root

        elif method == 'getdatalist':
            # Unclear what this method does, return a dummy response
            root = Node.void('cardmng')
            return root

        # Invalid method
        return None
Пример #12
0
 def register_all(cls) -> None:
     for game in ['KBR', 'LBR', 'MBR']:
         Base.register(game, ReflecBeatFactory)
Пример #13
0
 def register_all(cls) -> None:
     for game in ['PIX']:
         Base.register(game, MusecaFactory)