From cc4f2689887355875a6c4ca0a2ffe6b8b8462344 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Thu, 11 Nov 2010 08:02:50 +0000 Subject: [PATCH] - some additional AI caching for improved performance --- source/glest_game/ai/ai.cpp | 19 +++++ source/glest_game/ai/ai_interface.cpp | 53 +++++++++++++- source/glest_game/ai/ai_interface.h | 2 + source/glest_game/ai/ai_rule.cpp | 26 ++++++- source/glest_game/game/commander.cpp | 33 ++++++++- source/glest_game/game/game.cpp | 30 +++++--- source/glest_game/type_instances/faction.cpp | 76 ++++++++++++++++++++ source/glest_game/type_instances/faction.h | 6 ++ source/glest_game/type_instances/unit.cpp | 21 ++++++ source/glest_game/types/command_type.cpp | 4 +- source/glest_game/world/map.cpp | 27 +++++++ source/glest_game/world/unit_updater.cpp | 30 +++++++- 12 files changed, 309 insertions(+), 18 deletions(-) diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index 6d0dfe9f..bba077cc 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -141,19 +141,38 @@ Ai::~Ai() { } void Ai::update() { + + Chrono chrono; + chrono.start(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [START]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //process ai rules for(int ruleIdx = 0; ruleIdx < aiRules.size(); ++ruleIdx) { AiRule *rule = aiRules[ruleIdx]; if(rule == NULL) { throw runtime_error("rule == NULL"); } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),ruleIdx); + if((aiInterface->getTimer() % (rule->getTestInterval() * GameConstants::updateFps / 1000)) == 0) { + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, before rule->test()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),ruleIdx); + if(rule->test()) { aiInterface->printLog(3, intToStr(1000 * aiInterface->getTimer() / GameConstants::updateFps) + ": Executing rule: " + rule->getName() + '\n'); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, before rule->execute() [%s]]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),ruleIdx,rule->getName().c_str()); + rule->execute(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [ruleIdx = %d, after rule->execute() [%s]]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),ruleIdx,rule->getName().c_str()); } } } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [END]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } diff --git a/source/glest_game/ai/ai_interface.cpp b/source/glest_game/ai/ai_interface.cpp index bfef0f52..67cdaddc 100644 --- a/source/glest_game/ai/ai_interface.cpp +++ b/source/glest_game/ai/ai_interface.cpp @@ -64,7 +64,7 @@ AiInterface::AiInterface(Game &game, int factionIndex, int teamIndex, int useSta // ==================== main ==================== -void AiInterface::update(){ +void AiInterface::update() { timer++; ai.update(); } @@ -92,6 +92,10 @@ void AiInterface::printLog(int logLevel, const string &s){ // ==================== interaction ==================== +Faction *AiInterface::getMyFaction() { + return world->getFaction(factionIndex); +} + bool AiInterface::executeCommandOverNetwork() { bool enableServerControlledAI = gameSettings->getEnableServerControlledAI(); bool isNetworkGame = gameSettings->isNetworkGame(); @@ -124,6 +128,53 @@ CommandResult AiInterface::giveCommand(int unitIndex, CommandClass commandClass, } } +CommandResult AiInterface::giveCommand(Unit *unit, const CommandType *commandType, const Vec2i &pos) { + assert(this->gameSettings != NULL); + + if(unit == NULL) { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s Line: %d] Can not find AI unit in AI factionIndex = %d. Game out of synch.",__FILE__,__FUNCTION__,__LINE__,factionIndex); + throw runtime_error(szBuf); + } + const UnitType* unitType= unit->getType(); + if(unitType == NULL) { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s Line: %d] Can not find AI unittype with unit id: %d, AI factionIndex = %d. Game out of synch.",__FILE__,__FUNCTION__,__LINE__,unit->getId(),factionIndex); + throw runtime_error(szBuf); + } + const CommandType* ct= unit->getType()->findCommandTypeById(commandType->getId()); + if(ct == NULL) { + char szBuf[4096]=""; + sprintf(szBuf,"In [%s::%s Line: %d]\nCan not find AI command type for:\nunit = %d\n[%s]\n[%s]\nactual local factionIndex = %d.\nGame out of synch.", + __FILE__,__FUNCTION__,__LINE__, + unit->getId(), unit->getFullName().c_str(),unit->getDesc().c_str(), + unit->getFaction()->getIndex()); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",szBuf); + + std::string worldLog = world->DumpWorldToLog(); + std::string sError = "worldLog = " + worldLog + " " + string(szBuf); + throw runtime_error(sError); + } + + if(executeCommandOverNetwork() == true) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit id = %d\nunit = [%s]\ncommandType = %d - [%s]\nCommand Type List:\n%s\n",__FILE__,__FUNCTION__,__LINE__,unit->getId(),unit->toString().c_str(),commandType->getId(),commandType->toString().c_str(),unit->getType()->getCommandTypeListDesc().c_str()); + + CommandResult result = commander->tryGiveCommand(unit, commandType, pos, unit->getType(),CardinalDir::NORTH); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + return result; + } + else { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + CommandResult result = unit->giveCommand(new Command(commandType, pos)); + + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + return result; + } +} + CommandResult AiInterface::giveCommand(int unitIndex, const CommandType *commandType, const Vec2i &pos){ assert(this->gameSettings != NULL); diff --git a/source/glest_game/ai/ai_interface.h b/source/glest_game/ai/ai_interface.h index b7038527..f7a7a7c9 100644 --- a/source/glest_game/ai/ai_interface.h +++ b/source/glest_game/ai/ai_interface.h @@ -67,6 +67,7 @@ public: 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(); @@ -81,6 +82,7 @@ public: const Unit *getMyUnit(int unitIndex); const Unit *getOnSightUnit(int unitIndex); const FactionType *getMyFactionType(); + Faction *getMyFaction(); 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); diff --git a/source/glest_game/ai/ai_rule.cpp b/source/glest_game/ai/ai_rule.cpp index 129b4771..ba2a1052 100644 --- a/source/glest_game/ai/ai_rule.cpp +++ b/source/glest_game/ai/ai_rule.cpp @@ -105,11 +105,34 @@ bool AiRuleRepair::test(){ return false; } -void AiRuleRepair::execute(){ +void AiRuleRepair::execute() { AiInterface *aiInterface= ai->getAiInterface(); const Unit *damagedUnit= aiInterface->getMyUnit(damagedUnitIndex); //find a repairer and issue command + + if(damagedUnit != NULL) { + static std::vector skillClassList; + if(skillClassList.size() == 0) { + skillClassList.push_back(scStop); + skillClassList.push_back(scMove); + } + Faction *faction = aiInterface->getMyFaction(); + Unit *repairer = faction->findClosestUnitWithSkillClass( damagedUnit->getPos(), + ccRepair, + skillClassList, + damagedUnit->getType()); + if(repairer != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + const RepairCommandType *rct= static_cast(repairer->getType()->getFirstCtOfClass(ccRepair)); + aiInterface->giveCommand(repairer, rct, damagedUnit->getPos()); + aiInterface->printLog(3, "Repairing order issued"); + return; + } + } + +/* for(int i=0; igetMyUnitCount(); ++i){ const Unit *u= aiInterface->getMyUnit(i); const RepairCommandType *rct= static_cast(u->getType()->getFirstCtOfClass(ccRepair)); @@ -123,6 +146,7 @@ void AiRuleRepair::execute(){ } } } +*/ } // ===================================================== diff --git a/source/glest_game/game/commander.cpp b/source/glest_game/game/commander.cpp index 1e16ab19..817a5755 100644 --- a/source/glest_game/game/commander.cpp +++ b/source/glest_game/game/commander.cpp @@ -114,6 +114,9 @@ CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *com CardinalDir facing, bool tryQueue,Unit *targetUnit) const { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + Chrono chrono; + chrono.start(); + assert(this->world != NULL); assert(unit != NULL); assert(commandType != NULL); @@ -121,14 +124,22 @@ CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *com SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), commandType->getId(), pos, unitType->getId(), (targetUnit != NULL ? targetUnit->getId() : -1), facing, tryQueue); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - return pushNetworkCommand(&networkCommand); + CommandResult result = pushNetworkCommand(&networkCommand); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + return result; } CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos, const Unit *targetUnit, bool tryQueue) const{ @@ -376,8 +387,16 @@ void Commander::giveNetworkCommandSpecial(const NetworkCommand* networkCommand) */ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { + + Chrono chrono; + chrono.start(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [START]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + networkCommand->preprocessNetworkCommand(this->world); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after networkCommand->preprocessNetworkCommand]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + /* if(networkCommand->getNetworkCommandType() == nctNetworkCommand) { giveNetworkCommandSpecial(networkCommand); @@ -387,6 +406,8 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { { Unit* unit= world->findUnitById(networkCommand->getUnitId()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after world->findUnitById]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //execute command, if unit is still alive if(unit != NULL) { switch(networkCommand->getNetworkCommandType()) { @@ -397,10 +418,14 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { Command* command= buildCommand(networkCommand); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after buildCommand]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] command = %p\n",__FILE__,__FUNCTION__,__LINE__,command); unit->giveCommand(command, (networkCommand->getWantQueue() != 0)); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after unit->giveCommand]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); } break; @@ -409,6 +434,8 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { unit->cancelCommand(); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after unit->cancelCommand]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found nctCancelCommand\n",__FILE__,__FUNCTION__,__LINE__); } break; @@ -417,6 +444,8 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { unit->setMeetingPos(networkCommand->getPosition()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [after unit->setMeetingPos]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found nctSetMeetingPoint\n",__FILE__,__FUNCTION__,__LINE__); } break; @@ -428,6 +457,8 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] NULL Unit for id = %d, networkCommand->getNetworkCommandType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId(),networkCommand->getNetworkCommandType()); } } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld [END]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } Command* Commander::buildCommand(const NetworkCommand* networkCommand) const { diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 9fbbf5f1..2981cc63 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -681,24 +681,30 @@ void Game::update() { bool isNetworkGame = this->gameSettings.isNetworkGame(); NetworkRole role = networkManager.getNetworkRole(); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [before ReplaceDisconnectedNetworkPlayersWithAI]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + // Check to see if we are playing a network game and if any players // have disconnected? ReplaceDisconnectedNetworkPlayersWithAI(isNetworkGame, role); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after ReplaceDisconnectedNetworkPlayersWithAI]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //update for(int i = 0; i < updateLoops; ++i) { chrono.start(); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //AiInterface - for(int i = 0; i < world.getFactionCount(); ++i) { - Faction *faction = world.getFaction(i); + for(int j = 0; j < world.getFactionCount(); ++j) { + Faction *faction = world.getFaction(j); if( faction->getCpuControl(enableServerControlledAI,isNetworkGame,role) == true && - scriptManager.getPlayerModifiers(i)->getAiEnabled() == true) { + scriptManager.getPlayerModifiers(j)->getAiEnabled() == true) { - aiInterfaces[i]->update(); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] [i = %d] faction = %d, factionCount = %d, took msecs: %lld [before AI updates]\n",__FILE__,__FUNCTION__,__LINE__,i,j,world.getFactionCount(),chrono.getMillis()); - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] i = %d, world.getFactionCount() = %d, took msecs: %lld [AI updates]\n",__FILE__,__FUNCTION__,__LINE__,i,world.getFactionCount(),chrono.getMillis()); + aiInterfaces[j]->update(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] [i = %d] faction = %d, factionCount = %d, took msecs: %lld [after AI updates]\n",__FILE__,__FUNCTION__,__LINE__,i,j,world.getFactionCount(),chrono.getMillis()); } } @@ -708,33 +714,33 @@ void Game::update() { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //World world.update(); - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [world update]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [world update i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i); if(chrono.getMillis() > 0) chrono.start(); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); // Commander commander.updateNetwork(); - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [commander updating network]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + 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(); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //Gui gui.update(); - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [gui updating]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [gui updating i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i); if(chrono.getMillis() > 0) chrono.start(); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //Particle systems - if(weatherParticleSystem != NULL){ + if(weatherParticleSystem != NULL) { weatherParticleSystem->setPos(gameCamera.getPos()); } - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [weather particle updating]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [weather particle updating i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i); if(chrono.getMillis() > 0) chrono.start(); Renderer &renderer= Renderer::getInstance(); renderer.updateParticleManager(rsGame,avgRenderFps); - if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [particle manager updating]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [particle manager updating i = %d]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),i); if(chrono.getMillis() > 0) chrono.start(); //good_fpu_control_registers(NULL,__FILE__,__FUNCTION__,__LINE__); @@ -743,6 +749,8 @@ void Game::update() { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); //call the chat manager chatManager.updateNetwork(); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [chatManager.updateNetwork]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(chrono.getMillis() > 0) chrono.start(); //check for quiting status if(NetworkManager::getInstance().getGameNetworkInterface() != NULL && diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 25629ea4..fa324311 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -974,6 +974,82 @@ void Faction::deletePixels() { } } +Unit * Faction::findClosestUnitWithSkillClass( const Vec2i &pos,const CommandClass &cmdClass, + const std::vector &skillClassList, + const UnitType *unitType) { + Unit *result = NULL; + + std::map >::iterator iterFind = cacheUnitCommandClassList.find(cmdClass); + if(iterFind != cacheUnitCommandClassList.end()) { + for(std::map::iterator iter = iterFind->second.begin(); + iter != iterFind->second.end(); ++iter) { + Unit *curUnit = findUnit(iter->second); + if(curUnit != NULL) { + + bool isUnitPossibleCandidate = true; + if(skillClassList.size() > 0) { + isUnitPossibleCandidate = false; + + for(int j = 0; j < skillClassList.size(); ++j) { + SkillClass skValue = skillClassList[j]; + if(curUnit->getCurrSkill()->getClass() == skValue) { + isUnitPossibleCandidate = true; + break; + } + } + } + + if(isUnitPossibleCandidate == true) { + if(result == NULL || curUnit->getPos().dist(pos) < result->getPos().dist(pos)) { + result = curUnit; + } + } + } + } + } + + if(result == NULL) { + for(int i = 0; i < getUnitCount(); ++i) { + Unit *curUnit = getUnit(i); + + bool isUnitPossibleCandidate = false; + + const CommandType *cmdType = curUnit->getType()->getFirstCtOfClass(cmdClass); + if(cmdType != NULL) { + const RepairCommandType *rct = dynamic_cast(cmdType); + if(rct != NULL && rct->isRepairableUnitType(unitType)) { + isUnitPossibleCandidate = true; + } + } + else { + isUnitPossibleCandidate = false; + } + + if(isUnitPossibleCandidate == true && skillClassList.size() > 0) { + isUnitPossibleCandidate = false; + + for(int j = 0; j < skillClassList.size(); ++j) { + SkillClass skValue = skillClassList[j]; + if(curUnit->getCurrSkill()->getClass() == skValue) { + isUnitPossibleCandidate = true; + break; + } + } + } + + + if(isUnitPossibleCandidate == true) { + cacheUnitCommandClassList[cmdClass][curUnit->getId()] = curUnit->getId(); + + if(result == NULL || curUnit->getPos().dist(pos) < result->getPos().dist(pos)) { + result = curUnit; + } + } + } + } + return result; +} + std::string Faction::toString() const { std::string result = ""; diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index dd84104d..35cec705 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -19,6 +19,7 @@ #include "texture.h" #include "resource.h" #include "game_constants.h" +#include "command_type.h" #include "leak_dumper.h" using std::map; @@ -89,6 +90,7 @@ private: std::map cachedCloseResourceTargetLookupList; time_t lastResourceTargettListPurge; + std::map > cacheUnitCommandClassList; // This cache stores the units free cell movement calcs during a world // update of the faction //std::map > > localCacheForUnitCellMovement; @@ -171,6 +173,10 @@ public: Vec2i getClosestResourceTypeTargetFromCache(const Vec2i &pos, const ResourceType *type); void cleanupResourceTypeTargetCache(std::vector *deleteListPtr); + Unit * findClosestUnitWithSkillClass(const Vec2i &pos,const CommandClass &cmdClass, + const std::vector &skillClassList, + const UnitType *unitType); + void deletePixels(); std::string toString() const; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 0cb720af..c290af3b 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -749,6 +749,9 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"\n======================\nUnit Command tryQueue = %d\nUnit Info:\n%s\nCommand Info:\n%s\n",tryQueue,this->toString().c_str(),command->toString().c_str()); + Chrono chrono; + chrono.start(); + assert(command != NULL); assert(command->getCommandType() != NULL); @@ -760,8 +763,11 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { const int command_priority = command->getCommandType()->getPriority(); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(command->getCommandType()->isQueuable(tryQueue) && (commands.empty() || (command_priority >= commands.back()->getCommandType()->getPriority()))){ + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); //Delete all lower-prioirty commands for (list::iterator i = commands.begin(); i != commands.end();) { @@ -774,6 +780,8 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { } } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //cancel current command if it is not queuable SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -782,20 +790,29 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { cancelCommand(); } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } else { //empty command queue SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); clearCommands(); this->unitPath->clear(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] A\n",__FILE__,__FUNCTION__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //check command SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); CommandResult result= checkCommand(command); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + if(result == crSuccess) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); applyCommand(command); @@ -803,6 +820,8 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] B\n",__FILE__,__FUNCTION__); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //push back command if(result == crSuccess) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -813,6 +832,8 @@ CommandResult Unit::giveCommand(Command *command, bool tryQueue) { delete command; } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result); return result; diff --git a/source/glest_game/types/command_type.cpp b/source/glest_game/types/command_type.cpp index 8b82381a..a99fd9ad 100644 --- a/source/glest_game/types/command_type.cpp +++ b/source/glest_game/types/command_type.cpp @@ -547,11 +547,11 @@ string RepairCommandType::toString() const{ //get bool RepairCommandType::isRepairableUnitType(const UnitType *unitType) const { - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unitType [%s] repairableUnits.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,unitType->toString().c_str(),repairableUnits.size()); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unitType [%s] repairableUnits.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,unitType->toString().c_str(),repairableUnits.size()); for(int i = 0; i < repairableUnits.size(); ++i) { const UnitType *curUnitType = static_cast(repairableUnits[i]); - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] curUnitType [%s] i = %d\n",__FILE__,__FUNCTION__,__LINE__,curUnitType->toString().c_str(),i); + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] curUnitType [%s] i = %d\n",__FILE__,__FUNCTION__,__LINE__,curUnitType->toString().c_str(),i); if(curUnitType == unitType) { return true; diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index 29dcbdf5..d5b9a1d9 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -782,6 +782,9 @@ bool Map::isNextToUnitTypeCells(const UnitType *ut, const Vec2i &pos, bool Map::isInUnitTypeCells(const UnitType *ut, const Vec2i &pos, const Vec2i &testPos) const { assert(ut!=NULL); + if(ut == NULL) { + throw runtime_error("ut == NULL"); + } Cell *testCell = getCell(testPos); for(int i=0; i < ut->getSize(); ++i){ @@ -802,14 +805,26 @@ bool Map::isInUnitTypeCells(const UnitType *ut, const Vec2i &pos, void Map::putUnitCells(Unit *unit, const Vec2i &pos) { assert(unit!=NULL); + if(unit == NULL) { + throw runtime_error("ut == NULL"); + } + const UnitType *ut= unit->getType(); for(int i = 0; i < ut->getSize(); ++i) { for(int j = 0; j < ut->getSize(); ++j) { Vec2i currPos= pos + Vec2i(i, j); assert(isInside(currPos)); + if(isInside(currPos) == false) { + throw runtime_error("isInside(currPos) == false"); + } + if( ut->hasCellMap() == false || ut->getCellMapCell(i, j, unit->getModelFacing())) { assert(getCell(currPos)->getUnit(unit->getCurrField()) == NULL); + if(getCell(currPos)->getUnit(unit->getCurrField()) != NULL) { + throw runtime_error("getCell(currPos)->getUnit(unit->getCurrField()) != NULL"); + } + getCell(currPos)->setUnit(unit->getCurrField(), unit); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] currPos = %s unit = %s\n",__FILE__,__FUNCTION__,__LINE__,currPos.getString().c_str(),unit->toString().c_str()); @@ -829,14 +844,26 @@ void Map::putUnitCells(Unit *unit, const Vec2i &pos) { //removes a unit from cells void Map::clearUnitCells(Unit *unit, const Vec2i &pos) { assert(unit!=NULL); + if(unit == NULL) { + throw runtime_error("unit == NULL"); + } + const UnitType *ut= unit->getType(); for(int i=0; igetSize(); ++i){ for(int j=0; jgetSize(); ++j){ Vec2i currPos= pos + Vec2i(i, j); assert(isInside(currPos)); + if(isInside(currPos) == false) { + throw runtime_error("isInside(currPos) == false"); + } + if(ut->hasCellMap() == false || ut->getCellMapCell(i, j, unit->getModelFacing())) { assert(getCell(currPos)->getUnit(unit->getCurrField())==unit); + if(getCell(currPos)->getUnit(unit->getCurrField()) != unit) { + throw runtime_error("getCell(currPos)->getUnit(unit->getCurrField()) != unit"); + } + getCell(currPos)->setUnit(unit->getCurrField(), NULL); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] currPos = %s unit = %s\n",__FILE__,__FUNCTION__,__LINE__,currPos.getString().c_str(),unit->toString().c_str()); diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index a47daddf..1a12fb76 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -93,6 +93,11 @@ UnitUpdater::~UnitUpdater() { //skill dependent actions void UnitUpdater::updateUnit(Unit *unit) { + Chrono chrono; + chrono.start(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [START OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + SoundRenderer &soundRenderer= SoundRenderer::getInstance(); //play skill sound @@ -106,6 +111,8 @@ void UnitUpdater::updateUnit(Unit *unit) { } } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after playsound]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //start attack particle system if(unit->getCurrSkill()->getClass() == scAttack) { const AttackSkillType *ast= static_cast(unit->getCurrSkill()); @@ -115,12 +122,20 @@ void UnitUpdater::updateUnit(Unit *unit) { } } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after attack particle system]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + bool update = unit->update(); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after unit->update()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //update unit - if(unit->update()) { + if(update == true) { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); updateUnitCommand(unit); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after updateUnitCommand()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //if unit is out of EP, it stops if(unit->computeEp()) { unit->setCurrSkill(scStop); @@ -131,21 +146,29 @@ void UnitUpdater::updateUnit(Unit *unit) { if(unit->getCurrSkill()->getClass() == scMove) { world->moveUnitCells(unit); + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after world->moveUnitCells()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //play water sound - if(map->getCell(unit->getPos())->getHeight()getWaterLevel() && unit->getCurrField()==fLand){ + if(map->getCell(unit->getPos())->getHeight() < map->getWaterLevel() && unit->getCurrField() == fLand) { soundRenderer.playFx( CoreData::getInstance().getWaterSound(), unit->getCurrVector(), gameCamera->getPos() ); + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after soundFx()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } } } + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //unit death if(unit->isDead() && unit->getCurrSkill()->getClass() != scDie) { unit->kill(); } + + if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld --------------------------- [END OF METHOD] ---------------------------\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } // ==================== progress commands ==================== @@ -380,6 +403,9 @@ void UnitUpdater::updateBuild(Unit *unit) { //if arrived destination assert(ut); + if(ut == NULL) { + throw runtime_error("ut == NULL"); + } bool canOccupyCell = false; switch(this->game->getGameSettings()->getPathFinderType()) {