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, }
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']), )
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'), }, )
def register_all(cls) -> None: for game in ['G15', 'H16', 'I17', 'J39', 'K39', 'L39', 'M39']: Base.register(game, PopnMusicFactory)
def register_all(cls) -> None: for game in ['KFC']: Base.register(game, SoundVoltexFactory)
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
def register_all(cls) -> None: for game in ['IBB']: Base.register(game, BishiBashiFactory)
def register_all(cls) -> None: for game in ['H44', 'I44', 'J44', 'K44', 'L44']: Base.register(game, JubeatFactory)
def register_all(cls) -> None: for game in ['JDJ', 'JDZ', 'KDZ', 'LDJ']: Base.register(game, IIDXFactory)
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
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
def register_all(cls) -> None: for game in ['KBR', 'LBR', 'MBR']: Base.register(game, ReflecBeatFactory)
def register_all(cls) -> None: for game in ['PIX']: Base.register(game, MusecaFactory)