Exemplo n.º 1
0
 def update_achievement(self, player, ach):
     """Update achievement given achievement string and player object"""
     if not player:
         say("[ERROR] failed achievement: invalid player.")
         sys.exit(1)
         return False
     timestamp = str(datetime.datetime.now().year) + \
         "-" +  str(datetime.datetime.now().month) + \
         "-" + str(datetime.datetime.now().day)
     if ach == "haxx0r":
         if not player.a_haxx0r == "":
             return False
         player.a_haxx0r = a_best(timestamp, player.a_haxx0r)
     elif ach == "blazeit":
         if not player.a_blazeit == "":
             return False
         player.a_blazeit = a_best(timestamp, player.a_blazeit)
     elif ach == "satan":
         if not player.a_satan == "":
             return False
         player.a_satan = a_best(timestamp, player.a_satan)
     elif ach == "virgin":
         if not player.a_virgin == "":
             return False
         player.a_virgin = a_best(timestamp, player.a_virgin)
     else:
         say("[WARNING] unknown achievement '" + str(ach) + "'")
         return False
     return True
Exemplo n.º 2
0
 def handle_flag_cap(self, data):
     """0.7 flag cap"""
     if self.settings.get("tw_version")[0:3] != "0.7":
         return
     # old 0.7
     # flag_capture player='0:ChillerDragon' team=0
     # new 0.7
     # flag_capture player='0:ChillerDragon' team=0 time=6.32
     # flag_capture player='0:ChillerDragon' team=0 time=0.72
     # flag_capture player='0:ChillerDragon' team=0 time=1.30
     # flag_capture player='0:ChillerDragon' team=0 time=113.94
     data = data[:-1]
     match = re.match(
         r"^\[game\]: flag_capture player='(?P<id>-?\d{1,2}):(?P<name>.*)' "
         r"team=(?P<team>-?\d{1,2}) time=(?P<time>\d+\.\d{2})$", data)
     if not match:
         if self.settings.get("debug"):
             say("[WARNING] flag time not found. Please update to newer version of teeworlds."
                 )
         return
     if self.settings.get("debug"):
         say("[DEBUG] flag cap in '" + match.group("time") + "' seconds.")
     player = self.players_controller.get_player_by_id(match.group("id"))
     flag_color = "red"
     if player.team == "red":
         flag_color = "blue"
     self.__handle_flag_cap(player, match.group("time"), flag_color)
Exemplo n.º 3
0
 def get_rank_player(self, msg, rank_cmd):
     """Parse command and return player object"""
     if self.settings.get("stats_mode") != "sql":
         say("not supported in file stats mode")
         return None, None
     msg_normal = msg
     msg = msg.lower()
     id_str = self.get_chat_id(msg_normal)
     rankname_start = -1
     if msg.find(rank_cmd + " ") != -1:
         cmd_end = msg.rfind(rank_cmd)
         rankname_start = msg.find(rank_cmd + " ",
                                   cmd_end) + len(rank_cmd + " ")
     rankname_end = len(msg) - 1  # cut off newline
     rankname = msg_normal[rankname_start:rankname_end]
     if not rankname or rankname == "" or rankname_start == -1:
         return self.players_controller.get_player_by_id(id_str), id_str
     argplayer = self.players_controller.get_player_by_name(rankname)
     if not argplayer:
         # try to find id prefix in argument name
         pattern = r'(\d{1,2}):(.*)'
         if self.settings.get("tw_version") == "ddnet":
             # F-DDrace 128 slots
             pattern = r'(\d{1,3}):(.*)'
         match = re.match(pattern, rankname)
         if match:
             r_id = match.group(1)
             r_name = match.group(2)
             r_player = self.players_controller.get_player_by_id(r_id)
             if r_player and r_player.name == r_name:
                 argplayer = r_player
     return argplayer, rankname
Exemplo n.º 4
0
 def update_player_deaths(self, player, killer, deaths):
     """bundle all the logic that happens on a death"""
     if not player:
         return False
     player.deaths += deaths
     # only activate killingsprees on 8+ players
     if self.count_players() > self.settings.get("spree_players"):
         if player.killingspree > 9 and self.settings.get("show_sprees") == 1:
             broadcast(
                 "'" + player.name +
                 "'s killing spree with " + str(player.killingspree) +
                 " kills was ended by '" + killer + "'"
                 )
         if player.killingspree > player.best_spree and self.settings.get("show_sprees") == 1:
             if player.killingspree > 9:
                 say(
                     "'" + player.name +
                     "' new killingspree record! Old: " +
                     str(player.best_spree) +
                     " New: "
                     + str(player.killingspree)
                     )
             player.best_spree = player.killingspree
             save_stats_partially(player)
         player.killingspree = 0
     return True
