def parseNewWorm(wormID, name):
	global worms

	name = name.replace("\t", " ").strip() # Do not allow tab in names, it will screw up our ranking tab-separated text-file database
	exists = False
	try:
		worm = worms[wormID]
		exists = True
	except KeyError: #Worm doesn't exist.
		worm = Worm()
	worm.Name = name
	worm.iID = wormID
	worm.Ping = []

	worms[wormID] = worm

	if io.getGameType() == "Hide and Seek":
		minSeekers = 1
		if len(worms.values()) >= 4: minSeekers = 2
		if io.getNumberWormsInTeam(1) < minSeekers:
			io.setWormTeam(wormID, 1) # Seeker
		else:
			io.setWormTeam(wormID, 0) # Hider		
	else:
		# Balance teams
		teams = [0,0,0,0]
		for w in worms.keys():
			teams[worms[w].Team] += 1
		minTeam = 0
		minTeamCount = teams[0]
		for f in range(cfg.MAX_TEAMS):
			if minTeamCount > teams[f]:
				minTeamCount = teams[f]
				minTeam = f

		io.setWormTeam(wormID, minTeam)

	if cfg.RANKING_AUTHENTICATION:
		if not name in ranking.auth:
			ranking.auth[name] = getWormSkin(wormID)
			try:
				f = open(io.getFullFileName("pwn0meter_auth.txt"),"r")
				try:
					portalocker.lock(f, portalocker.LOCK_EX)
				except:
					pass
				f.write( name + "\t" + str(ranking.auth[name][0]) + " " + ranking.auth[name][1] + "\n" )
				f.close()
			except IOError:
				msg("ERROR: Unable to open pwn0meter_auth.txt")
		else:
			if ranking.auth[name] != getWormSkin(wormID):
				io.kickWorm(wormID, "Player with name %s already registered" % name)

	wormIP = io.getWormIP(wormID).split(":")[0]
	# io.messageLog("Curtime " + str(time.time()) + " IP " + str(wormIP) + " Kicked worms: " + str(cmds.kickedUsers), io.LOG_INFO)
	if wormIP in cmds.kickedUsers and cmds.kickedUsers[ wormIP ] > time.time():
			io.kickWorm( wormID, "You can join in " + str(int(cmds.kickedUsers[ wormIP ] - time.time())/60 + 1) + " minutes" )
			return
	cmds.recheckVote()
Ejemplo n.º 2
0
def parseWormLeft(sig):
    global worms, gameState, scriptPaused

    wormID = int(sig[1])
    name = sig[2:]

    try:
        if worms[wormID].isAdmin:
            io.messageLog(
                ("Worm %i (%s) removed from admins" % (wormID, name)),
                io.LOG_ADMIN)
    except KeyError:
        io.messageLog(
            "AdminRemove: Our local copy of wormses doesn't match the real list.",
            io.LOG_ERROR)

    #NOTE: There may be a better way to do this...
    #Check which vote options to broadcast when this player leaves
    temp_votedstatus = []
    if wormID in worms.keys(
    ):  #Note: this should be always true but checked anyway...
        if worms[wormID].votedMap:
            temp_votedstatus.append("map")
        if worms[wormID].votedPreset:
            temp_votedstatus.append("mod")
        #NOTE: No need to check team votes here because team status will be checked separately.

    # Call last, that way we still have the data active.
    worms.pop(wormID)

    #Update voting status after removing this player from the worms table
    updateVotes(send_msg=tuple(temp_votedstatus))

    #Balance teams
    if io.getGameType() == 1:
        if gameState == GAME_LOBBY or cfg.BALANCE_TEAMS_INGAME:
            balanceTeams(bmsg="player left")

    # If all admins left unpause ded server (or it will be unusable)
    isAdmins = False
    for w in worms.keys():
        if worms[w].isAdmin:
            isAdmins = True
    if not isAdmins:
        scriptPaused = False
Ejemplo n.º 3
0
def parseUserCommand(wormid, message):

    try:  # Do not check on msg size or anything, exception handling is further down

        cmd = message.split(" ")[0]
        cmd = cmd.replace(cfg.USER_PREFIX, "", 1).lower()  #Remove the prefix

        if cfg.USERCOMMAND_LOGGING:
            if wormid >= 0:
                io.messageLog(
                    "%i:%s issued %s" % (wormid, hnd.worms[wormid].Name,
                                         cmd.replace(cfg.USER_PREFIX, "", 1)),
                    io.LOG_USRCMD)
            else:
                io.messageLog("ded admin issued %s" % cmd, io.LOG_USRCMD)

        # Unnecesary to split multiple times, this saves CPU.
        params = message.split(" ")[1:]

        if cmd == "help":
            userCommandHelp(wormid)
            return "none"

        elif cmd == "maphelp":
            mapHelp(wormid)
            return "none"

        #News feed (previously called updates, hence the command name...)
        elif cmd == "news":
            controlUpdatesList(wormid)
            return "none"

        #Teamchanges...
        elif cfg.ALLOW_TEAM_CHANGE and cmd == "team":
            #Not team deathmatch
            if io.getGameType() != 1:
                io.privateMsg(wormid, "Game type is not team deathmatch")
            #Not in lobby
            elif hnd.gameState != hnd.GAME_LOBBY:
                io.privateMsg(wormid, "You can only change team in lobby")
            #No team specified
            elif not params:
                io.privateMsg(wormid, "You need to specify a team")
            #Everything OK
            else:
                if params[0].lower() == "blue" or params[0].lower() == "b":
                    hnd.setTeam(wormid, 0)
                elif params[0].lower() == "red" or params[0].lower() == "r":
                    hnd.setTeam(wormid, 1)
                elif (params[0].lower() == "green"
                      or params[0].lower() == "g") and cfg.MAX_TEAMS >= 3:
                    hnd.setTeam(wormid, 2)
                elif (params[0].lower() == "yellow"
                      or params[0].lower() == "y") and cfg.MAX_TEAMS >= 4:
                    hnd.setTeam(wormid, 3)
                else:
                    io.privateMsg(wormid, "Invalid team")

        elif cfg.RANKING and cmd in ("rank", "toprank", "ranktotal"):
            if cmd == "toprank":
                ranking.firstRank(wormid)
            if cmd == "rank":
                if wormid in hnd.worms:
                    wormName = hnd.worms[wormid].Name
                    if params:
                        wormName = " ".join(params).replace(
                            "\"", "\'\'"
                        )  #Convert double quotes to prevent annoyance
                    ranking.myRank(wormName, wormid)
            if cmd == "ranktotal":
                if cfg.NAME_CHECK_ACTION == 1 and cfg.HANDLE_RANDOMS_IN_RANKTOTAL:
                    tmp_rankplayers = sortRankPlayers(
                        randoms=0, random_max=cfg.NAME_CHECK_RANDOM)
                    tmp_rankrandoms = sortRankPlayers(
                        randoms=1, random_max=cfg.NAME_CHECK_RANDOM)
                    io.privateMsg(
                        wormid, "There are " + str(len(tmp_rankplayers)) +
                        " players and " + str(len(tmp_rankrandoms)) +
                        " unnamed players in the ranking.")
                else:
                    io.privateMsg(
                        wormid, "There are " + str(len(ranking.rank)) +
                        " players in the ranking.")
            return "none"

        elif cfg.KICK_VOTING and cmd == "kick":
            try:
                kicked = int(params[0])
            except ValueError:
                io.privateMsg(wormid, "Invalid player ID")

            if not kicked in hnd.worms.keys():
                io.privateMsg(wormid, "Invalid player ID")
            else:
                hnd.worms[wormid].votedKick = kicked
                io.chatMsg(
                    hnd.worms[wormid].getCleanName() + " votes to kick " +
                    hnd.worms[kicked].getCleanName()
                )  #NOTE: We are using the real name here - so it should be cleaned
                return "kick"

        elif cfg.VOTING and cmd in ("mod", "map", "m"):

            if cmd == "mod":

                #NEW: only presets
                preset = -1
                for p in range(len(hnd.availablePresets)):
                    if hnd.availablePresets[p].lower().find(
                            params[0].lower()) != -1:
                        preset = p
                        break
                if preset != -1:
                    hnd.worms[wormid].votedPreset = hnd.availablePresets[
                        preset]
                    io.privateMsg(wormid, "You voted for %s" %
                                  hnd.worms[wormid].votedPreset
                                  )  #Send these as private msgs to reduce spam
                    return "mod"
                else:
                    io.privateMsg(
                        wormid, "Invalid preset, available presets: " +
                        ", ".join(hnd.availablePresets))

            if cmd == "map":
                level = ""
                for l in io.listMaps():
                    if l.lower().find(" ".join(params[0:]).lower()) != -1:
                        level = l
                        break
                if level != "":
                    hnd.worms[wormid].votedMap = level
                    io.privateMsg(
                        wormid,
                        "You voted for %s" % hnd.worms[wormid].votedMap)
                    return "map"
                else:
                    io.privateMsg(
                        wormid, "Invalid map, available maps: " +
                        ", ".join(io.listMaps())
                    )  #NOTE: This generates a very spammy message...

            #Quick map voting
            if cmd == "m":
                if not params:
                    io.privateMsg(
                        wormid,
                        "No map specified, try %smaphelp for a list of options"
                        % cfg.USER_PREFIX)
                elif params[0].lower() in presetcfg.MAP_SHORTCUTS.keys():
                    hnd.worms[wormid].votedMap = presetcfg.MAP_SHORTCUTS[
                        params[0].lower()]
                    io.privateMsg(
                        wormid,
                        "You voted for %s" % hnd.worms[wormid].votedMap)
                    return "map"
                else:
                    io.privateMsg(
                        wormid,
                        "Invalid map option, try %smaphelp for a list of available options"
                        % cfg.USER_PREFIX)

        elif cfg.TEAMGAMES_VOTING and (cmd == "teams" or cmd == "noteams"):
            if cmd == "teams":
                hnd.worms[wormid].votedTeams = 1
                io.privateMsg(wormid, "You voted for team game!")
            elif cmd == "noteams":
                hnd.worms[wormid].votedTeams = 0
                io.privateMsg(wormid, "You voted for deathmatch!")
            return "teams"

        #Team shuffling
        elif cmd == "shuffle" and cfg.TEAM_SHUFFLE:
            #Not TDM
            if io.getGameType() != 1:
                io.privateMsg(wormid, "Not TDM - cannot shuffle")
            #Not in lobby
            elif hnd.gameState != hnd.GAME_LOBBY:
                io.privateMsg(wormid, "Cannot shuffle when not in lobby")
            #Too many shuffles
            elif hnd.shuffle_counter >= cfg.TEAM_SHUFFLE:
                io.privateMsg(wormid, "Shuffle limit already reached")
            else:
                hnd.shuffleTeams()
            #Not in lobby

        #TEST: Use this to check team status...
        #elif cfg.TEAMCHANGE_LOGGING and cmd == "teamtest":
        #	io.messageLog("TEAMTEST: teamtest called by player " + str(wormid), io.LOG_INFO)
        #	teamtestresult = str(hnd.getNumberWormsInAllTeams()).replace("[","").replace("]","").replace(","," ")
        #	io.privateMsg(wormid, "Team status is "+teamtestresult+" - is this reasonable?")
        #	return "none"

        else:
            raise Exception, "Invalid user command"

    except:  # All python classes derive from main "Exception", but confused me, this has the same effect.
        if wormid >= 0:
            io.privateMsg(
                wormid,
                "Invalid user command - type !help for list of commands")
        if cfg.USERCOMMAND_ERROR_LOGGING:
            io.messageLog(io.formatExceptionInfo(),
                          io.LOG_ERROR)  #Helps to fix errors
        return None
    return "none"
