Running a Server

AutoChangeMapMut: Change the Map When Nobody Can Join a Killing Floor Server

Sometimes, after a Killing Floor dedicated server restarts, nobody can join even though the server is running. The log fills with:

RecvFrom returned SOCKET_ERROR 111
RecvFrom returned SOCKET_ERROR 113

On Linux, 111 is "connection refused" and 113 is "no route to host". Flame from killingfloor.ru ran into this on Linux servers in 2012, possibly after a game patch, and found that changing the map fixes it. Rather than wait for an admin, he wrote a mutator that does the change automatically.

What the mutator does

  • After the map starts, it checks once a minute whether at least one player has connected.
  • As soon as somebody is in, it stops checking for the rest of the map.
  • If the match is still waiting to start and the wait exceeds waitingInterval, it calls RestartGame() with level changes allowed, and the server moves to the next map in the rotation.

The switch is not instant: allow up to a minute for the timer plus about 48 seconds for the map change itself.

Installation

  1. Compile the source below (see ucc make) or take the original package.
  2. Add the mutator to the server's mutator list as AutoChangeMapMut.AutoChangeMapMut.
  3. Set the wait time in seconds in AutoChangeMapMut.ini:
[AutoChangeMapMut.AutoChangeMapMut]
waitingInterval=600

The forum post says the default is 10 minutes, but the published source has waitingInterval=7200 (two hours). Set the value explicitly.

Source code

class AutoChangeMapMut extends Mutator config(AutoChangeMapMut);

var config int waitingInterval;
var int startWaiting;
var bool playersCanConnect;

function PostBeginPlay()
{
    startWaiting = Level.TimeSeconds;
    playersCanConnect = false;
    SetTimer(60.0, true);
}

function Timer()
{
    local int playersN;

    // once at least one player got in, stop checking
    if (playersCanConnect)
        return;
    // only act while the match is waiting to start
    if (!Level.Game.bWaitingToStartMatch)
        return;

    playersN = PlayersNumber();
    if (playersN > 0)
    {
        playersCanConnect = true;
        return;
    }

    if (Level.TimeSeconds - startWaiting >= waitingInterval)
    {
        Level.Game.bChangeLevels = true;
        Level.Game.bAlreadyChanged = false;
        Level.Game.RestartGame();
    }
}

function int PlayersNumber()
{
    local int N;
    local Controller C;

    for (C = Level.ControllerList; C != None; C = C.NextController)
    {
        if (C.IsA('PlayerController') && C.PlayerReplicationInfo.PlayerID > 0)
            N++;
    }
    return N;
}

defaultproperties
{
    waitingInterval=7200
    bAddToServerPackages=True
    GroupName="AutoChangeMapMut"
    FriendlyName="AutoChangeMapMut"
    Description="Changes the map if nobody plays on current map for a period of time"
}

How it works

  • bChangeLevels = true and bAlreadyChanged = false make RestartGame() advance the map rotation instead of restarting the current map.
  • PlayersNumber() counts every PlayerController with a valid PlayerID, so spectators count too. A spectator who did get in is proof that connections work.
  • bAddToServerPackages=True is not needed for a server-only mutator: nothing runs on clients. You can set it to False so clients do not download the package.

Side effects

  • On a quiet server the mutator also changes the map when the server is simply empty: it cannot tell "nobody can connect" from "nobody came". With a long interval this is harmless.
  • It does not fix the network problem itself. If the errors come back after every restart, check the firewall and ports (7707 UDP for the game, 7708 UDP for queries, 28852 for the master server) and which network interface the server binds to.

What else helped

Another server owner had the same symptom on a LAN where the server sat on two networks (a router plus a direct LAN). After a map change one network could connect and the other could not see the server until the next change. The server ran Windows 7, and moving it to Windows Server 2008 made the problem go away.

Two more cases from the killingfloor.ru forum:

  • Only one player gets in, or the connection hangs forever. In the thread "Проблема: "Не удается установить соединение"" (Problem: "Unable to connect", 2013) the server still counted the only player as present (1/30) after he left and let nobody in until the map changed; raising the number of spectator slots fixed it. In the thread "Не заходит на сервер" (Can't join the server, 2012) DominatorRUS fixed endless connecting to a Linux server like this: KillingFloor.ini had MaxSpectators=0, and after changing it to MaxSpectators=2 everything worked.
  • A mutator is to blame. In the same thread MaxSpectators did not help another admin: the server stopped letting players in after one or two map changes until the admin switched the map by hand. By disabling all mutators and enabling them one at a time he found the culprits: the Kill Message mutator and a mutator that drops the whole inventory. According to him, the server worked with Kill Message on version 1032 and started misbehaving from 1033.