diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index bba077cc..877927d7 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -3,13 +3,13 @@ // // Copyright (C) 2001-2008 MartiƱo Figueroa // -// You can redistribute this code and/or modify it under -// the terms of the GNU General Public License as published -// by the Free Software Foundation; either version 2 of the +// You can redistribute this code and/or modify it under +// the terms of the GNU General Public License as published +// by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== -#include "ai.h" +#include "ai.h" #include "ai_interface.h" #include "ai_rule.h" #include "unit_type.h" @@ -85,7 +85,7 @@ string BuildTask::toString() const{ } return str; } - + // ===================================================== // class UpgradeTask // ===================================================== @@ -108,7 +108,7 @@ string UpgradeTask::toString() const{ // ===================================================== void Ai::init(AiInterface *aiInterface, int useStartLocation) { - this->aiInterface= aiInterface; + this->aiInterface= aiInterface; if(useStartLocation == -1) { startLoc = random.randRange(0, aiInterface->getMapMaxPlayers()-1); } @@ -136,8 +136,16 @@ void Ai::init(AiInterface *aiInterface, int useStartLocation) { } Ai::~Ai() { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",__FILE__,__FUNCTION__,__LINE__,aiInterface); deleteValues(tasks.begin(), tasks.end()); + tasks.clear(); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",__FILE__,__FUNCTION__,__LINE__,aiInterface); + deleteValues(aiRules.begin(), aiRules.end()); + aiRules.clear(); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] deleting AI aiInterface [%p]\n",__FILE__,__FUNCTION__,__LINE__,aiInterface); + + aiInterface = NULL; } void Ai::update() { @@ -176,7 +184,7 @@ void Ai::update() { } -// ==================== state requests ==================== +// ==================== state requests ==================== int Ai::getCountOfType(const UnitType *ut){ int count= 0; @@ -235,8 +243,8 @@ const ResourceType *Ai::getNeededResource(int unitIndex) { return neededResource; } -bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){ - int count= aiInterface->onSightUnitCount(); +bool Ai::beingAttacked(Vec2i &pos, Field &field, int radius){ + int count= aiInterface->onSightUnitCount(); const Unit *unit; for(int i=0; igetCurrField(); if(pos.dist(aiInterface->getHomeLocation())printLog(2, "Being attacked at pos "+intToStr(pos.x)+","+intToStr(pos.y)+"\n"); - return true; + return true; } } } @@ -257,11 +265,11 @@ bool Ai::isStableBase(){ if(getCountOfClass(ucWarrior)>minWarriors){ aiInterface->printLog(4, "Base is stable\n"); - return true; + return true; } else{ aiInterface->printLog(4, "Base is not stable\n"); - return false; + return false; } } @@ -270,12 +278,12 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, bool idleOnly){ *unitIndex= -1; for(int i=0; igetMyUnitCount(); ++i){ - const Unit *unit= aiInterface->getMyUnit(i); + const Unit *unit= aiInterface->getMyUnit(i); if(unit->getType()->hasCommandClass(ability)){ if(!idleOnly || !unit->anyCommand() || unit->getCurrCommand()->getCommandType()->getClass()==ccStop){ units.push_back(i); } - } + } } if(units.empty()){ @@ -292,12 +300,12 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass current *unitIndex= -1; for(int i=0; igetMyUnitCount(); ++i){ - const Unit *unit= aiInterface->getMyUnit(i); + const Unit *unit= aiInterface->getMyUnit(i); if(unit->getType()->hasCommandClass(ability)){ if(unit->anyCommand() && unit->getCurrCommand()->getCommandType()->getClass()==currentCommand){ units.push_back(i); } - } + } } if(units.empty()){ @@ -310,7 +318,7 @@ bool Ai::findAbleUnit(int *unitIndex, CommandClass ability, CommandClass current } bool Ai::findPosForBuilding(const UnitType* building, const Vec2i &searchPos, Vec2i &outPos){ - + const int spacing= 1; for(int currRadius=0; currRadiusgetHomeLocation(); } - + return expansionPositions[random.randRange(0, expansionPositions.size()-1)]; } -// ==================== actions ==================== +// ==================== actions ==================== void Ai::sendScoutPatrol(){ Vec2i pos; @@ -410,7 +418,7 @@ void Ai::sendScoutPatrol(){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); aiInterface->giveCommand(unit, ccAttack, pos); - aiInterface->printLog(2, "Scout patrol sent to: " + intToStr(pos.x)+","+intToStr(pos.y)+"\n"); + aiInterface->printLog(2, "Scout patrol sent to: " + intToStr(pos.x)+","+intToStr(pos.y)+"\n"); } } @@ -429,15 +437,15 @@ void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){ if(act != NULL && unit->getType()->hasCommandClass(ccProduce)) { producerWarriorCount++; } - + if( aiInterface->getControlType() == ctCpuMega || aiInterface->getControlType() == ctNetworkCpuMega) { if(producerWarriorCount > maxProducerWarriors) { if( unit->getCommandSize()>0 && unit->getCurrCommand()->getCommandType()!=NULL && ( - unit->getCurrCommand()->getCommandType()->getClass()==ccBuild || - unit->getCurrCommand()->getCommandType()->getClass()==ccMorph || + unit->getCurrCommand()->getCommandType()->getClass()==ccBuild || + unit->getCurrCommand()->getCommandType()->getClass()==ccMorph || unit->getCurrCommand()->getCommandType()->getClass()==ccProduce ) ) { @@ -455,7 +463,7 @@ void Ai::massiveAttack(const Vec2i &pos, Field field, bool ultraAttack){ else { isWarrior= !unit->getType()->hasCommandClass(ccHarvest) && !unit->getType()->hasCommandClass(ccProduce); } - + bool alreadyAttacking= (unit->getCurrSkill()->getClass() == scAttack); if(!alreadyAttacking && act!=NULL && (ultraAttack || isWarrior)) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -489,7 +497,7 @@ void Ai::returnBase(int unitIndex) { fi= aiInterface->getFactionIndex(); pos= Vec2i( - random.randRange(-villageRadius, villageRadius), random.randRange(-villageRadius, villageRadius)) + + random.randRange(-villageRadius, villageRadius), random.randRange(-villageRadius, villageRadius)) + getRandomHomePosition(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -505,7 +513,7 @@ void Ai::harvest(int unitIndex) { Vec2i resPos; if(hct != NULL && aiInterface->getNearestSightedResource(rt, aiInterface->getHomeLocation(), resPos, false)) { - resPos= resPos+Vec2i(random.randRange(-2, 2), random.randRange(-2, 2)); + resPos= resPos+Vec2i(random.randRange(-2, 2), random.randRange(-2, 2)); aiInterface->giveCommand(unitIndex, hct, resPos); //aiInterface->printLog(4, "Order harvest pos:" + intToStr(resPos.x)+", "+intToStr(resPos.y)+": "+rrToStr(r)+"\n"); } diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index d23219d2..0dcbf694 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -62,6 +62,10 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useSta SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } +AiInterface::~AiInterface() { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] deleting AI factionIndex = %d, teamIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,this->factionIndex,this->teamIndex); + cacheUnitHarvestResourceLookup.clear(); +} // ==================== main ==================== void AiInterface::update() { diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index f7a7a7c9..4c8737f9 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -3,9 +3,9 @@ // // Copyright (C) 2001-2008 Martio Figueroa // -// You can redistribute this code and/or modify it under -// the terms of the GNU General Public License as published -// by the Free Software Foundation; either version 2 of the +// You can redistribute this code and/or modify it under +// the terms of the GNU General Public License as published +// by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version // ============================================================== @@ -26,7 +26,7 @@ using Shared::Util::intToStr; namespace Glest{ namespace Game{ // ===================================================== -// class AiInterface +// class AiInterface // /// The AI will interact with the game through this interface // ===================================================== @@ -50,7 +50,8 @@ private: std::map cacheUnitHarvestResourceLookup; public: - AiInterface(Game &game, int factionIndex, int teamIndex, int useStartLocation=-1); + AiInterface(Game &game, int factionIndex, int teamIndex, int useStartLocation=-1); + ~AiInterface(); //main void update(); @@ -61,14 +62,14 @@ public: //misc void printLog(int logLevel, const string &s); - + //interact CommandResult giveCommand(int unitIndex, CommandClass commandClass, const Vec2i &pos=Vec2i(0)); CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType); CommandResult giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos); CommandResult giveCommand(int unitIndex, const CommandType *commandType, Unit *u= NULL); CommandResult giveCommand(Unit *unit, const CommandType *commandType, const Vec2i &pos); - + //get data const ControlType getControlType(); int getMapMaxPlayers(); @@ -83,13 +84,13 @@ public: const Unit *getOnSightUnit(int unitIndex); const FactionType *getMyFactionType(); Faction *getMyFaction(); - const TechTree *getTechTree(); + const TechTree *getTechTree(); bool isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos, Faction *faction, bool fallbackToPeersHarvestingSameResource) const; bool getNearestSightedResource(const ResourceType *rt, const Vec2i &pos, Vec2i &resultPos, bool usableResourceTypeOnly); bool isAlly(const Unit *unit) const; bool isAlly(int factionIndex) const; - bool reqsOk(const RequirableType *rt); - bool reqsOk(const CommandType *ct); + bool reqsOk(const RequirableType *rt); + bool reqsOk(const CommandType *ct); bool checkCosts(const ProducibleType *pt); bool isFreeCells(const Vec2i &pos, int size, Field field); diff --git a/source/glest_game/facilities/logger.cpp b/source/glest_game/facilities/logger.cpp index f72dc52c..cc7e8091 100644 --- a/source/glest_game/facilities/logger.cpp +++ b/source/glest_game/facilities/logger.cpp @@ -35,14 +35,15 @@ const int Logger::logLineCount= 15; // ===================== PUBLIC ======================== -Logger::Logger(){ +Logger::Logger() { string logs_path = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey); fileName= logs_path + "log.txt"; loadingTexture=NULL; + showProgressBar = false; } -Logger::~Logger(){ +Logger::~Logger() { cleanupLoadingTexture(); } @@ -66,12 +67,12 @@ void Logger::cleanupLoadingTexture() { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } -Logger & Logger::getInstance(){ +Logger & Logger::getInstance() { static Logger logger; return logger; } -void Logger::add(const string &str, bool renderScreen){ +void Logger::add(const string &str, bool renderScreen) { FILE *f=fopen(fileName.c_str(), "at+"); if(f!=NULL){ fprintf(f, "%s\n", str.c_str()); @@ -83,7 +84,7 @@ void Logger::add(const string &str, bool renderScreen){ } } -void Logger::clear(){ +void Logger::clear() { string s="Log file\n"; FILE *f= fopen(fileName.c_str(), "wt+"); @@ -97,8 +98,7 @@ void Logger::clear(){ fclose(f); } - -void Logger::loadLoadingScreen(string filepath){ +void Logger::loadLoadingScreen(string filepath) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -152,13 +152,14 @@ void Logger::renderLoadingScreen() { metrics.getVirtualW()/4, 62*metrics.getVirtualH()/100, false); - renderer.renderProgressBar( - progress, - metrics.getVirtualW()/4, - 59*metrics.getVirtualH()/100, - coreData.getDisplayFontSmall(), - 350,""); // no string here, because it has to be language specific and does not give much information - + if(showProgressBar == true) { + renderer.renderProgressBar( + progress, + metrics.getVirtualW()/4, + 59*metrics.getVirtualH()/100, + coreData.getDisplayFontSmall(), + 350,""); // no string here, because it has to be language specific and does not give much information + } renderer.swapBuffers(); } diff --git a/source/glest_game/facilities/logger.h b/source/glest_game/facilities/logger.h index e8724380..6c810dbc 100644 --- a/source/glest_game/facilities/logger.h +++ b/source/glest_game/facilities/logger.h @@ -43,7 +43,8 @@ private: string subtitle; string current; Texture2D *loadingTexture; - int progress; + int progress; + bool showProgressBar; private: Logger(); @@ -58,7 +59,9 @@ public: void setState(const string &state) {this->state= state;} void setSubtitle(const string &subtitle) {this->subtitle= subtitle;} void setProgress(int value) { this->progress = value; } - int getProgress() const {return progress;} + int getProgress() const {return progress;} + void showProgress() { showProgressBar = true;} + void hideProgress() { showProgressBar = false;} void add(const string &str, bool renderScreen= false); void loadLoadingScreen(string filepath); diff --git a/source/glest_game/game/commander.cpp b/source/glest_game/game/commander.cpp index f4e679e4..c894f1b6 100644 --- a/source/glest_game/game/commander.cpp +++ b/source/glest_game/game/commander.cpp @@ -152,18 +152,18 @@ void CommanderNetworkThread::execute() { // ===================================================== Commander::Commander() { - this->networkThread = new CommanderNetworkThread(this); - this->networkThread->setUniqueID(__FILE__); - this->networkThread->start(); + //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; + //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){ @@ -455,6 +455,9 @@ CommandResult Commander::pushNetworkCommand(const NetworkCommand* networkCommand } void Commander::signalNetworkUpdate(Game *game) { + + updateNetwork(game); +/* if(this->networkThread != NULL) { this->game = game; this->networkThread->signalUpdate(1); @@ -465,10 +468,11 @@ void Commander::signalNetworkUpdate(Game *game) { game->render(); } } +*/ } void Commander::commanderNetworkUpdateTask(int id) { - updateNetwork(game); + //updateNetwork(game); } void Commander::updateNetwork(Game *game) { @@ -476,26 +480,28 @@ void Commander::updateNetwork(Game *game) { //check that this is a keyframe //GameSettings *gameSettings = this->world->getGame()->getGameSettings(); - GameSettings *gameSettings = game->getGameSettings(); - if( networkManager.isNetworkGame() == false || - (world->getFrameCount() % gameSettings->getNetworkFramePeriod()) == 0) { + if(game != NULL) { + GameSettings *gameSettings = game->getGameSettings(); + if( networkManager.isNetworkGame() == false || + (world->getFrameCount() % gameSettings->getNetworkFramePeriod()) == 0) { - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] networkManager.isNetworkGame() = %d,world->getFrameCount() = %d, gameSettings->getNetworkFramePeriod() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkManager.isNetworkGame(),world->getFrameCount(),gameSettings->getNetworkFramePeriod()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] networkManager.isNetworkGame() = %d,world->getFrameCount() = %d, gameSettings->getNetworkFramePeriod() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkManager.isNetworkGame(),world->getFrameCount(),gameSettings->getNetworkFramePeriod()); - GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); - perfTimer.start(); - //update the keyframe - gameNetworkInterface->updateKeyframe(world->getFrameCount()); - if(perfTimer.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] gameNetworkInterface->updateKeyframe for %d took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,world->getFrameCount(),perfTimer.getMillis()); + perfTimer.start(); + //update the keyframe + gameNetworkInterface->updateKeyframe(world->getFrameCount()); + if(perfTimer.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] gameNetworkInterface->updateKeyframe for %d took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,world->getFrameCount(),perfTimer.getMillis()); - perfTimer.start(); - //give pending commands - for(int i= 0; i < gameNetworkInterface->getPendingCommandCount(); ++i){ - giveNetworkCommand(gameNetworkInterface->getPendingCommand(i)); - } - if(perfTimer.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] giveNetworkCommand took %lld msecs, PendingCommandCount = %d\n",__FILE__,__FUNCTION__,__LINE__,perfTimer.getMillis(),gameNetworkInterface->getPendingCommandCount()); - gameNetworkInterface->clearPendingCommands(); + perfTimer.start(); + //give pending commands + for(int i= 0; i < gameNetworkInterface->getPendingCommandCount(); ++i){ + giveNetworkCommand(gameNetworkInterface->getPendingCommand(i)); + } + if(perfTimer.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] giveNetworkCommand took %lld msecs, PendingCommandCount = %d\n",__FILE__,__FUNCTION__,__LINE__,perfTimer.getMillis(),gameNetworkInterface->getPendingCommandCount()); + gameNetworkInterface->clearPendingCommands(); + } } } diff --git a/source/glest_game/game/commander.h b/source/glest_game/game/commander.h index 87737a9b..c64b283c 100644 --- a/source/glest_game/game/commander.h +++ b/source/glest_game/game/commander.h @@ -77,8 +77,8 @@ private: World *world; Chrono perfTimer; - CommanderNetworkThread *networkThread; - Game *game; + //CommanderNetworkThread *networkThread; + //Game *game; public: Commander(); diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index c67a542e..5353df41 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -89,6 +89,9 @@ Game::Game(Program *program, const GameSettings *gameSettings): speed= sNormal; showFullConsole= false; + Logger &logger= Logger::getInstance(); + logger.showProgress(); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -108,14 +111,16 @@ Game::~Game() { logger.loadLoadingScreen(""); logger.setState(Lang::getInstance().get("Deleting")); logger.add("Game", true); + logger.hideProgress(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); SoundRenderer::getInstance().stopAllSounds(); - 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__); deleteValues(aiInterfaces.begin(), aiInterfaces.end()); + aiInterfaces.clear(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -125,7 +130,7 @@ Game::~Game() { world.end(); //must die before selection because of referencers - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] aiInterfaces.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,aiInterfaces.size()); // MUST DO THIS LAST!!!! Because objects above have pointers to things like // unit particles and fade them out etc and this end method deletes the original @@ -546,6 +551,8 @@ void Game::init(bool initForPreviewOnly) bool isNetworkGame = this->gameSettings.isNetworkGame(); NetworkRole role = networkManager.getNetworkRole(); + deleteValues(aiInterfaces.begin(), aiInterfaces.end()); + aiInterfaces.resize(world.getFactionCount()); for(int i=0; i < world.getFactionCount(); ++i) { Faction *faction= world.getFaction(i); diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 15eb0e28..b7c95bfe 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -124,13 +124,17 @@ void ClientInterface::update() { } } - int lastSendElapsed = difftime(time(NULL),lastNetworkCommandListSendTime); - if(lastNetworkCommandListSendTime > 0) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] lastSendElapsed = %d\n",__FILE__,__FUNCTION__,__LINE__,lastSendElapsed); + double lastSendElapsed = difftime(time(NULL),lastNetworkCommandListSendTime); + if(lastNetworkCommandListSendTime > 0) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] lastSendElapsed = %f\n",__FILE__,__FUNCTION__,__LINE__,lastSendElapsed); if(networkMessageCommandList.getCommandCount() > 0 || (lastNetworkCommandListSendTime > 0 && lastSendElapsed >= ClientInterface::maxNetworkCommandListSendTimeWait)) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + lastNetworkCommandListSendTime = time(NULL); sendMessage(&networkMessageCommandList); + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } // Possible cause of out of synch since we have more commands that need diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index c938d933..5a89ec21 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -263,6 +263,10 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex ConnectionSlot::~ConnectionSlot() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] START\n",__FILE__,__FUNCTION__,__LINE__); + close(); + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(BaseThread::shutdownAndWait(slotThreadWorker) == true) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); delete slotThreadWorker; @@ -270,8 +274,6 @@ ConnectionSlot::~ConnectionSlot() { } slotThreadWorker = NULL; - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - close(); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); } diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 43ac864a..378df740 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -264,22 +264,23 @@ bool ServerInterface::switchSlot(int fromPlayerIndex,int toPlayerIndex) { } void ServerInterface::removeSlot(int playerIndex,int lockedSlotIndex) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); MutexSafeWrapper safeMutex(&serverSynchAccessor,intToStr(__LINE__)); // Mention to everyone that this player is disconnected MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(playerIndex)); if(playerIndex != lockedSlotIndex) { - safeMutexSlot.setMutex(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + "_" + intToStr(playerIndex)); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); + safeMutexSlot.setMutex(&slotAccessorMutexes[playerIndex],intToStr(__LINE__) + string("_") + intToStr(playerIndex)); } ConnectionSlot *slot = slots[playerIndex]; bool notifyDisconnect = false; char szBuf[4096]=""; - if( slot != NULL) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + if(slot != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); if(slot->getLastReceiveCommandListTime() > 0) { const char* msgTemplate = "Player %s, disconnected from the game."; @@ -293,30 +294,31 @@ void ServerInterface::removeSlot(int playerIndex,int lockedSlotIndex) { notifyDisconnect = true; } } - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); slots[playerIndex]= NULL; safeMutexSlot.ReleaseLock(); safeMutex.ReleaseLock(); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); delete slot; - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); updateListen(); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); if(notifyDisconnect == true) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); string sMsg = szBuf; - sendTextMessage(sMsg,-1, true, lockedSlotIndex); + //sendTextMessage(sMsg,-1, true, lockedSlotIndex); + queueTextMessage(sMsg,-1, true); } - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d playerIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, lockedSlotIndex = %d\n",__FILE__,__FUNCTION__,__LINE__,playerIndex,lockedSlotIndex); } ConnectionSlot* ServerInterface::getSlot(int playerIndex) { @@ -602,6 +604,8 @@ void ServerInterface::update() { // properly identified themselves within the alloted time period validateConnectedClients(); + processTextMessageQueue(); + std::map socketTriggeredList; //update all slots updateSocketTriggeredList(socketTriggeredList); @@ -642,7 +646,7 @@ void ServerInterface::update() { threadsDone = true; // Examine all threads for completion of delegation for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { - MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + "_" + intToStr(i)); + MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],intToStr(__LINE__) + string("_") + intToStr(i)); ConnectionSlot* connectionSlot = slots[i]; if(connectionSlot != NULL && mapSlotSignalledList[i] == true && slotsCompleted.find(i) == slotsCompleted.end()) { @@ -1095,6 +1099,27 @@ void ServerInterface::waitUntilReady(Checksum* checksum) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] END\n",__FUNCTION__); } +void ServerInterface::processTextMessageQueue() { + MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__)); + if(textMessageQueue.size() > 0) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + for(int i = 0; i < textMessageQueue.size(); ++i) { + TextMessageQueue &item = textMessageQueue[i]; + sendTextMessage(item.text, item.teamIndex, item.echoLocal); + } + textMessageQueue.clear(); + } +} + +void ServerInterface::queueTextMessage(const string &text, int teamIndex, bool echoLocal) { + MutexSafeWrapper safeMutexSlot(&textMessageQueueThreadAccessor,intToStr(__LINE__)); + TextMessageQueue item; + item.text = text; + item.teamIndex = teamIndex; + item.echoLocal = echoLocal; + textMessageQueue.push_back(item); +} + void ServerInterface::sendTextMessage(const string &text, int teamIndex, bool echoLocal) { sendTextMessage(text, teamIndex, echoLocal, -1); } @@ -1327,6 +1352,8 @@ void ServerInterface::broadcastMessage(const NetworkMessage* networkMessage, int } } else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) { MutexSafeWrapper safeMutexSlot(NULL,intToStr(__LINE__) + "_" + intToStr(i)); if(i != lockedSlotIndex) { diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index 7214a2c8..0e8a4479 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -35,6 +35,13 @@ namespace Glest{ namespace Game{ class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbackInterface, public SimpleTaskCallbackInterface, public FTPClientValidationInterface { +class TextMessageQueue { +public: + string text; + int teamIndex; + bool echoLocal; +}; + private: ConnectionSlot* slots[GameConstants::maxPlayers]; Mutex slotAccessorMutexes[GameConstants::maxPlayers]; @@ -57,6 +64,9 @@ private: bool exitServer; int64 nextEventId; + Mutex textMessageQueueThreadAccessor; + vector textMessageQueue; + public: ServerInterface(); virtual ~ServerInterface(); @@ -75,6 +85,8 @@ public: virtual void sendTextMessage(const string &text, int teamIndex, bool echoLocal=false); void sendTextMessage(const string &text, int teamIndex, bool echoLocal, int lockedSlotIndex); + void queueTextMessage(const string &text, int teamIndex, bool echoLocal=false); + virtual void quitGame(bool userManuallyQuit); //misc @@ -138,6 +150,8 @@ private: std::map publishToMasterserver(); int64 getNextEventId(); + + void processTextMessageQueue(); }; }}//end namespace diff --git a/source/shared_lib/sources/util/conversion.cpp b/source/shared_lib/sources/util/conversion.cpp index 4eaee2c9..bd3c88f8 100644 --- a/source/shared_lib/sources/util/conversion.cpp +++ b/source/shared_lib/sources/util/conversion.cpp @@ -95,8 +95,8 @@ bool strToFloat(const string &s, float *f){ return true; } -string boolToStr(bool b){ - if(b){ +string boolToStr(bool b) { + if(b) { return "1"; } else{ @@ -106,25 +106,25 @@ string boolToStr(bool b){ string intToStr(int64 i) { char str[strSize]=""; - sprintf(str, "%lld", (long long int)i); + snprintf(str, strSize-1, "%lld", (long long int)i); return str; } string intToHex(int i){ char str[strSize]=""; - sprintf(str, "%x", i); + snprintf(str, strSize-1, "%x", i); return str; } -string floatToStr(float f,int precsion){ +string floatToStr(float f,int precsion) { char str[strSize]=""; - sprintf(str, "%.*f", precsion,f); + snprintf(str, strSize-1, "%.*f", precsion,f); return str; } -string doubleToStr(double d,int precsion){ +string doubleToStr(double d,int precsion) { char str[strSize]=""; - sprintf(str, "%.*f", precsion,d); + snprintf(str, strSize-1, "%.*f", precsion,d); return str; }