Ejemplo n.º 4
0
def updateVotes(send_msg=()):
    global gameState, oldGameState
    global vote_locked
    global worms, availablePresets

    votedMaps = {}
    votedPresets = {}
    teams_voted = 0
    teams_ready = False
    gametype_old = io.getGameType()

    #Reset kick vote counters to zero
    for w in worms.keys():
        worms[w].resetKickVotes()

    #Count all votes
    for w in worms.keys():
        #Count map votes
        if worms[w].votedMap:
            if not worms[w].votedMap in votedMaps.keys():
                votedMaps[worms[w].votedMap] = 1
            else:
                votedMaps[worms[w].votedMap] += 1
        #Count mod (preset) votes
        if worms[w].votedPreset:
            if not worms[w].votedPreset in votedPresets.keys():
                votedPresets[worms[w].votedPreset] = 1
            else:
                votedPresets[worms[w].votedPreset] += 1
        #Count kick votes for each player
        if worms[w].votedKick in worms.keys():
            worms[worms[w].votedKick].kickVoted += 1
        else:
            worms[
                w].votedKick = None  #If player is not on the server, remove vote
        #Count team votes
        if worms[w].votedTeams:
            teams_voted += 1

    #Find most voted ones
    mostVotedMap = ""
    mostVotedPreset = ""
    for m in votedMaps.keys():
        if not mostVotedMap:
            mostVotedMap = m
        else:
            if votedMaps[m] > votedMaps[mostVotedMap]:
                mostVotedMap = m
    for p in votedPresets.keys():
        if not mostVotedPreset:
            mostVotedPreset = p
        else:
            if votedPresets[p] > votedPresets[mostVotedPreset]:
                mostVotedPreset = p

    #Announce voting status
    if "map" in send_msg and mostVotedMap:
        io.chatMsg("Most voted map: " + mostVotedMap)
    if "mod" in send_msg and mostVotedPreset:
        io.chatMsg("Most voted preset: " + mostVotedPreset)

    #Check teamgame votes
    if len(worms) != 0 and (float(teams_voted) / float(
            len(worms))) * 100 >= cfg.VOTING_PERCENT and len(
                worms) >= cfg.MIN_PLAYERS_TEAMS:
        teams_ready = True
    else:
        teams_ready = False

    #Announce team voting status
    if "teams" in send_msg and teams_voted != 0:
        if teams_ready:
            io.chatMsg(
                "Team voting status: Looks like the next game will be Team Deathmatch!"
            )
        elif len(worms) < cfg.MIN_PLAYERS_TEAMS:
            io.chatMsg(
                "Team voting status: Not enough players for team game (" +
                str(cfg.MIN_PLAYERS_TEAMS) + " is minimum)")
        elif (float(teams_voted) /
              float(len(worms))) * 100 < cfg.VOTING_PERCENT:
            io.chatMsg(
                "Team voting status: Not enough votes for team game yet")

    #Check kick votes
    for w in worms.keys():
        if (float(worms[w].kickVoted) /
                float(len(worms))) * 100 > cfg.VOTING_PERCENT:
            kickWithTime(w, "other players voted to kick you")

    #If we are safely in lobby, load settings
    if gameState == GAME_LOBBY and not vote_locked:
        #Set map and preset
        if mostVotedMap:
            loadMap(mostVotedMap)
        if mostVotedPreset:
            loadPreset(mostVotedPreset)
        #Set team game
        if teams_ready:
            if io.getGameType() == 0:
                io.setvar("GameOptions.GameInfo.GameType", 1)
                setupTeams()
        else:
            io.setvar("GameOptions.GameInfo.GameType", 0)

    #Announce team game status if 1) it has not been announced and 2) game type has been changed
    if not "teams" in send_msg and gametype_old != io.getGameType():
        if teams_ready:
            io.chatMsg(
                "Team voting status: Looks like the next game will be Team Deathmatch!"
            )
        elif len(worms) < cfg.MIN_PLAYERS_TEAMS:
            io.chatMsg(
                "Team voting status: Not enough players for team game (" +
                str(cfg.MIN_PLAYERS_TEAMS) + " is minimum)")
        elif (float(teams_voted) /
              float(len(worms))) * 100 < cfg.VOTING_PERCENT:
            io.chatMsg("Team voting status: Not enough votes for team game")

    return (mostVotedMap, mostVotedPreset, int(teams_ready))
