diff --git a/lib/constants.py b/lib/constants.py index 7a0c3e2..320a7e7 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -57,6 +57,12 @@ TEAM_MAP = { 3: 'SPECTATOR' } +# GAME_TYPE codes from MATCH_STARTED that are team-based; matching on the code +# is immune to customized factory titles (g_factoryTitle) +TEAM_GAME_TYPE_CODES = { + 'TDM', 'CA', 'CTF', '1FLAG', 'HARVESTER', 'FT', 'DOM', 'RR' +} + TEAM_COLORS = { 'RED': '^1(RED)^7', 'BLUE': '^4(BLUE)^7', diff --git a/lib/parser.py b/lib/parser.py index c34cd6a..b6a4e94 100644 --- a/lib/parser.py +++ b/lib/parser.py @@ -103,14 +103,15 @@ class EventParser: def _handle_player_connect(self, data): """Track a connecting player so the roster is complete; connects to the - server land as spectators until they join a team. No feed line: the + server land as spectators until they join a team — except reconnects of + already-tracked players, whose known team is kept. No feed line: the RCON connect broadcast already displays one.""" name = data.get('NAME') if not name: return None team = data.get('TEAM') if team is None: - team = 'SPECTATOR' + team = self.game_state.player_tracker.get_team(name) or 'SPECTATOR' self.game_state.player_tracker.update_team(name, team) self.game_state.player_tracker.add_player(name) return None @@ -343,6 +344,12 @@ class EventParser: # Get Match Time self._sync_match_time(data) + # GAME_TYPE/FACTORY_TITLE are the authoritative gametype for this match; + # the title alone can be customized and defeat exact team-mode matching + self.game_state.server_info.game_type_code = data.get('GAME_TYPE', '') + if data.get('FACTORY_TITLE'): + self.game_state.server_info.gametype = data['FACTORY_TITLE'] + # The PLAYERS array is the authoritative roster at match start: sync # teams (numeric codes via TEAM_MAP) and reset scores, clear dead # markers, and drop stale dedup signatures (TIME restarts at 0) diff --git a/lib/state.py b/lib/state.py index 4f3f7ac..77e9615 100644 --- a/lib/state.py +++ b/lib/state.py @@ -5,7 +5,7 @@ Tracks server info, players, and teams """ import logging -from .constants import TEAM_MODES, TEAM_MAP, MAX_RECENT_EVENTS +from .constants import TEAM_MODES, TEAM_MAP, MAX_RECENT_EVENTS, TEAM_GAME_TYPE_CODES from .formatter import strip_color_codes logger = logging.getLogger('state') @@ -18,6 +18,7 @@ class ServerInfo: self.hostname = 'Unknown' self.map = 'Unknown' self.gametype = 'Unknown' + self.game_type_code = '' self.timelimit = '0' self.fraglimit = '0' self.roundlimit = '0' @@ -36,8 +37,9 @@ class ServerInfo: self.match_time_last_sync = 0 # Timestamp of last TIME update from server def is_team_mode(self): - """Check if current gametype is a team mode""" - return self.gametype in TEAM_MODES + """Check if current gametype is a team mode, by GAME_TYPE code from + MATCH_STARTED or by factory title""" + return self.gametype in TEAM_MODES or self.game_type_code in TEAM_GAME_TYPE_CODES def reset_round_scores(self): """Reset round scores (for new matches)"""