hostile-takeover/server/levelinfocache.cpp
2016-01-01 22:41:21 -08:00

132 lines
3.5 KiB
C++

#include "server/levelinfocache.h"
#include "server/ncpackfile.h"
#include "mpshared/indexloader.h"
#include "base/log.h"
namespace wi {
void LevelInfoCache::SubmitIndex(const std::string& indexfile) {
int cLoaded = 0;
IndexLoader index;
if (index.InitFromFile(indexfile.c_str())) {
int c = index.GetCount();
for (int i = 0; i < c; i++) {
const IndexEntry *entry = index.GetEntry(i);
if (SubmitHelper(entry->packid)) {
cLoaded++;
}
}
}
RLOG() << cLoaded << " mission packs successfully submitted.";
}
bool LevelInfoCache::SubmitHelper(const PackId& packid) {
bool success = false;
NoCachePackFileReader pakr;
if (packm_.Mount(pakr, &packid)) {
success = Submit(pakr, packid);
packm_.Unmount(pakr, &packid);
}
return success;
}
bool LevelInfoCache::Submit(PackFileReader& pakr, const PackId& packid) {
// Create new infomap before removing old (if it exists), in case invalid
LevelInfoMap infomap;
CreateLevelInfoMap(pakr, packid, &infomap);
if (infomap.size() == 0) {
return false;
}
// Remove the old pack, if present, then add this pack
PackMap::iterator it = map_.find(packid.id);
if (it != map_.end()) {
map_.erase(it);
}
map_.insert(PackMap::value_type(packid.id,
std::make_pair(packid, infomap)));
return true;
}
void LevelInfoCache::CreateLevelInfoMap(PackFileReader& pakr,
const PackId& packid, LevelInfoMap *infomap) {
Enum enm;
char szFile[256];
while (pakr.EnumFiles(&enm, PACKENUM_LAST, szFile, sizeof(szFile))) {
if (strlen(szFile) <= 4) {
continue;
}
if (strcmp(&szFile[strlen(szFile) - 4], ".lvl") != 0) {
continue;
}
LevelInfo info;
if (!info.Load(pakr, szFile)) {
continue;
}
infomap->insert(LevelInfoMap::value_type(std::string(szFile), info));
}
}
int LevelInfoCache::FindInfo(const PackId& packid, const std::string& level,
LevelInfo *pinfo, PackId *ppackidUpgrade) {
if (packid.id != PACKID_MAIN) {
switch (packm_.IsInstalled(&packid, ppackidUpgrade)) {
case 0:
// Don't know about this pack at all
return 0;
case 1:
// Know about this pack, and have this version
break;
case 2:
// Know about this pack, but client has wrong version
return 2;
}
}
// Lazy load the LevelInfo if necessary
PackMap::iterator it0 = map_.find(packid.id);
if (it0 == map_.end()) {
if (!SubmitHelper(packid)) {
return 0;
}
it0 = map_.find(packid.id);
if (it0 == map_.end()) {
return 0;
}
}
// Same packid? If not, re-submit
if (memcmp(&it0->second.first, &packid, sizeof(packid)) != 0) {
if (!SubmitHelper(packid)) {
return 0;
}
it0 = map_.find(packid.id);
if (it0 == map_.end()) {
return 0;
}
}
LevelInfoMap::iterator it1 = it0->second.second.find(level);
if (it1 == it0->second.second.end()) {
return 0;
}
if (pinfo != NULL) {
*pinfo = it1->second;
}
return 1;
}
void LevelInfoCache::RemoveInfo(const PackId& packid) {
PackMap::iterator it = map_.find(packid.id);
if (it != map_.end()) {
if (memcmp(&it->second.first, &packid, sizeof(packid)) == 0) {
map_.erase(it);
}
}
}
} // namespace wi