Exemplo n.º 5
0
 def process_multi_kills(self, player, weapon):
     """Check if a kill is a multikill"""
     now = base.generic.get_timestamp()
     diff = now - player.last_kill
     if diff > 300000000:
         return now
     if player.last_kill == player.last_multi_kill:
         player.current_multi += 1
         if player.current_multi > 32:
             player.current_multi = 2  # after Duotriguple start from double agian
     else:
         player.current_multi = 2
         player.is_combo_multi = False
     if player.last_kill_weapon != weapon:
         player.is_combo_multi = True
     weapon_str = self.game_controller.WEAPONS[weapon]
     if player.is_combo_multi:
         weapon_str = "combo"
     if self.settings.get("show_combos") == 1:
         say(
             "'" + player.name + \
             "' did a " + weapon_str + " " + \
             self.game_controller.MULTIS[player.current_multi] + " kill!"
         )
     player.double_kills[weapon] += 1
     player.last_multi_kill = now
     return now
Exemplo n.º 6
0
def load_stats_file(name: str):
    """Return player object given a name"""
    if not hash_stats(name):
        return None
    try:
        with open(stats_path(name), "r", encoding='UTF-8') as stats_file:
            player = Player(name)
            player.kills = int(stats_file.readline())
            player.deaths = int(stats_file.readline())
            player.flag_grabs = int(stats_file.readline())
            player.flag_caps_red = int(stats_file.readline())
            player.flag_caps_blue = int(stats_file.readline())
            player.flag_time = float(stats_file.readline())
            player.flagger_kills = int(stats_file.readline())
            player.best_spree = int(stats_file.readline())
            player.wins = int(stats_file.readline())
            player.looses = int(stats_file.readline())
            player.a_haxx0r = str(stats_file.readline())
            player.a_blazeit = str(stats_file.readline())
            player.a_satan = str(stats_file.readline())
            player.a_virgin = str(stats_file.readline())
            stats_file.close()
            return player
    except OSError:
        say("[ERROR] (load) failed to loaded stats for name='" + name +
            "' filename='" + stats_path(name) + "'")
        sys.exit(1)
        return None
Exemplo n.º 7
0
 def spam_protection(self, msg):
     """Takes a message and mutes the author if it is spam"""
     player = self.get_spam_player(msg)
     if not player:
         if self.settings.get("hotplug") == 1:
             return False
         say("[ERROR] spam_protection() failed! please contact an admin")
         sys.exit(1)
     now = datetime.datetime.now()
     diff = now - player.last_chat
     player.last_chat = now
     #say("chat diff seconds: " + str(diff.seconds) + " last_chat: " + str(player.last_chat))
     seconds = diff.seconds
     if seconds < 15:
         player.mute_score += 1
     if player.mute_score > 5:
         if not player.is_muted:
             player.is_muted = True
             say("'" + str(player.name) +
                 "' is banned from the command system (spam)")
     if seconds > 120:
         player.is_muted = False
         player.mute_score = 0
     if player.is_muted:
         return True
     return False
Exemplo n.º 8
0
 def create_player(self, name, cid=-1, ip_addr="", team="", show_stats=True, spree=0):
     """Get player object from init_player and append it to the player list"""
     global CONNECTED_PLAYERS
     player = self.init_player(name, cid, ip_addr, team, show_stats, spree)
     if not player:
         say("[ERROR] CreatePlayer init_player=None name='" + str(name) + "' id=" + str(cid))
         sys.exit(1)
     CONNECTED_PLAYERS.append(player)
Exemplo n.º 9
0
 def admin_contact_msg(self):
     """Display the admin contact message in chat"""
     if str(self.settings.get("admin_contact")) == "":
         return
     say(
         "[INFO] Contact the admin " + \
         str(self.settings.get("admin_contact")) + \
         " to report players."
     )
