- added missing gamesettings to network packet and added experimental threaded server message broadcasts to client

This commit is contained in:
Mark Vejvoda 2010-06-03 07:52:17 +00:00
parent 1b000376d4
commit 6b10c5696f
9 changed files with 161 additions and 18 deletions

View File

@ -118,6 +118,8 @@ void Game::load(){
originalDisplayMsgCallback = NetworkInterface::getDisplayMessageFunction();
NetworkInterface::setDisplayMessageFunction(ErrorDisplayMessage);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings = [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->gameSettings.toString().c_str());
Logger &logger= Logger::getInstance();
string mapName= gameSettings.getMap();
string tilesetName= gameSettings.getTileset();

View File

@ -13,6 +13,9 @@
#define _GLEST_GAME_GAMESETTINGS_H_
#include "game_constants.h"
#include "conversion.h"
using namespace Shared::Util;
namespace Glest{ namespace Game{
@ -115,6 +118,38 @@ public:
void setFogOfWar(bool fogOfWar) {this->fogOfWar = fogOfWar;}
void setEnableObserverModeAtEndGame(bool value) {this->enableObserverModeAtEndGame = value;}
void setEnableServerControlledAI(bool value) {this->enableServerControlledAI = value;}
string toString() const {
string result = "";
result += "description = " + description + "\n";
result += "map = " + map + "\n";
result += "tileset = " + tileset + "\n";
result += "tech = " + tech + "\n";
result += "scenario = " + scenario + "\n";
result += "scenarioDir = " + scenarioDir + "\n";
for(int idx =0; idx < GameConstants::maxPlayers; idx++) {
result += "player index = " + intToStr(idx) + "\n";
result += "factionTypeName = " + factionTypeNames[idx] + "\n";
result += "networkPlayerName = " + networkPlayerNames[idx] + "\n";
result += "factionControl = " + intToStr(factionControls[idx]) + "\n";
result += "team = " + intToStr(teams[idx]) + "\n";
result += "startLocationIndex = " + intToStr(startLocationIndex[idx]) + "\n";
}
result += "thisFactionIndex = " + intToStr(thisFactionIndex) + "\n";
result += "factionCount = " + intToStr(factionCount) + "\n";
result += "defaultUnits = " + intToStr(defaultUnits) + "\n";
result += "defaultResources = " + intToStr(defaultResources) + "\n";
result += "defaultVictoryConditions = " + intToStr(defaultVictoryConditions) + "\n";
result += "fogOfWar = " + intToStr(fogOfWar) + "\n";
result += "enableObserverModeAtEndGame = " + intToStr(enableObserverModeAtEndGame) + "\n";
result += "enableServerControlledAI = " + intToStr(enableServerControlledAI) + "\n";
return result;
}
};
}}//end namespace

View File

@ -617,7 +617,7 @@ bool MenuStateConnectedGame::loadFactions(const GameSettings *gameSettings, bool
for(int idx = 0; idx < techPaths.size(); idx++) {
string &techPath = techPaths[idx];
findAll(techPath + "/" + gameSettings->getTech() + "xx/factions/*.", results, false, false);
findAll(techPath + "/" + gameSettings->getTech() + "/factions/*.", results, false, false);
if(results.size() > 0) {
break;
}

View File

@ -553,4 +553,10 @@ bool ConnectionSlot::updateCompleted() {
return (waitingForThread == false);
}
void ConnectionSlot::sendMessage(const NetworkMessage* networkMessage) {
MutexSafeWrapper safeMutex(&socketSynchAccessor);
NetworkInterface::sendMessage(networkMessage);
safeMutex.ReleaseLock();
}
}}//end namespace

View File

@ -34,8 +34,17 @@ class ConnectionSlot;
class ConnectionSlotEvent {
public:
ConnectionSlotEvent() {
triggerId = -1;
connectionSlot = NULL;
networkMessage = NULL;
socketTriggered = false;
eventCompleted = false;
}
int64 triggerId;
ConnectionSlot* connectionSlot;
const NetworkMessage* networkMessage;
bool socketTriggered;
bool eventCompleted;
};
@ -120,10 +129,13 @@ public:
void signalUpdate(ConnectionSlotEvent *event);
bool updateCompleted();
virtual void sendMessage(const NetworkMessage* networkMessage);
protected:
Mutex * getServerSynchAccessor();
std::vector<std::string> threadErrorList;
Mutex socketSynchAccessor;
};
}}//end namespace

View File

@ -74,7 +74,7 @@ public:
string getIp() const {return getSocket()->getIp();}
string getHostName() const {return getSocket()->getHostName();}
void sendMessage(const NetworkMessage* networkMessage);
virtual void sendMessage(const NetworkMessage* networkMessage);
NetworkMessageType getNextMessageType(bool checkHasDataFirst = false);
bool receiveMessage(NetworkMessage* networkMessage);

View File

