Пример #1
0
    def cancel(self):
        # Check if there's a current vote in the first place.
        cs = minqlbot.get_configstring(9, cached=False)
        if not cs:
            return

        res = re_vote.match(cs)
        vote = res.group("vote")
        args = res.group("args")
        votes = (int(minqlbot.get_configstring(10)), int(minqlbot.get_configstring(11)))
        # Return None if the vote's cancelled (like if the round starts before vote's over).
        super().trigger(votes, vote, args, None)
Пример #2
0
    def cancel(self):
        # Check if there's a current vote in the first place.
        cs = minqlbot.get_configstring(9, cached=False)
        if not cs:
            return

        res = re_vote.match(cs)
        vote = res.group("vote")
        args = res.group("args")
        votes = (int(minqlbot.get_configstring(10)),
                 int(minqlbot.get_configstring(11)))
        # Return None if the vote's cancelled (like if the round starts before vote's over).
        super().trigger(votes, vote, args, None)
Пример #3
0
    def trigger(self, passed):
        cs = minqlbot.get_configstring(9)
        if not cs:
            debug("vote_ended weird behavior.")
            return

        split_cs = cs.split()
        if len(split_cs) > 1:
            args = " ".join(split_cs[1:])
        else:
            args = None

        votes = (int(minqlbot.get_configstring(10)), int(minqlbot.get_configstring(11)))
        super().trigger(split_cs[0], args, votes, passed)
Пример #4
0
    def trigger(self, passed):
        cs = minqlbot.get_configstring(9)
        if not cs:
            debug("vote_ended weird behavior.")
            return

        split_cs = cs.split()
        if len(split_cs) > 1:
            args = " ".join(split_cs[1:])
        else:
            args = None

        votes = (int(minqlbot.get_configstring(10)),
                 int(minqlbot.get_configstring(11)))
        super().trigger(split_cs[0], args, votes, passed)
Пример #5
0
 def __init__(self, cached=True):
     self.cached = cached
     self.__valid = True
     cs = minqlbot.get_configstring(0, self.cached)
     if not cs:
         self.__valid = False
         raise NonexistentPlayerError("Tried to initialize a Game instance with no active game.")
Пример #6
0
 def __player_configstrings(self):
     players = {}
     for i in range(24):
         cs = minqlbot.get_configstring(i + 529)
         if cs:
             players[i] = cs
     
     return players
Пример #7
0
    def __player_configstrings(cls):
        players = {}
        for i in range(24):
            cs = minqlbot.get_configstring(i + 529)
            if cs:
                players[i] = cs

        return players
Пример #8
0
 def __init__(self, cached=True):
     self.cached = cached
     self.__valid = True
     cs = minqlbot.get_configstring(0, self.cached)
     if not cs:
         self.__valid = False
         raise NonexistentPlayerError(
             "Tried to initialize a Game instance with no active game.")
Пример #9
0
    def __getitem__(self, key):
        cs = minqlbot.get_configstring(0, self.cached)
        if not cs:
            self.__valid = False
            raise NonexistentGameError("Invalid game. Did the bot disconnect?")

        cvars = minqlbot.parse_variables(cs)
        return cvars[key]
Пример #10
0
    def __getitem__(self, key):
        cs = minqlbot.get_configstring(0, self.cached)
        if not cs:
            self.__valid = False
            raise NonexistentGameError("Invalid game. Did the bot disconnect?")

        cvars = minqlbot.parse_variables(cs)
        return cvars[key]
Пример #11
0
def get_player(name):
    for i in range(24):
        cs = minqlbot.get_configstring(i + 529)
        if cs:
            cvars = parse_variables(cs)
            if name == cvars["n"]:
                return minqlbot.Player(i)

    return None
Пример #12
0
def get_player(name):
    for i in range(24):
        cs = minqlbot.get_configstring(i + 529)
        if cs:
            cvars = parse_variables(cs)
            if name == cvars["n"]:
                return minqlbot.Player(i)

    return None
Пример #13
0
 def map(self):
     return minqlbot.get_configstring(3, self.cached)