Exemplo n.º 10
0
    def handle_kills_07_and_ddnet(self, data):
        """Handle kill messages in ddnet or 0.7 format"""
        if self.settings.get("tw_version") == "ddnet":
            # [game]: kill killer='5:chiller' victim='5:chiller'
            # weapon=-3 special=0 killer_team:0 victim_team:0

            # [game]: kill killer='6:chiller.*' victim='5:chiller'
            # weapon=-2 special=0 killer_team:0 victim_team:0

            # F-DDrace has 128 and thus ids can be up to 3 digits
            match = re.match(
                r"^\[game\]: kill killer='(?P<k_id>-?\d{1,3}):(?P<k_name>.*)' "
                r"victim='(?P<v_id>-?\d{1,3}):(?P<v_name>.+?)' "
                r"weapon=(?P<weapon>-?\d) "
                r"special=(\d) killer_team:(?P<k_team>-?\d{1,3}) "
                r"victim_team:(?P<v_team>-?\d{1,3})$", data)
        else:
            # teeworlds 0.7
            #                     id:team                   id:team
            # [game]: kill killer='0:0:nameless tee' victim='0:0:nameless tee' weapon=-1 special=0
            # [game]: kill killer='-2:1:' victim='0:0:ChillerDragon' weapon=3 special=0
            # use .* for killer but .+? for victim
            # because killer can be empty if it left the server before the projectile hit
            match = re.match(
                r"^\[game\]: kill killer='(?P<k_id>-?\d{1,2}):"
                r"(?P<k_team>-?\d{1,2}):(?P<k_name>.*)' "
                r"victim='(?P<v_id>-?\d{1,2}):(?P<v_team>-?\d{1,2}):(?P<v_name>.+?)' "
                r"weapon=(?P<weapon>-?\d) special=(\d)$", data)

        if match:
            if self.settings.get("debug"):
                say("KILLER ID=<%s> TEAM=<%s> NAME=<%s> "
                    "VICTIM ID=<%s> TEAM=<%s> NAME=<%s> weapon=<%s>" %
                    (match.group("k_id"), match.group("k_team"),
                     match.group("k_name"), match.group("v_id"),
                     match.group("v_team"), match.group("v_name"),
                     match.group("weapon")))
            if match.group("k_name") == "" or int(match.group("k_id")) < 0:
                killer_name = "a left player"
                killer_id = match.group("k_id")
                killer = None
            else:
                killer_name = match.group("k_name")
                killer_id = match.group("k_id")
                killer = self.players_controller.get_player_by_id(killer_id)

            victim_name = match.group("v_name")
            victim_id = match.group("v_id")
            victim = self.players_controller.get_player_by_id(victim_id)

            weapon = match.group("weapon")
        else:
            say("[ERROR] failed parsing kill msg: " + str(data))
            sys.exit(1)
        return Kill(Player(killer, killer_name, killer_id),
                    Player(victim, victim_name, victim_id), weapon)
Exemplo n.º 11
0
 def team_won(self, team):
     """Update wins and loses for all players"""
     global CONNECTED_PLAYERS
     if not team == "red" and not team == "blue":
         say("[WARNING] invalid team won " + str(team))
     for player in CONNECTED_PLAYERS:
         if player.team == team:
             player.wins += 1
         elif not player.team == "" and not player.team == "spectator":
             player.looses += 1
Exemplo n.º 12
0
 def handle_player_team(self, data):
     """Parse 'team_join' message"""
     global CONNECTED_PLAYERS
     id_start = data.find("'") + 1
     id_end = base.generic.cfind(data, ":", 2)
     id_str = data[id_start:id_end]
     player = self.get_player_by_id(id_str)
     if player is None:
         if self.settings.get("hotplug") == 1:
             return
         say("[ERROR] teamchange failed id=" + str(id_str) + " data=" +
             str(data))
         self.debug_player_list()
         sys.exit(1)
     team = "invalid"
     data_end = data[-5:]
     change = data_end.rfind(">")
     if change != -1:
         team = data_end[change + 1:]
     else:
         team = str(data[data.rfind("=") + 1:])
     if team == "0":
         player.team = "red"
     elif team == "1":
         player.team = "blue"
     elif team == "-1":
         player.team = "spectator"
     else:
         say("[ERROR] invalid team=" + str(team))
         sys.exit(1)
     name_start = base.generic.cfind(data, ":", 2) + 1
     name_end = data.rfind("'")
     name = data[name_start:name_end]
     if player.name is None:
         # player just joined and still has to be loaded
         self.delete_player(player.cid)  # delete invalid tmp player
         self.create_player(name, player.cid, player.ip_addr, player.team)
         locked = locked_names.get_instance()
         if not locked.check(name, player.ip_addr):
             rcon_exec("kick " + str(player.cid) + " please change name")
     elif player.name != name:
         # https://github.com/chillavanilla/TeeworldsEconMod/issues/49
         # it is very rare but possible that one joins without name
         # the during join the placeholder (connecting) is shown in the logs
         # but later the actual name is used
         if player.name == "(connecting)":
             say("[WARNING] untracked namechange from '" + player.name +
                 "' to '" + name + "'")
             player.name = name
         else:
             say("[ERROR] untracked namechange from '" + player.name +
                 "' to '" + name + "'")
             say('[ERROR] data=' + data)
             sys.exit(1)
