1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include <algorithm>
#include "System/mmgr.h"
#include "PathCache.h"
#include "Sim/Misc/GlobalSynced.h"
#include "System/Log/ILog.h"
using namespace std;
CPathCache::CPathCache(int blocksX,int blocksZ)
: blocksX(blocksX),
blocksZ(blocksZ)
{
numCacheHits=0;
numCacheMisses=0;
}
CPathCache::~CPathCache(void)
{
LOG("Path cache hits %i %.0f%%",
numCacheHits, ((numCacheHits + numCacheMisses) != 0)
? (float(numCacheHits) / float(numCacheHits + numCacheMisses) * 100.0f)
: 0.0f);
for(std::map<unsigned int,CacheItem*>::iterator ci=cachedPaths.begin();ci!=cachedPaths.end();++ci)
delete ci->second;
}
void CPathCache::AddPath(IPath::Path* path, IPath::SearchResult result, int2 startBlock,int2 goalBlock,float goalRadius,int pathType)
{
if(cacheQue.size()>100)
RemoveFrontQueItem();
unsigned int hash=(unsigned int)(((((goalBlock.y)*blocksX+goalBlock.x)*blocksZ+startBlock.y)*blocksX)+startBlock.x*(pathType+1)*max(1.0f,goalRadius));
if(cachedPaths.find(hash)!=cachedPaths.end()){
return;
}
CacheItem* ci=new CacheItem;
ci->path=*path;
ci->result=result;
ci->startBlock=startBlock;
ci->goalBlock=goalBlock;
ci->goalRadius=goalRadius;
ci->pathType=pathType;
cachedPaths[hash]=ci;
CacheQue cq;
cq.hash=hash;
cq.timeout=gs->frameNum+200;
cacheQue.push_back(cq);
}
CPathCache::CacheItem* CPathCache::GetCachedPath(int2 startBlock,int2 goalBlock,float goalRadius,int pathType)
{
unsigned int hash=(unsigned int)(((((goalBlock.y)*blocksX+goalBlock.x)*blocksZ+startBlock.y)*blocksX)+startBlock.x*(pathType+1)*max(1.0f,goalRadius));
std::map<unsigned int,CacheItem*>::iterator ci=cachedPaths.find(hash);
if(ci!=cachedPaths.end() && ci->second->startBlock.x==startBlock.x && ci->second->startBlock.y==startBlock.y && ci->second->goalBlock.x==goalBlock.x && ci->second->pathType==pathType){
++numCacheHits;
return ci->second;
}
++numCacheMisses;
return 0;
}
void CPathCache::Update(void)
{
while(!cacheQue.empty() && cacheQue.front().timeout<gs->frameNum)
RemoveFrontQueItem();
}
void CPathCache::RemoveFrontQueItem(void)
{
delete cachedPaths[cacheQue.front().hash];
cachedPaths.erase(cacheQue.front().hash);
cacheQue.pop_front();
}
|