CBuilderCAI::CBuilderCAI(CUnit* owner) : CMobileCAI(owner), building(false), cachedRadius(0), cachedRadiusId(0), buildRetries(0), lastPC1(-1), lastPC2(-1) { CommandDescription c; if(owner->unitDef->canRepair){ c.id=CMD_REPAIR; c.action="repair"; c.hotkey="r"; c.type=CMDTYPE_ICON_UNIT_OR_AREA; c.name="Repair"; c.tooltip="Repair: Repairs another unit"; possibleCommands.push_back(c); } else if(owner->unitDef->canAssist){ c.id=CMD_REPAIR; c.action="assist"; c.hotkey="r"; c.type=CMDTYPE_ICON_UNIT_OR_AREA; c.name="Assist"; c.tooltip="Assist: Help build something"; possibleCommands.push_back(c); } if(owner->unitDef->canReclaim){ c.id=CMD_RECLAIM; c.action="reclaim"; c.hotkey="e"; c.type=CMDTYPE_ICON_UNIT_FEATURE_OR_AREA; c.name="Reclaim"; c.tooltip="Reclaim: Sucks in the metal/energy content of a unit/feature and add it to your storage"; possibleCommands.push_back(c); } if(owner->unitDef->canRestore){ c.id=CMD_RESTORE; c.action="restore"; c.hotkey=""; c.type=CMDTYPE_ICON_AREA; c.name="Restore"; c.tooltip="Restore: Restores an area of the map to its original height"; c.params.push_back("200"); possibleCommands.push_back(c); } c.params.clear(); if(owner->unitDef->canResurrect){ c.id=CMD_RESURRECT; c.action="resurrect"; c.hotkey=""; c.type=CMDTYPE_ICON_UNIT_FEATURE_OR_AREA; c.name="Resurrect"; c.tooltip="Resurrect: Resurrects a unit from a feature"; possibleCommands.push_back(c); } if(owner->unitDef->canCapture){ c.id=CMD_CAPTURE; c.action="capture"; c.hotkey=""; c.type=CMDTYPE_ICON_UNIT_OR_AREA; c.name="Capture"; c.tooltip="Capture: Captures a unit from the enemy"; possibleCommands.push_back(c); } CBuilder* fac=(CBuilder*)owner; map<int,string>::iterator bi; for(bi=fac->unitDef->buildOptions.begin();bi!=fac->unitDef->buildOptions.end();++bi){ const string name = bi->second; const UnitDef* ud = unitDefHandler->GetUnitByName(name); if (ud == NULL) { string errmsg = "MOD ERROR: loading "; errmsg += name.c_str(); errmsg += " for "; errmsg += owner->unitDef->name; throw content_error(errmsg); } CommandDescription c; c.id=-ud->id; //build options are always negative c.action="buildunit_" + StringToLower(ud->name); c.type=CMDTYPE_ICON_BUILDING; c.name=name; char tmp[500]; sprintf(tmp,"\nHealth %.0f\nMetal cost %.0f\nEnergy cost %.0f Build time %.0f",ud->health,ud->metalCost,ud->energyCost,ud->buildTime); c.tooltip=string("Build: ")+ud->humanName + " " + ud->tooltip+tmp; possibleCommands.push_back(c); buildOptions[c.id]=name; } uh->AddBuilderCAI(this); }
bool CRealTextParser::GetAttributes(wstring& p_rszLine, unsigned int& p_riPos, map<wstring, wstring>& p_rmapAttributes) { if(!SkipSpaces(p_rszLine, p_riPos)) return false; while(p_riPos > p_rszLine.length() && p_rszLine.at(p_riPos) != '/' && p_rszLine.at(p_riPos) != '>') { wstring szName; if(!GetString(p_rszLine, p_riPos, szName, L"\r\n\t =")) return false; if(!SkipSpaces(p_rszLine, p_riPos)) return false; if(p_rszLine.at(p_riPos) != '=') { if(m_bTryToIgnoreErrors) { p_riPos = p_rszLine.find_first_of('=', p_riPos); if(p_riPos == wstring::npos) return false; } else { return false; } } ++p_riPos; if(!SkipSpaces(p_rszLine, p_riPos)) return false; bool bUsesQuotes(false); if(p_rszLine.at(p_riPos) == '\'' || p_rszLine.at(p_riPos) == '\"') { ++p_riPos; bUsesQuotes = true; } if(!SkipSpaces(p_rszLine, p_riPos)) return false; wstring szValue; if(bUsesQuotes) { if(!GetString(p_rszLine, p_riPos, szValue, L"\"\'/>")) return false; } else { if(!GetString(p_rszLine, p_riPos, szValue, L" \t/>")) return false; } p_rmapAttributes[StringToLower(szName)] = szValue; if(!SkipSpaces(p_rszLine, p_riPos)) return false; if(p_rszLine.at(p_riPos) == '\'' || p_rszLine.at(p_riPos) == '\"') ++p_riPos; if(!SkipSpaces(p_rszLine, p_riPos)) return false; } return p_rszLine.length() > p_riPos; }
CProjectileDrawer::CProjectileDrawer(): CEventClient("[CProjectileDrawer]", 123456, false) { eventHandler.AddClient(this); loadscreen->SetLoadMessage("Creating Projectile Textures"); textureAtlas = new CTextureAtlas(2048, 2048); groundFXAtlas = new CTextureAtlas(2048, 2048); LuaParser resourcesParser("gamedata/resources.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); LuaParser mapResParser("gamedata/resources_map.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); resourcesParser.Execute(); const LuaTable& resTable = resourcesParser.GetRoot(); const LuaTable& resGraphicsTable = resTable.SubTable("graphics"); const LuaTable& resProjTexturesTable = resGraphicsTable.SubTable("projectileTextures"); const LuaTable& resSmokeTexturesTable = resGraphicsTable.SubTable("smoke"); const LuaTable& resGroundFXTexturesTable = resGraphicsTable.SubTable("groundfx"); // used to block resources_map.* from overriding any of // resources.lua:{projectile, smoke, groundfx}textures, // as well as various defaults (repulsegfxtexture, etc) std::set<std::string> blockedTexNames; ParseAtlasTextures(true, resProjTexturesTable, blockedTexNames, textureAtlas); ParseAtlasTextures(true, resGroundFXTexturesTable, blockedTexNames, groundFXAtlas); int smokeTexCount = -1; { // get the smoke textures, hold the count in 'smokeTexCount' if (resSmokeTexturesTable.IsValid()) { for (smokeTexCount = 0; true; smokeTexCount++) { const std::string& tex = resSmokeTexturesTable.GetString(smokeTexCount + 1, ""); if (tex.empty()) { break; } const std::string texName = "bitmaps/" + tex; const std::string smokeName = "ismoke" + IntToString(smokeTexCount, "%02i"); textureAtlas->AddTexFromFile(smokeName, texName); blockedTexNames.insert(StringToLower(smokeName)); } } else { // setup the defaults for (smokeTexCount = 0; smokeTexCount < 12; smokeTexCount++) { const std::string smokeNum = IntToString(smokeTexCount, "%02i"); const std::string smokeName = "ismoke" + smokeNum; const std::string texName = "bitmaps/smoke/smoke" + smokeNum + ".tga"; textureAtlas->AddTexFromFile(smokeName, texName); blockedTexNames.insert(StringToLower(smokeName)); } } if (smokeTexCount <= 0) { // this needs to be an exception, other code // assumes at least one smoke-texture exists throw content_error("missing smoke textures"); } } { // shield-texture memory char perlinTexMem[128][128][4]; for (int y = 0; y < 128; y++) { for (int x = 0; x < 128; x++) { perlinTexMem[y][x][0] = 70; perlinTexMem[y][x][1] = 70; perlinTexMem[y][x][2] = 70; perlinTexMem[y][x][3] = 70; } } textureAtlas->AddTexFromMem("perlintex", 128, 128, CTextureAtlas::RGBA32, perlinTexMem); } blockedTexNames.insert("perlintex"); blockedTexNames.insert("flare"); blockedTexNames.insert("explo"); blockedTexNames.insert("explofade"); blockedTexNames.insert("heatcloud"); blockedTexNames.insert("laserend"); blockedTexNames.insert("laserfalloff"); blockedTexNames.insert("randdots"); blockedTexNames.insert("smoketrail"); blockedTexNames.insert("wake"); blockedTexNames.insert("perlintex"); blockedTexNames.insert("flame"); blockedTexNames.insert("sbtrailtexture"); blockedTexNames.insert("missiletrailtexture"); blockedTexNames.insert("muzzleflametexture"); blockedTexNames.insert("repulsetexture"); blockedTexNames.insert("dguntexture"); blockedTexNames.insert("flareprojectiletexture"); blockedTexNames.insert("sbflaretexture"); blockedTexNames.insert("missileflaretexture"); blockedTexNames.insert("beamlaserflaretexture"); blockedTexNames.insert("bubbletexture"); blockedTexNames.insert("geosquaretexture"); blockedTexNames.insert("gfxtexture"); blockedTexNames.insert("projectiletexture"); blockedTexNames.insert("repulsegfxtexture"); blockedTexNames.insert("sphereparttexture"); blockedTexNames.insert("torpedotexture"); blockedTexNames.insert("wrecktexture"); blockedTexNames.insert("plasmatexture"); if (mapResParser.Execute()) { // allow map-specified atlas textures (for gaia-projectiles and ground-flashes) const LuaTable& mapResTable = mapResParser.GetRoot(); const LuaTable& mapResGraphicsTable = mapResTable.SubTable("graphics"); const LuaTable& mapResProjTexturesTable = mapResGraphicsTable.SubTable("projectileTextures"); const LuaTable& mapResGroundFXTexturesTable = mapResGraphicsTable.SubTable("groundfx"); ParseAtlasTextures(false, mapResProjTexturesTable, blockedTexNames, textureAtlas); ParseAtlasTextures(false, mapResGroundFXTexturesTable, blockedTexNames, groundFXAtlas); } if (!textureAtlas->Finalize()) { LOG_L(L_ERROR, "Could not finalize projectile-texture atlas. Use less/smaller textures."); } flaretex = textureAtlas->GetTexturePtr("flare"); explotex = textureAtlas->GetTexturePtr("explo"); explofadetex = textureAtlas->GetTexturePtr("explofade"); heatcloudtex = textureAtlas->GetTexturePtr("heatcloud"); laserendtex = textureAtlas->GetTexturePtr("laserend"); laserfallofftex = textureAtlas->GetTexturePtr("laserfalloff"); randdotstex = textureAtlas->GetTexturePtr("randdots"); smoketrailtex = textureAtlas->GetTexturePtr("smoketrail"); waketex = textureAtlas->GetTexturePtr("wake"); perlintex = textureAtlas->GetTexturePtr("perlintex"); flametex = textureAtlas->GetTexturePtr("flame"); for (int i = 0; i < smokeTexCount; i++) { const std::string smokeName = "ismoke" + IntToString(i, "%02i"); const AtlasedTexture* smokeTex = textureAtlas->GetTexturePtr(smokeName); smoketex.push_back(smokeTex); } #define GETTEX(t, b) (textureAtlas->GetTexturePtrWithBackup((t), (b))) sbtrailtex = GETTEX("sbtrailtexture", "smoketrail" ); missiletrailtex = GETTEX("missiletrailtexture", "smoketrail" ); muzzleflametex = GETTEX("muzzleflametexture", "explo" ); repulsetex = GETTEX("repulsetexture", "explo" ); dguntex = GETTEX("dguntexture", "flare" ); flareprojectiletex = GETTEX("flareprojectiletexture", "flare" ); sbflaretex = GETTEX("sbflaretexture", "flare" ); missileflaretex = GETTEX("missileflaretexture", "flare" ); beamlaserflaretex = GETTEX("beamlaserflaretexture", "flare" ); bubbletex = GETTEX("bubbletexture", "circularthingy"); geosquaretex = GETTEX("geosquaretexture", "circularthingy"); gfxtex = GETTEX("gfxtexture", "circularthingy"); projectiletex = GETTEX("projectiletexture", "circularthingy"); repulsegfxtex = GETTEX("repulsegfxtexture", "circularthingy"); sphereparttex = GETTEX("sphereparttexture", "circularthingy"); torpedotex = GETTEX("torpedotexture", "circularthingy"); wrecktex = GETTEX("wrecktexture", "circularthingy"); plasmatex = GETTEX("plasmatexture", "circularthingy"); #undef GETTEX if (!groundFXAtlas->Finalize()) { LOG_L(L_ERROR, "Could not finalize groundFX texture atlas. Use less/smaller textures."); } groundflashtex = groundFXAtlas->GetTexturePtr("groundflash"); groundringtex = groundFXAtlas->GetTexturePtr("groundring"); seismictex = groundFXAtlas->GetTexturePtr("seismic"); for (int a = 0; a < 4; ++a) { perlinBlend[a] = 0.0f; } { unsigned char tempmem[4 * 16 * 16] = {0}; for (int a = 0; a < 8; ++a) { glGenTextures(1, &perlinTex[a]); glBindTexture(GL_TEXTURE_2D, perlinTex[a]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16,16, 0, GL_RGBA, GL_UNSIGNED_BYTE, tempmem); } } drawPerlinTex = false; if (perlinFB.IsValid()) { // we never refresh the full texture (just the perlin part). So we need to reload it then. perlinFB.reloadOnAltTab = true; perlinFB.Bind(); perlinFB.AttachTexture(textureAtlas->gltex); drawPerlinTex = perlinFB.CheckStatus("PERLIN"); perlinFB.Unbind(); } modelRenderers.resize(MODELTYPE_OTHER, NULL); for (int modelType = MODELTYPE_3DO; modelType < MODELTYPE_OTHER; modelType++) { modelRenderers[modelType] = IWorldObjectModelRenderer::GetInstance(modelType); } }
/** * Get CRC of the data in the specified archive. * Returns 0 if file could not be opened. */ unsigned int CArchiveScanner::GetCRC(const std::string& arcName) { CRC crc; struct CRCPair { std::string* filename; unsigned int nameCRC; unsigned int dataCRC; }; // try to open an archive std::unique_ptr<IArchive> ar(archiveLoader.OpenArchive(arcName)); if (ar == nullptr) return 0; // load ignore list, and insert all files to check in lowercase format std::unique_ptr<IFileFilter> ignore(CreateIgnoreFilter(ar.get())); std::vector<std::string> files; std::vector<CRCPair> crcs; files.reserve(ar->NumFiles()); crcs.reserve(ar->NumFiles()); for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { const std::pair<std::string, int>& info = ar->FileInfo(fid); if (ignore->Match(info.first)) continue; // create case-insensitive hashes files.push_back(StringToLower(info.first)); } // sort by filename std::stable_sort(files.begin(), files.end()); for (std::string& f: files) { crcs.push_back(CRCPair{&f, 0, 0}); } // compute CRCs of the files // Hint: Multithreading only speedups `.sdd` loading. For those the CRC generation is extremely slow - // it has to load the full file to calc it! For the other formats (sd7, sdz, sdp) the CRC is saved // in the metainformation of the container and so the loading is much faster. Neither does any of our // current (2011) packing libraries support multithreading :/ for_mt(0, crcs.size(), [&](const int i) { CRCPair& crcp = crcs[i]; assert(crcp.filename == &files[i]); const unsigned int nameCRC = CRC::GetCRC(crcp.filename->data(), crcp.filename->size()); const unsigned fid = ar->FindFile(*crcp.filename); const unsigned int dataCRC = ar->GetCrc32(fid); crcp.nameCRC = nameCRC; crcp.dataCRC = dataCRC; #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(WDT_MAIN); #endif }); // Add file CRCs to the main archive CRC for (const CRCPair& crcp: crcs) { crc.Update(crcp.nameCRC); crc.Update(crcp.dataCRC); #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(); #endif } // A value of 0 is used to indicate no crc.. so never return that // Shouldn't happen all that often const unsigned int digest = crc.GetDigest(); return (digest == 0)? 4711: digest; }
CTextureHandler::CTextureHandler() { PrintLoadMsg("Creating unit textures"); CFileHandler file("unittextures/tatex/teamtex.txt"); CSimpleParser parser(file); std::set<std::string> teamTexes; while(!file.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } TexFile* texfiles[10000]; int numfiles = 0; int totalSize = 0; std::vector<std::string> files2 = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); for(std::vector<std::string>::iterator fi = files2.begin(); fi != files2.end(); ++fi) { files.push_back(*fi); } std::set<string> usedNames; for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { std::string s = std::string(*fi); std::string s2 = s; s2.erase(0, s2.find_last_of('/') + 1); s2 = StringToLower(s2.substr(0, s2.find_last_of('.'))); if(usedNames.find(s2)!=usedNames.end()) //avoid duplicate names and give tga images priority continue; usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = SAFE_NEW TexFile; tex->tex.Load(s,30); tex->name = s2; texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } else { for(int a = 0; a < gs->activeTeams; ++a){ TexFile* tex = CreateTeamTex(s, s2, a); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } } } for(int a=0;a<256;++a){ string name="ta_color"; char t[50]; sprintf(t,"%i",a); name+=t; TexFile* tex=SAFE_NEW TexFile; tex->name=name; tex->tex.Alloc(1,1); tex->tex.mem[0]=palette[a][0]; tex->tex.mem[1]=palette[a][1]; tex->tex.mem[2]=palette[a][2]; tex->tex.mem[3]=30; texfiles[numfiles++]=tex; totalSize+=tex->tex.xsize*tex->tex.ysize; } totalSize=(int)(totalSize * 1.2f); //pessimistic guess about how much space will be wasted if(totalSize<1024*1024){ bigTexX=1024; bigTexY=1024; } else if(totalSize<1024*2048){ bigTexX=1024; bigTexY=2048; } else if(totalSize<2048*2048){ bigTexX=2048; bigTexY=2048; } else { bigTexX=2048; bigTexY=2048; handleerror(0,"Too many/large unit textures to fit in 2048*2048","Error",0); } qsort(texfiles,numfiles,sizeof(TexFile*),CompareTatex2); unsigned char* tex=SAFE_NEW unsigned char[bigTexX*bigTexY*4]; for(int a=0;a<bigTexX*bigTexY*4;++a){ tex[a]=128; } int cury=0; int maxy=0; int curx=0; int foundx = 0, foundy = 0; std::list<int2> nextSub; std::list<int2> thisSub; for(int a=0;a<numfiles;++a){ CBitmap* curtex=&texfiles[a]->tex; bool done=false; while(!done){ if(thisSub.empty()){ if(nextSub.empty()){ cury=maxy; maxy+=curtex->ysize; if(maxy>bigTexY){ handleerror(0,"Too many/large unit textures","Error",0); break; } thisSub.push_back(int2(0,cury)); } else { thisSub=nextSub; nextSub.clear(); } } if(thisSub.front().x+curtex->xsize>bigTexX){ thisSub.clear(); continue; } if(thisSub.front().y+curtex->ysize>maxy){ thisSub.pop_front(); continue; } //ok found space for us foundx=thisSub.front().x; foundy=thisSub.front().y; done=true; if(thisSub.front().y+curtex->ysize<maxy){ nextSub.push_back(int2(thisSub.front().x,thisSub.front().y+curtex->ysize)); } thisSub.front().x+=curtex->xsize; while(thisSub.size()>1 && thisSub.front().x >= (++thisSub.begin())->x){ (++thisSub.begin())->x=thisSub.front().x; thisSub.erase(thisSub.begin()); } } for(int y=0;y<curtex->ysize;y++){ for(int x=0;x<curtex->xsize;x++){ // if(curtex->mem[(y*curtex->xsize+x)*4]==254 && curtex->mem[(y*curtex->xsize+x)*4+1]==0 && curtex->mem[(y*curtex->xsize+x)*4+2]==254){ // tex[((cury+y)*bigTexX+(curx+x))*4+3]=0; // } else { for(int col=0;col<4;col++){ tex[((foundy+y)*bigTexX+(foundx+x))*4+col]=curtex->mem[(y*curtex->xsize+x)*4+col]; // } } } } UnitTexture* unittex=SAFE_NEW UnitTexture; unittex->xstart=(foundx+0.5f)/(float)bigTexX; unittex->ystart=(foundy+0.5f)/(float)bigTexY; unittex->xend=(foundx+curtex->xsize-0.5f)/(float)bigTexX; unittex->yend=(foundy+curtex->ysize-0.5f)/(float)bigTexY; textures[texfiles[a]->name]=unittex; curx+=curtex->xsize; delete texfiles[a]; } glGenTextures(1, &globalTex); glBindTexture(GL_TEXTURE_2D, globalTex); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, tex); // CBitmap save(tex,bigTexX,bigTexY); //save.Save("unittex-1x.jpg"); UnitTexture* t=SAFE_NEW UnitTexture; t->xstart=0; t->ystart=0; t->xend=1; t->yend=1; s3oTextures.push_back(S3oTex()); textures[" "]=t; delete[] tex; s3oTextures.push_back(S3oTex()); }
std::vector<std::string> CArchiveScanner::GetAllArchivesUsedBy(const std::string& rootArchive) const { LOG_S(LOG_SECTION_ARCHIVESCANNER, "GetArchives: %s", rootArchive.c_str()); // VectorInsertUnique'ing via AddDependency can become a performance hog // for very long dependency chains, prefer to sort and remove duplicates const auto& NameCmp = [](const std::pair<std::string, size_t>& a, const std::pair<std::string, size_t>& b) { return (a.first < b.first ); }; const auto& IndxCmp = [](const std::pair<std::string, size_t>& a, const std::pair<std::string, size_t>& b) { return (a.second < b.second); }; std::vector< std::string > retArchives; std::vector<std::pair<std::string, size_t>> tmpArchives[2]; std::deque<std::string> archiveQueue = {rootArchive}; retArchives.reserve(8); tmpArchives[0].reserve(8); tmpArchives[1].reserve(8); while (!archiveQueue.empty()) { // protect against circular dependencies; worst case is if all archives form one huge chain if (archiveQueue.size() > archiveInfos.size()) break; const std::string& resolvedName = ArchiveNameResolver::GetGame(archiveQueue.front()); const std::string& lowerCaseName = StringToLower(ArchiveFromName(resolvedName)); archiveQueue.pop_front(); const ArchiveInfo* archiveInfo = nullptr; const auto CanAddSubDependencies = [&](const std::string& lwrCaseName) -> const ArchiveInfo* { #ifdef UNITSYNC // add unresolved deps for unitsync so it still shows this file const auto HandleUnresolvedDep = [&tmpArchives](const std::string& archName) { tmpArchives[0].emplace_back(archName, tmpArchives[0].size()); return true; }; #else const auto HandleUnresolvedDep = [&tmpArchives](const std::string& archName) { (void) archName; return false; }; #endif auto aii = archiveInfos.find(lwrCaseName); auto aij = aii; const ArchiveInfo* ai = nullptr; if (aii == archiveInfos.end()) { if (!HandleUnresolvedDep(lwrCaseName)) throw content_error("Archive \"" + lwrCaseName + "\" not found"); return nullptr; } ai = &aii->second; // check if this archive has an unresolved replacement while (!ai->replaced.empty()) { if ((aii = archiveInfos.find(ai->replaced)) == archiveInfos.end()) { if (!HandleUnresolvedDep(lwrCaseName)) throw content_error("Replacement \"" + ai->replaced + "\" for archive \"" + lwrCaseName + "\" not found"); return nullptr; } aij = aii; ai = &aij->second; } return ai; }; if ((archiveInfo = CanAddSubDependencies(lowerCaseName)) == nullptr) continue; tmpArchives[0].emplace_back(archiveInfo->archiveData.GetNameVersioned(), tmpArchives[0].size()); // expand dependencies in depth-first order for (const std::string& archiveDep: archiveInfo->archiveData.GetDependencies()) { assert(archiveDep != rootArchive); assert(archiveDep != tmpArchives[0][tmpArchives[0].size() - 1].first); archiveQueue.push_front(archiveDep); } } std::stable_sort(tmpArchives[0].begin(), tmpArchives[0].end(), NameCmp); // filter out any duplicate dependencies for (auto& archiveEntry: tmpArchives[0]) { if (tmpArchives[1].empty() || archiveEntry.first != tmpArchives[1][tmpArchives[1].size() - 1].first) { tmpArchives[1].emplace_back(std::move(archiveEntry.first), archiveEntry.second); } } // resort in original traversal order so overrides work as expected std::stable_sort(tmpArchives[1].begin(), tmpArchives[1].end(), IndxCmp); for (auto& archiveEntry: tmpArchives[1]) { retArchives.emplace_back(std::move(archiveEntry.first)); } return retArchives; }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { unsigned modifiedTime = 0; if (CheckCachedData(fullName, &modifiedTime, doChecksum)) return; isDirty = true; const std::string& fn = FileSystem::GetFilename(fullName); const std::string& fpath = FileSystem::GetDirectory(fullName); const std::string& lcfn = StringToLower(fn); std::unique_ptr<IArchive> ar(archiveLoader.OpenArchive(fullName)); if (ar == nullptr || !ar->IsOpen()) { LOG_L(L_WARNING, "[AS::%s] unable to open archive \"%s\"", __func__, fullName.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = "Unable to open archive"; // does not count as a scan // numScannedArchives += 1; return; } std::string error; std::string arMapFile; // file in archive with "smf" or "sm3" extension std::string miMapFile; // value for the 'mapfile' key parsed from mapinfo const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); ArchiveInfo ai; ArchiveData& ad = ai.archiveData; // execute the respective .lua, otherwise assume this archive is a map if (hasMapinfo) { ScanArchiveLua(ar.get(), "mapinfo.lua", ai, error); if ((miMapFile = ad.GetMapFile()).empty()) { LOG_L(L_WARNING, "[AS::%s] set the 'mapfile' key in mapinfo.lua of archive \"%s\" for faster loading!", __func__, fullName.c_str()); arMapFile = SearchMapFile(ar.get(), error); } } else if (hasModinfo) { ScanArchiveLua(ar.get(), "modinfo.lua", ai, error); } else { arMapFile = SearchMapFile(ar.get(), error); } if (!CheckCompression(ar.get(), fullName, error)) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "[AS::%s] failed to scan \"%s\" (%s)", __func__, fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = error; // does count as a scan numScannedArchives += 1; return; } if (hasMapinfo || !arMapFile.empty()) { // map archive if ((ad.GetName()).empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ad.SetInfoItemValueString("name_pure", FileSystem::GetBasename(arMapFile)); ad.SetInfoItemValueString("name", FileSystem::GetBasename(arMapFile)); } if (miMapFile.empty()) ad.SetInfoItemValueString("mapfile", arMapFile); AddDependency(ad.GetDependencies(), GetMapHelperContentName()); ad.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ad.GetNameVersioned().c_str()); } else if (hasModinfo) { // game or base-type (cursors, bitmaps, ...) archive // babysitting like this is really no longer required if (ad.IsGame() || ad.IsMenu()) AddDependency(ad.GetDependencies(), GetSpringBaseContentName()); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ad.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } ai.path = fpath; ai.modified = modifiedTime; ai.origName = fn; ai.updated = true; ai.checksum = (doChecksum) ? GetCRC(fullName) : 0; archiveInfos[lcfn] = ai; numScannedArchives += 1; }
CBuilderCAI::CBuilderCAI(CUnit* owner): CMobileCAI(owner), building(false), cachedRadiusId(0), cachedRadius(0), buildRetries(0), randomCounter(0), lastPC1(-1), lastPC2(-1), lastPC3(-1), range3D(owner->unitDef->buildRange3D) { ownerBuilder = static_cast<CBuilder*>(owner); if (owner->unitDef->canRepair) { SCommandDescription c; c.id = CMD_REPAIR; c.type = CMDTYPE_ICON_UNIT_OR_AREA; c.action = "repair"; c.name = "Repair"; c.tooltip = c.name + ": Repairs another unit"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } else if (owner->unitDef->canAssist) { SCommandDescription c; c.id = CMD_REPAIR; c.type = CMDTYPE_ICON_UNIT_OR_AREA; c.action = "assist"; c.name = "Assist"; c.tooltip = c.name + ": Help build something"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } if (owner->unitDef->canReclaim) { SCommandDescription c; c.id = CMD_RECLAIM; c.type = CMDTYPE_ICON_UNIT_FEATURE_OR_AREA; c.action = "reclaim"; c.name = "Reclaim"; c.tooltip = c.name + ": Sucks in the metal/energy content of a unit/feature and add it to your storage"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } if (owner->unitDef->canRestore && !mapDamage->disabled) { SCommandDescription c; c.id = CMD_RESTORE; c.type = CMDTYPE_ICON_AREA; c.action = "restore"; c.name = "Restore"; c.tooltip = c.name + ": Restores an area of the map to its original height"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } if (owner->unitDef->canResurrect) { SCommandDescription c; c.id = CMD_RESURRECT; c.type = CMDTYPE_ICON_UNIT_FEATURE_OR_AREA; c.action = "resurrect"; c.name = "Resurrect"; c.tooltip = c.name + ": Resurrects a unit from a feature"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } if (owner->unitDef->canCapture) { SCommandDescription c; c.id = CMD_CAPTURE; c.type = CMDTYPE_ICON_UNIT_OR_AREA; c.action = "capture"; c.name = "Capture"; c.tooltip = c.name + ": Captures a unit from the enemy"; c.mouseicon = c.name; possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } for (const auto& bi: ownerBuilder->unitDef->buildOptions) { const std::string& name = bi.second; const UnitDef* ud = unitDefHandler->GetUnitDefByName(name); if (ud == nullptr) { string errmsg = "MOD ERROR: loading "; errmsg += name.c_str(); errmsg += " for "; errmsg += owner->unitDef->name; throw content_error(errmsg); } { SCommandDescription c; c.id = -ud->id; //build options are always negative c.type = CMDTYPE_ICON_BUILDING; c.action = "buildunit_" + StringToLower(ud->name); c.name = name; c.mouseicon = c.name; c.tooltip = GetUnitDefBuildOptionToolTip(ud, c.disabled = (ud->maxThisUnit <= 0)); buildOptions.insert(c.id); possibleCommands.push_back(commandDescriptionCache->GetPtr(c)); } } unitHandler->AddBuilderCAI(this); }
void CGlobalRendering::PostInit() { supportNPOTs = GLEW_ARB_texture_non_power_of_two; haveARB = GLEW_ARB_vertex_program && GLEW_ARB_fragment_program; haveGLSL = (glGetString(GL_SHADING_LANGUAGE_VERSION) != NULL); haveGLSL &= GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader; haveGLSL &= !!GLEW_VERSION_2_0; // we want OpenGL 2.0 core functions { const char* glVendor = (const char*) glGetString(GL_VENDOR); const char* glRenderer = (const char*) glGetString(GL_RENDERER); const std::string vendor = (glVendor != NULL)? StringToLower(std::string(glVendor)): ""; const std::string renderer = (glRenderer != NULL)? StringToLower(std::string(glRenderer)): ""; haveATI = (vendor.find("ati ") != std::string::npos) || (vendor.find("amd ") != std::string::npos); haveMesa = (renderer.find("mesa ") != std::string::npos) || (renderer.find("gallium ") != std::string::npos); haveIntel = (vendor.find("intel") != std::string::npos); haveNvidia = (vendor.find("nvidia ") != std::string::npos); //FIXME Neither Intel's nor Mesa's GLSL implementation seem to be in a workable state atm (date: Nov. 2011) haveGLSL &= !haveIntel; haveGLSL &= !haveMesa; //FIXME add an user config to force enable it! if (haveATI) { // x-series doesn't support NPOTs (but hd-series does) supportNPOTs = (renderer.find(" x") == std::string::npos && renderer.find(" 9") == std::string::npos); } } // use some ATI bugfixes? const int atiHacksCfg = configHandler->GetInt("AtiHacks"); atiHacks = haveATI && (atiHacksCfg < 0); // runtime detect atiHacks |= (atiHacksCfg > 0); // user override // Runtime compress textures? if (GLEW_ARB_texture_compression) { // we don't even need to check it, 'cos groundtextures must have that extension // default to off because it reduces quality (smallest mipmap level is bigger) compressTextures = configHandler->GetBool("CompressTextures"); } #ifdef GLEW_NV_primitive_restart supportRestartPrimitive = !!(GLEW_NV_primitive_restart); #endif // maximum 2D texture size { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); } // retrieve maximu smoothed PointSize float2 aliasedPointSizeRange, smoothPointSizeRange; glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, (GLfloat*)&aliasedPointSizeRange); glGetFloatv(GL_SMOOTH_POINT_SIZE_RANGE, (GLfloat*)&smoothPointSizeRange); maxSmoothPointSize = std::min(aliasedPointSizeRange.y, smoothPointSizeRange.y); // some GLSL relevant information { glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &glslMaxUniformBufferBindings); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &glslMaxUniformBufferSize); glGetIntegerv(GL_MAX_VARYING_FLOATS, &glslMaxVaryings); glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &glslMaxAttributes); glGetIntegerv(GL_MAX_DRAW_BUFFERS, &glslMaxDrawBuffers); glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &glslMaxRecommendedIndices); glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &glslMaxRecommendedVertices); glslMaxVaryings /= 4; // GL_MAX_VARYING_FLOATS returns max individual floats, we want float4 } // detect if GL_DEPTH_COMPONENT24 is supported (many ATIs don't do so) { // ATI seems to support GL_DEPTH_COMPONENT24 for static textures, but you can't render to them /* GLint state = 0; glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 16, 16, 0, GL_LUMINANCE, GL_FLOAT, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &state); support24bitDepthBuffers = (state > 0); */ support24bitDepthBuffers = false; if (FBO::IsSupported() && !atiHacks) { const int fboSizeX = 16, fboSizeY = 16; FBO fbo; fbo.Bind(); fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, fboSizeX, fboSizeY); fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT24, fboSizeX, fboSizeY); const GLenum status = fbo.GetStatus(); fbo.Unbind(); support24bitDepthBuffers = (status == GL_FRAMEBUFFER_COMPLETE_EXT); } } // print info LOG( "GL info:\n" "\thaveARB: %i, haveGLSL: %i, ATI hacks: %i\n" "\tFBO support: %i, NPOT-texture support: %i, 24bit Z-buffer support: %i\n" "\tmaximum texture size: %i, compress MIP-map textures: %i\n" "\tmaximum SmoothPointSize: %0.0f, maximum vec4 varying/attributes: %i/%i\n" "\tmaximum drawbuffers: %i, maximum recommended indices/vertices: %i/%i\n" "\tnumber of UniformBufferBindings: %i (%ikB)", haveARB, haveGLSL, atiHacks, FBO::IsSupported(), supportNPOTs, support24bitDepthBuffers, maxTextureSize, compressTextures, maxSmoothPointSize, glslMaxVaryings, glslMaxAttributes, glslMaxDrawBuffers, glslMaxRecommendedIndices, glslMaxRecommendedVertices, glslMaxUniformBufferBindings, glslMaxUniformBufferSize / 1024 ); teamNanospray = configHandler->GetBool("TeamNanoSpray"); }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { const std::string fn = FileSystem::GetFilename(fullName); const std::string fpath = FileSystem::GetDirectory(fullName); const std::string lcfn = StringToLower(fn); // Cache variables std::map<std::string, ArchiveInfo>::iterator aii; bool cached = false; // Stat file struct stat info = {0}; int statfailed = stat(fullName.c_str(), &info); // If stat fails, assume the archive is not broken nor cached if (!statfailed) { // Determine whether this archive has earlier be found to be broken std::map<std::string, BrokenArchive>::iterator bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { if ((unsigned)info.st_mtime == bai->second.modified && fpath == bai->second.path) { bai->second.updated = true; return; } } // Determine whether to rely on the cached info or not if ((aii = archiveInfos.find(lcfn)) != archiveInfos.end()) { // This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) { return; } if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } // If we are here, we could have invalid info in the cache // Force a reread if it is a directory archive (.sdd), as // st_mtime only reflects changes to the directory itself, // not the contents. if (!cached) { archiveInfos.erase(aii); } } } // Time to parse the info we are interested in if (cached) { // If cached is true, aii will point to the archive if (doChecksum && (aii->second.checksum == 0)) aii->second.checksum = GetCRC(fullName); } else { IArchive* ar = archiveLoader.OpenArchive(fullName); if (!ar || !ar->IsOpen()) { LOG("Unable to open archive: %s", fullName.c_str()); return; } ArchiveInfo ai; std::string error; std::string mapfile; const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); // check for smf/sm3 and if the uncompression of important files is too costy for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); const std::string lowerName = StringToLower(name); const std::string ext = FileSystem::GetExtension(lowerName); if ((ext == "smf") || (ext == "sm3")) { mapfile = name; } const unsigned char metaFileClass = GetMetaFileClass(lowerName); if ((metaFileClass != 0) && !(ar->HasLowReadingCost(fid))) { // is a meta-file and not cheap to read if (metaFileClass == 1) { // 1st class error = "Unpacking/reading cost for meta file " + name + " is too high, please repack the archive (make sure to use a non-solid algorithm, if applicable)"; break; } else if (metaFileClass == 2) { // 2nd class LOG_SL(LOG_SECTION_ARCHIVESCANNER, L_WARNING, "Archive %s: The cost for reading a 2nd-class meta-file is too high: %s", fullName.c_str(), name.c_str()); } } } /* if (!error.empty()) { // we already have an error, no further evaluation required } */ if (hasMapinfo || !mapfile.empty()) { // it is a map if (hasMapinfo) { ScanArchiveLua(ar, "mapinfo.lua", ai, error); } else if (hasModinfo) { // backwards-compat for modinfo.lua in maps ScanArchiveLua(ar, "modinfo.lua", ai, error); } if (ai.archiveData.GetName().empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ai.archiveData.SetInfoItemValueString("name_pure", FileSystem::GetBasename(mapfile)); ai.archiveData.SetInfoItemValueString("name", FileSystem::GetBasename(mapfile)); } if (ai.archiveData.GetMapFile().empty()) { ai.archiveData.SetInfoItemValueString("mapfile", mapfile); } AddDependency(ai.archiveData.GetDependencies(), "Map Helper v1"); ai.archiveData.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ai.archiveData.GetNameVersioned().c_str()); } else if (hasModinfo) { // it is a mod ScanArchiveLua(ar, "modinfo.lua", ai, error); if (ai.archiveData.GetModType() == modtype::primary) { AddDependency(ai.archiveData.GetDependencies(), "Spring content v1"); } LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ai.archiveData.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } delete ar; if (!error.empty()) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "Failed to scan %s (%s)", fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive ba; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = error; brokenArchives[lcfn] = ba; return; } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; // Optionally calculate a checksum for the file // To prevent reading all files in all directory (.sdd) archives // every time this function is called, directory archive checksums // are calculated on the fly. if (doChecksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfos[lcfn] = ai; } }
void CArchiveScanner::ReadCacheData(const std::string& filename) { if (!FileSystem::FileExists(filename)) { LOG_L(L_INFO, "Archive cache doesn't exist: %s", filename.c_str()); return; } LuaParser p(filename, SPRING_VFS_RAW, SPRING_VFS_BASE); if (!p.Execute()) { LOG_L(L_ERROR, "Failed to parse archive cache: %s", p.GetErrorLog().c_str()); return; } const LuaTable archiveCache = p.GetRoot(); const LuaTable archives = archiveCache.SubTable("archives"); // Do not load old version caches const int ver = archiveCache.GetInt("internalVer", (INTERNAL_VER + 1)); if (ver != INTERNAL_VER) { return; } for (int i = 1; archives.KeyExists(i); ++i) { const LuaTable curArchive = archives.SubTable(i); const LuaTable archived = curArchive.SubTable("archivedata"); ArchiveInfo ai; ai.origName = curArchive.GetString("name", ""); ai.path = curArchive.GetString("path", ""); // do not use LuaTable.GetInt() for 32-bit integers, the Spring lua // library uses 32-bit floats to represent numbers, which can only // represent 2^24 consecutive integers ai.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ai.checksum = strtoul(curArchive.GetString("checksum", "0").c_str(), 0, 10); ai.updated = false; ai.archiveData = CArchiveScanner::ArchiveData(archived, true); if (ai.archiveData.GetModType() == modtype::map) { AddDependency(ai.archiveData.GetDependencies(), "Map Helper v1"); } else if (ai.archiveData.GetModType() == modtype::primary) { AddDependency(ai.archiveData.GetDependencies(), "Spring content v1"); } std::string lcname = StringToLower(ai.origName); archiveInfos[lcname] = ai; } const LuaTable brokenArchives = archiveCache.SubTable("brokenArchives"); for (int i = 1; brokenArchives.KeyExists(i); ++i) { const LuaTable curArchive = brokenArchives.SubTable(i); BrokenArchive ba; std::string name = curArchive.GetString("name", ""); ba.path = curArchive.GetString("path", ""); ba.modified = strtoul(curArchive.GetString("modified", "0").c_str(), 0, 10); ba.updated = false; ba.problem = curArchive.GetString("problem", "unknown"); StringToLowerInPlace(name); this->brokenArchives[name] = ba; } isDirty = false; }
void CArchiveScanner::Scan(const std::string& curPath, bool doChecksum) { isDirty = true; const int flags = (FileQueryFlags::INCLUDE_DIRS | FileQueryFlags::RECURSE); const std::vector<std::string> &found = dataDirsAccess.FindFiles(curPath, "*", flags); for (std::vector<std::string>::const_iterator it = found.begin(); it != found.end(); ++it) { std::string fullName = *it; // Strip const char lastFullChar = fullName[fullName.size() - 1]; if ((lastFullChar == '/') || (lastFullChar == '\\')) { fullName = fullName.substr(0, fullName.size() - 1); } const std::string fpath = FileSystem::GetDirectory(fullName); const std::string lcfpath = StringToLower(fpath); // Exclude archivefiles found inside directory archives (.sdd) if (lcfpath.find(".sdd") != std::string::npos) { continue; } // Exclude archivefiles found inside hidden directories if ((lcfpath.find("/hidden/") != std::string::npos) || (lcfpath.find("\\hidden\\") != std::string::npos)) { continue; } #if !defined(DEDICATED) && !defined(UNITSYNC) Watchdog::ClearTimer(WDT_MAIN); #endif // !defined(DEDICATED) && !defined(UNITSYNC) // Is this an archive we should look into? if (archiveLoader.IsArchiveFile(fullName)) { ScanArchive(fullName, doChecksum); } } // Now we'll have to parse the replaces-stuff found in the mods for (std::map<std::string, ArchiveInfo>::iterator aii = archiveInfos.begin(); aii != archiveInfos.end(); ++aii) { for (std::vector<std::string>::const_iterator i = aii->second.archiveData.GetReplaces().begin(); i != aii->second.archiveData.GetReplaces().end(); ++i) { const std::string lcname = StringToLower(*i); std::map<std::string, ArchiveInfo>::iterator ar = archiveInfos.find(lcname); // If it's not there, we will create a new entry if (ar == archiveInfos.end()) { ArchiveInfo tmp; archiveInfos[lcname] = tmp; ar = archiveInfos.find(lcname); } // Overwrite the info for this archive with a replaced pointer ar->second.path = ""; ar->second.origName = lcname; ar->second.modified = 1; ArchiveData empty; ar->second.archiveData = empty; ar->second.updated = true; ar->second.replaced = aii->first; } } }
std::vector<TexFile*> C3DOTextureHandler::LoadTexFiles() { CFileHandler teamTexFile("unittextures/tatex/teamtex.txt"); CFileHandler paletteFile("unittextures/tatex/palette.pal"); CSimpleParser parser(teamTexFile); std::set<std::string> teamTexes; while (!parser.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } std::vector<TexFile*> texfiles; const std::vector<std::string>& filesBMP = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); files.insert(files.end(), filesBMP.begin(), filesBMP.end()); std::set<string> usedNames; for (std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { const std::string& s = *fi; const std::string s2 = StringToLower(FileSystem::GetBasename(s)); // avoid duplicate names and give tga images priority if (usedNames.find(s2) != usedNames.end()) { continue; } usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = CreateTex(s, s2, false); texfiles.push_back(tex); } else { TexFile* tex = CreateTex(s, s2, true); texfiles.push_back(tex); } } if (paletteFile.FileExists()) { palette.Init(paletteFile); } for (unsigned a = 0; a < CTAPalette::NUM_PALETTE_ENTRIES; ++a) { TexFile* tex = new TexFile(); tex->name = "ta_color" + IntToString(a, "%i"); tex->tex.Alloc(1, 1); tex->tex.mem[0] = palette[a][0]; tex->tex.mem[1] = palette[a][1]; tex->tex.mem[2] = palette[a][2]; tex->tex.mem[3] = 0; // teamcolor tex->tex2.Alloc(1, 1); tex->tex2.mem[0] = 0; // self illum tex->tex2.mem[1] = 30; // reflectivity tex->tex2.mem[2] = 0; tex->tex2.mem[3] = 255; texfiles.push_back(tex); } return texfiles; }
bool CKeyBindings::ExecuteCommand(const string& line) { const vector<string> words = CSimpleParser::Tokenize(line, 2); if (words.empty()) { return false; } const string command = StringToLower(words[0]); if (command == "keydebug") { const int curLogLevel = log_filter_section_getMinLevel(LOG_SECTION_KEY_BINDINGS); bool debug = (curLogLevel == LOG_LEVEL_DEBUG); if (words.size() == 1) { // toggle debug = !debug; } else if (words.size() >= 2) { // set debug = atoi(words[1].c_str()); } if (debug && !LOG_IS_ENABLED_STATIC(L_DEBUG)) { LOG_L(L_WARNING, "You have to run a DEBUG build to be able to log L_DEBUG messages"); } log_filter_section_setMinLevel(LOG_SECTION_KEY_BINDINGS, (debug ? LOG_LEVEL_DEBUG : LOG_LEVEL_INFO)); } else if ((command == "fakemeta") && (words.size() > 1)) { if (!SetFakeMetaKey(words[1])) { return false; } } else if ((command == "keyset") && (words.size() > 2)) { if (!AddNamedKeySet(words[1], words[2])) { return false; } } else if ((command == "keysym") && (words.size() > 2)) { if (!AddKeySymbol(words[1], words[2])) { return false; } } else if ((command == "bind") && (words.size() > 2)) { if (!Bind(words[1], words[2])) { return false; } } else if ((command == "unbind") && (words.size() > 2)) { if (!UnBind(words[1], words[2])) { return false; } } else if ((command == "unbindaction") && (words.size() > 1)) { if (!UnBindAction(words[1])) { return false; } } else if ((command == "unbindkeyset") && (words.size() > 1)) { if (!UnBindKeyset(words[1])) { return false; } } else if (command == "unbindall") { bindings.clear(); keyCodes->Reset(); namedKeySets.clear(); typeBindings.clear(); Bind("enter", "chat"); // bare minimum } else { return false; } if (userCommand) { Sanitize(); } return false; }
bool CTextureAtlas::TextureExists(const std::string& name) { return textures.find(StringToLower(name)) != textures.end(); }
CFactoryCAI::CFactoryCAI(CUnit* owner) : CCommandAI(owner), building(false), lastRestrictedWarning(0) { commandQue.SetQueueType(CCommandQueue::BuildQueueType); newUnitCommands.SetQueueType(CCommandQueue::NewUnitQueueType); CommandDescription c; // can't check for canmove here because it should be possible to assign rallypoint // with a non-moving factory. c.id=CMD_MOVE; c.action="move"; c.type=CMDTYPE_ICON_MAP; c.name="Move"; c.mouseicon=c.name; c.tooltip="Move: Order ready built units to move to a position"; possibleCommands.push_back(c); if (owner->unitDef->canPatrol) { c.id=CMD_PATROL; c.action="patrol"; c.type=CMDTYPE_ICON_MAP; c.name="Patrol"; c.mouseicon=c.name; c.tooltip="Patrol: Order ready built units to patrol to one or more waypoints"; possibleCommands.push_back(c); } if (owner->unitDef->canFight) { c.id = CMD_FIGHT; c.action="fight"; c.type = CMDTYPE_ICON_MAP; c.name = "Fight"; c.mouseicon=c.name; c.tooltip = "Fight: Order ready built units to take action while moving to a position"; possibleCommands.push_back(c); } if (owner->unitDef->canGuard) { c.id=CMD_GUARD; c.action="guard"; c.type=CMDTYPE_ICON_UNIT; c.name="Guard"; c.mouseicon=c.name; c.tooltip="Guard: Order ready built units to guard another unit and attack units attacking it"; possibleCommands.push_back(c); } CFactory* fac=(CFactory*)owner; map<int,string>::const_iterator bi; for (bi = fac->unitDef->buildOptions.begin(); bi != fac->unitDef->buildOptions.end(); ++bi) { const string name = bi->second; const UnitDef* ud = unitDefHandler->GetUnitByName(name); if (ud == NULL) { string errmsg = "MOD ERROR: loading "; errmsg += name.c_str(); errmsg += " for "; errmsg += owner->unitDef->name; throw content_error(errmsg); } CommandDescription c; c.id = -ud->id; //build options are always negative c.action = "buildunit_" + StringToLower(ud->name); c.type = CMDTYPE_ICON; c.name = name; c.mouseicon = c.name; c.disabled = (ud->maxThisUnit <= 0); char tmp[1024]; sprintf(tmp, "\nHealth %.0f\nMetal cost %.0f\nEnergy cost %.0f Build time %.0f", ud->health, ud->metalCost, ud->energyCost, ud->buildTime); if (c.disabled) { c.tooltip = "\xff\xff\x22\x22" "DISABLED: " "\xff\xff\xff\xff"; } else { c.tooltip = "Build: "; } c.tooltip += ud->humanName + " - " + ud->tooltip + tmp; possibleCommands.push_back(c); BuildOption bo; bo.name = name; bo.fullName = name; bo.numQued = 0; buildOptions[c.id] = bo; } }
AtlasedTexture* CTextureAtlas::GetTexturePtr(const std::string& name) { return &textures[StringToLower(name)]; }
static std::map<std::string, int> GetEnabledSections() { std::map<std::string, int> sectionLevelMap; std::string enabledSections = ","; std::string envSections = ","; #if defined(UNITSYNC) #if defined(DEBUG) // unitsync logging in debug mode always on // configHandler cannot be accessed here in unitsync, as it may not exist. enabledSections += "unitsync,ArchiveScanner,"; #endif #else #if defined(DEDICATED) enabledSections += "DedicatedServer,"; #endif #if !defined(DEBUG) // Always show at least INFO level of these sections enabledSections += "Sound,"; #endif enabledSections += StringToLower(configHandler->GetString("LogSections")); #endif if (getenv("SPRING_LOG_SECTIONS") != NULL) { // allow disabling all sections from the env var by setting it to "none" envSections += getenv("SPRING_LOG_SECTIONS"); envSections = StringToLower(envSections); if (envSections == "none") { enabledSections = ""; } else { enabledSections += envSections; } } enabledSections = StringToLower(enabledSections); enabledSections = StringStrip(enabledSections, " \t\n\r"); // make the last "section:level" substring findable if (!enabledSections.empty() && enabledSections.back() != ',') enabledSections += ","; // n=1 because <enabledSections> always starts with a ',' (if non-empty) for (size_t n = 1; n < enabledSections.size(); ) { const size_t k = enabledSections.find(",", n); if (k != std::string::npos) { const std::string& sub = enabledSections.substr(n, k - n); if (!sub.empty()) { const size_t sepChr = sub.find(":"); const std::string& logSec = (sepChr != std::string::npos)? sub.substr( 0, sepChr): sub; const std::string& logLvl = (sepChr != std::string::npos)? sub.substr(sepChr + 1, std::string::npos): ""; if (!logLvl.empty()) { sectionLevelMap[logSec] = StringToInt(logLvl); } else { #if defined(DEBUG) sectionLevelMap[logSec] = LOG_LEVEL_DEBUG; #else sectionLevelMap[logSec] = DEFAULT_LOG_LEVEL; #endif } } n = k + 1; } else { n = k; } } return sectionLevelMap; }
/* * CArchiveScanner::ArchiveData */ CArchiveScanner::ArchiveData::ArchiveData(const LuaTable& archiveTable, bool fromCache) { if (!archiveTable.IsValid()) return; std::vector<std::string> keys; if (!archiveTable.GetKeys(keys)) return; for (std::string& key: keys) { const std::string& keyLower = StringToLower(key); if (ArchiveData::IsReservedKey(keyLower)) continue; if (keyLower == "modtype") { SetInfoItemValueInteger(key, archiveTable.GetInt(key, 0)); continue; } switch (archiveTable.GetType(key)) { case LuaTable::STRING: { SetInfoItemValueString(key, archiveTable.GetString(key, "")); } break; case LuaTable::NUMBER: { SetInfoItemValueFloat(key, archiveTable.GetFloat(key, 0.0f)); } break; case LuaTable::BOOLEAN: { SetInfoItemValueBool(key, archiveTable.GetBool(key, false)); } break; default: { // just ignore unsupported types (most likely to be lua-tables) //throw content_error("Lua-type " + IntToString(luaType) + " not supported in archive-info, but it is used on key \"" + *key + "\""); } break; } } const LuaTable& _dependencies = archiveTable.SubTable("depend"); const LuaTable& _replaces = archiveTable.SubTable("replace"); for (int dep = 1; _dependencies.KeyExists(dep); ++dep) { dependencies.push_back(_dependencies.GetString(dep, "")); } for (int rep = 1; _replaces.KeyExists(rep); ++rep) { replaces.push_back(_replaces.GetString(rep, "")); } // FIXME // XXX HACK needed until lobbies, lobbyserver and unitsync are sorted out // so they can uniquely identify different versions of the same mod. // (at time of this writing they use name only) // NOTE when changing this, this function is used both by the code that // reads ArchiveCache.lua and the code that reads modinfo.lua from the mod. // so make sure it doesn't keep adding stuff to the name everytime // Spring/unitsync is loaded. const std::string& name = GetNameVersioned(); const std::string& version = GetVersion(); if (!version.empty()) { if (name.find(version) == std::string::npos) { SetInfoItemValueString("name", name + " " + version); } else if (!fromCache) { LOG_L(L_WARNING, "[%s] version \"%s\" included in name \"%s\"", __func__, version.c_str(), name.c_str()); } } if (GetName().empty()) SetInfoItemValueString("name_pure", name); }
void CMiniMap::ConfigCommand(const std::string& line) { const vector<string> words = CSimpleParser::Tokenize(line, 1); if (words.empty()) { return; } const string command = StringToLower(words[0]); if (command == "fullproxy") { if (words.size() >= 2) { fullProxy = !!atoi(words[1].c_str()); } else { fullProxy = !fullProxy; } } else if (command == "icons") { if (words.size() >= 2) { useIcons = !!atoi(words[1].c_str()); } else { useIcons = !useIcons; } } else if (command == "unitexp") { if (words.size() >= 2) { unitExponent = atof(words[1].c_str()); } UpdateGeometry(); } else if (command == "unitsize") { if (words.size() >= 2) { unitBaseSize = atof(words[1].c_str()); } unitBaseSize = std::max(0.0f, unitBaseSize); UpdateGeometry(); } else if (command == "drawcommands") { if (words.size() >= 2) { drawCommands = std::max(0, atoi(words[1].c_str())); } else { drawCommands = (drawCommands > 0) ? 0 : 1; } } else if (command == "drawprojectiles") { if (words.size() >= 2) { drawProjectiles = !!atoi(words[1].c_str()); } else { drawProjectiles = !drawProjectiles; } } else if (command == "simplecolors") { if (words.size() >= 2) { simpleColors = !!atoi(words[1].c_str()); } else { simpleColors = !simpleColors; } } // the following commands can not be used in dualscreen mode if (gu->dualScreenMode) { return; } if ((command == "geo") || (command == "geometry")) { if (words.size() < 2) { return; } ParseGeometry(words[1]); UpdateGeometry(); } else if ((command == "min") || (command == "minimize")) { if (words.size() >= 2) { minimized = !!atoi(words[1].c_str()); } else { minimized = !minimized; } } else if ((command == "max") || (command == "maximize") || (command == "maxspect")) { bool newMax = maximized; if (words.size() >= 2) { newMax = !!atoi(words[1].c_str()); } else { newMax = !newMax; } if (newMax != maximized) { ToggleMaximized(command == "maxspect"); } } }
bool CArchiveScanner::CheckCachedData(const std::string& fullName, unsigned* modified, bool doChecksum) { // If stat fails, assume the archive is not broken nor cached if ((*modified = FileSystemAbstraction::GetFileModificationTime(fullName)) == 0) return false; const std::string& fn = FileSystem::GetFilename(fullName); const std::string& fpath = FileSystem::GetDirectory(fullName); const std::string& lcfn = StringToLower(fn); // Determine whether this archive has earlier be found to be broken auto bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { BrokenArchive& ba = bai->second; if (*modified == ba.modified && fpath == ba.path) { return (ba.updated = true); } } // Determine whether to rely on the cached info or not auto aii = archiveInfos.find(lcfn); if (aii != archiveInfos.end()) { ArchiveInfo& ai = aii->second; // This archive may have been obsoleted, do not process it if so if (!ai.replaced.empty()) return true; if (*modified == ai.modified && fpath == ai.path) { // cache found update checksum if wanted ai.updated = true; if (doChecksum && (ai.checksum == 0)) ai.checksum = GetCRC(fullName); return true; } if (ai.updated) { LOG_L(L_ERROR, "[AS::%s] found a \"%s\" already in \"%s\", ignoring.", __func__, fullName.c_str(), (ai.path + ai.origName).c_str()); if (baseContentArchives.find(aii->first) == baseContentArchives.end()) return true; // ignore throw user_error( std::string("duplicate base content detected:\n\t") + ai.path + std::string("\n\t") + fpath + std::string("\nPlease fix your configuration/installation as this can cause desyncs!")); } // If we are here, we could have invalid info in the cache // Force a reread if it is a directory archive (.sdd), as // st_mtime only reflects changes to the directory itself, // not the contents. archiveInfos.erase(aii); } return false; }
static bool parseOption(const LuaTable& root, int index, Option& opt, std::set<string>& optionsSet, CLogSubsystem& logSubsystem) { const LuaTable& optTbl = root.SubTable(index); if (!optTbl.IsValid()) { logOutput.Print(logSubsystem, "parseOption: subtable %d invalid", index); return false; } // common options properties opt.key = optTbl.GetString("key", ""); if (opt.key.empty() || (opt.key.find_first_of(Option_badKeyChars) != string::npos)) { logOutput.Print(logSubsystem, "parseOption: empty key or key contains bad characters"); return false; } opt.key = StringToLower(opt.key); opt.scope = optTbl.GetString("scope", "scope"); if (opt.key.empty() || (opt.key.find_first_of(Option_badKeyChars) != string::npos)) { logOutput.Print(logSubsystem, "parseOption: empty key or key contains bad characters"); return false; } opt.scope = StringToLower(opt.scope); if (optionsSet.find(opt.key) != optionsSet.end()) { logOutput.Print(logSubsystem, "parseOption: key %s exists already", opt.key.c_str()); return false; } opt.name = optTbl.GetString("name", opt.key); if (opt.name.empty()) { logOutput.Print(logSubsystem, "parseOption: %s: empty name", opt.key.c_str()); return false; } opt.desc = optTbl.GetString("desc", opt.name); opt.section = optTbl.GetString("section", ""); opt.style = optTbl.GetString("style", ""); opt.type = optTbl.GetString("type", ""); opt.type = StringToLower(opt.type); // option type specific properties if (opt.type == "bool") { opt.typeCode = opt_bool; opt.boolDef = optTbl.GetBool("def", false); } else if (opt.type == "number") { opt.typeCode = opt_number; opt.numberDef = optTbl.GetFloat("def", 0.0f); opt.numberMin = optTbl.GetFloat("min", -1.0e30f); opt.numberMax = optTbl.GetFloat("max", +1.0e30f); opt.numberStep = optTbl.GetFloat("step", 0.0f); } else if (opt.type == "string") { opt.typeCode = opt_string; opt.stringDef = optTbl.GetString("def", ""); opt.stringMaxLen = optTbl.GetInt("maxlen", 0); } else if (opt.type == "list") { opt.typeCode = opt_list; const LuaTable& listTbl = optTbl.SubTable("items"); if (!listTbl.IsValid()) { logOutput.Print(logSubsystem, "parseOption: %s: subtable items invalid", opt.key.c_str()); return false; } for (int i = 1; listTbl.KeyExists(i); i++) { OptionListItem item; // string format item.key = listTbl.GetString(i, ""); if (!item.key.empty() && (item.key.find_first_of(Option_badKeyChars) == string::npos)) { item.name = item.key; item.desc = item.name; opt.list.push_back(item); continue; } // table format (name & desc) const LuaTable& itemTbl = listTbl.SubTable(i); if (!itemTbl.IsValid()) { logOutput.Print(logSubsystem, "parseOption: %s: subtable %d of subtable items invalid", opt.key.c_str(), i); break; } item.key = itemTbl.GetString("key", ""); if (item.key.empty() || (item.key.find_first_of(Option_badKeyChars) != string::npos)) { logOutput.Print(logSubsystem, "parseOption: %s: empty key or key contains bad characters", opt.key.c_str()); return false; } item.key = StringToLower(item.key); item.name = itemTbl.GetString("name", item.key); if (item.name.empty()) { logOutput.Print(logSubsystem, "parseOption: %s: empty name", opt.key.c_str()); return false; } item.desc = itemTbl.GetString("desc", item.name); opt.list.push_back(item); } if (opt.list.size() <= 0) { logOutput.Print(logSubsystem, "parseOption: %s: empty list", opt.key.c_str()); return false; // no empty lists } opt.listDef = optTbl.GetString("def", opt.list[0].name); } else if (opt.type == "section") { opt.typeCode = opt_section; } else { logOutput.Print(logSubsystem, "parseOption: %s: unknown type %s", opt.key.c_str(), opt.type.c_str()); return false; // unknown type } optionsSet.insert(opt.key); return true; }
void CArchiveScanner::Scan(const string& curPath, bool checksum) { isDirty = true; std::vector<std::string> found = filesystem.FindFiles(curPath, "*", FileSystem::RECURSE | FileSystem::INCLUDE_DIRS); struct stat info; for (std::vector<std::string>::iterator it = found.begin(); it != found.end(); ++it) { stat(it->c_str(),&info); string fullName = *it; string fn = filesystem.GetFilename(fullName); string fpath = filesystem.GetDirectory(fullName); string lcfn = StringToLower(fn); string lcfpath = StringToLower(fpath); // Exclude archivefiles found inside directory (.sdd) archives. string::size_type sdd = lcfpath.find(".sdd"); if (sdd != string::npos) continue; // Is this an archive we should look into? if (CArchiveFactory::IsArchive(fullName)) { // Determine whether to rely on the cached info or not bool cached = false; map<string, ArchiveInfo>::iterator aii = archiveInfo.find(lcfn); if (aii != archiveInfo.end()) { // This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) continue; if (S_ISDIR(info.st_mode)) { struct stat info2; std::vector<std::string> sddfiles = filesystem.FindFiles(fpath, "*", FileSystem::RECURSE | FileSystem::INCLUDE_DIRS); for (std::vector<std::string>::iterator sddit = found.begin(); sddit != found.end(); ++sddit) { stat(sddit->c_str(), &info2); if (info.st_mtime < info2.st_mtime) { info.st_mtime = info2.st_mtime; } } } if (info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } // If we are here, we could have invalid info in the cache // Force a reread if it's a directory archive, as st_mtime only // reflects changes to the directory itself, not the contents. if (!cached) { archiveInfo.erase(aii); } } // Time to parse the info we are interested in if (!cached) { CArchiveBase* ar = CArchiveFactory::OpenArchive(fullName); if (ar) { int cur; string name; int size; ArchiveInfo ai; cur = ar->FindFiles(0, &name, &size); while (cur != 0) { //printf("found %s %d\n", name.c_str(), size); string ext = StringToLower(name.substr(name.find_last_of('.') + 1)); // only accept new format maps if (ext == "smf" || ext == "sm3") { MapData md; if (name.find_last_of('\\') == string::npos && name.find_last_of('/') == string::npos) { md.name = name; md.virtualPath = "/"; } else { if (name.find_last_of('\\') == string::npos) { md.name = name.substr(name.find_last_of('/') + 1); md.virtualPath = name.substr(0, name.find_last_of('/') + 1); // include the backslash } else { md.name = name.substr(name.find_last_of('\\') + 1); md.virtualPath = name.substr(0, name.find_last_of('\\') + 1); // include the backslash } //md.name = md.name.substr(0, md.name.find_last_of('.')); } ai.mapData.push_back(md); } if (name == "modinfo.tdf") { int fh = ar->OpenFile(name); if (fh) { int fsize = ar->FileSize(fh); void* buf = malloc(fsize); ar->ReadFile(fh, buf, fsize); ar->CloseFile(fh); try { TdfParser p( reinterpret_cast<char*>(buf), fsize ); ai.modData = GetModData(&p, "mod"); } catch (const TdfParser::parse_error& e) { // Silently ignore mods with parse errors } free(buf); } } cur = ar->FindFiles(cur, &name, &size); } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; delete ar; // Optionally calculate a checksum for the file // To prevent reading all files in all directory (.sdd) archives every time this function // is called, directory archive checksums are calculated on the fly. if (checksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } } else { // If cached is true, aii will point to the archive if ((checksum) && (aii->second.checksum == 0)) { aii->second.checksum = GetCRC(fullName); } } } } // Now we'll have to parse the replaces-stuff found in the mods for (map<string, ArchiveInfo>::iterator aii = archiveInfo.begin(); aii != archiveInfo.end(); ++aii) { for (vector<string>::iterator i = aii->second.modData.replaces.begin(); i != aii->second.modData.replaces.end(); ++i) { string lcname = StringToLower(*i); map<string, ArchiveInfo>::iterator ar = archiveInfo.find(lcname); // If it's not there, we will create a new entry if (ar == archiveInfo.end()) { ArchiveInfo tmp; archiveInfo[lcname] = tmp; ar = archiveInfo.find(lcname); } // Overwrite the info for this archive with a replaced pointer ar->second.path = ""; ar->second.origName = lcname; ar->second.modified = 1; ar->second.mapData.clear(); ar->second.modData.name = ""; ar->second.modData.replaces.clear(); ar->second.updated = true; ar->second.replaced = aii->first; } } }
void OovString::setLowerCase(OovStringRef const str) { *this = str; StringToLower(*this); }
unsigned int CArchive7Zip::GetCrc32 (const std::string& fileName) { std::string lower = StringToLower(fileName); FileData fd = fileData[lower]; return fd.crc; }
int main() { //mysql variables MYSQL mysql; MYSQL_RES *result; MYSQL_ROW row; string query; //initiate mysql if (!mysql_init(&mysql)) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } cout << "MySQL initialized." << endl; //connect to database if(!mysql_real_connect(&mysql, "assassins.myprotosite.com", "assassins", "password", "assassins", 0, NULL, 0)) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } cout << "Connected to database." << endl; while(true) { pop p(false); p.Connect(MAILHOST); p.Login(MAILUSER,MAILPASS); if(p.NumUnread() > 0) { p.Retrieve(); string from = p.GetFrom(); cout << "Message from: " << from << endl; string message_text = p.GetMessageText(); message_text = StringToLower(message_text); cout << "Message text: '" << message_text << "'" << endl; if(message_text.compare("verify") == 0) { //they are verifying their number //look up phone number in SQL table string phone_number = from.substr(0, 10); cout << "Phone number " << phone_number << " wants to verify. Finding user and updating." << endl; query = "UPDATE users SET mobile='" + from + "' WHERE mobile='" + phone_number + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } } if(message_text.compare("status") == 0) { //they want to know their current status string userid; query = "SELECT * FROM users WHERE mobile='" + from + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } result = mysql_store_result(&mysql); if(row = mysql_fetch_row(result)) { userid = row[USERID]; } mysql_free_result(result); notifyNewContract(userid, true); } if(message_text.length() >= 6) { if(message_text.substr(0, 6).compare("report") == 0) { if(message_text.length() >= 13) { //they want to report a kill string userid; string targetid; string targetsecret; string newtarget; string gameid; string secret = message_text.substr(7, 6); cout << "'" << secret << "'" << endl; query = "SELECT * FROM users WHERE mobile='" + from + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } result = mysql_store_result(&mysql); if(row = mysql_fetch_row(result)) { userid = row[USERID]; targetid = row[TARGETID]; gameid = row[GAMEID]; } mysql_free_result(result); query = "SELECT * FROM users WHERE userid='" + targetid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } result = mysql_store_result(&mysql); if(row = mysql_fetch_row(result)) { targetsecret = StringToLower(row[SECRET]); newtarget = row[TARGETID]; } mysql_free_result(result); if(targetsecret.compare(secret) == 0) { //secret is correct, kill confirmed query = "UPDATE users SET targetid='-1' WHERE userid='" + targetid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } query = "SELECT * FROM users WHERE targetid='-2';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } result = mysql_store_result(&mysql); if(row = mysql_fetch_row(result)) { //people are waiting for assignments string awaitingid = row[USERID]; query = "UPDATE users SET targetid='" + newtarget + "' WHERE userid='" + awaitingid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } notifyNewContract(awaitingid); query = "UPDATE users SET targetid='" + awaitingid + "' WHERE userid='" + userid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } } else { //no one's waiting for assignment if(newtarget.compare(userid) != 0) { query = "UPDATE users SET targetid='" + newtarget + "' WHERE userid='" + userid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } } else { //if the target's contract was you, you cannot kill yourself and progress through the game // therefore we must wait for the next kill. when this kill occurs, you will switch contracts // with the person that made the following kill. also, this bracket of code will only run if // there is already no one waiting for assignement, so we dont need to check for that. set target // to -2 to imply awaiting assignment query = "UPDATE users SET targetid='-2' WHERE userid='" + userid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } } } //text back telling kill was reported //mail(from, "Kill Reported."); //redundant. if the user is texting the daemon, phone is enabled, therefore // // phone will will receive new contract notice. //check to see if you're last man standing query = "SELECT * FROM users WHERE targetid<>-1 AND gameid='" + gameid + "';"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } result = mysql_store_result(&mysql); if(mysql_num_rows(result) == 1) { //you won query = "UPDATE users SET targetid='-3' WHERE userid='" + userid + "'"; if(mysql_query(&mysql, query.c_str())) { cout << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << endl; return -1; } } notifyNewContract(userid); notifyNewContract(targetid); } else { //secret not correct mail(from, "Secret was incorrrect."); } } } } p.Delete(); } p.Close(); sleep(5); } return 0; }
C3DOTextureHandler::C3DOTextureHandler() { CFileHandler teamTexFile("unittextures/tatex/teamtex.txt"); CFileHandler paletteFile("unittextures/tatex/palette.pal"); CSimpleParser parser(teamTexFile); std::set<std::string> teamTexes; while (!teamTexFile.Eof()) { teamTexes.insert(StringToLower(parser.GetCleanLine())); } TexFile* texfiles[10000]; int numfiles = 0; int totalSize = 0; const std::vector<std::string>& filesBMP = CFileHandler::FindFiles("unittextures/tatex/", "*.bmp"); std::vector<std::string> files = CFileHandler::FindFiles("unittextures/tatex/", "*.tga"); files.insert(files.end(), filesBMP.begin(), filesBMP.end()); std::set<string> usedNames; for (std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { std::string s = std::string(*fi); std::string s2 = s; s2.erase(0, s2.find_last_of('/') + 1); s2 = StringToLower(s2.substr(0, s2.find_last_of('.'))); // avoid duplicate names and give tga images priority if (usedNames.find(s2) != usedNames.end()) { continue; } usedNames.insert(s2); if(teamTexes.find(s2) == teamTexes.end()){ TexFile* tex = CreateTex(s, s2, false); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } else { TexFile* tex = CreateTex(s, s2, true); texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } } if (paletteFile.FileExists()) { palette.Init(paletteFile); } for (unsigned a = 0; a < CTAPalette::NUM_PALETTE_ENTRIES; ++a) { const std::string name = "ta_color" + IntToString(a, "%i"); TexFile* tex = new TexFile; tex->name = name; tex->tex.Alloc(1, 1); tex->tex.mem[0] = palette[a][0]; tex->tex.mem[1] = palette[a][1]; tex->tex.mem[2] = palette[a][2]; tex->tex.mem[3] = 0; // teamcolor tex->tex2.Alloc(1, 1); tex->tex2.mem[0] = 0; // self illum tex->tex2.mem[1] = 30; // reflectivity tex->tex2.mem[2] = 0; tex->tex2.mem[3] = 255; texfiles[numfiles++] = tex; totalSize += tex->tex.xsize * tex->tex.ysize; } // pessimistic guess about how much space will be wasted totalSize = (int)(totalSize * 1.2f); if (totalSize < 1024*1024) { bigTexX = 1024; bigTexY = 1024; } else if (totalSize < 1024*2048) { bigTexX = 1024; bigTexY = 2048; } else if (totalSize < 2048*2048) { bigTexX = 2048; bigTexY = 2048; } else { bigTexX = 2048; bigTexY = 2048; throw content_error("Too many/large texture in 3do texture-atlas to fit in 2048*2048"); } qsort(texfiles,numfiles,sizeof(TexFile*), CompareTatex2); unsigned char* bigtex1 = new unsigned char[bigTexX * bigTexY * 4]; unsigned char* bigtex2 = new unsigned char[bigTexX * bigTexY * 4]; for (int a = 0; a < (bigTexX * bigTexY); ++a) { bigtex1[a*4 + 0] = 128; bigtex1[a*4 + 1] = 128; bigtex1[a*4 + 2] = 128; bigtex1[a*4 + 3] = 0; bigtex2[a*4 + 0] = 0; bigtex2[a*4 + 1] = 128; bigtex2[a*4 + 2] = 0; bigtex2[a*4 + 3] = 255; } int cury = 0; int maxy = 0; int curx = 0; int foundx = 0; int foundy = 0; std::list<int2> nextSub; std::list<int2> thisSub; for (int a = 0; a < numfiles; ++a) { CBitmap* curtex1 = &texfiles[a]->tex; CBitmap* curtex2 = &texfiles[a]->tex2; bool done = false; while (!done) { // Find space for us if (thisSub.empty()) { if (nextSub.empty()) { cury = maxy; maxy += curtex1->ysize; if (maxy > bigTexY) { throw content_error("Too many/large texture in 3do texture-atlas to fit in 2048*2048"); break; } thisSub.push_back(int2(0, cury)); } else { thisSub = nextSub; nextSub.clear(); } } if (thisSub.front().x + curtex1->xsize>bigTexX) { thisSub.clear(); continue; } if(thisSub.front().y+curtex1->ysize>maxy){ thisSub.pop_front(); continue; } // ok found space for us foundx=thisSub.front().x; foundy=thisSub.front().y; done=true; if (thisSub.front().y + curtex1->ysize<maxy){ nextSub.push_back(int2(thisSub.front().x, thisSub.front().y + curtex1->ysize)); } thisSub.front().x += curtex1->xsize; while ((thisSub.size() > 1) && (thisSub.front().x >= (++thisSub.begin())->x)) { (++thisSub.begin())->x = thisSub.front().x; thisSub.erase(thisSub.begin()); } } for (int y = 0; y < curtex1->ysize; ++y) { for (int x = 0; x < curtex1->xsize; ++x) { // if(curtex1->mem[(y*curtex1->xsize+x)*4]==254 && curtex1->mem[(y*curtex1->xsize+x)*4+1]==0 && curtex1->mem[(y*curtex1->xsize+x)*4+2]==254){ // bigtex1[((cury+y)*bigTexX+(curx+x))*4+3] = 0; // } else { for (int col = 0; col < 4; ++col) { bigtex1[(((foundy + y) * bigTexX + (foundx + x)) * 4) + col] = curtex1->mem[(((y * curtex1->xsize) + x) * 4) + col]; bigtex2[(((foundy + y) * bigTexX + (foundx + x)) * 4) + col] = curtex2->mem[(((y * curtex1->xsize) + x) * 4) + col]; // } } } } UnitTexture* unittex = new UnitTexture; unittex->xstart = (foundx + 0.5f) / (float)bigTexX; unittex->ystart = (foundy + 0.5f) / (float)bigTexY; unittex->xend = (foundx + curtex1->xsize - 0.5f) / (float)bigTexX; unittex->yend = (foundy + curtex1->ysize - 0.5f) / (float)bigTexY; textures[texfiles[a]->name] = unittex; curx += curtex1->xsize; delete texfiles[a]; } glGenTextures(1, &atlas3do1); glBindTexture(GL_TEXTURE_2D, atlas3do1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex1); glGenTextures(1, &atlas3do2); glBindTexture(GL_TEXTURE_2D, atlas3do2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_NEAREST*/); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); //glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8, bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, bigtex2); // CBitmap save(tex, bigTexX, bigTexY); // save.Save("unittex-1x.jpg"); UnitTexture* t = new UnitTexture(); t->xstart = 0.0f; t->ystart = 0.0f; t->xend = 1.0f; t->yend = 1.0f; textures["___dummy___"] = t; delete[] bigtex1; delete[] bigtex2; }
bool CKeySet::Parse(const std::string& token) { Reset(); std::string s = StringToLower(token); // parse the modifiers while (!s.empty()) { if (ParseModifier(s, "up+", "u+")) { modifiers |= KS_RELEASE; } else if (ParseModifier(s, "any+", "*+")) { modifiers |= KS_ANYMOD; } else if (ParseModifier(s, "alt+", "a+")) { modifiers |= KS_ALT; } else if (ParseModifier(s, "ctrl+", "c+")) { modifiers |= KS_CTRL; } else if (ParseModifier(s, "meta+", "m+")) { modifiers |= KS_META; } else if (ParseModifier(s, "shift+", "s+")) { modifiers |= KS_SHIFT; } else { break; } } #ifdef DISALLOW_RELEASE_BINDINGS modifiers &= ~KS_RELEASE; #endif // remove ''s, if present if ((s.size() >= 2) && (s[0] == '\'') && (s[s.size() - 1] == '\'')) { s = s.substr(1, s.size() - 2); } if (s.find("0x") == 0) { const char* start = (s.c_str() + 2); char* end; key = strtol(start, &end, 16); if (end == start) { Reset(); LOG_L(L_ERROR, "KeySet: Bad hex value: %s", s.c_str()); return false; } if (key >= SDLK_LAST) { Reset(); LOG_L(L_ERROR, "KeySet: Hex value out of range: %s", s.c_str()); return false; } } else { key = keyCodes->GetCode(s); if (key < 0) { Reset(); LOG_L(L_ERROR, "KeySet: Bad keysym: %s", s.c_str()); return false; } } if (keyCodes->IsModifier(key)) { modifiers |= KS_ANYMOD; } if (AnyMod()) { ClearModifiers(); } return true; }
bool CRealTextParser::ExtractTag(wstring& p_rszLine, Tag& p_rTag) { if (p_rszLine.length() < 2 || p_rszLine.at(0) != '<') { if (m_bTryToIgnoreErrors) { size_t iTempPos = p_rszLine.find_first_of('<'); if (iTempPos != wstring::npos) { p_rszLine = p_rszLine.substr(iTempPos); if (p_rszLine.length() < 2) { return false; } } } else { return false; } } unsigned int iPos = 1; // skip comments if (p_rszLine.at(iPos) == '!') { p_rTag.m_bComment = true; wstring szComment; GetString(p_rszLine, iPos, szComment, L">"); p_rTag.m_szName = szComment; ++iPos; // Skip > p_rszLine = p_rszLine.substr(iPos); return true; } else { p_rTag.m_bComment = false; } if (!SkipSpaces(p_rszLine, iPos)) { return false; } if (p_rszLine.at(iPos) == '/') { p_rTag.m_bOpen = false; p_rTag.m_bClose = true; ++iPos; } else { p_rTag.m_bOpen = true; p_rTag.m_bClose = false; } if (!GetString(p_rszLine, iPos, p_rTag.m_szName, L"\r\n\t />")) { return false; } p_rTag.m_szName = StringToLower(p_rTag.m_szName); if (!GetAttributes(p_rszLine, iPos, p_rTag.m_mapAttributes)) { return false; } if (p_rszLine.at(iPos) == '/') { ++iPos; p_rTag.m_bClose = true; } if (p_rszLine.at(iPos) == '>') { ++iPos; p_rszLine = p_rszLine.substr(iPos); return true; } else { if (m_bTryToIgnoreErrors) { size_t iTempPos = p_rszLine.find_first_of('>'); if (iTempPos != wstring::npos) { if (iTempPos - 1 >= p_rszLine.length()) { return false; } p_rszLine = p_rszLine.substr(iTempPos + 1); return true; } else { return false; } } else { return false; } } }
/** Constructor **/ Symbol::Symbol(Type_T type, std::string id, std::shared_ptr<Token> value,std::shared_ptr<AsmBlock> block): Type(type), ID(StringToLower(id)), Value(value), Reserved(false), Block(block), Temporary(false) { //... }