Exemplo n.º 13
0
 def is_muted(self, msg):
     """Take a message and return of the message author is muted or not"""
     player = self.get_spam_player(msg)
     if not player:
         if self.settings.get("hotplug") == 1:
             return False
         say("[WARNING] is_muted() failed! please contact an admin")
         return False
     if player.is_muted:
         return True
     return False
Exemplo n.º 14
0
 def print_stats_all(self, debug=False):
     """Print stats of all players in chat"""
     global CONNECTED_PLAYERS
     if debug:
         say("Kills/Deaths/Spree Grabs/RedCaps/BlueCaps/CapTime/FlaggerKills")
         for player in CONNECTED_PLAYERS:
             say(
                 "'" + player.name +
                 "' k/d/s: " + str(player.kills) +
                 "/" + str(player.deaths) +
                 "/" + str(player.best_spree) +
                 " flag g" + str(player.flag_grabs) +
                 "/r" + str(player.flag_caps_red) +
                 "/b" + str(player.flag_caps_blue) +
                 "/t" + str(player.flag_time) +
                 "/k" + str(player.flagger_kills))
             #say("debug is_flagger: " + str(player.is_flagger))
     else:
         say("=== stats for all players ===")
         for player in CONNECTED_PLAYERS:
             say(
                 "'" + player.name +
                 "' k/d: " + str(player.kills) +
                 "/" + str(player.deaths) +
                 " spree: " + str(player.best_spree) +
                 " flags: " + str(player.flag_caps_red + player.flag_caps_blue) +
                 " fastest cap: " + str(player.flag_time))
Exemplo n.º 15
0
 def update_player_flag_caps(self, player, color, caps):
     """Update flag cap stats"""
     if not player:
         say("[ERROR] failed player.update_player_flag_caps: invalid player.")
         sys.exit(1)
         return False
     if self.count_players() <= self.settings.get("flag_players"):
         return False
     if color == "blue":
         player.flag_caps_blue += caps
     elif color == "red":
         player.flag_caps_red += caps
     else:
         say("savage '" + player.name + "' captured the pink flag")
         return False
     return True
Exemplo n.º 16
0
 def set_flagger(self, player, is_flag, timestamp=""):
     """Update flagger attribute of player object"""
     if not player:
         if is_flag:
             if self.settings.get("hotplug") == 1:
                 return
             say("[ERROR] set flagger failed: invalid player.")
             sys.exit(1)
         return False
     if is_flag and timestamp == "":
         say("[ERROR] set flagger failed: empty timestamp.")
         sys.exit(1)
         return False
     player.is_flagger = is_flag
     player.grab_timestamp = timestamp
     return True
Exemplo n.º 17
0
 def get_rank_name(self, msg, rank_cmd):
     """Parse message and return playername"""
     if self.settings.get("stats_mode") != "sql":
         say("not supported in file stats mode")
         return None
     msg_normal = msg
     msg = msg.lower()
     name_start = base.generic.cfind(msg, ":", 3) + 1
     name_end = msg.find(rank_cmd, name_start)
     name_end = msg.rfind(": ", name_end)
     name = msg_normal[name_start:name_end]
     rankname_start = -1
     if msg.find(rank_cmd + " ") != -1:
         rankname_start = msg.find(rank_cmd + " ",
                                   name_end) + len(rank_cmd + " ")
     rankname_end = len(msg) - 1  # cut off newline
     rankname = msg_normal[rankname_start:rankname_end]
     if not rankname or rankname == "" or rankname_start == -1:
         return name
     return rankname
Exemplo n.º 18
0
 def __handle_flag_cap(self, player_obj, time, flag_color):
     """called by 0.6 and 0.7 parser"""
     if not player_obj:
         if self.settings.get("hotplug") == 1:
             return
         say("[ERROR] flag capture error: player is invalid.")
         sys.exit(1)
     if flag_color == player_obj.team:
         say("[ERROR] flag capture error: flag color matches team color.")
         say("   team=" + player_obj.team)
         say("   flag=" + flag_color)
         sys.exit(1)
     name = player_obj.name
     self.achievements_controller.check_flag(player_obj, time)
     self.players_controller.update_player_flag_time(player_obj, time)
     self.players_controller.set_flagger(player_obj, False)
     self.players_controller.update_player_flag_caps(
         player_obj, flag_color, 1)
     if self.settings.get("debug"):
         say("[DEBUG] flag cap '" + name + "' in '" + str(time) +
             "' secs color: '" + flag_color + "'")