Ejemplo n.º 5
0
def parseNewWorm(wormID, name):
    global worms

    exists = False
    try:
        worm = worms[wormID]
        exists = True
    except KeyError:  #Worm doesn't exist.
        worm = Worm()

    worm.real_name = name  #NOTE: This is the name used by the server
    #Now prepare the name used by the script - used for ranking, for example
    name = name.replace("\t", " ").strip(
    )  # Do not allow tab in names, it will screw up our ranking tab-separated text-file database
    #Check if the player has quotation marks in his/her name
    quotemarks_in_nick = 0
    if "\"" in name:
        name = name.replace(
            "\"", "\'\'"
        )  #Double quotes (") cause problems with chat/private messages - convert to single quotes (')
        quotemarks_in_nick = 1

    worm.Name = name
    worm.iID = wormID
    worm.Ping = []

    wormIP = io.getWormIP(wormID).split(":")[
        0]  #Get worm IP address now - it will be needed later
    worm.Ip = wormIP

    worms[wormID] = worm

    #Set team for handler ##NOTE: OLX sets a team when the player joins - and it may not always be 0 (blue)!!! So get the team number now!
    #TEST: Log these initial teams
    if cfg.TEAMCHANGE_LOGGING:
        io.messageLog(
            "TEAMJOIN: Game reports team " + str(io.getWormTeam(wormID)) +
            " for joining worm " + str(name), io.LOG_INFO)
    worm.Team = io.getWormTeam(wormID)

    # io.messageLog("Curtime " + str(time.time()) + " IP " + str(wormIP) + " Kicked worms: " + str(kickedUsers), io.LOG_INFO)
    if wormIP in kickedUsers and kickedUsers[wormIP] > time.time():
        io.kickWorm(
            wormID, "You can join in " +
            str(int(kickedUsers[wormIP] - time.time()) / 60 + 1) + " minutes")
        return

    #Original ranking authentication based on skin color...
    #NOTE: This is a weak way of authentication
    if cfg.RANKING_AUTHENTICATION:
        if not name in ranking.auth:
            ranking.auth[name] = getWormSkin(wormID)
            try:
                rank_auth_file_path = io.getWriteFullFileName(
                    cfg.RANKING_AUTH_FILE)
                f = open(rank_auth_file_path, "a")
                try:
                    portalocker.lock(f, portalocker.LOCK_EX)
                except:
                    pass
                f.write(name + "\t" + str(ranking.auth[name][0]) + " " +
                        ranking.auth[name][1] + "\n")
                f.close()
            except IOError:
                io.messageLog(
                    "parseNewWorm: Unable to open ranking authentication file: "
                    + cfg.RANKING_AUTH_FILE + " from path: " +
                    rank_auth_file_path, io.LOG_ERROR)
        else:
            if ranking.auth[name] != getWormSkin(wormID):
                io.kickWorm(wormID,
                            "Player with name %s already registered" % name)
                return

    #Notify or kick players that have forbidden nicks
    if name in cfg.FORBIDDEN_NAMES:
        if cfg.NAME_CHECK_ACTION == 1:
            worm.Name = "random" + str(random.randint(
                0, cfg.NAME_CHECK_RANDOM))  #Assign random name
            io.privateMsg(wormID, cfg.NAME_CHECK_WARNMSG)
        elif cfg.NAME_CHECK_ACTION == 2:
            io.kickWorm(wormID, cfg.NAME_CHECK_KICKMSG)
            return

    #NEW: Kick players who have newline tags in their nicks - those can cause annoyance
    #NOTE: This may give false positives if there are nested tags, but it's an unlikely case
    if detectFormattingTags(name):
        io.kickWorm(
            wormID,
            "Please remove formatting tags ( <...> ) from your nickname - they cause problems"
        )
        return

    #Kick players with excessively long nicks.
    #NOTE: In 0.59, oversized name are truncated automatically so this becomes obsolete
    if len(name) > cfg.MAX_NAME_LENGTH:
        io.kickWorm(wormID, "name too long")
        return

    #Kick players with quotation marks in their name (only if configured!)
    #NOTE: This should not be needed anymore
    if quotemarks_in_nick == 1 and cfg.KICK_QUOTEMARKS == 1:
        io.kickWorm(
            wormID,
            "please remove quotation marks from your nickname - they screw up ranking."
        )
        return

    #If only one player per IP allowed, check if there is already a player from the IP
    #NOTE: This is a weak check and may cause more harm than good as it prevents people behind a shared IP from joining while not really preventing rank manipulation
    if cfg.ONE_PLAYER_PER_IP:
        for w in worms.keys():
            if worms[w].Ip == wormIP and w != wormID:
                io.kickWorm(wormID, "only one player per IP address allowed")
                return

    #Nag players to download the latest version. 0.58 rc3 may still be in use, and this is less harsh than kicking.
    #TODO: Do this in a better way?
    if cfg.VERSION_CHECK:
        ver = io.getWormVersion(wormID)
        newest_ver = io.getVar("GameOptions.State.NewestVersion")
        #Newest version, everything OK
        if distutils.version.LooseVersion(
                ver.lower()) == distutils.version.LooseVersion(
                    newest_ver.lower()):
            pass
        #Outdated 0.58 versions and older
        elif distutils.version.LooseVersion(
                ver.lower()) < distutils.version.LooseVersion(
                    newest_ver.lower()):
            io.privateMsg(
                wormID, "You're using an outdated version! Please download " +
                newest_ver.replace("/", " ").replace("_", " ") +
                " from http://openlierox.net/")
        #0.59 b10 and later are buggy
        elif distutils.version.LooseVersion(
                ver.lower()) >= distutils.version.LooseVersion(
                    "OpenLieroX/0.59_beta10".lower()):
            io.privateMsg(
                wormID,
                "You're using a buggy version of the game! You may want to download "
                + newest_ver.replace("/", " ").replace("_", " ") +
                " from http://openlierox.net/")
        #Other 0.59 versions are not as buggy but they lack the nice updates of 0.58 rc5
        else:
            io.privateMsg(
                wormID,
                "You seem to be using an experimental version of the game! You may want to download "
                + newest_ver.replace("/", " ").replace("_", " ") +
                " from http://openlierox.net/")

    #Assign team
    if io.getGameType() == 1:
        worms[
            wormID].votedTeams = 1  #Set vote status to 1 so that it will be TDM if it was TDM before this player joined
        io.privateMsg(
            wormID,
            "Game type is team deathmatch - say !noteams if you do not want teams for the next game"
        )
        #NOTE: The player is already assigned to a team by the game! - so assigning him to the smallest team here would lead to unbalancement
        # if the team status were, for example, [4, 4]. So check whether 1) teams are balanced (difference <=1) or not, and 2) the player is not in the smallest team
        #NOTE: Calling balanceTeams might look more elegant, but it might move other players as well, and it should not be called when we are not in lobby
        #NOTE: Be careful with RandomTeamForNewWorm option! It may cause an exception!
        team_status = getNumberWormsInAllTeams()  #Get team member counts
        team_status = team_status[
            0:cfg.MAX_TEAMS]  #Remove teams that are not used
        wormteam = io.getWormTeam(
            wormID)  #Could use worm.Team too, but this might be safer...
        if (max(team_status) - min(team_status)
            ) > 1 and wormteam != team_status.index(min(team_status)):
            setTeam(wormID, team_status.index(min(team_status)))

    #Update votes - this is needed if there are, let's say, 3 players who all vote for TDM but TDM requires 4 - now there are 4 and 3 of them vote so TDM should be selected!
    #No need to broadcast anything - TDM is broadcasted if the status changes.
    updateVotes()
