diff --git a/binaries/data/config/default.cfg b/binaries/data/config/default.cfg index d9efa0a2d9..a82f79aae2 100644 --- a/binaries/data/config/default.cfg +++ b/binaries/data/config/default.cfg @@ -388,7 +388,7 @@ enabledmods = "mod public" [network] duplicateplayernames = false ; Rename joining player to "User (2)" if "User" is already connected, otherwise prohibit join. -lateobserverjoins = true ; Allow observers to join the game after it started +lateobservers = buddies ; Allow observers to join the game after it started. Possible values: disabled, buddies, everyone. observerlimit = 8 ; Prevent further observer joins in running games if this limit is reached [overlay] diff --git a/binaries/data/mods/public/gui/options/options.json b/binaries/data/mods/public/gui/options/options.json index 6d2e5f34cc..44c31a1357 100644 --- a/binaries/data/mods/public/gui/options/options.json +++ b/binaries/data/mods/public/gui/options/options.json @@ -93,10 +93,17 @@ } }, { - "type": "boolean", + "type": "dropdown", "label": "Late Observer Joins", - "tooltip": "Allow observers to join the game after it started", - "parameters": { "config": "network.lateobserverjoins" } + "tooltip": "Allow everybody or buddies only to join the game as observer after it started", + "parameters": { + "config": "network.lateobservers", + "list": [ + { "value": "everyone", "label": "Everyone" }, + { "value": "buddies", "label": "Buddies" }, + { "value": "disabled", "label": "Disabled" } + ] + } }, { "type": "number", diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp index 977e34fe20..f9b086d109 100644 --- a/source/network/NetServer.cpp +++ b/source/network/NetServer.cpp @@ -930,10 +930,6 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event) return true; } - // Optionally allow observers to join after the game has started - bool observerLateJoin = false; - CFG_GET_VAL("network.lateobserverjoins", observerLateJoin); - int maxObservers = 0; CFG_GET_VAL("network.observerlimit", maxObservers); @@ -946,7 +942,6 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event) } else { - isRejoining = observerLateJoin; bool isObserver = true; int disconnectedPlayers = 0; int connectedPlayers = 0; @@ -970,7 +965,36 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event) ++disconnectedPlayers; } - // Players who weren't already in the game are not allowed to join now that it's started + // Optionally allow everyone or only buddies to join after the game has started + if (!isRejoining) + { + CStr observerLateJoin; + CFG_GET_VAL("network.lateobservers", observerLateJoin); + + if (observerLateJoin == "everyone") + { + isRejoining = true; + } + else if (observerLateJoin == "buddies") + { + std::size_t pos = username.find(L" ("); + CStrW usernameWithoutRating(pos == CStrW::npos ? username : username.substr(0, pos)); + + CStr buddies; + CFG_GET_VAL("lobby.buddies", buddies); + std::wstringstream buddiesStream(wstring_from_utf8(buddies)); + CStrW buddy; + while (std::getline(buddiesStream, buddy, L',')) + { + if (buddy == usernameWithoutRating) + { + isRejoining = true; + break; + } + } + } + } + if (!isRejoining) { LOGMESSAGE("Refused connection after game start from not-previously-known user \"%s\"", utf8_from_wstring(username));