Esempio n. 1
0
    def setUp(self):
        # create a Iourt41 parser
        self.parser_conf = XmlConfigParser()
        self.parser_conf.loadFromString("""<configuration><settings name="server"><set name="game_log"></set></settings></configuration>""")
        self.console = Iourt41Parser(self.parser_conf)

        self.console.write = Mock(name="write", side_effect=write)
        self.console.startup()

        # load the admin plugin
        self.adminPlugin = AdminPlugin(self.console, '@b3/conf/plugin_admin.ini')
        self.adminPlugin.onLoadConfig()
        self.adminPlugin.onStartup()

        # make sure the admin plugin obtained by other plugins is our admin plugin
        when(self.console).getPlugin('admin').thenReturn(self.adminPlugin)
Esempio n. 2
0
    def setUp(self):
        self.parser_conf = XmlConfigParser()
        self.parser_conf.loadFromString("""<configuration>
                <settings name="server">
                    <set name="game_log"/>
                </settings>
            </configuration>""")
        self.console = Iourt41Parser(self.parser_conf)
        self.console.PunkBuster = None # no Punkbuster support in that game

        self.output_mock = mock()
        # simulate game server actions
        def write(*args, **kwargs):
            pretty_args = map(repr, args) + ["%s=%s" % (k, v) for k, v in kwargs.iteritems()]
            log.info("write(%s)" % ', '.join(pretty_args))
            return self.output_mock.write(*args, **kwargs)
        self.console.write = write
Esempio n. 3
0
 def __new__(cls, *args, **kwargs):
     Iourt42Parser.patch_Clients()
     return Iourt41Parser.__new__(cls)
    def setUp(self):

        with logging_disabled():
            # create a Iourt41 parser
            self.parser_conf = XmlConfigParser()
            self.parser_conf.loadFromString(
                """<configuration><settings name="server"><set name="game_log"></set></settings></configuration>"""
            )
            self.console = Iourt41Parser(self.parser_conf)
            self.console.startup()

            # load the admin plugin
            if B3version(b3_version) >= B3version("1.10dev"):
                admin_plugin_conf_file = '@b3/conf/plugin_admin.ini'
            else:
                admin_plugin_conf_file = '@b3/conf/plugin_admin.xml'
            with logging_disabled():
                self.adminPlugin = AdminPlugin(self.console,
                                               admin_plugin_conf_file)
                self.adminPlugin.onLoadConfig()
                self.adminPlugin.onStartup()

            # make sure the admin plugin obtained by other plugins is our admin plugin
            when(self.console).getPlugin('admin').thenReturn(self.adminPlugin)

            # prepare a few players
            from b3.fake import FakeClient
            self.joe = FakeClient(self.console,
                                  name="Joe",
                                  exactName="Joe",
                                  guid="zaerezarezar",
                                  groupBits=1,
                                  team=TEAM_UNKNOWN,
                                  teamId=0,
                                  squad=0)
            self.simon = FakeClient(self.console,
                                    name="Simon",
                                    exactName="Simon",
                                    guid="qsdfdsqfdsqf",
                                    groupBits=0,
                                    team=TEAM_UNKNOWN,
                                    teamId=0,
                                    squad=0)
            self.reg = FakeClient(self.console,
                                  name="Reg",
                                  exactName="Reg",
                                  guid="qsdfdsqfdsqf33",
                                  groupBits=4,
                                  team=TEAM_UNKNOWN,
                                  teamId=0,
                                  squad=0)
            self.moderator = FakeClient(self.console,
                                        name="Moderator",
                                        exactName="Moderator",
                                        guid="sdf455ezr",
                                        groupBits=8,
                                        team=TEAM_UNKNOWN,
                                        teamId=0,
                                        squad=0)
            self.admin = FakeClient(self.console,
                                    name="Level-40-Admin",
                                    exactName="Level-40-Admin",
                                    guid="875sasda",
                                    groupBits=16,
                                    team=TEAM_UNKNOWN,
                                    teamId=0,
                                    squad=0)
            self.superadmin = FakeClient(self.console,
                                         name="God",
                                         exactName="God",
                                         guid="f4qfer654r",
                                         groupBits=128,
                                         team=TEAM_UNKNOWN,
                                         teamId=0,
                                         squad=0)