Ejemplo n.º 6
0
def controlHandlerDefault():

    global worms, gameState, lobbyChangePresetTimeout, lobbyWaitBeforeGame, lobbyWaitAfterGame
    global lobbyWaitGeneral, lobbyEnoughPlayers, oldGameState, scriptPaused, sentStartGame
    global currentAutocyclePreset, currentAutocycleMap
    global vote_locked, shuffle_counter

    if scriptPaused:
        return

    curTime = time.time()

    if gameState == GAME_LOBBY:

        # Do not check ping in lobby - it's wrong

        if oldGameState != GAME_LOBBY:
            lobbyEnoughPlayers = False  # reset the state
            lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
            lobbyWaitAfterGame = curTime
            if oldGameState == GAME_PLAYING:
                lobbyWaitAfterGame = curTime + cfg.WAIT_AFTER_GAME

            #Reset shuffle counter
            shuffle_counter = 0

            #Update votes when game ends
            updateResult = updateVotes(send_msg=("map", "mod", "teams"))
            #Autocycle if not voted
            #Advance autocycle counters first
            if not updateResult[0]:
                currentAutocycleMap += 1
                if currentAutocycleMap >= len(cfg.LEVELS):
                    currentAutocycleMap = 0
            if not updateResult[1]:
                currentAutocyclePreset += 1
                if currentAutocyclePreset >= len(cfg.PRESETS):
                    currentAutocyclePreset = 0
            ##Map
            if not updateResult[0]:
                io.setvar("GameOptions.GameInfo.LevelName",
                          cfg.LEVELS[currentAutocycleMap])
            ##Mod (preset)
            if not updateResult[1]:
                loadPreset(cfg.PRESETS[currentAutocyclePreset])

            #Check if teams are balanced
            ##This should be done because teams may become uneven if people leave during game and BALANCE_TEAMS_INGAME is not set
            if io.getGameType() == 1:
                io.chatMsg("Checking if teams are even...")
                balanceTeams(bmsg="game ended")

        if lobbyWaitAfterGame <= curTime:

            if not lobbyEnoughPlayers and lobbyWaitGeneral <= curTime:
                lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
                io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

            if not lobbyEnoughPlayers and len(
                    worms
            ) >= cfg.MIN_PLAYERS:  # Enough players already - start game
                lobbyEnoughPlayers = True
                io.chatMsg(cfg.WAIT_BEFORE_GAME_MESSAGE)
                lobbyWaitBeforeGame = curTime + cfg.WAIT_BEFORE_GAME

            if lobbyEnoughPlayers and len(
                    worms
            ) < cfg.MIN_PLAYERS:  # Some players left when game not yet started
                lobbyEnoughPlayers = False
                io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

            if lobbyEnoughPlayers and not sentStartGame:

                if lobbyWaitBeforeGame <= curTime:  # Start the game

                    #Starting game...		##NOTE Removed team check from here - teams should be assigned before the round starts
                    if io.startGame():
                        if cfg.ALLOW_TEAM_CHANGE and len(
                                worms) >= cfg.MIN_PLAYERS_TEAMS:
                            io.chatMsg(cfg.TEAM_CHANGE_MESSAGE)
                        sentStartGame = True
                        vote_locked = True  #Lock vote-able settings when starting
                        clearVotes()  #Clear votes when starting
                    else:
                        io.messageLog("Game could not be started",
                                      io.LOG_ERROR)  #Log these errors!
                        io.chatMsg("Game could not be started")
                        oldGameState == GAME_PLAYING  # hack that it resets at next control handler call

    if gameState == GAME_WEAPONS:

        # if we allow empty games, ignore this check
        if len(worms) < cfg.MIN_PLAYERS and not io.getVar(
                "GameOptions.GameInfo.AllowEmptyGames"
        ):  # Some players left when game not yet started
            io.chatMsg("Too few players -> back to lobby")
            io.gotoLobby()
            sentStartGame = False

    if gameState == GAME_PLAYING:

        if cfg.PING_CHECK:
            checkMaxPing()

    #Unlock voting when the game is safely running
    if (gameState == GAME_WEAPONS or gameState
            == GAME_PLAYING) and oldGameState != GAME_LOBBY and vote_locked:
        vote_locked = False