@ -184,6 +184,8 @@ NetworkMessageLaunch::NetworkMessageLaunch(const GameSettings *gameSettings,int8
data.defaultUnits= gameSettings->getDefaultUnits();
data.defaultVictoryConditions= gameSettings->getDefaultVictoryConditions();
data.fogOfWar = gameSettings->getFogOfWar();
data.enableObserverModeAtEndGame = gameSettings->getEnableObserverModeAtEndGame();
data.enableServerControlledAI = gameSettings->getEnableServerControlledAI();
for(int i= 0; i<data.factionCount; ++i){
data.factionTypeNames[i]= gameSettings->getFactionTypeName(i);
@ -206,6 +208,10 @@ void NetworkMessageLaunch::buildGameSettings(GameSettings *gameSettings) const{
gameSettings->setDefaultVictoryConditions(data.defaultVictoryConditions);
gameSettings->setFogOfWar(data.fogOfWar);
gameSettings->setFogOfWar(data.fogOfWar);
gameSettings->setEnableObserverModeAtEndGame(data.enableObserverModeAtEndGame);
gameSettings->setEnableServerControlledAI(data.enableServerControlledAI);
for(int i= 0; i<data.factionCount; ++i){
gameSettings->setFactionTypeName(i, data.factionTypeNames[i].getString());
gameSettings->setNetworkPlayerName(i,data.networkPlayerNames[i].getString());

View File

@ -165,6 +165,8 @@ private:
int8 defaultUnits;
int8 defaultVictoryConditions;
int8 fogOfWar;
int8 enableObserverModeAtEndGame;
int8 enableServerControlledAI;
};
private:

View File

@ -34,6 +34,9 @@ namespace Glest{ namespace Game{
// class ServerInterface
// =====================================================
// Experimental threading of broadcasts to clients
bool enabledThreadedClientCommandBroadcast = true;
ServerInterface::ServerInterface(){
gameHasBeenInitiated = false;
gameSettingsUpdateCount = 0;
@ -144,7 +147,15 @@ void ServerInterface::slotUpdateTask(ConnectionSlotEvent *event) {
if(event != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
updateSlot(event);
if(event->networkMessage != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
event->connectionSlot->sendMessage(event->networkMessage);
}
else {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
updateSlot(event);
}
}
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
@ -223,6 +234,7 @@ void ServerInterface::update() {
bool socketTriggered = (connectionSlot != NULL && connectionSlot->getSocket() != NULL ? socketTriggeredList[connectionSlot->getSocket()->getSocketId()] : false);
ConnectionSlotEvent &event = eventList[i];
event.networkMessage = NULL;
event.connectionSlot = connectionSlot;
event.socketTriggered = socketTriggered;
event.triggerId = i;
@ -682,32 +694,100 @@ void ServerInterface::broadcastGameSetup(const GameSettings* gameSettings) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot){
//SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
try {
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(i != excludeSlot && connectionSlot != NULL) {
if(connectionSlot->isConnected()) {
if(enabledThreadedClientCommandBroadcast == true) {
// Step #1 signal worker threads to send this broadcast to each client
std::map<int,ConnectionSlotEvent> eventList;
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot = slots[i];
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
ConnectionSlotEvent &event = eventList[i];
event.networkMessage = networkMessage;
event.connectionSlot = connectionSlot;
event.socketTriggered = true;
event.triggerId = i;
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
// Step #1 tell all connection slot worker threads to receive socket data
if(i != excludeSlot && connectionSlot != NULL) {
if(connectionSlot->isConnected()) {
connectionSlot->signalUpdate(&event);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__);
}
else if(gameHasBeenInitiated == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
else if(gameHasBeenInitiated == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Step #2 check all connection slot worker threads for completed status
std::map<int,bool> slotsCompleted;
for(bool threadsDone = false; threadsDone == false;) {
threadsDone = true;
// Examine all threads for completion of delegation
for(int i= 0; i< GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL && slotsCompleted.find(i) == slotsCompleted.end()) {
std::vector<std::string> errorList = connectionSlot->getThreadErrorList();
if(errorList.size() > 0) {
for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) {
string &sErr = errorList[iErrIdx];
DisplayErrorMessage(sErr);
}
connectionSlot->clearThreadErrorList();
}
if(connectionSlot->updateCompleted() == false) {
threadsDone = false;
break;
}
else {
slotsCompleted[i] = true;
}
}
}
sleep(0);
}
}
}
else {
for(int i= 0; i<GameConstants::maxPlayers; ++i) {
ConnectionSlot* connectionSlot= slots[i];
if(i != excludeSlot && connectionSlot != NULL) {
if(connectionSlot->isConnected()) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] before sendMessage\n",__FILE__,__FUNCTION__);
connectionSlot->sendMessage(networkMessage);
}
else if(gameHasBeenInitiated == true) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #1 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
else if(i == excludeSlot && gameHasBeenInitiated == true &&
connectionSlot != NULL && connectionSlot->isConnected() == false) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 before removeSlot for slot# %d\n",__FILE__,__FUNCTION__,i);
removeSlot(i);
}
}
}
}
catch(const exception &ex) {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ERROR [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());