Allow hosting matches with 8 players and up to 16 observers, fixes #3254.
The host can change the number of allowed observers in running games. Make sure that joining observers won't take the "slot" of disconnected players, fixes #3671. Send clients a new disconnect reason "Server full" instead of letting them timeout. This was SVN commit r17881.
This commit is contained in:
parent
dbbc600dc3
commit
042c9a9334
@ -354,6 +354,7 @@ enabledmods = "mod public"
|
||||
[network]
|
||||
duplicateplayernames = false ; Rename joining player to "User (2)" if "User" is already connected, otherwise prohibit join.
|
||||
lateobserverjoins = false ; Allow observers to join the game after it started
|
||||
observerlimit = 6 ; Prevent further observer joins in running games if this limit is reached
|
||||
|
||||
[overlay]
|
||||
fps = "false" ; Show frames per second in top right corner
|
||||
|
@ -58,6 +58,7 @@ function getDisconnectReason(id)
|
||||
case 5: return translate("You have been kicked");
|
||||
case 6: return translate("You have been banned");
|
||||
case 7: return translate("Playername in use. If you were disconnected, retry in few seconds");
|
||||
case 8: return translate("Server full");
|
||||
default:
|
||||
warn("Unknown disconnect-reason ID received: " + id);
|
||||
return sprintf(translate("\\[Invalid value %(id)s]"), { "id": id });
|
||||
|
@ -66,6 +66,12 @@
|
||||
"label": "Late Observer Joins",
|
||||
"tooltip": "Allow observers to join the game after it started",
|
||||
"parameters": { "config": "network.lateobserverjoins" }
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"label": "Observer Limit",
|
||||
"tooltip": "Prevent further observer from joining if the limit is reached",
|
||||
"parameters": { "config": "network.observerlimit", "min": 0, "max": 16 }
|
||||
}
|
||||
],
|
||||
"graphicsSetting":
|
||||
|
@ -66,7 +66,8 @@ enum NetDisconnectReason
|
||||
NDR_SERVER_ALREADY_IN_GAME,
|
||||
NDR_KICKED,
|
||||
NDR_BANNED,
|
||||
NDR_PLAYERNAME_IN_USE
|
||||
NDR_PLAYERNAME_IN_USE,
|
||||
NDR_SERVER_FULL
|
||||
};
|
||||
|
||||
class CNetHost
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#define PS_PROTOCOL_MAGIC 0x5073013f // 'P', 's', 0x01, '?'
|
||||
#define PS_PROTOCOL_MAGIC_RESPONSE 0x50630121 // 'P', 'c', 0x01, '!'
|
||||
#define PS_PROTOCOL_VERSION 0x01010010 // Arbitrary protocol
|
||||
#define PS_PROTOCOL_VERSION 0x01010011 // Arbitrary protocol
|
||||
#define PS_DEFAULT_PORT 0x5073 // 'P', 's'
|
||||
|
||||
// Defines the list of message types. The order of the list must not change.
|
||||
|
@ -39,9 +39,16 @@
|
||||
#include <miniupnpc/upnperrors.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Number of peers to allocate for the enet host.
|
||||
* Limited by ENET_PROTOCOL_MAXIMUM_PEER_ID (4096).
|
||||
*
|
||||
* At most 8 players, 16 observers and 1 temporary connection to send the "server full" disconnect-reason.
|
||||
*/
|
||||
#define MAX_CLIENTS 25
|
||||
|
||||
#define DEFAULT_SERVER_NAME L"Unnamed Server"
|
||||
#define DEFAULT_WELCOME_MESSAGE L"Welcome"
|
||||
#define MAX_CLIENTS 10
|
||||
|
||||
static const int CHANNEL_COUNT = 1;
|
||||
|
||||
@ -929,19 +936,39 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event)
|
||||
bool observerLateJoin = false;
|
||||
CFG_GET_VAL("network.lateobserverjoins", observerLateJoin);
|
||||
|
||||
// If the game has already started, only allow rejoins
|
||||
int maxObservers = 0;
|
||||
CFG_GET_VAL("network.observerlimit", maxObservers);
|
||||
|
||||
bool isRejoining = false;
|
||||
if (server.m_State != SERVER_STATE_PREGAME)
|
||||
bool serverFull = false;
|
||||
if (server.m_State == SERVER_STATE_PREGAME)
|
||||
{
|
||||
// Search for an old disconnected player of the same name
|
||||
// Don't check for maxObservers in the gamesetup, as we don't know yet who will be assigned
|
||||
serverFull = server.m_Sessions.size() >= MAX_CLIENTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
isRejoining = observerLateJoin;
|
||||
bool isObserver = true;
|
||||
int disconnectedPlayers = 0;
|
||||
int connectedPlayers = 0;
|
||||
// (TODO: if GUIDs were stable, we should use them instead)
|
||||
isRejoining =
|
||||
observerLateJoin ||
|
||||
std::find_if(
|
||||
server.m_PlayerAssignments.begin(), server.m_PlayerAssignments.end(),
|
||||
[&username] (const std::pair<CStr, PlayerAssignment>& pair)
|
||||
{ return !pair.second.m_Enabled && pair.second.m_Name == username; })
|
||||
!= server.m_PlayerAssignments.end();
|
||||
for (PlayerAssignmentMap::iterator it = server.m_PlayerAssignments.begin(); it != server.m_PlayerAssignments.end(); ++it)
|
||||
{
|
||||
if (!it->second.m_Enabled && it->second.m_Name == username)
|
||||
{
|
||||
isObserver = it->second.m_PlayerID == -1;
|
||||
isRejoining = true;
|
||||
}
|
||||
|
||||
if (it->second.m_PlayerID == -1)
|
||||
continue;
|
||||
|
||||
if (it->second.m_Enabled)
|
||||
++connectedPlayers;
|
||||
else
|
||||
++disconnectedPlayers;
|
||||
}
|
||||
|
||||
// Players who weren't already in the game are not allowed to join now that it's started
|
||||
if (!isRejoining)
|
||||
@ -950,6 +977,17 @@ bool CNetServerWorker::OnAuthenticate(void* context, CFsmEvent* event)
|
||||
session->Disconnect(NDR_SERVER_ALREADY_IN_GAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure all players will be able to rejoin
|
||||
serverFull = isObserver && (
|
||||
(int) server.m_Sessions.size() - connectedPlayers > maxObservers ||
|
||||
(int) server.m_Sessions.size() + disconnectedPlayers >= MAX_CLIENTS);
|
||||
}
|
||||
|
||||
if (serverFull)
|
||||
{
|
||||
session->Disconnect(NDR_SERVER_FULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: check server password etc?
|
||||
|
Loading…
Reference in New Issue
Block a user