def controlHandlerDefault():

    global worms, gameState, lobbyChangePresetTimeout, lobbyWaitBeforeGame, lobbyWaitAfterGame
    global lobbyWaitGeneral, lobbyEnoughPlayers, oldGameState, scriptPaused, sentStartGame
    global presetCicler, modCicler, mapCicler, LT_Cicler
    global videoRecorder, videoRecorderSignalTime

    if scriptPaused:
        return

    curTime = time.time()
    cmds.recheckVote(False)

    if gameState == GAME_LOBBY:

        # Do not check ping in lobby - it's wrong

        if oldGameState != GAME_LOBBY:
            mapCicler.check()
            modCicler.check()
            LT_Cicler.check()
            presetCicler.check()
            lobbyEnoughPlayers = False  # reset the state
            lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
            lobbyWaitAfterGame = curTime
            if oldGameState == GAME_PLAYING:
                lobbyWaitAfterGame = curTime + cfg.WAIT_AFTER_GAME
            if videoRecorder:
                os.kill(
                    videoRecorder.pid, signal.SIGINT
                )  # videoRecorder.send_signal(signal.SIGINT) # This is available only on Python 2.6
                videoRecorderSignalTime = time.time()
                io.chatMsg("Waiting for video recorder to finish")

        canStart = True
        if videoRecorder and videoRecorder.returncode == None:
            canStart = False
            videoRecorder.poll()
            if time.time(
            ) - videoRecorderSignalTime > cfg.TIME_TO_KILL_VIDEORECORDER:
                io.chatMsg("Video recorder stalled, killing")
                os.kill(videoRecorder.pid, signal.SIGKILL)
                videoRecorder.poll()
            if videoRecorder.returncode != None:
                io.chatMsg("Video recorder encoding took " +
                           str(int(time.time() - videoRecorderSignalTime)) +
                           " secs")
                canStart = True
                videoRecorder = None

        if lobbyWaitAfterGame <= curTime:

            if not lobbyEnoughPlayers and lobbyWaitGeneral <= curTime:
                lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
                io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

            if not lobbyEnoughPlayers and len(
                    worms
            ) >= cfg.MIN_PLAYERS:  # Enough players already - start game
                lobbyEnoughPlayers = True
                io.chatMsg(cfg.WAIT_BEFORE_GAME_MESSAGE)
                lobbyWaitBeforeGame = curTime + cfg.WAIT_BEFORE_GAME

            if lobbyEnoughPlayers and len(
                    worms
            ) < cfg.MIN_PLAYERS:  # Some players left when game not yet started
                lobbyEnoughPlayers = False
                io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

            if lobbyEnoughPlayers and not sentStartGame:

                if lobbyWaitBeforeGame <= curTime and canStart:  # Start the game

                    if io.getGameType() in ["Death Match", "Team Death Match"]:
                        if len(worms
                               ) >= cfg.MIN_PLAYERS_TEAMS:  # Split in teams
                            setvar("GameOptions.GameInfo.GameType",
                                   "Team Death Match")
                            if not cfg.ALLOW_TEAM_CHANGE:
                                counter = 0
                                for w in worms.values():
                                    if w.iID != -1:
                                        io.setWormTeam(w.iID,
                                                       counter % cfg.MAX_TEAMS)
                                        counter += 1
                        else:
                            io.setvar("GameOptions.GameInfo.GameType",
                                      "Death Match")

                    if io.startGame():
                        if cfg.ALLOW_TEAM_CHANGE and len(
                                worms) >= cfg.MIN_PLAYERS_TEAMS:
                            io.chatMsg(cfg.TEAM_CHANGE_MESSAGE)
                        sentStartGame = True
                        if cfg.RECORD_VIDEO:
                            try:
                                #io.messageLog("Running dedicated-video-record.sh, curdir " + os.path.abspath(os.path.curdir) ,io.LOG_INFO)
                                videoRecorder = subprocess.Popen(
                                    [
                                        "./dedicated-video-record.sh",
                                        "./dedicated-video-record.sh"
                                    ],
                                    stdin=open("/dev/null", "r"),
                                    stdout=open("../../../dedicatedVideo.log",
                                                "w"),
                                    stderr=subprocess.STDOUT,
                                    cwd="..")
                            except:
                                io.messageLog(formatExceptionInfo(),
                                              io.LOG_ERROR)
                    else:
                        io.chatMsg("Game could not be started")
                        oldGameState == GAME_PLAYING  # hack that it resets at next control handler call

    if gameState == GAME_WEAPONS:

        #checkMaxPing()

        # if we allow empty games, ignore this check
        if len(worms) < cfg.MIN_PLAYERS and not io.getVar(
                "GameOptions.GameInfo.AllowEmptyGames"
        ):  # Some players left when game not yet started
            io.chatMsg("Too less players -> back to lobby")
            io.gotoLobby()
            sentStartGame = False

    if gameState == GAME_PLAYING:

        checkMaxPing()