Пример #14
0
def parse(cmdstr):
    """Parses server commands or gamestates"""
    cmd = cmdstr.split(" ", 1)
    if cmd[0] == "chat":
        rm = re_chat.match(cmd[1])
        if rm:
            # I tested the client ID passed through this command several times, and sooner
            # or later, it starts sending incorrect data. This applies for chat, tchat and tell.
            #cid = int(rm.group(1))
            player = get_player(rm.group("name"))
            msg = rm.group("msg")
            channel = minqlbot.CHAT_CHANNEL  # Use static channel
            event_handlers["chat"].trigger(player, msg, channel)
            return
        else:  # Check if it's \tell
            rm = re_tell.match(cmd[1])
            if rm:
                #cid = int(rm.group(1))
                player = get_player(rm.group("name"))
                msg = rm.group("msg")
                channel = TellChannel(player)
                event_handlers["chat"].trigger(player, msg, channel)
                return
    elif cmd[0] == "tchat":  # Team chat.
        rm = re_tchat.match(cmd[1])
        if rm:
            #cid = int(rm.group(1))
            player = get_player(rm.group("name"))
            msg = rm.group("msg")
            channel = minqlbot.TEAM_CHAT_CHANNEL  # Use static channel
            event_handlers["chat"].trigger(player, msg, channel)
            return

    # big_configstring (bcs)
    res = re_bcs.match(cmdstr)
    if res:
        channel = int(res.group("mode"))
        index = int(res.group("index"))
        cvars = res.group("cvars")
        if channel == 0:
            bcs_buffer[index] = cvars
        elif channel == 1:
            bcs_buffer[index] += cvars
        elif channel == 2:
            full_cs = bcs_buffer[index] + cvars
            del bcs_buffer[index]
            handle_message('cs {} "{}"'.format(index, full_cs))
        return

    # player_connect
    res = re_connect.match(cmdstr)
    if res:
        #event_handlers["player_connect"].trigger(res.group("name"))
        return

    # player_disconnect
    res = re_disconnect.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("disconnect")
        return

    # round_start
    res = re_round_start.match(cmdstr)
    if res:
        cvars = parse_variables(res.group("cvars"))
        if cvars:
            round_number = int(cvars["round"])
            if round_number and "time" in cvars:
                if round_number == 1:  # This is the case when the first countdown starts.
                    event_handlers["round_countdown"].trigger(round_number)
                    return

                event_handlers["round_countdown"].trigger(round_number)
                return
            elif round_number:
                event_handlers["round_start"].trigger(round_number)
                return

    # round_end
    res = re_round_end.match(cmdstr)
    if res and int(res.group("score")) != 0:
        winner = minqlbot.TEAMS[int(res.group("team")) - 5]  # Offset by 5
        score = (-1, -1)
        if winner == minqlbot.TEAMS[1]:
            score = (int(res.group("score")),
                     int(minqlbot.get_configstring(7, cached=False)))
        elif winner == minqlbot.TEAMS[2]:
            score = (int(minqlbot.get_configstring(6, cached=False)),
                     int(res.group("score")))

        # If the game was forfeited, it'll act as if the round ended, but with -999 score
        # followed by the actual score. We simply skip the -999 one, since game_ended is
        # triggered later anyway.
        if score[0] == -999 or score[1] == -999:
            return

        # Otherwise, regular round end.
        event_handlers["round_end"].trigger(score, winner)
        return

    # game_change
    res = re_game_change.match(cmdstr)
    if res:
        cvars = res.group("cvars")
        cs = minqlbot.get_configstring(0, cached=False)

        if cvars and cs:
            old_cvars = parse_variables(cs)
            new_cvars = parse_variables(cvars)
            old_state = old_cvars["g_gameState"]
            new_state = new_cvars["g_gameState"]

            if old_state != new_state:
                if old_state == "PRE_GAME" and new_state == "IN_PROGRESS":
                    event_handlers["vote_ended"].cancel(
                    )  # Cancel current vote if any.
                    event_handlers["game_start"].trigger(minqlbot.Game())
                elif old_state == "PRE_GAME" and new_state == "COUNT_DOWN":
                    event_handlers["game_countdown"].trigger()
                elif old_state == "COUNT_DOWN" and new_state == "IN_PROGRESS":
                    event_handlers["vote_ended"].cancel(
                    )  # Cancel current vote if any.
                    event_handlers["game_start"].trigger(minqlbot.Game())
                elif old_state == "IN_PROGRESS" and new_state == "PRE_GAME":
                    pass
                else:
                    debug("UNKNOWN GAME STATES: {} - {}".format(
                        old_state, new_state))

        return

    # game_end
    # TODO: Proper handling of non-team game modes.
    res = re_game_end.match(cmdstr)
    if res:
        value = int(res.group("value"))
        if value == 1:
            red_score = int(minqlbot.get_configstring(6, cached=False))
            blue_score = int(minqlbot.get_configstring(7, cached=False))
            if red_score > blue_score:
                event_handlers["vote_ended"].cancel(
                )  # Cancel current vote if any.
                event_handlers["game_end"].trigger(minqlbot.Game(),
                                                   (red_score, blue_score),
                                                   minqlbot.TEAMS[1])
            elif red_score < blue_score:
                event_handlers["vote_ended"].cancel(
                )  # Cancel current vote if any.
                event_handlers["game_end"].trigger(minqlbot.Game(),
                                                   (red_score, blue_score),
                                                   minqlbot.TEAMS[2])
            else:
                event_handlers["game_end"].trigger(minqlbot.Game(),
                                                   (red_score, blue_score),
                                                   None)
            return

    # abort
    res = re_abort.match(cmdstr)
    if res:
        #player = get_player(res.group("name"))
        event_handlers["abort"].trigger()
        return

    # kick
    res = re_kick.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("kick")
        return

    # ragequit
    res = re_ragequit.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("ragequit")
        return

    # timeout
    res = re_timeout.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("timeout")
        return

    # vote_called
    res = re_vote_called.match(cmdstr)
    if res:
        name = res.group("name")
        # Remove clan tag if any.
        n_split = name.split()
        if len(n_split) > 1:
            name = n_split[1]

        player = get_player(name)

        # We don't know yet what kind of vote it is, so no event trigger yet.
        event_handlers["vote_called"].caller(player)
        return

    # vote_called_ex
    res = re_vote_called_ex.match(cmdstr)
    if res:
        event_handlers["vote_called"].trigger(res.group("vote"),
                                              res.group("args"))
        return

    # vote_ended
    res = re_vote_ended.match(cmdstr)
    if res:
        if res.group("result") == "passed":
            event_handlers["vote_ended"].trigger(True)
        else:
            event_handlers["vote_ended"].trigger(False)
        return

    # player_change
    res = re_player_change.match(cmdstr)
    if res:
        cid = int(res.group("id")) - 29  # Offset by 29
        cvars = res.group("cvars")
        csn = cid + 529  # Configstring number
        cs = minqlbot.get_configstring(csn, cached=False)

        if cvars and cs:
            old_cvars = parse_variables(cs)
            new_cvars = parse_variables(cvars)

            old_team = minqlbot.TEAMS[int(old_cvars["t"])]
            new_team = minqlbot.TEAMS[int(new_cvars["t"])]

            if old_team != new_team:
                event_handlers["team_switch"].trigger(minqlbot.Player(cid),
                                                      old_team, new_team)
        elif cvars:
            event_handlers["player_connect"].trigger(minqlbot.Player(cid))
        elif cs:
            # Make a Player instance without cached configstrings. This'll allow the plugin
            # to grab whatever info the player had before the instance is invalidated.
            event_handlers["player_disconnect"].trigger(
                minqlbot.Player(cid, cached=False))

        return

    # scores_ca
    res = re_scores_ca.match(cmdstr)
    if res:
        global castats_order
        total_players = int(res.group("total_players"))
        raw_scores = [int(i) for i in res.group("scores").split()]
        scores = []
        castats_order.clear()
        for i in range(total_players):
            castats_order.append(raw_scores[i * 17])
            scores.append(minqlbot.CaScores(raw_scores[i * 17:i * 17 + 17]))
        event_handlers["scores"].trigger(scores)
        return

    # castats
    res = re_castats.match(cmdstr)
    if res:
        global castats_buffer, castats_order
        raw_stats = [int(i) for i in res.group("stats").split()]
        cid = castats_order[0]
        del castats_order[0]
        castats_buffer.append(minqlbot.CaEndStats(cid, raw_stats))

        if not len(castats_order):  # Are we ready to trigger?
            tmp = castats_buffer
            castats_buffer = []
            event_handlers["stats"].trigger(tmp)
        return

    # scores_race
    res = re_scores_race.match(cmdstr)
    if res:
        # Race scores actually send the number of players currently playing.
        # In other words, total_players decrease if someone spectates, but still sends the stats.
        total_players = len(
            res.group("scores").split()) // 5  # Should never have a remainder.
        raw_scores = [int(i) for i in res.group("scores").split()]
        scores = []
        for i in range(total_players):
            scores.append(minqlbot.RaceScores(raw_scores[i * 5:i * 5 + 5]))
        event_handlers["scores"].trigger(scores)
        return