Esempio n. 5
0
 def __new__(cls, *args, **kwargs):
     Iourt42Parser.patch_Clients()
     return Iourt41Parser.__new__(cls)
Esempio n. 6
0
class Iourt42Parser(Iourt41Parser):
    gameName = 'iourt42'

    _commands = {
        'broadcast': '%(prefix)s^7 %(message)s',
        'message': 'tell %(cid)s %(prefix)s ^3[pm]^7 %(message)s',
        'deadsay': 'tell %(cid)s %(prefix)s [DEAD]^7 %(message)s',
        'say': 'say %(prefix)s %(message)s',
        'saybig': 'bigtext "%(prefix)s %(message)s"',
        'set': 'set %(name)s "%(value)s"',
        'kick': 'kick %(cid)s "%(reason)s"',
        'ban': 'addip %(cid)s',
        'tempban': 'kick %(cid)s "%(reason)s"',
        'banByIp': 'addip %(ip)s',
        'unbanByIp': 'removeip %(ip)s',
        'auth-permban': 'auth-ban %(cid)s 0 0 0',
        'auth-tempban': 'auth-ban %(cid)s %(days)s %(hours)s %(minutes)s',
        'slap': 'slap %(cid)s',
        'nuke': 'nuke %(cid)s',
        'mute': 'mute %(cid)s %(seconds)s',
        'kill': 'smite %(cid)s',
    }

    _eventMap = {
        #'warmup' : b3.events.EVT_GAME_HOTPOTATO,
        #'shutdowngame' : b3.events.EVT_GAME_ROUND_END
    }

    # remove the time off of the line
    _lineClear = re.compile(r'^(?:[0-9:]+\s?)?')
    #0:00 ClientUserinfo: 0:

    _lineFormats = (
        #Radio: 0 - 7 - 2 - "New Alley" - "I'm going for the flag"
        re.compile(
            r'''^(?P<action>Radio): (?P<data>(?P<cid>[0-9]+) - (?P<msg_group>[0-9]+) - (?P<msg_id>[0-9]+) - "(?P<location>.+)" - "(?P<text>.*)")$'''
        ),

        #Radio: 0 - 7 - 2 - "New Alley" - "I'm going for the flag"
        re.compile(
            r'''^(?P<action>Radio): (?P<data>(?P<cid>[0-9]+) - (?P<msg_group>[0-9]+) - (?P<msg_id>[0-9]+) - "(?P<location>.+)" - "(?P<text>.*)")$'''
        ),

        #Callvote: 1 - "map dressingroom"
        re.compile(
            r'''^(?P<action>Callvote): (?P<data>(?P<cid>[0-9]+) - "(?P<vote_string>.*)")$'''
        ),

        #Vote: 0 - 2
        re.compile(
            r'''^(?P<action>Vote): (?P<data>(?P<cid>[0-9]+) - (?P<value>.*))$'''
        ),

        #13:34 ClientJumpTimerStarted: 0 - way: 2 (Easy Way)
        re.compile(
            r'^(?P<action>ClientJumpTimerStarted):\s(?P<cid>\d+)\s-\s(?P<data>way: (?P<way_id>\d+)(?:\s\((?P<way_label>.+)\))?)$',
            re.IGNORECASE),
        #13:34 ClientJumpTimerStopped: 0 - 5 seconds - way: 1 (Hard Way)
        re.compile(
            r'^(?P<action>ClientJumpTimerStopped):\s(?P<cid>\d+)\s-\s(?P<data>(?P<duration>.+)\s-\sway: (?P<way_id>\d+)(?:\s\((?P<way_label>.+)\))?)$',
            re.IGNORECASE),

        #13:34 ClientSavePosition: 0 - 335.384887 - 67.469154 - -23.875000 - "unknown"
        #13:34 ClientLoadPosition: 0 - 335.384887 - 67.469154 - -23.875000 - "unknown"
        re.compile(
            r'^(?P<action>Client(Save|Load)Position):\s(?P<cid>\d+)\s-\s(?P<data>(?P<x>-?\d+(?:\.\d+)?)\s-\s(?P<y>-?\d+(?:\.\d+)?)\s-\s(?P<z>-?\d+(?:\.\d+)?)\s-\s"(?P<name>.*)")$',
            re.IGNORECASE),

        #Generated with ioUrbanTerror v4.1:
        #Hit: 12 7 1 19: BSTHanzo[FR] hit ercan in the Helmet
        #Hit: 13 10 0 8: Grover hit jacobdk92 in the Head
        re.compile(
            r'^(?P<action>Hit):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<hitloc>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>.*))$',
            re.IGNORECASE),
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<hitloc>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>(?P<aname>[^:])\shit\s(?P<name>[^:])\sin\sthe(?P<locname>.*)))$', re.IGNORECASE),

        #6:37 Kill: 0 1 16: XLR8or killed =lvl1=Cheetah by UT_MOD_SPAS
        #2:56 Kill: 14 4 21: Qst killed Leftovercrack by UT_MOD_PSG1
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<acid>[0-9]+)\s(?P<cid>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>.*))$',
            re.IGNORECASE),
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<acid>[0-9]+)\s(?P<cid>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>(?P<aname>[^:])\skilled\s(?P<name>[^:])\sby\s(?P<modname>.*)))$', re.IGNORECASE),

        #Processing chats and tell events...
        #5:39 saytell: 15 16 repelSteeltje: nno
        #5:39 saytell: 15 15 repelSteeltje: nno
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<name>.+?):\s+(?P<text>.*))$',
            re.IGNORECASE),

        # We're not using tell in this form so this one is disabled
        #5:39 tell: repelSteeltje to B!K!n1: nno
        #re.compile(r'^(?P<action>[a-z]+):\s+(?P<data>(?P<name>[^:]+)\s+to\s+(?P<aname>[^:]+):\s+(?P<text>.*))$', re.IGNORECASE),

        #3:53 say: 8 denzel: lol
        #15:37 say: 9 .:MS-T:.BstPL: this name is quite a challenge
        #2:28 sayteam: 12 New_UrT_Player_v4.1: woekele
        #16:33 Flag: 2 0: team_CTF_redflag
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<name>[^ ]+):\s+(?P<text>.*))$', re.IGNORECASE),
        # SGT: fix issue with OnSay when something like this come and the match could'nt find the name group
        # say: 7 -crespino-:
        # say: 6 ^5Marcel ^2[^6CZARMY^2]: !help
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<name>.+?):\s*(?P<text>.*))$',
            re.IGNORECASE),

        #15:42 Flag Return: RED
        #15:42 Flag Return: BLUE
        re.compile(r'^(?P<action>Flag Return):\s(?P<data>(?P<color>.+))$',
                   re.IGNORECASE),

        #Bombmode actions:
        #3:06 Bombholder is 2
        re.compile(r'^(?P<action>Bombholder)(?P<data>\sis\s(?P<cid>[0-9]))$',
                   re.IGNORECASE),
        #was planted, was defused, was tossed, has been collected (doh, how gramatically correct!)
        #2:13 Bomb was tossed by 2
        #2:32 Bomb was planted by 2
        #3:01 Bomb was defused by 3!
        #2:17 Bomb has been collected by 2
        re.compile(
            r'^(?P<action>Bomb)\s(?P<data>(was|has been)\s(?P<subaction>[a-z]+)\sby\s(?P<cid>[0-9]+).*)$',
            re.IGNORECASE),

        #Falling thru? Item stuff and so forth
        re.compile(r'^(?P<action>[a-z]+):\s(?P<data>.*)$', re.IGNORECASE),
        #Shutdowngame and Warmup... the one word lines
        re.compile(r'^(?P<action>[a-z]+):$', re.IGNORECASE))

    # map: ut4_casa
    # num score ping name            lastmsg address               qport rate
    # --- ----- ---- --------------- ------- --------------------- ----- -----
    #   2     0   19 ^1XLR^78^8^9or^7        0 145.99.135.227:27960  41893  8000  # player with a live ping
    #   4     0 CNCT Dz!k^7                450 83.175.191.27:64459   50308 20000  # connecting player (or inbetween rounds)
    #   9     0 ZMBI ^7                   1900 81.178.80.68:27960    10801  8000  # zombies (need to be disconnected!)
    _regPlayer = re.compile(
        r'^(?P<slot>[0-9]+)\s+(?P<score>[0-9-]+)\s+(?P<ping>[0-9]+|CNCT|ZMBI)\s+(?P<name>.*?)\s+(?P<last>[0-9]+)\s+(?P<ip>[0-9.]+):(?P<port>[0-9-]+)\s+(?P<qport>[0-9]+)\s+(?P<rate>[0-9]+)$',
        re.I)
    _reColor = re.compile(r'(\^.)|[\x00-\x20]|[\x7E-\xff]')

    # Map: ut4_algiers
    # Players: 8
    # Scores: R:97 B:98
    # 0:  FREE k:0 d:0 ping:0
    # 4: yene RED k:16 d:8 ping:50 92.104.110.192:63496
    _reTeamScores = re.compile(
        r'^Scores:\s+R:(?P<RedScore>.+)\s+B:(?P<BlueScore>.+)$', re.I)
    _rePlayerScore = re.compile(
        r'^(?P<slot>[0-9]+): (?P<name>.*) (?P<team>RED|BLUE|SPECTATOR|FREE) k:(?P<kill>[0-9]+) d:(?P<death>[0-9]+) ping:(?P<ping>[0-9]+|CNCT|ZMBI)( (?P<ip>[0-9.]+):(?P<port>[0-9-]+))?$',
        re.I
    )  # NOTE: this won't work properly if the server has private slots. see http://forums.urbanterror.net/index.php/topic,9356.0.html

    # /rcon auth-whois replies patterns
    _re_authwhois = re.compile(
        r"""^auth: id: (?P<cid>\d+) - name: \^7(?P<name>.+?) - login: (?P<login>.*?) - notoriety: (?P<notoriety>.+?) - level: (?P<level>-?\d+?)(?:\s+- (?P<extra>.*))?$""",
        re.MULTILINE)

    _permban_with_frozensand = False
    _tempban_with_frozensand = False

    ## kill modes
    MOD_WATER = '1'
    MOD_LAVA = '3'
    MOD_TELEFRAG = '5'
    MOD_FALLING = '6'
    MOD_SUICIDE = '7'
    MOD_TRIGGER_HURT = '9'
    MOD_CHANGE_TEAM = '10'
    UT_MOD_KNIFE = '12'
    UT_MOD_KNIFE_THROWN = '13'
    UT_MOD_BERETTA = '14'
    UT_MOD_DEAGLE = '15'
    UT_MOD_SPAS = '******'
    UT_MOD_UMP45 = '17'
    UT_MOD_MP5K = '18'
    UT_MOD_LR300 = '19'
    UT_MOD_G36 = '20'
    UT_MOD_PSG1 = '21'
    UT_MOD_HK69 = '22'
    UT_MOD_BLED = '23'
    UT_MOD_KICKED = '24'  # not exising in 4.2 ?
    UT_MOD_HEGRENADE = '25'
    UT_MOD_SR8 = '27'
    UT_MOD_AK103 = '29'
    UT_MOD_SPLODED = '30'
    UT_MOD_SLAPPED = '31'
    UT_MOD_SMITED = '32'
    UT_MOD_BOMBED = '33'
    UT_MOD_NUKED = '34'
    UT_MOD_NEGEV = '35'
    UT_MOD_HK69_HIT = '36'
    UT_MOD_M4 = '37'
    UT_MOD_GLOCK = '38'
    UT_MOD_FLAG = '39'
    UT_MOD_GOOMBA = '40'

    ## weapons id on Hit: lines are different than the one
    ## on the Kill: lines. Here the translation table
    hitweapon2killweapon = {
        1: UT_MOD_KNIFE,
        2: UT_MOD_BERETTA,
        3: UT_MOD_DEAGLE,
        4: UT_MOD_SPAS,
        5: UT_MOD_MP5K,
        6: UT_MOD_UMP45,
        8: UT_MOD_LR300,
        9: UT_MOD_G36,
        10: UT_MOD_PSG1,
        14: UT_MOD_SR8,
        15: UT_MOD_AK103,
        17: UT_MOD_NEGEV,
        19: UT_MOD_M4,
        20: UT_MOD_GLOCK,
        23: UT_MOD_KNIFE_THROWN,
    }

    def __new__(cls, *args, **kwargs):
        Iourt42Parser.patch_Clients()
        return Iourt41Parser.__new__(cls)

    def startup(self):
        try:
            gamename = self.getCvar('gamename').getString()
            if gamename != 'q3urt42':
                self.error(
                    "the iourt42 B3 parser cannot be used with a game server other than Urban Terror 4.2"
                )
                raise SystemExit(220)
        except Exception, e:
            self.warning("Could not query server for gamename.", exc_info=e)

        Iourt41Parser.startup(self)

        # add UrT 4.2 specific events
        self.EVT_CLIENT_RADIO = self.Events.createEvent(
            'EVT_CLIENT_RADIO', 'Event client radio')
        self.EVT_GAME_FLAG_HOTPOTATO = self.Events.createEvent(
            'EVT_GAME_FLAG_HOTPOTATO', 'Event game hotpotato')
        self._eventMap['hotpotato'] = self.EVT_GAME_FLAG_HOTPOTATO
        self.EVT_CLIENT_CALLVOTE = self.Events.createEvent(
            'EVT_CLIENT_CALLVOTE', 'Event client call vote')
        self.EVT_CLIENT_VOTE = self.Events.createEvent('EVT_CLIENT_VOTE',
                                                       'Event client vote')
        self.EVT_CLIENT_JUMP_TIMER_START = self.Events.createEvent(
            'EVT_CLIENT_JUMP_TIMER_START', 'Event client jump timer started')
        self.EVT_CLIENT_JUMP_TIMER_STOP = self.Events.createEvent(
            'EVT_CLIENT_JUMP_TIMER_STOP', 'Event client jump timer stopped')
        self.EVT_CLIENT_POS_SAVE = self.Events.createEvent(
            'EVT_CLIENT_POS_SAVE', 'Event client position saved')
        self.EVT_CLIENT_POS_LOAD = self.Events.createEvent(
            'EVT_CLIENT_POS_LOAD', 'Event client position loaded')
        self.EVT_CLIENT_SURVIVOR_WINNER = self.Events.createEvent(
            'EVT_CLIENT_SURVIVOR_WINNER', 'Event client survivor winner')

        self.load_conf_frozensand_ban_settings()
Esempio n. 7
0
class Iourt42Parser(Iourt41Parser):
    gameName = 'iourt42'

    _commands = {
        'broadcast': '%(prefix)s^7 %(message)s',
        'message': 'tell %(cid)s %(prefix)s ^3[pm]^7 %(message)s',
        'deadsay': 'tell %(cid)s %(prefix)s [DEAD]^7 %(message)s',
        'say': 'say %(prefix)s %(message)s',
        'saybig': 'bigtext "%(prefix)s %(message)s"',
        'set': 'set %(name)s "%(value)s"',
        'kick': 'kick %(cid)s "%(reason)s"',
        'ban': 'addip %(cid)s',
        'tempban': 'kick %(cid)s "%(reason)s"',
        'banByIp': 'addip %(ip)s',
        'unbanByIp': 'removeip %(ip)s',
        'slap': 'slap %(cid)s',
        'nuke': 'nuke %(cid)s',
        'mute': 'mute %(cid)s %(seconds)s',
        'kill': 'smite %(cid)s',
    }

    _eventMap = {
        #'warmup' : b3.events.EVT_GAME_HOTPOTATO,
        #'shutdowngame' : b3.events.EVT_GAME_ROUND_END
    }

    # remove the time off of the line
    _lineClear = re.compile(r'^(?:[0-9:]+\s?)?')
    #0:00 ClientUserinfo: 0:

    _lineFormats = (
        #Radio: 0 - 7 - 2 - "New Alley" - "I'm going for the flag"
        re.compile(
            r'''^(?P<action>Radio): (?P<data>(?P<cid>[0-9]+) - (?P<msg_group>[0-9]+) - (?P<msg_id>[0-9]+) - "(?P<location>.+)" - "(?P<text>.*)")$'''
        ),

        #Radio: 0 - 7 - 2 - "New Alley" - "I'm going for the flag"
        re.compile(
            r'''^(?P<action>Radio): (?P<data>(?P<cid>[0-9]+) - (?P<msg_group>[0-9]+) - (?P<msg_id>[0-9]+) - "(?P<location>.+)" - "(?P<text>.*)")$'''
        ),

        #Callvote: 1 - "map dressingroom"
        re.compile(
            r'''^(?P<action>Callvote): (?P<data>(?P<cid>[0-9]+) - "(?P<vote_string>.*)")$'''
        ),

        #Vote: 0 - 2
        re.compile(
            r'''^(?P<action>Vote): (?P<data>(?P<cid>[0-9]+) - (?P<value>.*))$'''
        ),

        #Generated with ioUrbanTerror v4.1:
        #Hit: 12 7 1 19: BSTHanzo[FR] hit ercan in the Helmet
        #Hit: 13 10 0 8: Grover hit jacobdk92 in the Head
        re.compile(
            r'^(?P<action>Hit):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<hitloc>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>.*))$',
            re.IGNORECASE),
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<hitloc>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>(?P<aname>[^:])\shit\s(?P<name>[^:])\sin\sthe(?P<locname>.*)))$', re.IGNORECASE),

        #6:37 Kill: 0 1 16: XLR8or killed =lvl1=Cheetah by UT_MOD_SPAS
        #2:56 Kill: 14 4 21: Qst killed Leftovercrack by UT_MOD_PSG1
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<acid>[0-9]+)\s(?P<cid>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>.*))$',
            re.IGNORECASE),
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<acid>[0-9]+)\s(?P<cid>[0-9]+)\s(?P<aweap>[0-9]+):\s+(?P<text>(?P<aname>[^:])\skilled\s(?P<name>[^:])\sby\s(?P<modname>.*)))$', re.IGNORECASE),

        #Processing chats and tell events...
        #5:39 saytell: 15 16 repelSteeltje: nno
        #5:39 saytell: 15 15 repelSteeltje: nno
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<acid>[0-9]+)\s(?P<name>[^ ]+):\s+(?P<text>.*))$',
            re.IGNORECASE),

        # We're not using tell in this form so this one is disabled
        #5:39 tell: repelSteeltje to B!K!n1: nno
        #re.compile(r'^(?P<action>[a-z]+):\s+(?P<data>(?P<name>[^:]+)\s+to\s+(?P<aname>[^:]+):\s+(?P<text>.*))$', re.IGNORECASE),

        #3:53 say: 8 denzel: lol
        #15:37 say: 9 .:MS-T:.BstPL: this name is quite a challenge
        #2:28 sayteam: 12 New_UrT_Player_v4.1: woekele
        #16:33 Flag: 2 0: team_CTF_redflag
        #re.compile(r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<name>[^ ]+):\s+(?P<text>.*))$', re.IGNORECASE),
        # SGT: fix issue with OnSay when something like this come and the match could'nt find the name group
        # say: 7 -crespino-:
        re.compile(
            r'^(?P<action>[a-z]+):\s(?P<data>(?P<cid>[0-9]+)\s(?P<name>[^ ]+):\s*(?P<text>.*))$',
            re.IGNORECASE),

        #15:42 Flag Return: RED
        #15:42 Flag Return: BLUE
        re.compile(r'^(?P<action>Flag Return):\s(?P<data>(?P<color>.+))$',
                   re.IGNORECASE),

        #Bombmode actions:
        #3:06 Bombholder is 2
        re.compile(r'^(?P<action>Bombholder)(?P<data>\sis\s(?P<cid>[0-9]))$',
                   re.IGNORECASE),
        #was planted, was defused, was tossed, has been collected (doh, how gramatically correct!)
        #2:13 Bomb was tossed by 2
        #2:32 Bomb was planted by 2
        #3:01 Bomb was defused by 3!
        #2:17 Bomb has been collected by 2
        re.compile(
            r'^(?P<action>Bomb)\s(?P<data>(was|has been)\s(?P<subaction>[a-z]+)\sby\s(?P<cid>[0-9]+).*)$',
            re.IGNORECASE),

        #Falling thru? Item stuff and so forth
        re.compile(r'^(?P<action>[a-z]+):\s(?P<data>.*)$', re.IGNORECASE),
        #Shutdowngame and Warmup... the one word lines
        re.compile(r'^(?P<action>[a-z]+):$', re.IGNORECASE))

    # map: ut4_casa
    # num score ping name            lastmsg address               qport rate
    # --- ----- ---- --------------- ------- --------------------- ----- -----
    #   2     0   19 ^1XLR^78^8^9or^7        0 145.99.135.227:27960  41893  8000  # player with a live ping
    #   4     0 CNCT Dz!k^7                450 83.175.191.27:64459   50308 20000  # connecting player (or inbetween rounds)
    #   9     0 ZMBI ^7                   1900 81.178.80.68:27960    10801  8000  # zombies (need to be disconnected!)
    _regPlayer = re.compile(
        r'^(?P<slot>[0-9]+)\s+(?P<score>[0-9-]+)\s+(?P<ping>[0-9]+|CNCT|ZMBI)\s+(?P<name>.*?)\s+(?P<last>[0-9]+)\s+(?P<ip>[0-9.]+):(?P<port>[0-9-]+)\s+(?P<qport>[0-9]+)\s+(?P<rate>[0-9]+)$',
        re.I)
    _reColor = re.compile(r'(\^.)|[\x00-\x20]|[\x7E-\xff]')

    # Map: ut4_algiers
    # Players: 8
    # Scores: R:97 B:98
    # 0:  FREE k:0 d:0 ping:0
    # 4: yene RED k:16 d:8 ping:50 92.104.110.192:63496
    _reTeamScores = re.compile(
        r'^Scores:\s+R:(?P<RedScore>.+)\s+B:(?P<BlueScore>.+)$', re.I)
    _rePlayerScore = re.compile(
        r'^(?P<slot>[0-9]+): (?P<name>.*) (?P<team>RED|BLUE|SPECTATOR|FREE) k:(?P<kill>[0-9]+) d:(?P<death>[0-9]+) ping:(?P<ping>[0-9]+|CNCT|ZMBI)( (?P<ip>[0-9.]+):(?P<port>[0-9-]+))?$',
        re.I
    )  # NOTE: this won't work properly if the server has private slots. see http://forums.urbanterror.net/index.php/topic,9356.0.html

    # /rcon auth-whois replies patterns
    _re_authwhois = re.compile(
        r"""^auth: id: (?P<cid>\d+) - name: \^7(?P<name>.+?) - login: (?P<login>.*?) - notoriety: (?P<notoriety>.+?) - level: (?P<level>-?\d+?)(?:\s+- (?P<extra>.*))?$""",
        re.MULTILINE)

    def __new__(cls, *args, **kwargs):
        Iourt42Parser.patch_Clients()
        return Iourt41Parser.__new__(cls)

    def startup(self):
        try:
            gamename = self.getCvar('gamename').getString()
            if gamename != 'q3urt42':
                self.error(
                    "the iourt42 B3 parser cannot be used with a game server other than Urban Terror 4.2"
                )
                raise SystemExit(220)
        except Exception, e:
            self.warning("Could not query server for gamename.", exc_info=e)

        Iourt41Parser.startup(self)

        # add UrT 4.2 specific events
        self.EVT_CLIENT_RADIO = self.Events.createEvent(
            'EVT_CLIENT_RADIO', 'Event client radio')
        self.EVT_GAME_FLAG_HOTPOTATO = self.Events.createEvent(
            'EVT_GAME_FLAG_HOTPOTATO', 'Event game hotpotato')
        self._eventMap['hotpotato'] = self.EVT_GAME_FLAG_HOTPOTATO
        self.EVT_CLIENT_CALLVOTE = self.Events.createEvent(
            'EVT_CLIENT_CALLVOTE', 'Event client call vote')
        self.EVT_CLIENT_VOTE = self.Events.createEvent('EVT_CLIENT_VOTE',
                                                       'Event client vote')
    def setUp(self):
        with logging_disabled():
            # create a Iourt41 parser
            self.parser_conf = XmlConfigParser()
            self.parser_conf.loadFromString(
                """<configuration><settings name="server"><set name="game_log"></set></settings></configuration>"""
            )
            self.console = Iourt41Parser(self.parser_conf)
            self.console.startup()

            # load the admin plugin
            if B3version(b3_version) >= B3version("1.10dev"):
                admin_plugin_conf_file = '@b3/conf/plugin_admin.ini'
            else:
                admin_plugin_conf_file = '@b3/conf/plugin_admin.xml'
            with logging_disabled():
                self.adminPlugin = AdminPlugin(self.console,
                                               admin_plugin_conf_file)
                self.adminPlugin.onStartup()

            # make sure the admin plugin obtained by other plugins is our admin plugin
            when(self.console).getPlugin('admin').thenReturn(self.adminPlugin)

            # when starting the PoweradminurtPlugin expects the game server to provide a few cvar values
            when(self.console).getCvar('timelimit').thenReturn(
                Cvar('timelimit', value=20))
            when(self.console).getCvar('g_maxGameClients').thenReturn(
                Cvar('g_maxGameClients', value=16))
            when(self.console).getCvar('sv_maxclients').thenReturn(
                Cvar('sv_maxclients', value=16))
            when(self.console).getCvar('sv_privateClients').thenReturn(
                Cvar('sv_privateClients', value=0))
            when(self.console).getCvar('g_allowvote').thenReturn(
                Cvar('g_allowvote', value=0))

            # prepare a few players
            self.joe = FakeClient(self.console,
                                  name="Joe",
                                  exactName="Joe",
                                  guid="zaerezarezar",
                                  groupBits=1,
                                  team=TEAM_UNKNOWN,
                                  teamId=0,
                                  squad=0)
            self.simon = FakeClient(self.console,
                                    name="Simon",
                                    exactName="Simon",
                                    guid="qsdfdsqfdsqf",
                                    groupBits=0,
                                    team=TEAM_UNKNOWN,
                                    teamId=0,
                                    squad=0)
            self.reg = FakeClient(self.console,
                                  name="Reg",
                                  exactName="Reg",
                                  guid="qsdfdsqfdsqf33",
                                  groupBits=4,
                                  team=TEAM_UNKNOWN,
                                  teamId=0,
                                  squad=0)
            self.moderator = FakeClient(self.console,
                                        name="Moderator",
                                        exactName="Moderator",
                                        guid="sdf455ezr",
                                        groupBits=8,
                                        team=TEAM_UNKNOWN,
                                        teamId=0,
                                        squad=0)
            self.admin = FakeClient(self.console,
                                    name="Level-40-Admin",
                                    exactName="Level-40-Admin",
                                    guid="875sasda",
                                    groupBits=16,
                                    team=TEAM_UNKNOWN,
                                    teamId=0,
                                    squad=0)
            self.superadmin = FakeClient(self.console,
                                         name="God",
                                         exactName="God",
                                         guid="f4qfer654r",
                                         groupBits=128,
                                         team=TEAM_UNKNOWN,
                                         teamId=0,
                                         squad=0)