def parseNewWorm(wormID, name):
    global worms

    name = name.replace("\t", " ").strip(
    )  # Do not allow tab in names, it will screw up our ranking tab-separated text-file database
    exists = False
    try:
        worm = worms[wormID]
        exists = True
    except KeyError:  #Worm doesn't exist.
        worm = Worm()
    worm.Name = name
    worm.iID = wormID
    worm.Ping = []

    worms[wormID] = worm

    if io.getGameType() == "Hide and Seek":
        minSeekers = 1
        if len(worms.values()) >= 4: minSeekers = 2
        if io.getNumberWormsInTeam(1) < minSeekers:
            io.setWormTeam(wormID, 1)  # Seeker
        else:
            io.setWormTeam(wormID, 0)  # Hider
    else:
        # Balance teams
        teams = [0, 0, 0, 0]
        for w in worms.keys():
            teams[worms[w].Team] += 1
        minTeam = 0
        minTeamCount = teams[0]
        for f in range(cfg.MAX_TEAMS):
            if minTeamCount > teams[f]:
                minTeamCount = teams[f]
                minTeam = f

        io.setWormTeam(wormID, minTeam)

    if cfg.RANKING_AUTHENTICATION:
        if not name in ranking.auth:
            ranking.auth[name] = getWormSkin(wormID)
            try:
                f = open(io.getFullFileName("pwn0meter_auth.txt"), "r")
                try:
                    portalocker.lock(f, portalocker.LOCK_EX)
                except:
                    pass
                f.write(name + "\t" + str(ranking.auth[name][0]) + " " +
                        ranking.auth[name][1] + "\n")
                f.close()
            except IOError:
                msg("ERROR: Unable to open pwn0meter_auth.txt")
        else:
            if ranking.auth[name] != getWormSkin(wormID):
                io.kickWorm(wormID,
                            "Player with name %s already registered" % name)

    wormIP = io.getWormIP(wormID).split(":")[0]
    # io.messageLog("Curtime " + str(time.time()) + " IP " + str(wormIP) + " Kicked worms: " + str(cmds.kickedUsers), io.LOG_INFO)
    if wormIP in cmds.kickedUsers and cmds.kickedUsers[wormIP] > time.time():
        io.kickWorm(
            wormID, "You can join in " +
            str(int(cmds.kickedUsers[wormIP] - time.time()) / 60 + 1) +
            " minutes")
        return
    cmds.recheckVote()
