mirror of
https://github.com/glest/glest-source.git
synced 2025-08-26 17:34:24 +02:00
- added optional server game pause if client lags
This commit is contained in:
@@ -42,6 +42,8 @@ bool enabledThreadedClientCommandBroadcast = false;
|
|||||||
int maxFrameCountLagAllowed = 20;
|
int maxFrameCountLagAllowed = 20;
|
||||||
// 65% of max we warn all users about the lagged client
|
// 65% of max we warn all users about the lagged client
|
||||||
double warnFrameCountLagPercent = 0.65;
|
double warnFrameCountLagPercent = 0.65;
|
||||||
|
// Should we wait for lagged clients instead of disconnect them?
|
||||||
|
bool pauseGameForLaggedClients = false;
|
||||||
|
|
||||||
ServerInterface::ServerInterface(){
|
ServerInterface::ServerInterface(){
|
||||||
gameHasBeenInitiated = false;
|
gameHasBeenInitiated = false;
|
||||||
@@ -51,7 +53,8 @@ ServerInterface::ServerInterface(){
|
|||||||
enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast","false");
|
enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast","false");
|
||||||
maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed",intToStr(maxFrameCountLagAllowed).c_str());
|
maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed",intToStr(maxFrameCountLagAllowed).c_str());
|
||||||
warnFrameCountLagPercent = Config::getInstance().getFloat("WarnFrameCountLagPercent",doubleToStr(warnFrameCountLagPercent).c_str());
|
warnFrameCountLagPercent = Config::getInstance().getFloat("WarnFrameCountLagPercent",doubleToStr(warnFrameCountLagPercent).c_str());
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] enabledThreadedClientCommandBroadcast = %d, maxFrameCountLagAllowed = %d\n",__FILE__,__FUNCTION__,__LINE__,enabledThreadedClientCommandBroadcast,maxFrameCountLagAllowed);
|
pauseGameForLaggedClients = Config::getInstance().getFloat("PauseGameForLaggedClients",boolToStr(pauseGameForLaggedClients).c_str());
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] enabledThreadedClientCommandBroadcast = %d, maxFrameCountLagAllowed = %d, pauseGameForLaggedClients = %d\n",__FILE__,__FUNCTION__,__LINE__,enabledThreadedClientCommandBroadcast,maxFrameCountLagAllowed,pauseGameForLaggedClients);
|
||||||
|
|
||||||
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
for(int i= 0; i<GameConstants::maxPlayers; ++i){
|
||||||
slots[i]= NULL;
|
slots[i]= NULL;
|
||||||
@@ -223,18 +226,25 @@ bool ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot) {
|
|||||||
if(maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) {
|
if(maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) {
|
||||||
clientLagExceeded = true;
|
clientLagExceeded = true;
|
||||||
char szBuf[4096]="";
|
char szBuf[4096]="";
|
||||||
|
|
||||||
|
const char* msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client.";
|
||||||
|
if(pauseGameForLaggedClients == true) {
|
||||||
|
msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, pausing game to wait for client to catch up...";
|
||||||
|
}
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
_snprintf(szBuf,4095,"%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client.",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount);
|
_snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount);
|
||||||
#else
|
#else
|
||||||
snprintf(szBuf,4095,"%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client.",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount);
|
snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount);
|
||||||
#endif
|
#endif
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
|
||||||
|
|
||||||
string sMsg = szBuf;
|
string sMsg = szBuf;
|
||||||
sendTextMessage(sMsg,-1);
|
sendTextMessage(sMsg,-1);
|
||||||
|
|
||||||
|
if(pauseGameForLaggedClients == true) {
|
||||||
connectionSlot->close();
|
connectionSlot->close();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// New lag check warning
|
// New lag check warning
|
||||||
else if(maxFrameCountLagAllowed > 0 && warnFrameCountLagPercent > 0 &&
|
else if(maxFrameCountLagAllowed > 0 && warnFrameCountLagPercent > 0 &&
|
||||||
(clientLagCount > (maxFrameCountLagAllowed * warnFrameCountLagPercent))) {
|
(clientLagCount > (maxFrameCountLagAllowed * warnFrameCountLagPercent))) {
|
||||||
@@ -261,50 +271,17 @@ bool ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot) {
|
|||||||
return clientLagExceeded;
|
return clientLagExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerInterface::update() {
|
void ServerInterface::signalClientReceiveCommands(ConnectionSlot* connectionSlot,
|
||||||
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
int slotIndex,
|
||||||
|
bool socketTriggered,
|
||||||
std::map<PLATFORM_SOCKET,bool> socketTriggeredList;
|
ConnectionSlotEvent &event) {
|
||||||
//update all slots
|
//bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
|
||||||
for(int i= 0; i < GameConstants::maxPlayers; ++i) {
|
//ConnectionSlotEvent &event = eventList[i];
|
||||||
ConnectionSlot* connectionSlot= slots[i];
|
|
||||||
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
|
|
||||||
slots[i]->getSocket()->getSocketId() > 0) {
|
|
||||||
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
|
||||||
|
|
||||||
//chatText.clear();
|
|
||||||
//chatSender.clear();
|
|
||||||
//chatTeamIndex= -1;
|
|
||||||
|
|
||||||
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
|
||||||
|
|
||||||
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) {
|
|
||||||
//if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socketTriggeredList.size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
|
||||||
|
|
||||||
std::map<int,ConnectionSlotEvent> eventList;
|
|
||||||
bool hasData = Socket::hasDataToRead(socketTriggeredList);
|
|
||||||
|
|
||||||
if(hasData) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
|
|
||||||
|
|
||||||
if(gameHasBeenInitiated == false || hasData == true) {
|
|
||||||
//update all slots
|
|
||||||
bool checkForNewClients = true;
|
|
||||||
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
|
|
||||||
ConnectionSlot* connectionSlot = slots[i];
|
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
|
||||||
|
|
||||||
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
|
|
||||||
ConnectionSlotEvent &event = eventList[i];
|
|
||||||
event.eventType = eReceiveSocketData;
|
event.eventType = eReceiveSocketData;
|
||||||
event.networkMessage = NULL;
|
event.networkMessage = NULL;
|
||||||
event.connectionSlot = connectionSlot;
|
event.connectionSlot = connectionSlot;
|
||||||
event.socketTriggered = socketTriggered;
|
event.socketTriggered = socketTriggered;
|
||||||
event.triggerId = i;
|
event.triggerId = slotIndex;
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
@@ -313,47 +290,43 @@ void ServerInterface::update() {
|
|||||||
connectionSlot->signalUpdate(&event);
|
connectionSlot->signalUpdate(&event);
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//updateSlot(event);
|
void ServerInterface::updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList) {
|
||||||
|
//update all slots
|
||||||
/*
|
for(int i= 0; i < GameConstants::maxPlayers; ++i) {
|
||||||
if(connectionSlot != NULL &&
|
ConnectionSlot* connectionSlot= slots[i];
|
||||||
(gameHasBeenInitiated == false || (connectionSlot->getSocket() != NULL && socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true))) {
|
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
|
||||||
if(connectionSlot->isConnected() == false ||
|
slots[i]->getSocket()->getSocketId() > 0) {
|
||||||
(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] == true)) {
|
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
|
||||||
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socketTriggeredList[i] = %i\n",__FILE__,__FUNCTION__,(socketTriggeredList[connectionSlot->getSocket()->getSocketId()] ? 1 : 0));
|
|
||||||
|
|
||||||
if(connectionSlot->isConnected()) {
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] about to call slots[i]->update() for slot = %d socketId = %d\n",
|
|
||||||
__FILE__,__FUNCTION__,i,connectionSlot->getSocket()->getSocketId());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(gameHasBeenInitiated) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] slot = %d getSocket() == NULL\n",__FILE__,__FUNCTION__,i);
|
|
||||||
}
|
|
||||||
connectionSlot->update(checkForNewClients);
|
|
||||||
|
|
||||||
// This means no clients are trying to connect at the moment
|
|
||||||
if(connectionSlot != NULL && connectionSlot->getSocket() == NULL) {
|
|
||||||
checkForNewClients = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(connectionSlot != NULL &&
|
|
||||||
connectionSlot->getChatText().empty() == false) {
|
|
||||||
chatText = connectionSlot->getChatText();
|
|
||||||
chatSender = connectionSlot->getChatSender();
|
|
||||||
chatTeamIndex = connectionSlot->getChatTeamIndex();
|
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 about to broadcast nmtText chatText [%s] chatSender [%s] chatTeamIndex = %d for SlotIndex# %d\n",__FILE__,__FUNCTION__,__LINE__,chatText.c_str(),chatSender.c_str(),chatTeamIndex,i);
|
|
||||||
|
|
||||||
NetworkMessageText networkMessageText(chatText,chatSender,chatTeamIndex);
|
|
||||||
broadcastMessage(&networkMessageText, i);
|
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
void ServerInterface::update() {
|
||||||
|
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
std::map<PLATFORM_SOCKET,bool> socketTriggeredList;
|
||||||
|
//update all slots
|
||||||
|
updateSocketTriggeredList(socketTriggeredList);
|
||||||
|
|
||||||
|
if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) {
|
||||||
|
std::map<int,ConnectionSlotEvent> eventList;
|
||||||
|
bool hasData = Socket::hasDataToRead(socketTriggeredList);
|
||||||
|
|
||||||
|
if(hasData) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] hasData == true\n",__FILE__,__FUNCTION__);
|
||||||
|
|
||||||
|
if(gameHasBeenInitiated == false || hasData == true) {
|
||||||
|
// Step #1 tell all connection slot worker threads to receive socket data
|
||||||
|
bool checkForNewClients = true;
|
||||||
|
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
|
||||||
|
ConnectionSlot* connectionSlot = slots[i];
|
||||||
|
|
||||||
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
|
||||||
|
ConnectionSlotEvent &event = eventList[i];
|
||||||
|
signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
|
||||||
@@ -379,11 +352,23 @@ void ServerInterface::update() {
|
|||||||
threadsDone = false;
|
threadsDone = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// New lag check
|
||||||
|
bool clientLagExceeded = clientLagCheck(connectionSlot);
|
||||||
|
// If the client has exceeded lag and the server wants
|
||||||
|
// to pause while they catch up, re-trigger the
|
||||||
|
// client reader thread
|
||||||
|
if(clientLagExceeded == true && pauseGameForLaggedClients == true) {
|
||||||
|
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
|
||||||
|
ConnectionSlotEvent &event = eventList[i];
|
||||||
|
signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
slotsCompleted[i] = true;
|
slotsCompleted[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sleep(0);
|
sleep(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -82,6 +82,12 @@ public:
|
|||||||
int getCurrentFrameCount() const { return currentFrameCount; }
|
int getCurrentFrameCount() const { return currentFrameCount; }
|
||||||
bool clientLagCheck(ConnectionSlot* connectionSlot);
|
bool clientLagCheck(ConnectionSlot* connectionSlot);
|
||||||
|
|
||||||
|
void signalClientReceiveCommands(ConnectionSlot* connectionSlot,
|
||||||
|
int slotIndex,
|
||||||
|
bool socketTriggered,
|
||||||
|
ConnectionSlotEvent &event);
|
||||||
|
void updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &socketTriggeredList);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Mutex * getServerSynchAccessor() { return &serverSynchAccessor; }
|
Mutex * getServerSynchAccessor() { return &serverSynchAccessor; }
|
||||||
|
Reference in New Issue
Block a user