From 56494f3cd23936503cf50ee2b2165a48fdd2fa8b Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Fri, 27 May 2016 16:15:27 -0700 Subject: [PATCH] - finally fixing issue #102 (bad cell visible handling when fog of war turned off) --- source/glest_game/ai/ai.cpp | 8 + source/glest_game/ai/ai.h | 2 +- source/glest_game/ai/path_finder.cpp | 128 ++++++++++----- source/glest_game/ai/path_finder.h | 145 +++++++++++++++-- source/glest_game/main/main.cpp | 1 + source/glest_game/type_instances/faction.cpp | 10 ++ source/glest_game/type_instances/unit.cpp | 52 +++++- source/glest_game/type_instances/unit.h | 8 +- source/glest_game/world/map.cpp | 55 ++++++- source/glest_game/world/map.h | 153 +++++++++++++++++- source/glest_game/world/minimap.cpp | 6 +- source/glest_game/world/unit_updater.cpp | 25 ++- source/glest_game/world/world.cpp | 75 +++++++-- source/glest_game/world/world.h | 6 +- source/shared_lib/include/graphics/vec.h | 10 +- .../shared_lib/include/platform/sdl/thread.h | 6 + source/shared_lib/include/util/util.h | 1 + .../sources/platform/posix/socket.cpp | 2 +- .../sources/platform/sdl/thread.cpp | 11 ++ source/shared_lib/sources/util/randomgen.cpp | 6 +- 20 files changed, 588 insertions(+), 122 deletions(-) diff --git a/source/glest_game/ai/ai.cpp b/source/glest_game/ai/ai.cpp index 21b5937d..d51f5b56 100644 --- a/source/glest_game/ai/ai.cpp +++ b/source/glest_game/ai/ai.cpp @@ -329,6 +329,14 @@ Ai::~Ai() { aiInterface = NULL; } +RandomGen* Ai::getRandom() { +// if(Thread::isCurrentThreadMainThread() == false) { +// throw megaglest_runtime_error("Invalid access to AI random from outside main thread current id = " + +// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); +// } + return &random; +} + void Ai::update() { Chrono chrono; diff --git a/source/glest_game/ai/ai.h b/source/glest_game/ai/ai.h index 31f70018..69dd3979 100644 --- a/source/glest_game/ai/ai.h +++ b/source/glest_game/ai/ai.h @@ -198,7 +198,7 @@ public: //state requests AiInterface *getAiInterface() const {return aiInterface;} - RandomGen* getRandom() {return &random;} + RandomGen* getRandom(); int getCountOfType(const UnitType *ut); int getMinWarriors() const { return minWarriors; } diff --git a/source/glest_game/ai/path_finder.cpp b/source/glest_game/ai/path_finder.cpp index 6a371557..84a72429 100644 --- a/source/glest_game/ai/path_finder.cpp +++ b/source/glest_game/ai/path_finder.cpp @@ -51,8 +51,9 @@ PathFinder::PathFinder() { } int PathFinder::getPathFindExtendRefreshNodeCount(FactionState &faction) { - int refreshNodeCount = faction.random.randRange(PathFinder::pathFindExtendRefreshNodeCountMin,PathFinder::pathFindExtendRefreshNodeCountMax); - return refreshNodeCount; + //int refreshNodeCount = faction.random.randRange(PathFinder::pathFindExtendRefreshNodeCountMin,PathFinder::pathFindExtendRefreshNodeCountMax); + //return refreshNodeCount; + return PathFinder::pathFindExtendRefreshNodeCountMin; } PathFinder::PathFinder(const Map *map) { @@ -202,11 +203,19 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu if(map->canMove(unit, unit->getPos(), pos)) { if(frameIndex < 0) { - unit->setTargetPos(pos); - - if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { char szBuf[8096]=""; - snprintf(szBuf,8096,"map->canMove to pos [%s] from [%s]",pos.getString().c_str(),unit->getPos().getString().c_str()); + snprintf(szBuf,8096,"#1 map->canMove to pos [%s] from [%s]",pos.getString().c_str(),unit->getPos().getString().c_str()); + unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + } + + unit->setTargetPos(pos,frameIndex < 0); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"#2 map->canMove to pos [%s] from [%s]",pos.getString().c_str(),unit->getPos().getString().c_str()); unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); } @@ -222,7 +231,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu if(map->canMove(unit, unit->getPos(), pos)) { if(frameIndex < 0) { advPath->pop(); - unit->setTargetPos(pos); + unit->setTargetPos(pos,frameIndex < 0); } return tsMoving; @@ -321,10 +330,29 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu int factionIndex = unit->getFactionIndex(); FactionState &faction = factions.getFactionState(factionIndex); - int tryRadius = faction.random.randRange(0,1); + if(Thread::isCurrentThreadMainThread() == false) { + throw megaglest_runtime_error("#2 Invalid access to FactionState random from outside main thread current id = " + + intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); + } + + int tryRadius = faction.random.randRange(1,2); + //int tryRadius = faction.random.IRandomX(1,2); + //int tryRadius = 1; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In astar bailout() tryRadius %d",tryRadius); + + if(frameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } // Try to bail out up to PathFinder::pathFindBailoutRadius cells away - if(tryRadius > 0) { + if(tryRadius == 2) { for(int bailoutX = -PathFinder::pathFindBailoutRadius; bailoutX <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutX) { for(int bailoutY = -PathFinder::pathFindBailoutRadius; bailoutY <= PathFinder::pathFindBailoutRadius && ts == tsBlocked; ++bailoutY) { const Vec2i newFinalPos = finalPos + Vec2i(bailoutX,bailoutY); @@ -413,7 +441,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu if(map->canMove(unit, unit->getPos(), pos)) { if(frameIndex < 0) { - unit->setTargetPos(pos); + unit->setTargetPos(pos,frameIndex < 0); } } else { @@ -438,7 +466,7 @@ TravelState PathFinder::findPath(Unit *unit, const Vec2i &finalPos, bool *wasStu if(map->canMove(unit, unit->getPos(), pos)) { if(frameIndex < 0) { advPath->pop(); - unit->setTargetPos(pos); + unit->setTargetPos(pos,frameIndex < 0); } } else { @@ -594,11 +622,11 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout } unit->setUsePathfinderExtendedMaxNodes(false); -// if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) { -// char szBuf[8096]=""; -// snprintf(szBuf,8096,"return factions[unitFactionIndex].precachedTravelState[unit->getId()];"); -// unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); -// } + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"return factions[unitFactionIndex].precachedTravelState[unit->getId()];"); + unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + } return faction.precachedTravelState[unit->getId()]; } @@ -638,7 +666,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout const Vec2i unitPos = unit->getPos(); const Vec2i finalPos= computeNearestFreePos(unit, targetPos); - float dist= unitPos.dist(finalPos); + float dist = unitPos.dist(finalPos); faction.useMaxNodeCount = PathFinder::pathFindNodesMax; @@ -808,9 +836,9 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(nodeLimitReached == true) { if(faction.closedNodesList.empty() == false) { - float bestHeuristic = faction.closedNodesList.begin()->first; + float bestHeuristic = truncateDecimal(faction.closedNodesList.begin()->first,6); if(lastNode != NULL && bestHeuristic < lastNode->heuristic) { - lastNode= faction.closedNodesList.begin()->second[0]; + lastNode= faction.closedNodesList.begin()->second.front(); } } } @@ -889,7 +917,6 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(minorDebugPathfinder) printf("nodePos [%s]\n",nodePos.getString().c_str()); if(frameIndex >= 0) { - faction.precachedPath[unit->getId()].push_back(nodePos); } else { @@ -903,19 +930,37 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true && chrono.getMillis() > 4) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis()); - if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { char szBuf[8096]=""; string pathToTake = ""; - for(int i = 0; i < path->getQueueCount(); ++i) { - Vec2i &pos = path->getQueue()[i]; - if(pathToTake != "") { - pathToTake += ", "; + if(frameIndex < 0) { + vector pathQueue = path->getQueue(); + for(unsigned int index = 0; index < pathQueue.size(); ++index) { + Vec2i &pos = pathQueue[index]; + if(pathToTake != "") { + pathToTake += ", "; + } + pathToTake += pos.getString(); + } + } + else { + for(unsigned int index = 0; index < faction.precachedPath[unit->getId()].size(); ++index) { + Vec2i &pos = faction.precachedPath[unit->getId()][index]; + if(pathToTake != "") { + pathToTake += ", "; + } + pathToTake += pos.getString(); } - pathToTake += pos.getString(); } - unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); snprintf(szBuf,8096,"Path for unit to take = %s",pathToTake.c_str()); + if(frameIndex < 0) { + unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + } + else { + unit->logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + } } if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) { @@ -976,25 +1021,24 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos, bool inBailout void PathFinder::processNearestFreePos(const Vec2i &finalPos, int i, int j, int size, Field field, int teamIndex,Vec2i unitPos, Vec2i &nearestPos, float &nearestDist) { try { - Vec2i currPos= finalPos + Vec2i(i, j); + Vec2i currPos= finalPos + Vec2i(i, j); - if(map->isAproxFreeCells(currPos, size, field, teamIndex)) { - float dist= currPos.dist(finalPos); + if(map->isAproxFreeCells(currPos, size, field, teamIndex)) { + float dist = currPos.dist(finalPos); - //if nearer from finalPos - if(dist < nearestDist){ - nearestPos= currPos; - nearestDist= dist; - } - //if the distance is the same compare distance to unit - else if(dist == nearestDist){ - if(currPos.dist(unitPos) < nearestPos.dist(unitPos)) { - nearestPos= currPos; + //if nearer from finalPos + if(dist < nearestDist){ + nearestPos = currPos; + nearestDist = dist; + } + //if the distance is the same compare distance to unit + else if(dist == nearestDist){ + if(currPos.dist(unitPos) < nearestPos.dist(unitPos)) { + nearestPos = currPos; + } } } } - - } catch(const exception &ex) { SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); @@ -1034,7 +1078,7 @@ Vec2i PathFinder::computeNearestFreePos(const Unit *unit, const Vec2i &finalPos) Vec2i unitPos= unit->getPosNotThreadSafe(); nearestPos= unitPos; - float nearestDist= unitPos.dist(finalPos); + float nearestDist = unitPos.dist(finalPos); for(int i= -maxFreeSearchRadius; i <= maxFreeSearchRadius; ++i) { for(int j= -maxFreeSearchRadius; j <= maxFreeSearchRadius; ++j) { diff --git a/source/glest_game/ai/path_finder.h b/source/glest_game/ai/path_finder.h index 9d1662e4..23717a77 100644 --- a/source/glest_game/ai/path_finder.h +++ b/source/glest_game/ai/path_finder.h @@ -24,7 +24,7 @@ #include "skill_type.h" #include "map.h" #include "unit.h" - +//#include "randomc.h" #include "leak_dumper.h" using std::vector; @@ -90,15 +90,16 @@ public: protected: Mutex *factionMutexPrecache; public: - FactionState() : + FactionState(int factionIndex) : //factionMutexPrecache(new Mutex) { - factionMutexPrecache(NULL) { + factionMutexPrecache(NULL) { //, random(factionIndex) { openPosList.clear(); openNodesList.clear(); closedNodesList.clear(); nodePool.clear(); nodePoolCount = 0; + this->factionIndex = factionIndex; useMaxNodeCount = 0; precachedTravelState.clear(); @@ -119,7 +120,9 @@ public: std::vector nodePool; int nodePoolCount; + int factionIndex; RandomGen random; + //CRandomMersenne random; int useMaxNodeCount; std::map precachedTravelState; @@ -133,7 +136,7 @@ public: void init() { for(int index = 0; index < GameConstants::maxPlayers; ++index) { - factions.push_back(new FactionState()); + factions.push_back(new FactionState(index)); } } @@ -224,6 +227,7 @@ private: } Vec2i computeNearestFreePos(const Unit *unit, const Vec2i &targetPos); + inline static float heuristic(const Vec2i &pos, const Vec2i &finalPos) { return pos.dist(finalPos); } @@ -240,29 +244,44 @@ private: throw megaglest_runtime_error("openNodesList.empty() == true"); } - Node *result = faction.openNodesList.begin()->second[0]; + Node *result = faction.openNodesList.begin()->second.front(); faction.openNodesList.begin()->second.erase(faction.openNodesList.begin()->second.begin()); - if(faction.openNodesList.begin()->second.size() == 0) { + if(faction.openNodesList.begin()->second.empty()) { faction.openNodesList.erase(faction.openNodesList.begin()); } return result; } inline bool processNode(Unit *unit, Node *node,const Vec2i finalPos, - int i, int j, bool &nodeLimitReached,int maxNodeCount) { + int x, int y, bool &nodeLimitReached,int maxNodeCount) { bool result = false; - Vec2i sucPos= node->pos + Vec2i(i, j); + Vec2i sucPos= node->pos + Vec2i(x, y); int unitFactionIndex = unit->getFactionIndex(); FactionState &faction = factions.getFactionState(unitFactionIndex); - if(openPos(sucPos, faction) == false && - canUnitMoveSoon(unit, node->pos, sucPos) == true) { + bool foundOpenPosForPos = openPos(sucPos, faction); + bool allowUnitMoveSoon = canUnitMoveSoon(unit, node->pos, sucPos); + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In processNode() nodeLimitReached %d unitFactionIndex %d foundOpenPosForPos %d allowUnitMoveSoon %d maxNodeCount %d node->pos = %s finalPos = %s sucPos = %s faction.openPosList.size() %ld closedNodesList.size() %ld", + nodeLimitReached,unitFactionIndex,foundOpenPosForPos, allowUnitMoveSoon, maxNodeCount,node->pos.getString().c_str(),finalPos.getString().c_str(),sucPos.getString().c_str(),faction.openPosList.size(),faction.closedNodesList.size()); + + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(foundOpenPosForPos == false && allowUnitMoveSoon) { //if node is not open and canMove then generate another node Node *sucNode= newNode(faction,maxNodeCount); if(sucNode != NULL) { sucNode->pos= sucPos; - sucNode->heuristic= heuristic(sucNode->pos, finalPos); + sucNode->heuristic = heuristic(sucNode->pos, finalPos); sucNode->prev= node; sucNode->next= NULL; sucNode->exploredCell = map->getSurfaceCell( @@ -274,6 +293,20 @@ private: faction.openPosList[sucNode->pos] = true; result = true; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In processNode() sucPos = %s",sucPos.getString().c_str()); + + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + } else { nodeLimitReached= true; @@ -287,7 +320,7 @@ private: Field field, int teamIndex,Vec2i unitPos, Vec2i &nearestPos, float &nearestDist); int getPathFindExtendRefreshNodeCount(FactionState &faction); - inline bool canUnitMoveSoon(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2) { + inline bool canUnitMoveSoon(Unit *unit, const Vec2i &pos1, const Vec2i &pos2) { bool result = map->aproxCanMoveSoon(unit, pos1, pos2); return result; } @@ -298,15 +331,58 @@ private: std::map cameFrom, std::map , bool> canAddNode, Unit *& unit, int & maxNodeCount, int curFrameIndex) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In doAStarPathSearch() nodeLimitReached %d whileLoopCount %d unitFactionIndex %d pathFound %d maxNodeCount %d", + nodeLimitReached,whileLoopCount,unitFactionIndex,pathFound, maxNodeCount); + + if(curFrameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + FactionState &faction = factions.getFactionState(unitFactionIndex); while(nodeLimitReached == false) { whileLoopCount++; if(faction.openNodesList.empty() == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In doAStarPathSearch() nodeLimitReached %d whileLoopCount %d unitFactionIndex %d pathFound %d maxNodeCount %d", + nodeLimitReached,whileLoopCount,unitFactionIndex,pathFound, maxNodeCount); + + if(curFrameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + pathFound = false; break; } node = minHeuristicFastLookup(faction); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In doAStarPathSearch() nodeLimitReached %d whileLoopCount %d unitFactionIndex %d pathFound %d maxNodeCount %d node->pos = %s finalPos = %s node->exploredCell = %d", + nodeLimitReached,whileLoopCount,unitFactionIndex,pathFound, maxNodeCount,node->pos.getString().c_str(),finalPos.getString().c_str(),node->exploredCell); + + if(curFrameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + if(node->pos == finalPos || node->exploredCell == false) { pathFound = true; break; @@ -321,8 +397,30 @@ private: int failureCount = 0; int cellCount = 0; - int tryDirection = faction.random.randRange(0, 3); - if(tryDirection == 3) { +// if(Thread::isCurrentThreadMainThread() == false) { +// throw megaglest_runtime_error("#1 Invalid access to FactionState random from outside main thread current id = " + +// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); +// } + + //int tryDirection = 1; + //int tryDirection = faction.random.IRandomX(1, 4); + int tryDirection = faction.random.randRange(1, 4); + //int tryDirection = unit->getRandom(true)->randRange(1, 4); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In doAStarPathSearch() tryDirection %d",tryDirection); + + if(curFrameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(tryDirection == 4) { for(int i = 1;i >= -1 && nodeLimitReached == false;--i) { for(int j = -1;j <= 1 && nodeLimitReached == false;++j) { if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { @@ -332,7 +430,7 @@ private: } } } - else if(tryDirection == 2) { + else if(tryDirection == 3) { for(int i = -1;i <= 1 && nodeLimitReached == false;++i) { for(int j = 1;j >= -1 && nodeLimitReached == false;--j) { if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { @@ -342,7 +440,7 @@ private: } } } - else if(tryDirection == 1) { + else if(tryDirection == 2) { for(int i = -1;i <= 1 && nodeLimitReached == false;++i) { for(int j = -1;j <= 1 && nodeLimitReached == false;++j) { if(processNode(unit, node, finalPos, i, j, nodeLimitReached, maxNodeCount) == false) { @@ -363,6 +461,21 @@ private: } } } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In doAStarPathSearch() nodeLimitReached %d whileLoopCount %d unitFactionIndex %d pathFound %d maxNodeCount %d", + nodeLimitReached,whileLoopCount,unitFactionIndex,pathFound, maxNodeCount); + + if(curFrameIndex >= 0) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + } }; diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index 40276ca8..24b2b34e 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -4129,6 +4129,7 @@ int glestMain(int argc, char** argv) { #endif + Thread::setMainThreadId(); // printf("START ALLOC char 200\n"); //char *ptr = new char[200]; // printf("END ALLOC char 200\n"); diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index 1cf5550a..fda62e0e 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -1542,7 +1542,13 @@ Vec2i Faction::getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceT // First look immediately around the unit's position // 0 means start looking leftbottom to top right +// if(Thread::isCurrentThreadMainThread() == false) { +// throw megaglest_runtime_error("#1 Invalid access to Faction random from outside main thread current id = " + +// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); +// } int tryRadius = random.randRange(0,1); + //int tryRadius = unit->getRandom(true)->randRange(0,1); + //int tryRadius = 0; if(tryRadius == 0) { for(int j = -harvestDistance; j <= harvestDistance && foundCloseResource == false; ++j) { for(int k = -harvestDistance; k <= harvestDistance && foundCloseResource == false; ++k) { @@ -1665,6 +1671,10 @@ Vec2i Faction::getClosestResourceTypeTargetFromCache(const Vec2i &pos, const Res bool foundCloseResource = false; // 0 means start looking leftbottom to top right +// if(Thread::isCurrentThreadMainThread() == false) { +// throw megaglest_runtime_error("#2 Invalid access to Faction random from outside main thread current id = " + +// intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); +// } int tryRadius = random.randRange(0,1); if(tryRadius == 0) { // First look immediately around the given position diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 26794c7a..e180a64d 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -120,6 +120,11 @@ void UnitPathBasic::add(const Vec2i &path) { } } + if(Thread::isCurrentThreadMainThread() == false) { + throw megaglest_runtime_error("Invalid access to UnitPathBasic add from outside main thread current id = " + + intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); + } + pathQueue.push_back(path); } @@ -129,6 +134,11 @@ Vec2i UnitPathBasic::pop(bool removeFrontPos) { } Vec2i p= pathQueue.front(); if(removeFrontPos == true) { + if(Thread::isCurrentThreadMainThread() == false) { + throw megaglest_runtime_error("Invalid access to UnitPathBasic delete from outside main thread current id = " + + intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); + } + pathQueue.erase(pathQueue.begin()); } return p; @@ -1371,7 +1381,15 @@ void Unit::setTarget(const Unit *unit){ targetRef= unit; } -void Unit::setPos(const Vec2i &pos, bool clearPathFinder) { +RandomGen* Unit::getRandom(bool threadAccessAllowed) { + if(threadAccessAllowed == false && Thread::isCurrentThreadMainThread() == false) { + throw megaglest_runtime_error("Invalid access to unit random from outside main thread current id = " + + intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); + } + return &random; +} + +void Unit::setPos(const Vec2i &pos, bool clearPathFinder, bool threaded) { if(map->isInside(pos) == false || map->isInsideSurface(map->toSurfCoords(pos)) == false) { throw megaglest_runtime_error("#3 Invalid path position = " + pos.getString()); } @@ -1379,6 +1397,13 @@ void Unit::setPos(const Vec2i &pos, bool clearPathFinder) { static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__); MutexSafeWrapper safeMutex(mutexCommands,mutexOwnerId); + if(threaded) { + logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } + else { + logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } + if(clearPathFinder == true && this->unitPath != NULL) { this->unitPath->clear(); } @@ -1394,7 +1419,12 @@ void Unit::setPos(const Vec2i &pos, bool clearPathFinder) { refreshPos(); - logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + if(threaded) { + logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } + else { + logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } } void Unit::refreshPos(bool forceRefresh) { @@ -1452,7 +1482,7 @@ void Unit::calculateFogOfWarRadius(bool forceRefresh) { } } -void Unit::setTargetPos(const Vec2i &targetPos) { +void Unit::setTargetPos(const Vec2i &targetPos, bool threaded) { if(map->isInside(targetPos) == false || map->isInsideSurface(map->toSurfCoords(targetPos)) == false) { throw megaglest_runtime_error("#4 Invalid path position = " + targetPos.getString()); @@ -1474,7 +1504,12 @@ void Unit::setTargetPos(const Vec2i &targetPos) { this->targetPos= targetPos; map->clampPos(this->targetPos); - logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + if(threaded) { + logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } + else { + logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__); + } } void Unit::addAttackParticleSystem(ParticleSystem *ps) { @@ -3608,7 +3643,7 @@ void Unit::morphAttackBoosts(Unit *unit) { } } -bool Unit::morph(const MorphCommandType *mct) { +bool Unit::morph(const MorphCommandType *mct, int frameIndex) { if(mct == NULL) { char szBuf[8096]=""; @@ -3670,7 +3705,7 @@ bool Unit::morph(const MorphCommandType *mct) { Field original_field = this->currField; this->currField=morphUnitField; computeTotalUpgrade(); - map->putUnitCells(this, this->pos); + map->putUnitCells(this, this->pos, false, frameIndex < 0); this->faction->applyDiscount(morphUnitType, mct->getDiscount()); // add new storage @@ -4445,7 +4480,7 @@ void Unit::exploreCells(bool forceRefresh) { } else { // Try the world exploration scan or possible cache - cacheExploredCells = game->getWorld()->exploreCells(newPos, sightRange, teamIndex); + cacheExploredCells = game->getWorld()->exploreCells(newPos, sightRange, teamIndex, this); // Cache the result for this unit cacheExploredCellsKey.first = newPos; @@ -4464,7 +4499,7 @@ void Unit::logSynchDataCommon(string file,int line,string source,bool threadedMo if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { char szBuf[8096]=""; snprintf(szBuf,8096, - "FrameCount [%d] Unit = %d [%s][%s] pos = %s, lastPos = %s, targetPos = %s, targetVec = %s, meetingPos = %s, progress [" MG_I64_SPECIFIER "], progress2 [%d]\nUnit Path [%s]\n", + "FrameCount [%d] Unit = %d [%s][%s] pos = %s, lastPos = %s, targetPos = %s, targetVec = %s, meetingPos = %s, progress [" MG_I64_SPECIFIER "], progress2 [%d] random [%d]\nUnit Path [%s]\n", getFrameCount(), id, getFullName(false).c_str(), @@ -4480,6 +4515,7 @@ void Unit::logSynchDataCommon(string file,int line,string source,bool threadedMo // rotation, progress, progress2, + random.getLastNumber(), (unitPath != NULL ? unitPath->toString().c_str() : "NULL")); if( lastSynchDataString != string(szBuf) || diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index 05a169b1..7534a62c 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -626,9 +626,9 @@ public: inline void setLoadCount(int loadCount) {this->loadCount= loadCount;} inline void setLoadType(const ResourceType *loadType) {this->loadType= loadType;} inline void setProgress2(int progress2) {this->progress2= progress2;} - void setPos(const Vec2i &pos,bool clearPathFinder=false); + void setPos(const Vec2i &pos,bool clearPathFinder=false, bool threaded=false); void refreshPos(bool forceRefresh=false); - void setTargetPos(const Vec2i &targetPos); + void setTargetPos(const Vec2i &targetPos, bool threaded=false); void setTarget(const Unit *unit); //void setTargetVec(const Vec3f &targetVec); void setMeetingPos(const Vec2i &meetingPos); @@ -683,7 +683,7 @@ public: int update2(); bool update(); void tick(); - RandomGen* getRandom() { return &random; } + RandomGen* getRandom(bool threadAccessAllowed=false); bool applyAttackBoost(const AttackBoost *boost, const Unit *source); void deapplyAttackBoost(const AttackBoost *boost, const Unit *source); @@ -691,7 +691,7 @@ public: void applyUpgrade(const UpgradeType *upgradeType); void computeTotalUpgrade(); void incKills(int team); - bool morph(const MorphCommandType *mct); + bool morph(const MorphCommandType *mct, int frameIndex); std::pair checkCommand(Command *command) const; void applyCommand(Command *command); diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index 965c2a66..b48153ea 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -132,9 +132,9 @@ SurfaceCell::SurfaceCell() { nearSubmerged = false; cellChangedFromOriginalMapLoad = false; - for(int i = 0; i < GameConstants::maxPlayers + GameConstants::specialFactions; ++i) { - visible[i] = false; - explored[i] = false; + for(int index = 0; index < GameConstants::maxPlayers + GameConstants::specialFactions; ++index) { + setVisible(index,false); + setExplored(index,false); } } @@ -190,6 +190,45 @@ void SurfaceCell::setVisible(int teamIndex, bool visible) { } this->visible[teamIndex]= visible; + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In setVisible() teamIndex %d visible %d",teamIndex,visible); + +// if(frameIndex < 0) { +// unit->logSynchData(__FILE__,__LINE__,szBuf); +// } +// else { +// unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); +// } + + if(Thread::isCurrentThreadMainThread()) { + //unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,szBuf); + } + else { + //unit->logSynchData(__FILE__,__LINE__,szBuf); + printf("%s",szBuf); + } + + } + +} + +string SurfaceCell::isVisibleString() const { + string result = "isVisibleList = "; + for(int index = 0; index < GameConstants::maxPlayers + GameConstants::specialFactions; ++index) { + result += string(visible[index] ? "true" : "false"); + } + return result; +} +string SurfaceCell::isExploredString() const { + string result = "isExploredList = "; + for(int index = 0; index < GameConstants::maxPlayers + GameConstants::specialFactions; ++index) { + result += string(explored[index] ? "true" : "false"); + } + return result; } void SurfaceCell::saveGame(XmlNode *rootNode,int index) const { @@ -1309,12 +1348,12 @@ bool Map::isInUnitTypeCells(const UnitType *ut, const Vec2i &pos, } //put a units into the cells -void Map::putUnitCells(Unit *unit, const Vec2i &pos, bool ignoreSkill) { +void Map::putUnitCells(Unit *unit, const Vec2i &pos, bool ignoreSkill, bool threaded) { assert(unit != NULL); if(unit == NULL) { throw megaglest_runtime_error("ut == NULL"); } - putUnitCellsPrivate(unit, pos, unit->getType(), false); + putUnitCellsPrivate(unit, pos, unit->getType(), false, threaded); // block space for morphing units if(ignoreSkill==false && @@ -1323,13 +1362,13 @@ void Map::putUnitCells(Unit *unit, const Vec2i &pos, bool ignoreSkill) { Command *command= unit->getCurrCommand(); if(command != NULL && command->getCommandType()->commandTypeClass == ccMorph){ const MorphCommandType *mct= static_cast(command->getCommandType()); - putUnitCellsPrivate(unit, pos, mct->getMorphUnit(),true); + putUnitCellsPrivate(unit, pos, mct->getMorphUnit(),true, threaded); unit->setMorphFieldsBlocked(true); } } } -void Map::putUnitCellsPrivate(Unit *unit, const Vec2i &pos, const UnitType *ut, bool isMorph) { +void Map::putUnitCellsPrivate(Unit *unit, const Vec2i &pos, const UnitType *ut, bool isMorph, bool threaded) { assert(unit != NULL); if(unit == NULL) { throw megaglest_runtime_error("ut == NULL"); @@ -1409,7 +1448,7 @@ void Map::putUnitCellsPrivate(Unit *unit, const Vec2i &pos, const UnitType *ut, } } if(canPutInCell == true) { - unit->setPos(pos); + unit->setPos(pos, false, threaded); } } diff --git a/source/glest_game/world/map.h b/source/glest_game/world/map.h index 18e9415d..ce334a7f 100644 --- a/source/glest_game/world/map.h +++ b/source/glest_game/world/map.h @@ -158,6 +158,8 @@ public: inline bool isVisible(int teamIndex) const {return visible[teamIndex];} inline bool isExplored(int teamIndex) const {return explored[teamIndex];} + string isVisibleString() const; + string isExploredString() const; //set inline void setVertex(const Vec3f &vertex) {this->vertex= vertex;} @@ -335,7 +337,7 @@ public: //unit placement bool aproxCanMove(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2, std::map > > > > *lookupCache=NULL) const; bool canMove(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2,std::map > > > *lookupCache=NULL) const; - void putUnitCells(Unit *unit, const Vec2i &pos,bool ignoreSkill = false); + void putUnitCells(Unit *unit, const Vec2i &pos,bool ignoreSkill = false, bool threaded = false); void clearUnitCells(Unit *unit, const Vec2i &pos,bool ignoreSkill = false); Vec2i computeRefPos(const Selection *selection) const; @@ -392,11 +394,23 @@ public: } //checks if a unit can move from between 2 cells using only visible cells (for pathfinding) - inline bool aproxCanMoveSoon(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2) const { + inline bool aproxCanMoveSoon(Unit *unit, const Vec2i &pos1, const Vec2i &pos2) const { if(isInside(pos1) == false || isInsideSurface(toSurfCoords(pos1)) == false || isInside(pos2) == false || isInsideSurface(toSurfCoords(pos2)) == false) { //printf("[%s] Line: %d returning false\n",__FUNCTION__,__LINE__); + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() return false"); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + return false; } @@ -410,14 +424,93 @@ public: //single cell units if(size == 1) { - if(isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),pos2, field, teamIndex) == false) { + bool tryPosResult = isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),pos2, field, teamIndex); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + string extraInfo = (string("tryPosResult = ") + (tryPosResult ? string("true") : string("false"))); + const SurfaceCell *sc= getSurfaceCell(toSurfCoords(pos2)); + if(sc->isVisible(teamIndex)) { + bool testCond = isFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(), pos2, field); + extraInfo += (string("isFreeCellOrMightBeFreeSoon = ") + (testCond ? string("true") : string("false"))); + } + else if(sc->isExplored(teamIndex)) { + bool testCond = field==fLand? sc->isFree() && !getDeepSubmerged(getCell(pos2)): true; + extraInfo += (string("field==fLand = ") + (testCond ? string("true") : string("false"))); + } + + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() pos2 = %s extraInfo = %s %s %s",pos2.getString().c_str(),extraInfo.c_str(),sc->isVisibleString().c_str(),sc->isExploredString().c_str()); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(tryPosResult == false) { return false; } if(pos1.x != pos2.x && pos1.y != pos2.y) { - if(isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),Vec2i(pos1.x, pos2.y), field, teamIndex) == false) { + Vec2i tryPos = Vec2i(pos1.x, pos2.y); + bool tryPosResult = isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),tryPos, field, teamIndex); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + string extraInfo = (string("tryPosResult = ") + (tryPosResult ? string("true") : string("false"))); + const SurfaceCell *sc= getSurfaceCell(toSurfCoords(tryPos)); + if(sc->isVisible(teamIndex)) { + bool testCond = isFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(), tryPos, field); + extraInfo += (string("isFreeCellOrMightBeFreeSoon = ") + (testCond ? string("true") : string("false"))); + } + else if(sc->isExplored(teamIndex)) { + bool testCond = field==fLand? sc->isFree() && !getDeepSubmerged(getCell(tryPos)): true; + extraInfo += (string("field==fLand = ") + (testCond ? string("true") : string("false"))); + } + + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() extraInfo = %s",extraInfo.c_str()); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(tryPosResult == false) { return false; } - if(isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),Vec2i(pos2.x, pos1.y), field, teamIndex) == false) { + + tryPos = Vec2i(pos2.x, pos1.y); + tryPosResult = isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),tryPos, field, teamIndex); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + string extraInfo = (string("tryPosResult = ") + (tryPosResult ? string("true") : string("false"))); + const SurfaceCell *sc= getSurfaceCell(toSurfCoords(tryPos)); + if(sc->isVisible(teamIndex)) { + bool testCond = isFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(), tryPos, field); + extraInfo += (string("isFreeCellOrMightBeFreeSoon = ") + (testCond ? string("true") : string("false"))); + } + else if(sc->isExplored(teamIndex)) { + bool testCond = field==fLand? sc->isFree() && !getDeepSubmerged(getCell(tryPos)): true; + extraInfo += (string("field==fLand = ") + (testCond ? string("true") : string("false"))); + } + + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() extraInfo = %s",extraInfo.c_str()); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(tryPosResult == false) { + return false; } } @@ -432,6 +525,18 @@ public: } if(unit == NULL || isBadHarvestPos == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() return false"); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + return false; } @@ -446,11 +551,35 @@ public: if(isInside(cellPos) && isInsideSurface(toSurfCoords(cellPos))) { if(getCell(cellPos)->getUnit(unit->getCurrField()) != unit) { if(isAproxFreeCellOrMightBeFreeSoon(unit->getPosNotThreadSafe(),cellPos, field, teamIndex) == false) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() return false"); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + return false; } } } else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() return false"); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + return false; } } @@ -466,6 +595,18 @@ public: } if(isBadHarvestPos == true) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In aproxCanMoveSoon() return false"); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + return false; } @@ -483,7 +624,7 @@ private: void smoothSurface(Tileset *tileset); void computeNearSubmerged(); void computeCellColors(); - void putUnitCellsPrivate(Unit *unit, const Vec2i &pos, const UnitType *ut, bool isMorph); + void putUnitCellsPrivate(Unit *unit, const Vec2i &pos, const UnitType *ut, bool isMorph, bool threaded); }; diff --git a/source/glest_game/world/minimap.cpp b/source/glest_game/world/minimap.cpp index 91eae686..8cc0e1a9 100644 --- a/source/glest_game/world/minimap.cpp +++ b/source/glest_game/world/minimap.cpp @@ -205,8 +205,8 @@ void Minimap::resetFowTex() { for(int indexPixelHeight = 0; indexPixelHeight < fowTex->getPixmap()->getH(); ++indexPixelHeight){ - if ((fogOfWar == false && overridefogOfWarValue == false) && - (gameSettings->getFlagTypes1() & ft1_show_map_resources) != ft1_show_map_resources) { + if ((fogOfWar == false && overridefogOfWarValue == false)) { + //(gameSettings->getFlagTypes1() & ft1_show_map_resources) != ft1_show_map_resources) { //printf("Line: %d\n",__LINE__); float p0 = fowPixmap0->getPixelf(indexPixelWidth, indexPixelHeight); @@ -219,7 +219,7 @@ void Minimap::resetFowTex() { } } else if((fogOfWar && overridefogOfWarValue) || - (gameSettings->getFlagTypes1() & ft1_show_map_resources) != ft1_show_map_resources) { + (gameSettings->getFlagTypes1() & ft1_show_map_resources) == ft1_show_map_resources) { //printf("Line: %d\n",__LINE__); float p0= fowPixmap0->getPixelf(indexPixelWidth, indexPixelHeight); diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 1243e222..3a5c88e6 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -282,7 +282,7 @@ bool UnitUpdater::updateUnit(Unit *unit) { //move unit in cells if(unit->getCurrSkill()->getClass() == scMove) { - world->moveUnitCells(unit); + world->moveUnitCells(unit, true); if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after world->moveUnitCells()]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); @@ -750,6 +750,13 @@ void UnitUpdater::updateAttack(Unit *unit, int frameIndex) { } else { //if unit arrives destPos order has ended + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0 && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"#1 [updateAttack] tsValue = %d",tsValue); + unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + } + switch (tsValue) { case tsMoving: unit->setCurrSkill(act->getMoveSkillType()); @@ -804,9 +811,10 @@ void UnitUpdater::updateAttack(Unit *unit, int frameIndex) { } */ - if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0 && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { char szBuf[8096]=""; - snprintf(szBuf,8096,"[updateAttack]"); + snprintf(szBuf,8096,"#2 [updateAttack] tsValue = %d",tsValue); unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); } @@ -1254,7 +1262,7 @@ void UnitUpdater::updateHarvestEmergencyReturn(Unit *unit, int frameIndex) { if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && frameIndex < 0) { char szBuf[8096]=""; snprintf(szBuf,8096,"[updateHarvestEmergencyReturn]"); - unit->logSynchDataThreaded(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); + unit->logSynchData(extractFileFromDirectoryPath(__FILE__).c_str(),__LINE__,szBuf); } //printf("\n#1 updateHarvestEmergencyReturn\n"); @@ -2304,7 +2312,7 @@ void UnitUpdater::updateProduce(Unit *unit, int frameIndex) { if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); //place unit creates the unit - if(!world->placeUnit(unit->getCenteredPos(), 10, produced)) { + if(!world->placeUnit(unit->getCenteredPos(), 10, produced, false, frameIndex < 0)) { if(SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled) SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] COULD NOT PLACE UNIT for unitID [%d]\n",__FILE__,__FUNCTION__,__LINE__,produced->getId()); delete produced; } @@ -2437,7 +2445,7 @@ void UnitUpdater::updateMorph(Unit *unit, int frameIndex) { if(map->canMorph(unit->getPos(),unit,mct->getMorphUnit())){ unit->setCurrSkill(mct->getMorphSkillType()); // block space for morphing units ( block space before and after morph ! ) - map->putUnitCells(unit, unit->getPos()); + map->putUnitCells(unit, unit->getPos(), false, frameIndex < 0); } else{ if(unit->getFactionIndex()==world->getThisFactionIndex()){ @@ -2460,7 +2468,7 @@ void UnitUpdater::updateMorph(Unit *unit, int frameIndex) { } //finish the command - if(unit->morph(mct)){ + if(unit->morph(mct, frameIndex)){ unit->finishCommand(); if(gui->isSelected(unit)){ gui->onSelectionChanged(); @@ -2966,7 +2974,8 @@ bool UnitUpdater::unitOnRange(Unit *unit, int range, Unit **rangedPtr, unit->getRandom()->addLastCaller(randomInfoData); - if( attackingEnemySeen!=NULL && unit->getRandom()->randRange(0,2,extractFileFromDirectoryPath(__FILE__) + intToStr(__LINE__)) != 2 ) { + if( attackingEnemySeen != NULL && unit->getRandom()->randRange(0,2,extractFileFromDirectoryPath(__FILE__) + intToStr(__LINE__)) != 2 ) { + //if( attackingEnemySeen != NULL) { *rangedPtr = attackingEnemySeen; enemySeen = attackingEnemySeen; //printf("Da hat er wen gefunden:%s\n",enemySeen->getType()->getName(false).c_str()); diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 6c4b56c3..74fb6f7d 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -39,6 +39,7 @@ namespace Glest{ namespace Game{ // This limit is to keep RAM use under control while offering better performance. int MaxExploredCellsLookupItemCache = 9500; +//int MaxExploredCellsLookupItemCache = 0; time_t ExploredCellsLookupItem::lastDebug = 0; // ===================== PUBLIC ======================== @@ -1127,7 +1128,7 @@ const UnitType * World::findUnitTypeByName(const string factionName, const strin } //looks for a place for a unit around a start location, returns true if succeded -bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated) { +bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated, bool threaded) { if(unit == NULL) { throw megaglest_runtime_error("unit == NULL"); } @@ -1149,7 +1150,7 @@ bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spacia } if(freeSpace) { - unit->setPos(pos); + unit->setPos(pos, false, threaded); Vec2i meetingPos = pos-Vec2i(1); unit->setMeetingPos(meetingPos); return true; @@ -1161,7 +1162,7 @@ bool World::placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spacia } //clears a unit old position from map and places new position -void World::moveUnitCells(Unit *unit) { +void World::moveUnitCells(Unit *unit, bool threaded) { if(unit == NULL) { throw megaglest_runtime_error("unit == NULL"); } @@ -1174,7 +1175,7 @@ void World::moveUnitCells(Unit *unit) { // from the old one if(newPos != unit->getPos()) { map.clearUnitCells(unit, unit->getPos()); - map.putUnitCells(unit, newPos); + map.putUnitCells(unit, newPos, false, threaded); } // Add resources close by to the faction's cache unit->getFaction()->addCloseResourceTargetToCache(newPos); @@ -1182,6 +1183,12 @@ void World::moveUnitCells(Unit *unit) { //water splash if(tileset.getWaterEffects() && unit->getCurrField() == fLand) { if(map.getSubmerged(map.getCell(unit->getLastPos()))) { + + if(Thread::isCurrentThreadMainThread() == false) { + throw megaglest_runtime_error("#1 Invalid access to World random from outside main thread current id = " + + intToStr(Thread::getCurrentThreadId()) + " main = " + intToStr(Thread::getMainThreadId())); + } + int unitSize= unit->getType()->getSize(); for(int i = 0; i < 3; ++i) { waterEffects.addWaterSplash( @@ -1808,7 +1815,7 @@ void World::setUnitPosition(int unitId, Vec2i pos) { throw megaglest_runtime_error("Can not find unit to set position unitId = " + intToStr(unitId),true); } unit->setTargetPos(pos); - this->moveUnitCells(unit); + this->moveUnitCells(unit, false); } void World::addCellMarker(Vec2i pos, int factionIndex, const string ¬e, const string textureFile) { @@ -1960,10 +1967,20 @@ void World::initCells(bool fogOfWar) { sc->setExplored(k, (game->getGameSettings()->getFlagTypes1() & ft1_show_map_resources) == ft1_show_map_resources); sc->setVisible(k, !fogOfWar); } + for (int k = GameConstants::maxPlayers; k < GameConstants::maxPlayers + GameConstants::specialFactions; k++) { sc->setExplored(k, true); sc->setVisible(k, true); } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In initCells() x = %d y = %d %s %s",i,j,sc->isVisibleString().c_str(),sc->isExploredString().c_str()); + if(Thread::isCurrentThreadMainThread()) { + //unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,szBuf); + } + } } } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -2333,7 +2350,7 @@ void World::exploreCells(int teamIndex, ExploredCellsLookupItem &exploredCellsCa // ==================== exploration ==================== -ExploredCellsLookupItem World::exploreCells(const Vec2i &newPos, int sightRange, int teamIndex) { +ExploredCellsLookupItem World::exploreCells(const Vec2i &newPos, int sightRange, int teamIndex, Unit *unit) { // cache lookup of previously calculated cells + sight range if(MaxExploredCellsLookupItemCache > 0) { if(difftime(time(NULL),ExploredCellsLookupItem::lastDebug) >= 10) { @@ -2413,13 +2430,28 @@ ExploredCellsLookupItem World::exploreCells(const Vec2i &newPos, int sightRange, //explore float posLength = currRelPos.length(); - if(posLength < surfSightRange + indirectSightRange + 1) { + bool updateExplored = (posLength < surfSightRange + indirectSightRange + 1); + bool updateVisible = (posLength < surfSightRange); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true && + SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynchMax).enabled == true) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In exploreCells() currRelPos = %s currPos = %s posLength = %f updateExplored = %d updateVisible = %d sightRange = %d teamIndex = %d", + currRelPos.getString().c_str(), currPos.getString().c_str(),posLength,updateExplored, updateVisible, sightRange, teamIndex); + if(Thread::isCurrentThreadMainThread() == false) { + unit->logSynchDataThreaded(__FILE__,__LINE__,szBuf); + } + else { + unit->logSynchData(__FILE__,__LINE__,szBuf); + } + } + + if(updateExplored) { sc->setExplored(teamIndex, true); exploredCellsCache.exploredCellList.push_back(sc); } - //visible - if(posLength < surfSightRange) { + if(updateVisible) { sc->setVisible(teamIndex, true); exploredCellsCache.visibleCellList.push_back(sc); } @@ -2509,7 +2541,7 @@ void World::computeFow() { // Once we have calculated fog of war texture alpha, they are cached so we // restore the default texture in one shot for speed - if(cacheFowAlphaTexture == true) { + if(fogOfWar && cacheFowAlphaTexture == true) { if(cacheFowAlphaTextureFogOfWarValue != fogOfWar) { cacheFowAlphaTexture = false; } @@ -2521,7 +2553,18 @@ void World::computeFow() { for(int indexFaction = 0; indexFaction < GameConstants::maxPlayers + GameConstants::specialFactions; ++indexFaction) { - if(fogOfWar || indexFaction != thisTeamIndex) { + + // If fog of war enabled set cell visible to false and later set those close to units to true + if(fogOfWar) { + for(int indexSurfaceW = 0; indexSurfaceW < map.getSurfaceW(); ++indexSurfaceW) { + for(int indexSurfaceH = 0; indexSurfaceH < map.getSurfaceH(); ++indexSurfaceH) { + // set all cells to not visible + map.getSurfaceCell(indexSurfaceW, indexSurfaceH)->setVisible(indexFaction, false); + } + } + } + + if(!fogOfWar || (indexFaction != thisTeamIndex)) { bool showWorldForFaction = showWorldForPlayer(indexFaction); if(showWorldForFaction == true) { resetFowAlphaFactionCount++; @@ -2529,13 +2572,10 @@ void World::computeFow() { for(int indexSurfaceW = 0; indexSurfaceW < map.getSurfaceW(); ++indexSurfaceW) { for(int indexSurfaceH = 0; indexSurfaceH < map.getSurfaceH(); ++indexSurfaceH) { - // set all cells to not visible - map.getSurfaceCell(indexSurfaceW, indexSurfaceH)->setVisible(indexFaction, false); - // reset fog of ware texture alpha values - if(cacheFowAlphaTexture == false && + if(!fogOfWar || (cacheFowAlphaTexture == false && showWorldForFaction == true && - resetFowAlphaFactionCount <= 1) { + resetFowAlphaFactionCount <= 1)) { const Vec2i surfPos(indexSurfaceW,indexSurfaceH); //compute max alpha @@ -2558,12 +2598,13 @@ void World::computeFow() { } } } + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s] Line: %d in frame: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,getFrameCount()); } // Once we have calculated fog of war texture alpha, will we cache it so that we // can restore it later - if(cacheFowAlphaTexture == false && resetFowAlphaFactionCount > 0) { + if(fogOfWar && cacheFowAlphaTexture == false && resetFowAlphaFactionCount > 0) { cacheFowAlphaTexture = true; cacheFowAlphaTextureFogOfWarValue = fogOfWar; minimap.copyFowTexAlphaSurface(); diff --git a/source/glest_game/world/world.h b/source/glest_game/world/world.h index 8e8fd566..57630be4 100644 --- a/source/glest_game/world/world.h +++ b/source/glest_game/world/world.h @@ -215,8 +215,8 @@ public: Unit* findUnitById(int id) const; const UnitType* findUnitTypeById(const FactionType* factionType, int id); const UnitType *findUnitTypeByName(const string factionName, const string unitTypeName); - bool placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated= false); - void moveUnitCells(Unit *unit); + bool placeUnit(const Vec2i &startLoc, int radius, Unit *unit, bool spaciated= false, bool threaded=false); + void moveUnitCells(Unit *unit, bool threaded); bool toRenderUnit(const Unit *unit, const Quad2i &visibleQuad) const; bool toRenderUnit(const Unit *unit) const; @@ -297,7 +297,7 @@ public: } bool canTickWorld() const; - ExploredCellsLookupItem exploreCells(const Vec2i &newPos, int sightRange, int teamIndex); + ExploredCellsLookupItem exploreCells(const Vec2i &newPos, int sightRange, int teamIndex, Unit *unit); void exploreCells(int teamIndex,ExploredCellsLookupItem &exploredCellsCache); bool showWorldForPlayer(int factionIndex, bool excludeFogOfWarCheck=false) const; diff --git a/source/shared_lib/include/graphics/vec.h b/source/shared_lib/include/graphics/vec.h index 73cad1ae..176a613e 100644 --- a/source/shared_lib/include/graphics/vec.h +++ b/source/shared_lib/include/graphics/vec.h @@ -260,7 +260,6 @@ public: inline float dist(const Vec2 &v) const{ float distance = Vec2(v-*this).length(); - distance = truncateDecimal(distance,6); return distance; } @@ -270,8 +269,12 @@ public: } inline float length() const { +#ifdef USE_STREFLOP + float len = static_cast(streflop::sqrt(static_cast(x*x + y*y))); +#else float len = static_cast(std::sqrt(static_cast(x*x + y*y))); len = truncateDecimal(len,6); +#endif return len; } @@ -494,13 +497,16 @@ public: inline float dist(const Vec3 &v) const { float distance = Vec3(v-*this).length(); - distance = truncateDecimal(distance,6); return distance; } inline float length() const { +#ifdef USE_STREFLOP + float len = static_cast(streflop::sqrt(static_cast(x*x + y*y + z*z))); +#else float len = static_cast(std::sqrt(x*x + y*y + z*z)); len = truncateDecimal(len,6); +#endif return len; } diff --git a/source/shared_lib/include/platform/sdl/thread.h b/source/shared_lib/include/platform/sdl/thread.h index 1bf8ab4e..be3d8ab6 100644 --- a/source/shared_lib/include/platform/sdl/thread.h +++ b/source/shared_lib/include/platform/sdl/thread.h @@ -79,6 +79,7 @@ private: static Mutex mutexthreadList; static vector threadList; static bool enableVerboseMode; + static unsigned long mainThreadId; protected: void addThreadToList(); @@ -90,6 +91,11 @@ public: Thread(); virtual ~Thread(); + static unsigned long getCurrentThreadId(); + static unsigned long getMainThreadId() { return mainThreadId; } + static void setMainThreadId(); + static bool isCurrentThreadMainThread(); + static void setEnableVerboseMode(bool value) { enableVerboseMode = value; } static bool getEnableVerboseMode() { return enableVerboseMode; } diff --git a/source/shared_lib/include/util/util.h b/source/shared_lib/include/util/util.h index eb7a4404..5d23c536 100644 --- a/source/shared_lib/include/util/util.h +++ b/source/shared_lib/include/util/util.h @@ -74,6 +74,7 @@ public: debugNetwork, debugPerformance, debugWorldSynch, + debugWorldSynchMax, debugUnitCommands, debugPathFinder, debugLUA, diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 293e34d2..7a90e017 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -686,7 +686,7 @@ std::vector Socket::getLocalIPAddressList() { for(int ipIdx = 0; myhostent->h_addr_list[ipIdx] != NULL; ++ipIdx) { Ip::Inet_NtoA(SockAddrToUint32((struct in_addr *)myhostent->h_addr_list[ipIdx]), myhostaddr); - printf("ipIdx = %d [%s]\n",ipIdx,myhostaddr); + //printf("ipIdx = %d [%s]\n",ipIdx,myhostaddr); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] myhostaddr = [%s]\n",__FILE__,__FUNCTION__,__LINE__,myhostaddr); if(strlen(myhostaddr) > 0 && diff --git a/source/shared_lib/sources/platform/sdl/thread.cpp b/source/shared_lib/sources/platform/sdl/thread.cpp index a2470591..f71673b5 100644 --- a/source/shared_lib/sources/platform/sdl/thread.cpp +++ b/source/shared_lib/sources/platform/sdl/thread.cpp @@ -26,6 +26,7 @@ namespace Shared { namespace Platform { bool Thread::enableVerboseMode = false; Mutex Thread::mutexthreadList; vector Thread::threadList; +unsigned long Thread::mainThreadId = -1; auto_ptr Mutex::mutexMutexList(new Mutex(CODE_AT_LINE)); vector Mutex::mutexList; @@ -138,6 +139,16 @@ Thread::Thread() : thread(NULL), addThreadToList(); } +unsigned long Thread::getCurrentThreadId() { + return SDL_ThreadID(); +} +void Thread::setMainThreadId() { + mainThreadId = getCurrentThreadId(); +} +bool Thread::isCurrentThreadMainThread() { + return getCurrentThreadId() == mainThreadId; +} + void Thread::addThreadToList() { MutexSafeWrapper safeMutex(&Thread::mutexthreadList); Thread::threadList.push_back(this); diff --git a/source/shared_lib/sources/util/randomgen.cpp b/source/shared_lib/sources/util/randomgen.cpp index 731b310f..f2608b89 100644 --- a/source/shared_lib/sources/util/randomgen.cpp +++ b/source/shared_lib/sources/util/randomgen.cpp @@ -31,7 +31,7 @@ const int RandomGen::m= 714025; const int RandomGen::a= 1366; const int RandomGen::b= 150889; -RandomGen::RandomGen(){ +RandomGen::RandomGen() { lastNumber= 0; disableLastCallerTracking = false; } @@ -77,7 +77,7 @@ int RandomGen::randRange(int min, int max,string lastCaller) { } int diff= max-min; - float numerator = static_cast(diff + 1) * static_cast(RandomGen::rand(lastCaller)); + float numerator = static_cast(diff + 1) * static_cast(this->rand(lastCaller)); int res= min + static_cast(truncateDecimal(numerator / static_cast(m),6)); if(res < min || res > max) { char szBuf[8096]=""; @@ -94,7 +94,7 @@ float RandomGen::randRange(float min, float max,string lastCaller) { throw megaglest_runtime_error(szBuf); } - float rand01 = static_cast(RandomGen::rand(lastCaller)) / (m-1); + float rand01 = static_cast(this->rand(lastCaller)) / (m-1); float res= min + (max - min) * rand01; res = truncateDecimal(res,6);