Exemplo n.º 19
0
 def handle_name_change(self, data):
     """Parse 'changed name to' chat message"""
     old_start = data.find("'") + 1
     old_end = data.find("' changed name to '")
     old = data[old_start:old_end]
     new_start = old_end + len("' changed name to '")
     new_end = data.rfind("'")
     new = data[new_start:new_end]
     team = ""
     player = self.get_player_by_name(old)
     if not player:
         if self.settings.get("hotplug") == 1:
             return
         say("[ERROR] name_change player not found name=" + str(old))
         sys.exit(1)
     team = player.team
     self.save_and_delete_player_by_name(old)
     self.create_player(new, player.cid, player.ip_addr, team=team)
     locked = locked_names.get_instance()
     if not locked.check(new, player.ip_addr):
         rcon_exec("kick " + str(player.cid) + " please change name")
Exemplo n.º 20
0
 def handle_call_vote(self, data):
     """Recive vote log line and parse it"""
     # TODO: use regex here to avoid false positives
     if data.find("' voted option '") != -1:
         if self.settings.get("debug"):
             say("[VOTES] skip force on option vote")
         return
     if self.settings.get("votes_force") != 0:
         if self.settings.get("votes_blocked_reasons") is None:
             rcon_exec("vote no")
         else:
             match = re.match(
                 r'.*server\]: \'.+\' voted (spectate|kick) \'.+\' '
                 r'reason=\'(.+)\' cmd=\'.*', data)
             if match:
                 reason = match.group(2)
                 if self.is_blocked_reason(reason):
                     rcon_exec("vote no")
                     say("[ANTI-FUNVOTE] please provide a better reason.")
             else:
                 say("[WARNING] Vote parsing error. Please contact a admin.")
     if self.settings.get("votes_discord") != 0:
         self.chat_controller.admin_contact_msg()
     if self.settings.get("votes_discord") == 2:
         send_discord("vote called " + str(self.settings.get("mod_discord"))
             + "!\n" + str(data[:data.find(" cmd='ban")]))
Exemplo n.º 21
0
 def check_flag(self, player_obj, time):
     """Check if the flag time is an achievement"""
     if not player_obj:
         if self.settings.get("hotplug") == 1:
             return
         say("[ERROR] check flag failed: invalid player.")
         sys.exit(1)
     name = player_obj.name
     if str(time) == "13.37":
         if self.players_controller.update_achievement(
                 player_obj, "haxx0r"):
             say("[achievement] '" + str(name) + "' unlocked: haxx0r")
     elif str(time) == "4.20":
         if self.players_controller.update_achievement(
                 player_obj, "blazeit"):
             say("[achievement] '" + str(name) + "' unlocked: blaze it")
     elif str(time) == "6.66":
         if self.players_controller.update_achievement(player_obj, "satan"):
             say("[achievement] '" + str(name) + "' unlocked: satan")
     elif str(time) == "6.90":
         if self.players_controller.update_achievement(
                 player_obj, "virgin"):
             say("[achievement] '" + str(name) + "' unlocked: virgin")
Exemplo n.º 22
0
 def handle_game(self, timestamp, data):
     """Parse game messages"""
     if data.find("kill killer") != -1:
         self.kills_controller.handle_kills(timestamp, data)
     elif data.startswith("[game]: start round type='"):
         global CAPS_RED
         global CAPS_BLUE
         # [game]: start round type='CTF' teamplay='1'
         say("[SERVER] ChillerDragon wishes you all hf & gl c:")
         self.players_controller.refresh_all_players()
         if data.startswith("[game]: start round type='CTF'"):
             if CAPS_RED == 0 and CAPS_BLUE == 0:  # already catched by 10 flags auto detection
                 return
             if CAPS_RED > CAPS_BLUE:
                 self.update_wins(True)
             elif CAPS_RED < CAPS_BLUE:
                 self.update_wins(False)
             else:
                 say("draw lul")
     elif data.startswith("[game]: flag_grab player='"):
         self.flags_controller.handle_flag_grab(timestamp, data)
     # [2019-10-15 11:41:04][game]: flag_capture player='0:ChillerDragon' team=0
     elif data.startswith("[game]: flag_capture player='"):
         self.flags_controller.handle_flag_cap(data)
