Ticket #3254: t3254_arbitrary_observer_limit_v1.patch

File t3254_arbitrary_observer_limit_v1.patch, 6.1 KB (added by elexis, 5 years ago)
  • binaries/data/config/default.cfg

    xpartamupp = "wfgbot20" ; Na  
    352352enabledmods = "mod public"
    353353
    354354[network]
    355355duplicateplayernames = false      ; Rename joining player to "User (2)" if "User" is already connected, otherwise prohibit join.
    356356lateobserverjoins = false         ; Allow observers to join the game after it started
     357observerlimit = 5                 ; Allow observers to join the game after it started
    357358
    358359[overlay]
    359360fps = "false"                     ; Show frames per second in top right corner
    360361realtime = "false"                ; Show current system time in top right corner
    361362netwarnings = "true"              ; Show warnings if the network connection is bad
  • binaries/data/mods/public/gui/common/network.js

    function getDisconnectReason(id)  
    5656    case 3: return translate("Game is loading, please try later");
    5757    case 4: return translate("Game has already started, no observers allowed");
    5858    case 5: return translate("You have been kicked");
    5959    case 6: return translate("You have been banned");
    6060    case 7: return translate("Playername in use. If you were disconnected, retry in few seconds");
     61    case 8: return translate("Server full");
    6162    default:
    6263        warn("Unknown disconnect-reason ID received: " + id);
    6364        return sprintf(translate("\\[Invalid value %(id)s]"), { "id": id });
    6465    }
    6566}
  • binaries/data/mods/public/gui/options/options.json

     
    6464        {
    6565            "type": "boolean",
    6666            "label": "Late Observer Joins",
    6767            "tooltip": "Allow observers to join the game after it started",
    6868            "parameters": { "config": "network.lateobserverjoins" }
     69        },
     70        {
     71            "type": "number",
     72            "label": "Observer Limit",
     73            "tooltip": "Prevent further observer from joining if the limit is reached",
     74            "parameters": { "config": "network.observerlimit", "min": 0, "max": 16 }
    6975        }
    7076    ],
    7177    "graphicsSetting":
    7278    [
    7379        {
  • source/network/NetHost.h

    enum NetDisconnectReason  
    6464    NDR_INCORRECT_PROTOCOL_VERSION,
    6565    NDR_SERVER_LOADING,
    6666    NDR_SERVER_ALREADY_IN_GAME,
    6767    NDR_KICKED,
    6868    NDR_BANNED,
    69     NDR_PLAYERNAME_IN_USE
     69    NDR_PLAYERNAME_IN_USE,
     70    NDR_SERVER_FULL
    7071};
    7172
    7273class CNetHost
    7374{
    7475public:
  • source/network/NetServer.cpp

     
    3737#include <miniupnpc/miniupnpc.h>
    3838#include <miniupnpc/upnpcommands.h>
    3939#include <miniupnpc/upnperrors.h>
    4040#endif
    4141
     42/**
     43 * Number of peers to allocate for the enet host.
     44 * Limited by ENET_PROTOCOL_MAXIMUM_PEER_ID (4096).
     45 *
     46 * At most 8 players, 16 observers and 1 temporary connection to send the "server full" disconnect-reason.
     47 */
     48#define MAX_CLIENTS 25
     49
    4250#define DEFAULT_SERVER_NAME         L"Unnamed Server"
    4351#define DEFAULT_WELCOME_MESSAGE     L"Welcome"
    44 #define MAX_CLIENTS                 10
    4552
    4653static const int CHANNEL_COUNT = 1;
    4754
    4855/**
    4956 * enet_host_service timeout (msecs).
    bool CNetServerWorker::OnAuthenticate(vo  
    927934
    928935    // Optionally allow observers to join after the game has started
    929936    bool observerLateJoin = false;
    930937    CFG_GET_VAL("network.lateobserverjoins", observerLateJoin);
    931938
    932     // If the game has already started, only allow rejoins
     939    int maxObservers = 0;
     940    CFG_GET_VAL("network.observerlimit", maxObservers);
     941
    933942    bool isRejoining = false;
    934     if (server.m_State != SERVER_STATE_PREGAME)
     943    bool serverFull = false;
     944    if (server.m_State == SERVER_STATE_PREGAME)
    935945    {
    936         // Search for an old disconnected player of the same name
    937         // (TODO: if GUIDs were stable, we should use them instead)
    938         isRejoining =
    939             observerLateJoin ||
    940             std::find_if(
    941                 server.m_PlayerAssignments.begin(), server.m_PlayerAssignments.end(),
    942                 [&username] (const std::pair<CStr, PlayerAssignment>& pair)
    943                 { return !pair.second.m_Enabled && pair.second.m_Name == username; })
    944             != server.m_PlayerAssignments.end();
     946        // Don't check for maxObservers in the gamesetup, as we don't know who will be assigned
     947        serverFull = server.m_Sessions.size() >= MAX_CLIENTS;
     948    }
     949    else
     950    {
     951        isRejoining = observerLateJoin;
     952        bool isObserver = true;
     953        int disconnectedPlayers = 0;
     954        int connectedPlayers = 0;
     955        for (PlayerAssignmentMap::iterator it = server.m_PlayerAssignments.begin(); it != server.m_PlayerAssignments.end(); ++it)
     956        {
     957            // (TODO: if GUIDs were stable, we should use them instead)
     958            if (!it->second.m_Enabled && it->second.m_Name == username)
     959            {
     960                isObserver = it->second.m_PlayerID == -1;
     961                isRejoining = true;
     962            }
     963
     964            if (it->second.m_PlayerID == -1)
     965                continue;
    945966
     967            if (it->second.m_Enabled)
     968                ++connectedPlayers;
     969            else
     970                ++disconnectedPlayers;
     971        }
     972
     973        // If the game has already started, only allow rejoins
    946974        // Players who weren't already in the game are not allowed to join now that it's started
    947975        if (!isRejoining)
    948976        {
    949977            LOGMESSAGE("Refused connection after game start from not-previously-known user \"%s\"", utf8_from_wstring(username));
    950978            session->Disconnect(NDR_SERVER_ALREADY_IN_GAME);
    951979            return true;
    952980        }
     981
     982        // Ensure all players will be able to rejoin
     983        serverFull = isObserver && (
     984            (int) server.m_Sessions.size() - connectedPlayers > maxObservers ||
     985            (int) server.m_Sessions.size() + disconnectedPlayers >= MAX_CLIENTS);
     986    }
     987
     988    if (serverFull)
     989    {
     990        session->Disconnect(NDR_SERVER_FULL);
     991        return true;
    953992    }
    954993
    955994    // TODO: check server password etc?
    956995
    957996    u32 newHostID = server.m_NextHostID++;