def controlHandlerDefault():

	global worms, gameState, lobbyChangePresetTimeout, lobbyWaitBeforeGame, lobbyWaitAfterGame
	global lobbyWaitGeneral, lobbyEnoughPlayers, oldGameState, scriptPaused, sentStartGame
	global presetCicler, modCicler, mapCicler, LT_Cicler
	global videoRecorder, videoRecorderSignalTime
	
	if scriptPaused:
		return

	curTime = time.time()
	cmds.recheckVote(False)
	
	if gameState == GAME_LOBBY:

		# Do not check ping in lobby - it's wrong

		if oldGameState != GAME_LOBBY:
			mapCicler.check()
			modCicler.check()
			LT_Cicler.check()
			presetCicler.check()
			lobbyEnoughPlayers = False # reset the state
			lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
			lobbyWaitAfterGame = curTime
			if oldGameState == GAME_PLAYING:
				lobbyWaitAfterGame = curTime + cfg.WAIT_AFTER_GAME
			if videoRecorder:
				os.kill(videoRecorder.pid, signal.SIGINT)  # videoRecorder.send_signal(signal.SIGINT) # This is available only on Python 2.6
				videoRecorderSignalTime = time.time()
				io.chatMsg("Waiting for video recorder to finish")

		canStart = True
		if videoRecorder and videoRecorder.returncode == None:
			canStart = False
			videoRecorder.poll()
			if time.time() - videoRecorderSignalTime > cfg.TIME_TO_KILL_VIDEORECORDER:
				io.chatMsg("Video recorder stalled, killing")
				os.kill(videoRecorder.pid, signal.SIGKILL)
				videoRecorder.poll()
			if videoRecorder.returncode != None:
				io.chatMsg("Video recorder encoding took " + str(int(time.time() - videoRecorderSignalTime)) + " secs")
				canStart = True
				videoRecorder = None

		if lobbyWaitAfterGame <= curTime:

			if not lobbyEnoughPlayers and lobbyWaitGeneral <= curTime:
				lobbyWaitGeneral = curTime + cfg.WAIT_BEFORE_SPAMMING_TOO_FEW_PLAYERS_MESSAGE
				io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

			if not lobbyEnoughPlayers and len(worms) >= cfg.MIN_PLAYERS: # Enough players already - start game
				lobbyEnoughPlayers = True
				io.chatMsg(cfg.WAIT_BEFORE_GAME_MESSAGE)
				lobbyWaitBeforeGame = curTime + cfg.WAIT_BEFORE_GAME

			if lobbyEnoughPlayers and len(worms) < cfg.MIN_PLAYERS: # Some players left when game not yet started
				lobbyEnoughPlayers = False
				io.chatMsg(cfg.TOO_FEW_PLAYERS_MESSAGE)

			if lobbyEnoughPlayers and not sentStartGame:

				if lobbyWaitBeforeGame <= curTime and canStart: # Start the game

					if io.getGameType() in ["Death Match","Team Death Match"]:
						if len(worms) >= cfg.MIN_PLAYERS_TEAMS: # Split in teams
							setvar("GameOptions.GameInfo.GameType", "Team Death Match")
							if not cfg.ALLOW_TEAM_CHANGE:
								counter = 0
								for w in worms.values():
									if w.iID != -1:
										io.setWormTeam( w.iID, counter % cfg.MAX_TEAMS )
										counter += 1
						else:
							io.setvar("GameOptions.GameInfo.GameType", "Death Match")

					if io.startGame():
						if cfg.ALLOW_TEAM_CHANGE and len(worms) >= cfg.MIN_PLAYERS_TEAMS:
							io.chatMsg(cfg.TEAM_CHANGE_MESSAGE)
						sentStartGame = True
						if cfg.RECORD_VIDEO:
							try:
								#io.messageLog("Running dedicated-video-record.sh, curdir " + os.path.abspath(os.path.curdir) ,io.LOG_INFO)
								videoRecorder = subprocess.Popen( ["./dedicated-video-record.sh", "./dedicated-video-record.sh"],
												stdin=open("/dev/null","r"), stdout=open("../../../dedicatedVideo.log","w"),
												stderr=subprocess.STDOUT, cwd=".." )
							except:
								io.messageLog(formatExceptionInfo(),io.LOG_ERROR)
					else:
						io.chatMsg("Game could not be started")
						oldGameState == GAME_PLAYING # hack that it resets at next control handler call
					
	if gameState == GAME_WEAPONS:

		#checkMaxPing()

		# if we allow empty games, ignore this check
		if len(worms) < cfg.MIN_PLAYERS and not io.getVar("GameOptions.GameInfo.AllowEmptyGames"): # Some players left when game not yet started
			io.chatMsg("Too less players -> back to lobby")
			io.gotoLobby()
			sentStartGame = False

	if gameState == GAME_PLAYING:

		checkMaxPing()