def update_bans(self): self.new_bans = NetworkDict() defers = [] for url, filter in self.urls: defers.append(self.protocol.getPage(url).addCallback(self.got_bans, filter)) DeferredList(defers).addCallback(self.bans_finished)
def __init__(self, interface, config): self.config = config if config.get('random_rotation', False): self.map_rotator_type = random_choice_cycle else: self.map_rotator_type = itertools.cycle self.default_time_limit = config.get('default_time_limit', 20.0) self.default_cap_limit = config.get('cap_limit', 10.0) self.advance_on_win = int(config.get('advance_on_win', False)) self.win_count = itertools.count(1) self.bans = NetworkDict() try: self.bans.read_list(json.load(open('bans.txt', 'rb'))) except IOError: pass self.hard_bans = set() # possible DDoS'ers are added here self.player_memory = deque(maxlen = 100) self.config = config if len(self.name) > MAX_SERVER_NAME_SIZE: print '(server name too long; it will be truncated to "%s")' % ( self.name[:MAX_SERVER_NAME_SIZE]) self.respawn_time = config.get('respawn_time', 8) self.respawn_waves = config.get('respawn_waves', False) game_mode = config.get('game_mode', 'ctf') if game_mode == 'ctf': self.game_mode = CTF_MODE elif game_mode == 'tc': self.game_mode = TC_MODE elif self.game_mode is None: raise NotImplementedError('invalid game mode: %s' % game_mode) self.game_mode_name = game_mode team1 = config.get('team1', {}) team2 = config.get('team2', {}) self.team1_name = team1.get('name', 'Blue') self.team2_name = team2.get('name', 'Green') self.team1_color = tuple(team1.get('color', (0, 0, 196))) self.team2_color = tuple(team2.get('color', (0, 196, 0))) self.friendly_fire = config.get('friendly_fire', True) self.friendly_fire_time = config.get('grief_friendly_fire_time', 2.0) self.spade_teamkills_on_grief = config.get('spade_teamkills_on_grief', False) self.fall_damage = config.get('fall_damage', True) self.teamswitch_interval = config.get('teamswitch_interval', 0) self.max_players = config.get('max_players', 20) self.melee_damage = config.get('melee_damage', 100) self.max_connections_per_ip = config.get('max_connections_per_ip', 0) self.passwords = config.get('passwords', {}) self.server_prefix = encode(config.get('server_prefix', '[*]')) self.time_announcements = config.get('time_announcements', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2400, 3000]) self.balanced_teams = config.get('balanced_teams', None) self.login_retries = config.get('login_retries', 1) # voting configuration self.default_ban_time = config.get('default_ban_duration', 24*60) self.speedhack_detect = config.get('speedhack_detect', True) if config.get('user_blocks_only', False): self.user_blocks = set() self.set_god_build = config.get('set_god_build', False) self.debug_log = config.get('debug_log', False) if self.debug_log: pyspades.debug.open_debug_log() ssh = config.get('ssh', {}) if ssh.get('enabled', False): from ssh import RemoteConsole self.remote_console = RemoteConsole(self, ssh) irc = config.get('irc', {}) if irc.get('enabled', False): from irc import IRCRelay self.irc_relay = IRCRelay(self, irc) status = config.get('status_server', {}) if status.get('enabled', False): from statusserver import StatusServerFactory self.status_server = StatusServerFactory(self, status) publish = config.get('ban_publish', {}) if publish.get('enabled', False): from banpublish import PublishServer self.ban_publish = PublishServer(self, publish) ban_subscribe = config.get('ban_subscribe', {}) if ban_subscribe.get('enabled', True): import bansubscribe self.ban_manager = bansubscribe.BanManager(self, ban_subscribe) logfile = config.get('logfile', None) if logfile is not None and logfile.strip(): if config.get('rotate_daily', False): create_filename_path(logfile) logging_file = DailyLogFile(logfile, '.') else: logging_file = open_create(logfile, 'a') log.addObserver(log.FileLogObserver(logging_file).emit) log.msg('pyspades server started on %s' % time.strftime('%c')) log.startLogging(sys.stdout) # force twisted logging self.start_time = reactor.seconds() self.end_calls = [] self.console = create_console(self) for password in self.passwords.get('admin', []): if password == 'replaceme': print 'REMEMBER TO CHANGE THE DEFAULT ADMINISTRATOR PASSWORD!' elif not password: self.everyone_is_admin = True for user_type, func_names in config.get('rights', {}).iteritems(): for func_name in func_names: commands.add_rights(func_name, user_type) port = self.port = config.get('port', 32887) ServerProtocol.__init__(self, port, interface) self.host.receiveCallback = self.receive_callback ret = self.set_map_rotation(config['maps']) if not ret: print 'Invalid map in map rotation (%s), exiting.' % ret.map raise SystemExit self.update_format() self.tip_frequency = config.get('tip_frequency', 0) if self.tips is not None and self.tip_frequency > 0: reactor.callLater(self.tip_frequency * 60, self.send_tip) self.master = config.get('master', True) self.set_master() get_external_ip(config.get('network_interface', '')).addCallback( self.got_external_ip)
class FeatureProtocol(ServerProtocol): connection_class = FeatureConnection bans = None ban_publish = None ban_manager = None everyone_is_admin = False player_memory = None irc_relay = None balanced_teams = None timestamps = None building = True killing = True global_chat = True remote_console = None debug_log = None advance_call = None master_reconnect_call = None master = False ip = None identifier = None planned_map = None map_info = None spawns = None user_blocks = None god_blocks = None last_time = None interface = None team_class = FeatureTeam game_mode = None # default to None so we can check time_announce_schedule = None server_version = SERVER_VERSION def __init__(self, interface, config): self.config = config if config.get('random_rotation', False): self.map_rotator_type = random_choice_cycle else: self.map_rotator_type = itertools.cycle self.default_time_limit = config.get('default_time_limit', 20.0) self.default_cap_limit = config.get('cap_limit', 10.0) self.advance_on_win = int(config.get('advance_on_win', False)) self.win_count = itertools.count(1) self.bans = NetworkDict() try: self.bans.read_list(json.load(open('bans.txt', 'rb'))) except IOError: pass self.hard_bans = set() # possible DDoS'ers are added here self.player_memory = deque(maxlen = 100) self.config = config if len(self.name) > MAX_SERVER_NAME_SIZE: print '(server name too long; it will be truncated to "%s")' % ( self.name[:MAX_SERVER_NAME_SIZE]) self.respawn_time = config.get('respawn_time', 8) self.respawn_waves = config.get('respawn_waves', False) game_mode = config.get('game_mode', 'ctf') if game_mode == 'ctf': self.game_mode = CTF_MODE elif game_mode == 'tc': self.game_mode = TC_MODE elif self.game_mode is None: raise NotImplementedError('invalid game mode: %s' % game_mode) self.game_mode_name = game_mode team1 = config.get('team1', {}) team2 = config.get('team2', {}) self.team1_name = team1.get('name', 'Blue') self.team2_name = team2.get('name', 'Green') self.team1_color = tuple(team1.get('color', (0, 0, 196))) self.team2_color = tuple(team2.get('color', (0, 196, 0))) self.friendly_fire = config.get('friendly_fire', True) self.friendly_fire_time = config.get('grief_friendly_fire_time', 2.0) self.spade_teamkills_on_grief = config.get('spade_teamkills_on_grief', False) self.fall_damage = config.get('fall_damage', True) self.teamswitch_interval = config.get('teamswitch_interval', 0) self.max_players = config.get('max_players', 20) self.melee_damage = config.get('melee_damage', 100) self.max_connections_per_ip = config.get('max_connections_per_ip', 0) self.passwords = config.get('passwords', {}) self.server_prefix = encode(config.get('server_prefix', '[*]')) self.time_announcements = config.get('time_announcements', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2400, 3000]) self.balanced_teams = config.get('balanced_teams', None) self.login_retries = config.get('login_retries', 1) # voting configuration self.default_ban_time = config.get('default_ban_duration', 24*60) self.speedhack_detect = config.get('speedhack_detect', True) if config.get('user_blocks_only', False): self.user_blocks = set() self.set_god_build = config.get('set_god_build', False) self.debug_log = config.get('debug_log', False) if self.debug_log: pyspades.debug.open_debug_log() ssh = config.get('ssh', {}) if ssh.get('enabled', False): from ssh import RemoteConsole self.remote_console = RemoteConsole(self, ssh) irc = config.get('irc', {}) if irc.get('enabled', False): from irc import IRCRelay self.irc_relay = IRCRelay(self, irc) status = config.get('status_server', {}) if status.get('enabled', False): from statusserver import StatusServerFactory self.status_server = StatusServerFactory(self, status) publish = config.get('ban_publish', {}) if publish.get('enabled', False): from banpublish import PublishServer self.ban_publish = PublishServer(self, publish) ban_subscribe = config.get('ban_subscribe', {}) if ban_subscribe.get('enabled', True): import bansubscribe self.ban_manager = bansubscribe.BanManager(self, ban_subscribe) logfile = config.get('logfile', None) if logfile is not None and logfile.strip(): if config.get('rotate_daily', False): create_filename_path(logfile) logging_file = DailyLogFile(logfile, '.') else: logging_file = open_create(logfile, 'a') log.addObserver(log.FileLogObserver(logging_file).emit) log.msg('pyspades server started on %s' % time.strftime('%c')) log.startLogging(sys.stdout) # force twisted logging self.start_time = reactor.seconds() self.end_calls = [] self.console = create_console(self) for password in self.passwords.get('admin', []): if password == 'replaceme': print 'REMEMBER TO CHANGE THE DEFAULT ADMINISTRATOR PASSWORD!' elif not password: self.everyone_is_admin = True for user_type, func_names in config.get('rights', {}).iteritems(): for func_name in func_names: commands.add_rights(func_name, user_type) port = self.port = config.get('port', 32887) ServerProtocol.__init__(self, port, interface) self.host.receiveCallback = self.receive_callback ret = self.set_map_rotation(config['maps']) if not ret: print 'Invalid map in map rotation (%s), exiting.' % ret.map raise SystemExit self.update_format() self.tip_frequency = config.get('tip_frequency', 0) if self.tips is not None and self.tip_frequency > 0: reactor.callLater(self.tip_frequency * 60, self.send_tip) self.master = config.get('master', True) self.set_master() get_external_ip(config.get('network_interface', '')).addCallback( self.got_external_ip) def got_external_ip(self, ip): self.ip = ip self.identifier = make_server_identifier(ip, self.port) print 'Server identifier is %s' % self.identifier def set_time_limit(self, time_limit = None, additive = False): advance_call = self.advance_call add_time = 0.0 if advance_call is not None: add_time = ((advance_call.getTime() - reactor.seconds()) / 60.0) advance_call.cancel() self.advance_call = None time_limit = time_limit or self.default_time_limit if time_limit == False: for call in self.end_calls[:]: call.set(None) return if additive: time_limit = min(time_limit + add_time, self.default_time_limit) seconds = time_limit * 60.0 self.advance_call = reactor.callLater(seconds, self._time_up) for call in self.end_calls[:]: call.set(seconds) if self.time_announce_schedule is not None: self.time_announce_schedule.reset() self.time_announce_schedule = Scheduler(self) for seconds in self.time_announcements: self.time_announce_schedule.call_end(seconds, self._next_time_announce) return time_limit def _next_time_announce(self): remaining = self.advance_call.getTime() - reactor.seconds() if remaining < 60.001: if remaining < 10.001: self.send_chat('%s...' % int(round(remaining))) else: self.send_chat('%s seconds remaining.' % int(round(remaining))) else: self.send_chat('%s minutes remaining.' % int(round(remaining/60))) def _time_up(self): self.advance_call = None self.advance_rotation('Time up!') def advance_rotation(self, message = None): self.set_time_limit(False) if self.planned_map is None: self.planned_map = self.map_rotator.next() map = self.planned_map self.planned_map = None self.on_advance(map) if message is None: self.set_map_name(map) else: self.send_chat('%s Next map: %s.' % (message, map.full_name), irc = True) reactor.callLater(5, self.set_map_name, map) def get_mode_name(self): return self.game_mode_name def set_map_name(self, rot_info): try: map_info = self.get_map(rot_info) except MapNotFound, e: return e if self.map_info: self.on_map_leave() self.map_info = map_info self.max_score = self.map_info.cap_limit or self.default_cap_limit self.set_map(self.map_info.data) self.set_time_limit(self.map_info.time_limit) self.update_format() return True
def __init__(self, interface, config): self.config = config if config.get('random_rotation', False): self.map_rotator_type = random_choice_cycle else: self.map_rotator_type = itertools.cycle self.default_time_limit = config.get('default_time_limit', 20.0) self.default_cap_limit = config.get('cap_limit', 10.0) self.advance_on_win = int(config.get('advance_on_win', False)) self.win_count = itertools.count(1) self.bans = NetworkDict() try: self.bans.read_list(json.load(open('bans.txt', 'rb'))) except IOError: pass self.hard_bans = set() # possible DDoS'ers are added here self.player_memory = deque(maxlen=100) self.config = config if len(self.name) > MAX_SERVER_NAME_SIZE: print '(server name too long; it will be truncated to "%s")' % ( self.name[:MAX_SERVER_NAME_SIZE]) self.respawn_time = config.get('respawn_time', 8) self.respawn_waves = config.get('respawn_waves', False) game_mode = config.get('game_mode', 'ctf') if game_mode == 'ctf': self.game_mode = CTF_MODE elif game_mode == 'tc': self.game_mode = TC_MODE elif self.game_mode is None: raise NotImplementedError('invalid game mode: %s' % game_mode) self.game_mode_name = game_mode team1 = config.get('team1', {}) team2 = config.get('team2', {}) self.team1_name = team1.get('name', 'Blue') self.team2_name = team2.get('name', 'Green') self.team1_color = tuple(team1.get('color', (0, 0, 196))) self.team2_color = tuple(team2.get('color', (0, 196, 0))) self.friendly_fire = config.get('friendly_fire', True) self.friendly_fire_time = config.get('grief_friendly_fire_time', 2.0) self.spade_teamkills_on_grief = config.get('spade_teamkills_on_grief', False) self.fall_damage = config.get('fall_damage', True) self.teamswitch_interval = config.get('teamswitch_interval', 0) self.max_players = config.get('max_players', 20) self.melee_damage = config.get('melee_damage', 100) self.max_connections_per_ip = config.get('max_connections_per_ip', 0) self.passwords = config.get('passwords', {}) self.server_prefix = encode(config.get('server_prefix', '[*]')) self.time_announcements = config.get('time_announcements', [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2400, 3000 ]) self.balanced_teams = config.get('balanced_teams', None) self.login_retries = config.get('login_retries', 1) # voting configuration self.default_ban_time = config.get('default_ban_duration', 24 * 60) self.speedhack_detect = config.get('speedhack_detect', True) if config.get('user_blocks_only', False): self.user_blocks = set() self.set_god_build = config.get('set_god_build', False) self.debug_log = config.get('debug_log', False) if self.debug_log: pyspades.debug.open_debug_log() ssh = config.get('ssh', {}) if ssh.get('enabled', False): from ssh import RemoteConsole self.remote_console = RemoteConsole(self, ssh) irc = config.get('irc', {}) if irc.get('enabled', False): from irc import IRCRelay self.irc_relay = IRCRelay(self, irc) status = config.get('status_server', {}) if status.get('enabled', False): from statusserver import StatusServerFactory self.status_server = StatusServerFactory(self, status) publish = config.get('ban_publish', {}) if publish.get('enabled', False): from banpublish import PublishServer self.ban_publish = PublishServer(self, publish) ban_subscribe = config.get('ban_subscribe', {}) if ban_subscribe.get('enabled', True): import bansubscribe self.ban_manager = bansubscribe.BanManager(self, ban_subscribe) logfile = config.get('logfile', None) if logfile is not None and logfile.strip(): if config.get('rotate_daily', False): create_filename_path(logfile) logging_file = DailyLogFile(logfile, '.') else: logging_file = open_create(logfile, 'a') log.addObserver(log.FileLogObserver(logging_file).emit) log.msg('pyspades server started on %s' % time.strftime('%c')) log.startLogging(sys.stdout) # force twisted logging self.start_time = reactor.seconds() self.end_calls = [] self.console = create_console(self) for password in self.passwords.get('admin', []): if password == 'replaceme': print 'REMEMBER TO CHANGE THE DEFAULT ADMINISTRATOR PASSWORD!' elif not password: self.everyone_is_admin = True for user_type, func_names in config.get('rights', {}).iteritems(): for func_name in func_names: commands.add_rights(func_name, user_type) port = self.port = config.get('port', 32887) ServerProtocol.__init__(self, port, interface) self.host.receiveCallback = self.receive_callback ret = self.set_map_rotation(config['maps']) if not ret: print 'Invalid map in map rotation (%s), exiting.' % ret.map raise SystemExit self.update_format() self.tip_frequency = config.get('tip_frequency', 0) if self.tips is not None and self.tip_frequency > 0: reactor.callLater(self.tip_frequency * 60, self.send_tip) self.master = config.get('master', True) self.set_master() get_external_ip(config.get('network_interface', '')).addCallback(self.got_external_ip)
class FeatureProtocol(ServerProtocol): connection_class = FeatureConnection bans = None ban_publish = None ban_manager = None everyone_is_admin = False player_memory = None irc_relay = None balanced_teams = None timestamps = None building = True killing = True global_chat = True remote_console = None debug_log = None advance_call = None master_reconnect_call = None master = False ip = None identifier = None planned_map = None map_info = None spawns = None user_blocks = None god_blocks = None last_time = None interface = None team_class = FeatureTeam game_mode = None # default to None so we can check time_announce_schedule = None server_version = SERVER_VERSION def __init__(self, interface, config): self.config = config if config.get('random_rotation', False): self.map_rotator_type = random_choice_cycle else: self.map_rotator_type = itertools.cycle self.default_time_limit = config.get('default_time_limit', 20.0) self.default_cap_limit = config.get('cap_limit', 10.0) self.advance_on_win = int(config.get('advance_on_win', False)) self.win_count = itertools.count(1) self.bans = NetworkDict() try: self.bans.read_list(json.load(open('bans.txt', 'rb'))) except IOError: pass self.hard_bans = set() # possible DDoS'ers are added here self.player_memory = deque(maxlen=100) self.config = config if len(self.name) > MAX_SERVER_NAME_SIZE: print '(server name too long; it will be truncated to "%s")' % ( self.name[:MAX_SERVER_NAME_SIZE]) self.respawn_time = config.get('respawn_time', 8) self.respawn_waves = config.get('respawn_waves', False) game_mode = config.get('game_mode', 'ctf') if game_mode == 'ctf': self.game_mode = CTF_MODE elif game_mode == 'tc': self.game_mode = TC_MODE elif self.game_mode is None: raise NotImplementedError('invalid game mode: %s' % game_mode) self.game_mode_name = game_mode team1 = config.get('team1', {}) team2 = config.get('team2', {}) self.team1_name = team1.get('name', 'Blue') self.team2_name = team2.get('name', 'Green') self.team1_color = tuple(team1.get('color', (0, 0, 196))) self.team2_color = tuple(team2.get('color', (0, 196, 0))) self.friendly_fire = config.get('friendly_fire', True) self.friendly_fire_time = config.get('grief_friendly_fire_time', 2.0) self.spade_teamkills_on_grief = config.get('spade_teamkills_on_grief', False) self.fall_damage = config.get('fall_damage', True) self.teamswitch_interval = config.get('teamswitch_interval', 0) self.max_players = config.get('max_players', 20) self.melee_damage = config.get('melee_damage', 100) self.max_connections_per_ip = config.get('max_connections_per_ip', 0) self.passwords = config.get('passwords', {}) self.server_prefix = encode(config.get('server_prefix', '[*]')) self.time_announcements = config.get('time_announcements', [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2400, 3000 ]) self.balanced_teams = config.get('balanced_teams', None) self.login_retries = config.get('login_retries', 1) # voting configuration self.default_ban_time = config.get('default_ban_duration', 24 * 60) self.speedhack_detect = config.get('speedhack_detect', True) if config.get('user_blocks_only', False): self.user_blocks = set() self.set_god_build = config.get('set_god_build', False) self.debug_log = config.get('debug_log', False) if self.debug_log: pyspades.debug.open_debug_log() ssh = config.get('ssh', {}) if ssh.get('enabled', False): from ssh import RemoteConsole self.remote_console = RemoteConsole(self, ssh) irc = config.get('irc', {}) if irc.get('enabled', False): from irc import IRCRelay self.irc_relay = IRCRelay(self, irc) status = config.get('status_server', {}) if status.get('enabled', False): from statusserver import StatusServerFactory self.status_server = StatusServerFactory(self, status) publish = config.get('ban_publish', {}) if publish.get('enabled', False): from banpublish import PublishServer self.ban_publish = PublishServer(self, publish) ban_subscribe = config.get('ban_subscribe', {}) if ban_subscribe.get('enabled', True): import bansubscribe self.ban_manager = bansubscribe.BanManager(self, ban_subscribe) logfile = config.get('logfile', None) if logfile is not None and logfile.strip(): if config.get('rotate_daily', False): create_filename_path(logfile) logging_file = DailyLogFile(logfile, '.') else: logging_file = open_create(logfile, 'a') log.addObserver(log.FileLogObserver(logging_file).emit) log.msg('pyspades server started on %s' % time.strftime('%c')) log.startLogging(sys.stdout) # force twisted logging self.start_time = reactor.seconds() self.end_calls = [] self.console = create_console(self) for password in self.passwords.get('admin', []): if password == 'replaceme': print 'REMEMBER TO CHANGE THE DEFAULT ADMINISTRATOR PASSWORD!' elif not password: self.everyone_is_admin = True for user_type, func_names in config.get('rights', {}).iteritems(): for func_name in func_names: commands.add_rights(func_name, user_type) port = self.port = config.get('port', 32887) ServerProtocol.__init__(self, port, interface) self.host.receiveCallback = self.receive_callback ret = self.set_map_rotation(config['maps']) if not ret: print 'Invalid map in map rotation (%s), exiting.' % ret.map raise SystemExit self.update_format() self.tip_frequency = config.get('tip_frequency', 0) if self.tips is not None and self.tip_frequency > 0: reactor.callLater(self.tip_frequency * 60, self.send_tip) self.master = config.get('master', True) self.set_master() get_external_ip(config.get('network_interface', '')).addCallback(self.got_external_ip) def got_external_ip(self, ip): self.ip = ip self.identifier = make_server_identifier(ip, self.port) print 'Server identifier is %s' % self.identifier def set_time_limit(self, time_limit=None, additive=False): advance_call = self.advance_call add_time = 0.0 if advance_call is not None: add_time = ((advance_call.getTime() - reactor.seconds()) / 60.0) advance_call.cancel() self.advance_call = None time_limit = time_limit or self.default_time_limit if time_limit == False: for call in self.end_calls[:]: call.set(None) return if additive: time_limit = min(time_limit + add_time, self.default_time_limit) seconds = time_limit * 60.0 self.advance_call = reactor.callLater(seconds, self._time_up) for call in self.end_calls[:]: call.set(seconds) if self.time_announce_schedule is not None: self.time_announce_schedule.reset() self.time_announce_schedule = Scheduler(self) for seconds in self.time_announcements: self.time_announce_schedule.call_end(seconds, self._next_time_announce) return time_limit def _next_time_announce(self): remaining = self.advance_call.getTime() - reactor.seconds() if remaining < 60.001: if remaining < 10.001: self.send_chat('%s...' % int(round(remaining))) else: self.send_chat('%s seconds remaining.' % int(round(remaining))) else: self.send_chat('%s minutes remaining.' % int(round(remaining / 60))) def _time_up(self): self.advance_call = None self.advance_rotation('Time up!') def advance_rotation(self, message=None): self.set_time_limit(False) if self.planned_map is None: self.planned_map = self.map_rotator.next() map = self.planned_map self.planned_map = None self.on_advance(map) if message is None: self.set_map_name(map) else: self.send_chat('%s Next map: %s.' % (message, map.full_name), irc=True) reactor.callLater(5, self.set_map_name, map) def get_mode_name(self): return self.game_mode_name def set_map_name(self, rot_info): try: map_info = self.get_map(rot_info) except MapNotFound, e: return e if self.map_info: self.on_map_leave() self.map_info = map_info self.max_score = self.map_info.cap_limit or self.default_cap_limit self.set_map(self.map_info.data) self.set_time_limit(self.map_info.time_limit) self.update_format() return True
# Copyright (c) Mathias Kaerlev 2011-2012.