Пример #15
0
def parse(cmdstr):
    """Parses server commands or gamestates"""
    cmd = cmdstr.split(" ", 1)
    if cmd[0] == "chat":
        rm = re_chat.match(cmd[1])
        if rm:
            # I tested the client ID passed through this command several times, and sooner
            # or later, it starts sending incorrect data. This applies for chat, tchat and tell.
            #cid = int(rm.group(1))
            player = get_player(rm.group("name"))
            msg = rm.group("msg")
            channel = minqlbot.CHAT_CHANNEL # Use static channel
            event_handlers["chat"].trigger(player, msg, channel)
            return
        else: # Check if it's \tell
            rm = re_tell.match(cmd[1])
            if rm:
                #cid = int(rm.group(1))
                player = get_player(rm.group("name"))
                msg = rm.group("msg")
                channel = TellChannel(player)
                event_handlers["chat"].trigger(player, msg, channel) 
                return
    elif cmd[0] == "tchat": # Team chat.
        rm = re_tchat.match(cmd[1])
        if rm:
            #cid = int(rm.group(1))
            player = get_player(rm.group("name"))
            msg = rm.group("msg")
            channel = minqlbot.TEAM_CHAT_CHANNEL # Use static channel
            event_handlers["chat"].trigger(player, msg, channel)
            return
    
    # big_configstring (bcs)
    res = re_bcs.match(cmdstr)
    if res:
        channel = int(res.group("mode"))
        index = int(res.group("index"))
        cvars = res.group("cvars")
        if channel == 0:
            bcs_buffer[index] = cvars
        elif channel == 1:
            bcs_buffer[index] += cvars
        elif channel == 2:
            full_cs = bcs_buffer[index] + cvars
            del bcs_buffer[index]
            handle_message('cs {} "{}"'.format(index, full_cs))
        return

    # player_connect
    res = re_connect.match(cmdstr)
    if res:
        #event_handlers["player_connect"].trigger(res.group("name"))
        return
    
    # player_disconnect
    res = re_disconnect.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("disconnect")
        return
    
    # round_start
    res = re_round_start.match(cmdstr)
    if res:
        cvars = parse_variables(res.group("cvars"))
        if cvars:
            round_number = int(cvars["round"])
            if round_number and "time" in cvars:
                if round_number == 1:  # This is the case when the first countdown starts.
                    event_handlers["round_countdown"].trigger(round_number)
                    return

                event_handlers["round_countdown"].trigger(round_number)
                return
            elif round_number:
                event_handlers["round_start"].trigger(round_number)
                return
    
    # round_end
    res = re_round_end.match(cmdstr)
    if res and int(res.group("score")) != 0:
        winner = minqlbot.TEAMS[int(res.group("team")) - 5] # Offset by 5
        score = (-1, -1)
        if winner == minqlbot.TEAMS[1]:
            score = (int(res.group("score")), int(minqlbot.get_configstring(7, cached=False)))
        elif winner == minqlbot.TEAMS[2]:
            score = (int(minqlbot.get_configstring(6, cached=False)), int(res.group("score")))

        # If the game was forfeited, it'll act as if the round ended, but with -999 score
        # followed by the actual score. We simply skip the -999 one, since game_ended is
        # triggered later anyway.
        if score[0] == -999 or score[1] == -999:
            return
        
        # Otherwise, regular round end.
        event_handlers["round_end"].trigger(score, winner)
        return
    
    # game_change
    res = re_game_change.match(cmdstr)
    if res:
        cvars = res.group("cvars")
        cs = minqlbot.get_configstring(0, cached=False)
        
        if cvars and cs:
            old_cvars = parse_variables(cs)
            new_cvars = parse_variables(cvars)
            old_state = old_cvars["g_gameState"]
            new_state = new_cvars["g_gameState"]
            
            if old_state != new_state:
                if old_state == "PRE_GAME" and new_state == "IN_PROGRESS":
                    event_handlers["vote_ended"].cancel() # Cancel current vote if any.
                    event_handlers["game_start"].trigger(minqlbot.Game())
                elif old_state == "PRE_GAME" and new_state == "COUNT_DOWN":
                    event_handlers["game_countdown"].trigger()
                elif old_state == "COUNT_DOWN" and new_state == "IN_PROGRESS":
                    event_handlers["vote_ended"].cancel() # Cancel current vote if any.
                    event_handlers["game_start"].trigger(minqlbot.Game())
                elif old_state == "IN_PROGRESS" and new_state == "PRE_GAME":
                    pass
                else:
                    debug("UNKNOWN GAME STATES: {} - {}".format(old_state, new_state))
            
        return
    
    # game_end
    res = re_game_end.match(cmdstr)
    if res:
        value = int(res.group("value"))
        if value == 1:
            red_score = int(minqlbot.get_configstring(6, cached=False))
            blue_score = int(minqlbot.get_configstring(7, cached=False))
            if red_score > blue_score:
                event_handlers["vote_ended"].cancel() # Cancel current vote if any.
                event_handlers["game_end"].trigger(minqlbot.Game(), (red_score, blue_score), minqlbot.TEAMS[1])
            elif red_score < blue_score:
                event_handlers["vote_ended"].cancel() # Cancel current vote if any.
                event_handlers["game_end"].trigger(minqlbot.Game(), (red_score, blue_score), minqlbot.TEAMS[2])
            else:
                debug("game_end: Weird behaviour!")
            return
    
    # kick
    res = re_kick.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("kick")
        return

    # ragequit
    res = re_ragequit.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("ragequit")
        return

    # timeout
    res = re_timeout.match(cmdstr)
    if res:
        event_handlers["player_disconnect"].reason("timeout")
        return
    
    # vote_called
    res = re_vote_called.match(cmdstr)
    if res:
        name = res.group("name")
        # Remove clan tag if any.
        n_split = name.split()
        if len(n_split) > 1:
            name = n_split[1]
        
        player = get_player(name)
        
        # We don't know yet what kind of vote it is, so no event trigger yet.
        event_handlers["vote_called"].caller(player)
        return
    
    # vote_called_ex
    res = re_vote_called_ex.match(cmdstr)
    if res:
        event_handlers["vote_called"].trigger(res.group("vote"), res.group("args"))
        return
    
    # vote_ended
    res = re_vote_ended.match(cmdstr)
    if res:
        if res.group("result") == "passed":
            event_handlers["vote_ended"].trigger(True)
        else:
            event_handlers["vote_ended"].trigger(False)
        return
    
    # player_change
    res = re_player_change.match(cmdstr)
    if res:
        cid = int(res.group("id")) - 29 # Offset by 29
        cvars = res.group("cvars")
        csn = cid + 529 # Configstring number
        cs = minqlbot.get_configstring(csn, cached=False)
        
        if cvars and cs:
            old_cvars = parse_variables(cs)
            new_cvars = parse_variables(cvars)
            
            old_team = minqlbot.TEAMS[int(old_cvars["t"])]
            new_team = minqlbot.TEAMS[int(new_cvars["t"])]
            
            if old_team != new_team:
                event_handlers["team_switch"].trigger(minqlbot.Player(cid), old_team, new_team)
        elif cvars:
            event_handlers["player_connect"].trigger(minqlbot.Player(cid))
        elif cs:
            # Make a Player instance without cached configstrings. This'll allow the plugin
            # to grab whatever info the player had before the instance is invalidated.
            event_handlers["player_disconnect"].trigger(minqlbot.Player(cid, cached=False))
            
        return

    # scores_ca
    res = re_scores_ca.match(cmdstr)
    if res:
        global castats_order
        total_players = int(res.group("total_players"))
        raw_scores = [int(i) for i in res.group("scores").split()]
        scores = []
        castats_order.clear()
        for i in range(total_players):
            castats_order.append(raw_scores[i*17])
            scores.append(minqlbot.CaScores(raw_scores[i*17:i*17+17]))
        event_handlers["scores"].trigger(scores)
        return

    # castats
    res = re_castats.match(cmdstr)
    if res:
        global castats_buffer, castats_order
        raw_scores = [int(i) for i in res.group("scores").split()]
        cid = castats_order[0]
        del castats_order[0]
        castats_buffer.append(minqlbot.CaEndScores(cid, raw_scores))

        if not len(castats_order): # Are we ready to trigger?
            tmp = castats_buffer
            castats_buffer = []
            event_handlers["stats"].trigger(tmp)
        return

    # scores_race
    res = re_scores_race.match(cmdstr)
    if res:
        # Race scores actually send the number of players currently playing.
        # In other words, total_players decrease if someone spectates, but still sends the stats.
        total_players = len(res.group("scores").split()) // 5 # Should never have a remainder.
        raw_scores = [int(i) for i in res.group("scores").split()]
        scores = []
        for i in range(total_players):
            scores.append(minqlbot.RaceScores(raw_scores[i*5:i*5+5]))
        event_handlers["scores"].trigger(scores)
        return
Пример #16
0
 def is_vote_active(cls):
     if minqlbot.get_configstring(9):
         return True
     else:
         return False
Пример #17
0
 def red_score(self):
     return int(minqlbot.get_configstring(6, self.cached))
Пример #18
0
 def blue_score(self):
     return int(minqlbot.get_configstring(7, self.cached))
Пример #19
0
 def blue_score(self):
     return int(minqlbot.get_configstring(7, self.cached))
Пример #20
0
 def map(self):
     return minqlbot.get_configstring(3, self.cached)
Пример #21
0
 def is_vote_active(self):
     if minqlbot.get_configstring(9):
         return True
     else:
         return False
Пример #22
0
 def red_score(self):
     return int(minqlbot.get_configstring(6, self.cached))