Exemplo n.º 23
0
 def update_player_flag_time(self, player, time):
     """Update flag time stats"""
     if not player:
         say("[ERROR] failed player.update_player_flag_time: invalid player."
             )
         sys.exit(1)
     time = float(time)
     try:  # TypeError: unorderable types: float() < str()
         if time < float(player.flag_time):
             diff = player.flag_time - time
             diff = float("{0:.2f}".format(diff))
             say("[FastCap] '" + player.name + "' " + str(diff) +
                 " seconds faster")
             player.flag_time = time
         elif int(player.flag_time) == 0:
             player.flag_time = time
         return True
     except TypeError as error:
         say("[ERROR] error calculating flag time (" + str(time) +
             ") and (" + str(player.flag_time) + ")")
         say(error)
         sys.exit(1)
Exemplo n.º 24
0
def save_stats_partially_file(player: Player) -> bool:
    """Save only killingspree"""
    if not player:
        say("[stats] (partially) failed to load player.")
        return False
    name = player.name
    if hash_stats(name):
        #say("[stats] found stats --> loading and appending")
        load_player = load_stats_file(name)
        if not load_player:
            say(
                "[stats] (partially) error loading stats for player='" + \
                name + \
                "' filename='" + \
                stats_path(name) + "'"
                )
            sys.exit(1)
        player = player + load_player
    try:
        with open(stats_path(name), "w", encoding='UTF-8') as stats_file:
            stats_file.write("0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("0.0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write(str(player.best_spree) + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("0" + "\n")
            stats_file.write("" + "\n")
            stats_file.write("" + "\n")
            stats_file.write("" + "\n")
            stats_file.write("" + "\n")
            stats_file.close()
            return True
    except OSError:
        say(
            "[stats] (partially) error saving stats for player='" + \
            name + "' filename='" + stats_path(name) + "'")
        sys.exit(1)
Exemplo n.º 25
0
def save_stats_file(player: Player):
    """Save stats to file given a player object"""
    if not player:
        say("[stats] failed to save player.")
        return False
    name = player.name
    if hash_stats(name):
        #say("[stats] found stats --> loading and appending")
        load_player = load_stats_file(name)
        if not load_player:
            say(
                "[stats] (save) error loading stats for player='" + \
                name + "' filename='" + \
                stats_path(name) + "'"
                )
            sys.exit(1)
        player = player + load_player
    try:
        with open(stats_path(name), "w", encoding='UTF-8') as stats_file:
            stats_file.write(str(player.kills) + "\n")
            stats_file.write(str(player.deaths) + "\n")
            stats_file.write(str(player.flag_grabs) + "\n")
            stats_file.write(str(player.flag_caps_red) + "\n")
            stats_file.write(str(player.flag_caps_blue) + "\n")
            stats_file.write(str(player.flag_time) + "\n")
            stats_file.write(str(player.flagger_kills) + "\n")
            stats_file.write(str(player.best_spree) + "\n")
            stats_file.write(str(player.wins) + "\n")
            stats_file.write(str(player.looses) + "\n")
            stats_file.write(str(player.a_haxx0r) + "\n")
            stats_file.write(str(player.a_blazeit) + "\n")
            stats_file.write(str(player.a_satan) + "\n")
            stats_file.write(str(player.a_virgin) + "\n")
            stats_file.close()
            return True
    except OSError:
        say(
            "[stats] (save) error saving stats for player='" + \
            name + "' filename='" + stats_path(name) + "'")
        sys.exit(1)
Exemplo n.º 26
0
 def handle_flag_grab(self, timestamp, data):
     """parse flag grab message"""
     id_start = data.find("'", 10) + 1
     id_end = base.generic.cfind(data, ":", 2)
     id_str = data[id_start:id_end]
     player = self.players_controller.get_player_by_id(id_str)
     if not player:
         if self.settings.get("hotplug") == 1:
             return
         say("[ERROR] flag_grab player not found ID=" + str(id_str))
         self.players_controller.debug_player_list()
         sys.exit(1)
     name_start = data.find(":", 10) + 1  # first '
     name_end = data.rfind("'")  # last '
     name = data[name_start:name_end]
     if player.name != name:
         say("[ERROR] name missmatch p.name='" + str(player.name) +
             "' name='" + str(name) + "'")
         sys.exit(1)
     self.players_controller.update_player_flag_grabs(player, 1)
     self.players_controller.set_flagger(player, True, timestamp)
     if self.settings.get("debug"):
         say("[DEBUG] '" + str(name) + "' grabbed the flag ts=" +
             str(timestamp))
Exemplo n.º 27
0
 def debug_player_list(self):
     """Print player list in chat"""
     global CONNECTED_PLAYERS
     for p in CONNECTED_PLAYERS:
         say("  id=" + str(p.cid) + " name='" + str(p.name) + "'")
Exemplo n.º 28
0
 def handle_chat_message(self, msg):
     """
         Main method of this module
         takes a message and parses it for chat commands
     """
     if self.is_muted(msg):
         return
     prefix = self.settings.get("chat_command_prefix")
     is_cmd = True
     msg_normal = msg
     msg = msg.lower()
     # the first possible occurence of a chat command (to filter chat command names)
     chat_cmd_start = base.generic.cfind(msg, ":", 4)
     cmd = msg[chat_cmd_start:-1]  # cut newline at end
     if cmd.endswith(": " + prefix + "help") or \
         cmd.endswith(": " + prefix + "info") or \
         cmd.endswith(": " + prefix + "cmdlist"):
         say("==== Teeworlds Econ Mod (TEM) ====")
         say("developed by ChillerDragon version: " + str(version.VERSION))
         say("https://github.com/ChillaVanilla/TeeworldsEconMod")
         say("'" + prefix + "help' to show this help")
         say("'" + prefix + "stats' to show round stats")
         say("'" + prefix + "achievements' to show achievements")
         if self.settings.get("stats_mode") == "sql":
             say("'" + prefix + "top5' for all time stats commands")
             say("'" + prefix + "rank' for all rank commands")
     elif cmd.endswith(": " + prefix + "top5"):
         if self.settings.get("stats_mode") == "sql":
             say("'" + prefix +
                 "top_kills' to see top5 killers of all time")
         if self.settings.get("stats_mode") == "sql":
             say("'" + prefix +
                 "top_flags' to see top5 flag cap times of all time")
         if self.settings.get("stats_mode") == "sql":
             say("'" + prefix +
                 "top_caps' to see top5 flag amount of all time")
         if self.settings.get("stats_mode") == "sql":
             say("'" + prefix +
                 "top_sprees' to see top5 killing sprees of all time")
         else:
             say("not supported in file stats mode")
     #elif cmd.endswith(": " + prefix + "stats_all"):
     #player.print_stats_all(True)
     elif cmd.find(": " + prefix + "stats") != -1:
         if self.settings.get("stats_mode") != "sql":
             say("not supported in file stats mode")
             return
         player, name = self.get_rank_player(msg_normal,
                                             ": " + prefix + "stats")
         if not player:
             say("[stats] player '" + str(name) + "' is not online.")
             return
         player.show_stats_round()
         #player.print_stats_all()
     elif cmd.endswith(": " + prefix + "top_caps"):
         if self.settings.get("stats_mode") == "sql":
             sql_stats.best_flag_caps()
         else:
             say("not supported in file stats mode")
     elif cmd.endswith(": " + prefix + "top_flags"):
         if self.settings.get("stats_mode") == "sql":
             sql_stats.best_times()
         else:
             say("not supported in file stats mode")
     elif cmd.endswith(": " + prefix + "top_kills"):
         if self.settings.get("stats_mode") == "sql":
             sql_stats.best_killers()
         else:
             say("not supported in file stats mode")
     elif cmd.endswith(": " + prefix + "top_sprees"):
         if self.settings.get("stats_mode") == "sql":
             sql_stats.best_spree()
         else:
             say("not supported in file stats mode")
     elif cmd.find("" + prefix + "rank_kills") != -1:
         sql_stats.rank_kills(
             self.get_rank_name(msg_normal, ": " + prefix + "rank_kills"))
     elif msg.find("" + prefix + "rank_flags") != -1:
         sql_stats.rank_flag_time(
             self.get_rank_name(msg_normal, ": " + prefix + "rank_flags"))
     elif msg.find("" + prefix + "rank_caps") != -1:
         sql_stats.rank_flag_caps(
             self.get_rank_name(msg_normal, ": " + prefix + "rank_caps"))
     elif cmd.find("" + prefix + "rank_sprees") != -1:
         sql_stats.rank_spree(
             self.get_rank_name(msg_normal, ": " + prefix + "rank_sprees"))
     elif cmd.find("" + prefix + "rank_all") != -1:
         name = self.get_rank_name(msg_normal, ": " + prefix + "rank_all")
         if not name:
             return
         say("=== '" + str(name) + "'s stats ===")
         sql_stats.rank_kills(str(name))
         sql_stats.rank_flag_time(str(name))
         sql_stats.rank_flag_caps(str(name))
         sql_stats.rank_spree(str(name))
     elif cmd.find("" + prefix + "rank") != -1:
         if self.settings.get("stats_mode") != "sql":
             say("not supported in file stats mode")
             return
         say("'" + prefix + "rank_kills' to show global kills rank")
         say("'" + prefix + "rank_sprees' to show global spree rank")
         say("'" + prefix + "rank_flags' to show global flag time rank")
         say("'" + prefix + "rank_caps' to show global flag capture rank")
     elif cmd.find("" + prefix + "achievements") != -1:
         name = self.get_rank_name(msg_normal,
                                   ": " + prefix + "achievements")
         self.achievements_controller.show_achievements(name)
     elif cmd.endswith(": " + prefix + "test"):
         player, name = self.get_rank_player(msg_normal,
                                             ": " + prefix + "test")
         if not player:
             if self.settings.get("hotplug") == 1:
                 return
             say("error")
             sys.exit(1)
         say("got player: " + str(name))
         # say("current spree: " + str(p.killingspree))
     # handle this like a chat command (so it has spam prot)
     elif self.is_ban_reason_in_str(cmd):
         self.admin_contact_msg()
         # players containing : will be cutted in discord message but this is fine for now
         name = self.get_rank_name(msg_normal, ": ")
         if self.settings.get("filter_discord") == 1:
             send_discord(
                 "chat trigger " + \
                 str(self.settings.get("mod_discord")) + \
                 "!\n" + str(msg)
             )
     else:
         is_cmd = False
     if is_cmd:
         self.spam_protection(msg_normal)
Exemplo n.º 29
0
    def handle_kills(self, timestamp, data):
        """Parse kill message. Track kills, deaths and flags"""
        kill = None

        if self.settings.get("tw_version")[0:3] == "0.6" or \
            self.settings.get("tw_version") is None: # default 6
            kill = self.handle_kills_06(data)
        else:  # teeworlds 0.7 or ddnet
            kill = self.handle_kills_07_and_ddnet(data[:-1])

        # don't count suicide as kill or when killer left already
        if not kill.killer.obj == kill.victim.obj and kill.killer.obj:
            if not self.players_controller.update_player_kills(
                    kill.killer.obj, 1, int(kill.weapon)):
                if self.settings.get("hotplug") == 1:
                    return
                say("[ERROR] failed adding kill:")
                say("   ID=" + str(kill.killer.cid))
                say("   NAME=" + str(kill.killer.name))
                say("   OBJ=" + str(kill.killer.obj))
                say("   DATA=" + data)
                sys.exit(1)
        if str(kill.weapon
               ) != "-3":  # don't count disconnect or teamswitch as death
            if not self.players_controller.update_player_deaths(
                    kill.victim.obj, kill.killer.name, 1):
                if self.settings.get("hotplug") == 1:
                    return
                say("[ERROR] failed adding death:")
                say("   ID=" + str(kill.victim.cid))
                say("   NAME=" + str(kill.victim.name))
                say("   OBJ=" + str(kill.victim.obj))
                say("   DATA=" + data)
                sys.exit(1)

        # say("[KILL] killer=" + killer_name + " victim=" + victim_name + " weapon=" + str(weapon))
        self.players_controller.check_flagger_kill(kill.victim.name,
                                                   kill.killer.name)
        self.players_controller.set_flagger(kill.victim.obj, False, timestamp)
Exemplo n.º 30
0
    def show_achievements(self, name):
        """Print achievements of player in chat"""
        global CONNECTED_PLAYERS
        _player = None
        for player in CONNECTED_PLAYERS:
            if player.name == name:
                _player = player
                break
        # player not online -> load from database
        if not _player:
            _player = save_stats.load_stats(name)
        if not _player:
            say("'" + str(name) + "' is unranked on this server")
            return False

        if str(_player.a_haxx0r) == "" and str(
                _player.a_blazeit) == "" and str(
                    _player.a_satan) == "" and str(_player.a_virgin) == "":
            say("'" + str(name) + "' didn't unlock any achievements yet")
            return True
        say("=== '" + str(name) + "'s achievements ===")
        if str(_player.a_haxx0r) != "":
            say("[" + str(_player.a_haxx0r) + "] haxx0r")
        if str(_player.a_blazeit) != "":
            say("[" + str(_player.a_blazeit) + "] blaze it")
        if str(_player.a_satan) != "":
            say("[" + str(_player.a_satan) + "] satan")
        if str(_player.a_virgin) != "":
            say("[" + str(_player.a_virgin) + "] virgin")
        return True