- attempt to fix game freeze when lag causes game pauses

This commit is contained in:
Mark Vejvoda 2011-01-11 08:45:58 +00:00
parent b778098d13
commit e319c2cf62
8 changed files with 281 additions and 22 deletions

View File

@ -37,6 +37,135 @@ namespace Glest{ namespace Game{
// ===================== PUBLIC ======================== // ===================== PUBLIC ========================
CommanderNetworkThread::CommanderNetworkThread() : BaseThread() {
this->idStatus = make_pair<int,bool>(-1,false);
this->commanderInterface = NULL;
}
CommanderNetworkThread::CommanderNetworkThread(CommanderNetworkCallbackInterface *commanderInterface) : BaseThread() {
this->idStatus = make_pair<int,bool>(-1,false);
this->commanderInterface = commanderInterface;
}
void CommanderNetworkThread::setQuitStatus(bool value) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d value = %d\n",__FILE__,__FUNCTION__,__LINE__,value);
BaseThread::setQuitStatus(value);
if(value == true) {
signalUpdate(-1);
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void CommanderNetworkThread::signalUpdate(int id) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] event = %p\n",__FILE__,__FUNCTION__,__LINE__,event);
MutexSafeWrapper safeMutex(&idMutex);
this->idStatus.first = id;
this->idStatus.second = false;
safeMutex.ReleaseLock();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
semTaskSignalled.signal();
}
void CommanderNetworkThread::setTaskCompleted(int id) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
MutexSafeWrapper safeMutex(&idMutex);
this->idStatus.second = true;
safeMutex.ReleaseLock();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
bool CommanderNetworkThread::isSignalCompleted(int id) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
MutexSafeWrapper safeMutex(&idMutex);
bool result = this->idStatus.second;
safeMutex.ReleaseLock();
//if(result == false) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, result = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,result);
return result;
}
void CommanderNetworkThread::execute() {
RunningStatusSafeWrapper runningStatus(this);
try {
//setRunningStatus(true);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
unsigned int idx = 0;
for(;this->commanderInterface != NULL;) {
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
semTaskSignalled.waitTillSignalled();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
MutexSafeWrapper safeMutex(&idMutex);
if(idStatus.first > 0) {
int updateId = this->idStatus.first;
safeMutex.ReleaseLock();
this->commanderInterface->commanderNetworkUpdateTask(updateId);
setTaskCompleted(updateId);
}
else {
safeMutex.ReleaseLock();
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
if(getQuitStatus() == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
catch(const exception &ex) {
//setRunningStatus(false);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
throw runtime_error(ex.what());
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
//setRunningStatus(false);
}
// =====================================================
// class
// =====================================================
Commander::Commander() {
this->networkThread = new CommanderNetworkThread(this);
this->networkThread->setUniqueID(__FILE__);
this->networkThread->start();
}
Commander::~Commander() {
if(BaseThread::shutdownAndWait(networkThread) == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete networkThread;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
networkThread = NULL;
}
void Commander::init(World *world){ void Commander::init(World *world){
this->world= world; this->world= world;
} }
@ -325,11 +454,29 @@ CommandResult Commander::pushNetworkCommand(const NetworkCommand* networkCommand
return cr; return cr;
} }
void Commander::updateNetwork() { void Commander::signalNetworkUpdate(Game *game) {
if(this->networkThread != NULL) {
this->game = game;
this->networkThread->signalUpdate(1);
time_t elapsedWait = time(NULL);
for(;difftime(time(NULL),elapsedWait) <= 4 &&
this->networkThread->isSignalCompleted(1) == false;) {
game->render();
}
}
}
void Commander::commanderNetworkUpdateTask(int id) {
updateNetwork(game);
}
void Commander::updateNetwork(Game *game) {
NetworkManager &networkManager= NetworkManager::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance();
//check that this is a keyframe //check that this is a keyframe
GameSettings *gameSettings = this->world->getGame()->getGameSettings(); //GameSettings *gameSettings = this->world->getGame()->getGameSettings();
GameSettings *gameSettings = game->getGameSettings();
if( networkManager.isNetworkGame() == false || if( networkManager.isNetworkGame() == false ||
(world->getFrameCount() % gameSettings->getNetworkFramePeriod()) == 0) { (world->getFrameCount() % gameSettings->getNetworkFramePeriod()) == 0) {

View File

@ -18,6 +18,7 @@
#include "selection.h" #include "selection.h"
#include "command_type.h" #include "command_type.h"
#include "platform_util.h" #include "platform_util.h"
#include "base_thread.h"
#include "leak_dumper.h" #include "leak_dumper.h"
using std::vector; using std::vector;
@ -32,6 +33,7 @@ class Unit;
class Command; class Command;
class CommandType; class CommandType;
class NetworkCommand; class NetworkCommand;
class Game;
// ===================================================== // =====================================================
// class Commander // class Commander
@ -39,7 +41,35 @@ class NetworkCommand;
/// Gives commands to the units /// Gives commands to the units
// ===================================================== // =====================================================
class Commander{ //
// This interface describes the methods a callback object must implement
//
class CommanderNetworkCallbackInterface {
public:
virtual void commanderNetworkUpdateTask(int id) = 0;
};
class CommanderNetworkThread : public BaseThread
{
protected:
CommanderNetworkCallbackInterface *commanderInterface;
Semaphore semTaskSignalled;
virtual void setQuitStatus(bool value);
virtual void setTaskCompleted(int id);
Mutex idMutex;
std::pair<int,bool> idStatus;
public:
CommanderNetworkThread();
CommanderNetworkThread(CommanderNetworkCallbackInterface *commanderInterface);
virtual void execute();
void signalUpdate(int id);
bool isSignalCompleted(int id);
};
class Commander : public CommanderNetworkCallbackInterface {
private: private:
typedef vector<CommandResult> CommandResultContainer; typedef vector<CommandResult> CommandResultContainer;
@ -47,9 +77,16 @@ private:
World *world; World *world;
Chrono perfTimer; Chrono perfTimer;
CommanderNetworkThread *networkThread;
Game *game;
public: public:
Commander();
~Commander();
void signalNetworkUpdate(Game *game);
void init(World *world); void init(World *world);
void updateNetwork(); void updateNetwork(Game *game);
CommandResult tryGiveCommand(const Selection *selection, const CommandType *commandType, CommandResult tryGiveCommand(const Selection *selection, const CommandType *commandType,
const Vec2i &pos, const UnitType* unitType, const Vec2i &pos, const UnitType* unitType,
@ -68,6 +105,8 @@ private:
CommandResult computeResult(const CommandResultContainer &results) const; CommandResult computeResult(const CommandResultContainer &results) const;
void giveNetworkCommand(NetworkCommand* networkCommand) const; void giveNetworkCommand(NetworkCommand* networkCommand) const;
Command* buildCommand(const NetworkCommand* networkCommand) const; Command* buildCommand(const NetworkCommand* networkCommand) const;
virtual void commanderNetworkUpdateTask(int id);
}; };
}} //end namespace }} //end namespace

View File

@ -735,7 +735,9 @@ void Game::update() {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Commander // Commander
commander.updateNetwork(); //commander.updateNetwork();
commander.signalNetworkUpdate(this);
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [commander updateNetwork i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i); if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [commander updateNetwork i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i);
if(chrono.getMillis() > 0) chrono.start(); if(chrono.getMillis() > 0) chrono.start();

View File

@ -62,30 +62,60 @@ void ConnectionSlotThread::signalUpdate(ConnectionSlotEvent *event) {
if(event != NULL) { if(event != NULL) {
MutexSafeWrapper safeMutex(&triggerIdMutex); MutexSafeWrapper safeMutex(&triggerIdMutex);
eventList.push_back(event); eventList.push_back(*event);
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
} }
//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__);
semTaskSignalled.signal(); semTaskSignalled.signal();
} }
void ConnectionSlotThread::setTaskCompleted(ConnectionSlotEvent *event) { void ConnectionSlotThread::setTaskCompleted(int eventId) {
//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__);
if(event != NULL) { if(eventId > 0) {
MutexSafeWrapper safeMutex(&triggerIdMutex); MutexSafeWrapper safeMutex(&triggerIdMutex);
event->eventCompleted = true; //event->eventCompleted = true;
eventList.erase(eventList.begin()); for(int i = 0; i < eventList.size(); ++i) {
ConnectionSlotEvent &slotEvent = eventList[i];
if(slotEvent.eventId == eventId) {
//eventList.erase(eventList.begin() + i);
slotEvent.eventCompleted = true;
break;
}
}
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
} }
//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__);
} }
void ConnectionSlotThread::purgeCompletedEvents() {
MutexSafeWrapper safeMutex(&triggerIdMutex);
//event->eventCompleted = true;
for(int i = eventList.size() - 1; i >= 0; i--) {
ConnectionSlotEvent &slotEvent = eventList[i];
if(slotEvent.eventCompleted == true) {
eventList.erase(eventList.begin() + i);
}
}
safeMutex.ReleaseLock();
}
bool ConnectionSlotThread::isSignalCompleted(ConnectionSlotEvent *event) { bool ConnectionSlotThread::isSignalCompleted(ConnectionSlotEvent *event) {
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
MutexSafeWrapper safeMutex(&triggerIdMutex); MutexSafeWrapper safeMutex(&triggerIdMutex);
bool result = (event != NULL ? event->eventCompleted : true); //bool result = (event != NULL ? event->eventCompleted : true);
bool result = false;
if(event != NULL) {
for(int i = 0; i < eventList.size(); ++i) {
ConnectionSlotEvent &slotEvent = eventList[i];
if(slotEvent.eventId == event->eventId) {
//eventList.erase(eventList.begin() + i);
result = slotEvent.eventCompleted;
break;
}
}
}
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
//if(result == false) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, result = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,result); //if(result == false) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d, result = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex,result);
return result; return result;
@ -118,11 +148,22 @@ void ConnectionSlotThread::execute() {
MutexSafeWrapper safeMutex(&triggerIdMutex); MutexSafeWrapper safeMutex(&triggerIdMutex);
int eventCount = eventList.size(); int eventCount = eventList.size();
if(eventCount > 0) { if(eventCount > 0) {
ConnectionSlotEvent *event = eventList[0]; ConnectionSlotEvent *event = NULL;
for(int i = 0; i < eventList.size(); ++i) {
ConnectionSlotEvent &slotEvent = eventList[i];
if(slotEvent.eventCompleted == false) {
event = &slotEvent;
break;
}
}
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
this->slotInterface->slotUpdateTask(event); if(event != NULL) {
setTaskCompleted(event); this->slotInterface->slotUpdateTask(event);
setTaskCompleted(event->eventId);
}
} }
else { else {
safeMutex.ReleaseLock(); safeMutex.ReleaseLock();
@ -201,6 +242,9 @@ ConnectionSlot::~ConnectionSlot() {
} }
void ConnectionSlot::update() { void ConnectionSlot::update() {
if(slotThreadWorker != NULL) {
slotThreadWorker->purgeCompletedEvents();
}
update(true); update(true);
} }

View File

@ -49,6 +49,7 @@ public:
networkMessage = NULL; networkMessage = NULL;
socketTriggered = false; socketTriggered = false;
eventCompleted = false; eventCompleted = false;
eventId = -1;
} }
int64 triggerId; int64 triggerId;
@ -57,6 +58,7 @@ public:
const NetworkMessage *networkMessage; const NetworkMessage *networkMessage;
bool socketTriggered; bool socketTriggered;
bool eventCompleted; bool eventCompleted;
int64 eventId;
}; };
// //
@ -74,11 +76,11 @@ protected:
ConnectionSlotCallbackInterface *slotInterface; ConnectionSlotCallbackInterface *slotInterface;
Semaphore semTaskSignalled; Semaphore semTaskSignalled;
Mutex triggerIdMutex; Mutex triggerIdMutex;
vector<ConnectionSlotEvent *> eventList; vector<ConnectionSlotEvent> eventList;
int slotIndex; int slotIndex;
virtual void setQuitStatus(bool value); virtual void setQuitStatus(bool value);
virtual void setTaskCompleted(ConnectionSlotEvent *event); virtual void setTaskCompleted(int eventId);
public: public:
ConnectionSlotThread(int slotIndex); ConnectionSlotThread(int slotIndex);
@ -87,6 +89,8 @@ public:
void signalUpdate(ConnectionSlotEvent *event); void signalUpdate(ConnectionSlotEvent *event);
bool isSignalCompleted(ConnectionSlotEvent *event); bool isSignalCompleted(ConnectionSlotEvent *event);
int getSlotIndex() const {return slotIndex; } int getSlotIndex() const {return slotIndex; }
void purgeCompletedEvents();
}; };
// ===================================================== // =====================================================

View File

@ -58,10 +58,11 @@ double LAG_CHECK_GRACE_PERIOD = 15;
// The max amount of time to 'freeze' gameplay per packet when a client is lagging // The max amount of time to 'freeze' gameplay per packet when a client is lagging
// badly and we want to give time for them to catch up // badly and we want to give time for them to catch up
double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 1; double MAX_CLIENT_WAIT_SECONDS_FOR_PAUSE = 2;
ServerInterface::ServerInterface() : GameNetworkInterface() { ServerInterface::ServerInterface() : GameNetworkInterface() {
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__);
nextEventId = 1;
gameHasBeenInitiated = false; gameHasBeenInitiated = false;
exitServer = false; exitServer = false;
gameSettingsUpdateCount = 0; gameSettingsUpdateCount = 0;
@ -349,11 +350,21 @@ int ServerInterface::getConnectedSlotCount() {
return connectedSlotCount; return connectedSlotCount;
} }
int64 ServerInterface::getNextEventId() {
nextEventId++;
// Rollover when # gets large
if(nextEventId > INT_MAX) {
nextEventId = 1;
}
return nextEventId;
}
void ServerInterface::slotUpdateTask(ConnectionSlotEvent *event) { void ServerInterface::slotUpdateTask(ConnectionSlotEvent *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__);
if(event != NULL) { if(event != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] event->eventType = %d\n",__FILE__,__FUNCTION__,__LINE__,event->eventType);
if(event->eventType == eSendSocketData) { if(event->eventType == eSendSocketData) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage, event->networkMessage = %p\n",__FILE__,__FUNCTION__,event->networkMessage); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage, event->networkMessage = %p\n",__FILE__,__FUNCTION__,event->networkMessage);
@ -364,6 +375,9 @@ void ServerInterface::slotUpdateTask(ConnectionSlotEvent *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); updateSlot(event);
} }
else {
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__); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
} }
@ -536,6 +550,7 @@ bool ServerInterface::signalClientReceiveCommands(ConnectionSlot* connectionSlot
event.connectionSlot = connectionSlot; event.connectionSlot = connectionSlot;
event.socketTriggered = socketTriggered; event.socketTriggered = socketTriggered;
event.triggerId = slotIndex; event.triggerId = slotIndex;
event.eventId = getNextEventId();
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex); //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] slotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,slotIndex);
@ -580,6 +595,7 @@ void ServerInterface::validateConnectedClients() {
void ServerInterface::update() { void ServerInterface::update() {
//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__);
const int MAX_SLOT_THREAD_WAIT_TIME = 3;
std::vector<string> errorMsgList; std::vector<string> errorMsgList;
try { try {
// The first thing we will do is check all clients to ensure they have // The first thing we will do is check all clients to ensure they have
@ -619,7 +635,6 @@ void ServerInterface::update() {
// Step #2 check all connection slot worker threads for completed status // Step #2 check all connection slot worker threads for completed status
time_t waitForThreadElapsed = time(NULL); time_t waitForThreadElapsed = time(NULL);
const int MAX_SLOT_THREAD_WAIT_TIME = 6;
std::map<int,bool> slotsCompleted; std::map<int,bool> slotsCompleted;
for(bool threadsDone = false; for(bool threadsDone = false;
exitServer == false && threadsDone == false && exitServer == false && threadsDone == false &&
@ -725,7 +740,10 @@ void ServerInterface::update() {
if(connectionSlot != NULL) { if(connectionSlot != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second);
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false); bool socketTriggered = false;
if(connectionSlot->getSocket() != NULL && connectionSlot->getSocket()->getSocketId() > 0) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
}
ConnectionSlotEvent &event = eventList[i]; ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event); mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
threadsDone = false; threadsDone = false;
@ -1249,6 +1267,7 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int
event.connectionSlot = connectionSlot; event.connectionSlot = connectionSlot;
event.socketTriggered = true; event.socketTriggered = true;
event.triggerId = i; event.triggerId = i;
event.eventId = getNextEventId();
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__);
@ -1574,7 +1593,8 @@ void ServerInterface::simpleTask(BaseThread *callingThread) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__)); MutexSafeWrapper safeMutex(&masterServerThreadAccessor,intToStr(__LINE__));
if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= 30) { const int MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS = 30;
if(difftime(time(NULL),lastMasterserverHeartbeatTime) >= MASTERSERVER_HEARTBEAT_GAME_STATUS_SECONDS) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
lastMasterserverHeartbeatTime = time(NULL); lastMasterserverHeartbeatTime = time(NULL);

View File

@ -55,6 +55,7 @@ private:
Shared::PlatformCommon::FTPServerThread *ftpServer; Shared::PlatformCommon::FTPServerThread *ftpServer;
bool exitServer; bool exitServer;
int64 nextEventId;
public: public:
ServerInterface(); ServerInterface();
@ -135,6 +136,8 @@ private:
void validateConnectedClients(); void validateConnectedClients();
std::map<string,string> publishToMasterserver(); std::map<string,string> publishToMasterserver();
int64 getNextEventId();
}; };
}}//end namespace }}//end namespace

View File

@ -69,7 +69,7 @@ public:
protected: protected:
friend class SoundPlayerOpenAL; friend class SoundPlayerOpenAL;
static const size_t STREAMBUFFERSIZE = 1024 * 500; static const size_t STREAMBUFFERSIZE = 1024 * 500;
static const size_t STREAMFRAGMENTS = 10; static const size_t STREAMFRAGMENTS = 5;
static const size_t STREAMFRAGMENTSIZE static const size_t STREAMFRAGMENTSIZE
= STREAMBUFFERSIZE / STREAMFRAGMENTS; = STREAMBUFFERSIZE / STREAMFRAGMENTS;