- attempt to fix game freeze when lag causes game pauses
This commit is contained in:
parent
b778098d13
commit
e319c2cf62
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue