bool CMouseCursor::BuildFromFileNames(const string& name, int lastFrame) { // find the image file type to use const char* ext = ""; const char* exts[] = { "png", "tga", "bmp" }; const int extCount = sizeof(exts) / sizeof(exts[0]); for (int e = 0; e < extCount; e++) { ext = exts[e]; std::ostringstream namebuf; namebuf << "anims/" << name << "_0." << ext; CFileHandler* f = new CFileHandler(namebuf.str()); if (f->FileExists()) { delete f; break; } delete f; } while (int(frames.size()) < lastFrame) { std::ostringstream namebuf; namebuf << "anims/" << name << "_" << frames.size() << "." << ext; ImageData image; if (!LoadCursorImage(namebuf.str(), image)) break; images.push_back(image); FrameData frame(image, defFrameLength); frames.push_back(frame); } hwCursor->Finish(); return true; }
/** Called by the map-selecting CglList. */ void CPreGame::SelectMap(std::string s) { if (s == "Random map") { s = pregame->showList->items[1 + gu->usRandInt() % (pregame->showList->items.size() - 1)]; } stupidGlobalMapname = pregame->mapName = s; delete pregame->showList; pregame->showList = 0; logOutput << "Map: " << s.c_str() << "\n"; // Determine if the map is inside an archive, and possibly map needed archives CFileHandler* f = SAFE_NEW CFileHandler("maps/" + s); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(s); if (ars.empty()) throw content_error("Couldn't find any archives for map '" + s + "'."); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { if (!hpiHandler->AddArchive(*i, false)) throw content_error("Couldn't load archive '" + *i + "' for map '" + s + "'."); } } delete f; if (net && net->GetDemoRecorder()) net->GetDemoRecorder()->SetName(s); }
int CAICallback::GetFileSize (const char *name) { CFileHandler fh (name); if (!fh.FileExists ()) return -1; return fh.FileSize(); }
int CAICallback::GetFileSize (const char *filename, const char* modes) { CFileHandler fh (filename, modes); if (!fh.FileExists ()) return -1; return fh.FileSize(); }
bool CAICallback::ReadFile (const char *name, void *buffer, int bufferLength) { CFileHandler fh (name); int fs; if (!fh.FileExists() || bufferLength < (fs = fh.FileSize())) return false; fh.Read (buffer, fs); return true; }
int CArchiveDir::OpenFile(const std::string& fileName) { CFileHandler* f = SAFE_NEW CFileHandler(archiveName + lcNameToOrigName[StringToLower(fileName)]); if (!f || !f->FileExists()) return 0; ++curFileHandle; fileHandles[curFileHandle] = f; return curFileHandle; }
bool CMouseCursor::LoadCursorImage(const string& name, ImageData& image) { CFileHandler* f = new CFileHandler(name); if (!f->FileExists()) { return false; } CBitmap b; if (!b.Load(name)) { logOutput.Print("CMouseCursor: Bad image file: %s", name.c_str()); return false; } b.ReverseYAxis(); CBitmap* final = getAlignedBitmap(b); // coded bmp transparency mask if ((name.size() >= 3) && (StringToLower(name.substr(name.size() - 3)) == "bmp")) { setBitmapTransparency(*final, 84, 84, 252); }
void CPreGame::LoadMap(const std::string& mapName, const bool forceReload) { static bool alreadyLoaded = false; if (!alreadyLoaded || forceReload) { CFileHandler* f = new CFileHandler("maps/" + mapName); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(mapName); if (ars.empty()) { throw content_error("Couldn't find any archives for map '" + mapName + "'."); } for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { if (!vfsHandler->AddArchive(*i, false)) { throw content_error("Couldn't load archive '" + *i + "' for map '" + mapName + "'."); } } } delete f; alreadyLoaded = true; } }
bool CMouseCursor::BuildFromFileNames(const string& name, int lastFrame) { char namebuf[128]; if (name.size() > (sizeof(namebuf) - 20)) { logOutput.Print("CMouseCursor: Long name %s", name.c_str()); return false; } // find the image file type to use const char* ext = ""; const char* exts[] = { "png", "tga", "bmp" }; const int extCount = sizeof(exts) / sizeof(exts[0]); for (int e = 0; e < extCount; e++) { ext = exts[e]; SNPRINTF(namebuf, sizeof(namebuf), "anims/%s_%d.%s", name.c_str(), 0, ext); CFileHandler* f = new CFileHandler(namebuf); if (f->FileExists()) { delete f; break; } delete f; } while (frames.size() < lastFrame) { SNPRINTF(namebuf, sizeof(namebuf), "anims/%s_%d.%s", name.c_str(), frames.size(), ext); ImageData image; if (!LoadCursorImage(namebuf, image)) { break; } images.push_back(image); FrameData frame(image, defFrameLength); frames.push_back(frame); } return true; }
bool CPreGame::Update(void) { if(waitOnAddress && !userWriting){ waitOnAddress=false; if (saveAddress) configHandler.SetString("address",userInput); if(net->InitClient(userInput.c_str(),8452,0)==-1){ info->AddLine("Client couldnt connect"); return false; } userWriting=false; } if(!server && !waitOnAddress){ net->Update(); UpdateClientNet(); } if(waitOnScript && !showList){ waitOnScript=false; mapName=CScriptHandler::Instance().chosenScript->GetMapName(); if(mapName==""){ ShowMapList(); waitOnMap=true; } else { allReady=true; } } if(allReady){ ENTER_MIXED; // Map all required archives depending on selected mod(s) stupidGlobalModName = MOD_FILE; if (gameSetup) stupidGlobalModName = gameSetup->baseMod; vector<string> ars = archiveScanner->GetArchives(stupidGlobalModName); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { hpiHandler->AddArchive(*i, false); } // Determine if the map is inside an archive, and possibly map needed archives CFileHandler* f = new CFileHandler("maps/" + mapName); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(mapName); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { hpiHandler->AddArchive(*i, false); } } delete f; LoadStartPicture(); game=new CGame(server,mapName); ENTER_UNSYNCED; game->Update(); pregame=0; delete this; return true; } return true; }
bool CGameSetup::Init(char* buf, int size) { for(int a=0;a<MAX_PLAYERS;a++){ gs->players[a]->team=0; //needed in case one tries to spec a game with only one team } gameSetupText=SAFE_NEW char[size]; memcpy(gameSetupText,buf,size); gameSetupTextLength=size; file.LoadBuffer(buf,size); if(!file.SectionExist("GAME")) return false; mapname=file.SGetValueDef("","GAME\\mapname"); scriptName=file.SGetValueDef("Commanders","GAME\\scriptname"); baseMod=archiveScanner->ModArchiveToModName(file.SGetValueDef(MOD_FILE,"GAME\\Gametype")); file.GetDef(hostip,"0","GAME\\HostIP"); file.GetDef(hostport,"0","GAME\\HostPort"); file.GetDef(maxUnits,"500","GAME\\MaxUnits"); file.GetDef(gs->gameMode,"0","GAME\\GameMode"); file.GetDef(sourceport,"0","GAME\\SourcePort"); file.GetDef(limitDgun,"0","GAME\\LimitDgun"); file.GetDef(diminishingMMs,"0","GAME\\DiminishingMMs"); file.GetDef(disableMapDamage,"0","GAME\\DisableMapDamage"); demoName=file.SGetValueDef("","GAME\\Demofile"); if(!demoName.empty()) hostDemo=true; file.GetDef(ghostedBuildings,"1","GAME\\GhostedBuildings"); file.GetDef(maxSpeed, "3", "GAME\\MaxSpeed"); file.GetDef(minSpeed, "0.3", "GAME\\MinSpeed"); // Determine if the map is inside an archive, and possibly map needed archives CFileHandler* f = SAFE_NEW CFileHandler("maps/" + mapname); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(mapname); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { if (!hpiHandler->AddArchive(*i, false)) logOutput.Print("Warning: Couldn't load archive '%s'.", i->c_str()); } } delete f; file.GetDef(myPlayer,"0","GAME\\MyPlayerNum"); gu->myPlayerNum=myPlayer; file.GetDef(numPlayers,"2","GAME\\NumPlayers"); file.GetDef(gs->activeTeams,"2","GAME\\NumTeams"); file.GetDef(gs->activeAllyTeams,"2","GAME\\NumAllyTeams"); file.GetDef(startPosType,"0","GAME\\StartPosType"); if(startPosType==2){ for(int a=0;a<gs->activeTeams;++a) readyTeams[a]=false; for(int a=0;a<gs->activeTeams;++a) teamStartNum[a]=a; SAFE_NEW CStartPosSelecter(); } else { for(int a=0;a<gs->activeTeams;++a) readyTeams[a]=true; if(startPosType==0){ //in order for(int a=0;a<gs->activeTeams;++a) teamStartNum[a]=a; } else { //random order std::multimap<int,int> startNums; for(int a=0;a<gs->activeTeams;++a) startNums.insert(pair<int,int>(gu->usRandInt(),a)); //server syncs these later int b=0; for(std::multimap<int,int>::iterator si=startNums.begin();si!=startNums.end();++si){ teamStartNum[si->second]=b; ++b; } } } for(int a=0;a<numPlayers;++a){ char section[50]; sprintf(section,"GAME\\PLAYER%i\\",a); string s(section); gs->players[a]->team=atoi(file.SGetValueDef("0",s+"team").c_str()); gs->players[a]->spectator=!!atoi(file.SGetValueDef("0",s+"spectator").c_str()); gs->players[a]->playerName=file.SGetValueDef("0",s+"name"); int fromDemo; file.GetDef(fromDemo,"0",s+"IsFromDemo"); if(fromDemo) numDemoPlayers++; } gu->spectating = gs->players[myPlayer]->spectator; gu->spectatingFullView = gu->spectating; TdfParser p2; CReadMap::OpenTDF (mapname, p2); for(int a=0;a<gs->activeTeams;++a){ char section[50]; sprintf(section,"GAME\\TEAM%i\\",a); string s(section); int colorNum=atoi(file.SGetValueDef("0",s+"color").c_str()); colorNum%=palette.NumTeamColors(); float3 defaultCol(palette.teamColor[colorNum][0]/255.0f,palette.teamColor[colorNum][1]/255.0f,palette.teamColor[colorNum][2]/255.0f); float3 color=file.GetFloat3(defaultCol,s+"rgbcolor"); for(int b=0;b<3;++b) gs->Team(a)->color[b]=int(color[b]*255); gs->Team(a)->color[3]=255; gs->Team(a)->handicap=atof(file.SGetValueDef("0",s+"handicap").c_str())/100+1; gs->Team(a)->leader=atoi(file.SGetValueDef("0",s+"teamleader").c_str()); gs->Team(a)->side = StringToLower(file.SGetValueDef("arm",s+"side").c_str()); gs->SetAllyTeam(a, atoi(file.SGetValueDef("0",s+"allyteam").c_str())); if (demoName.empty()) aiDlls[a]=file.SGetValueDef("",s+"aidll"); else aiDlls[a]=""; float x,z; char teamName[50]; sprintf(teamName,"TEAM%i",teamStartNum[a]); p2.GetDef(x,"1000",string("MAP\\")+teamName+"\\StartPosX"); p2.GetDef(z,"1000",string("MAP\\")+teamName+"\\StartPosZ"); gs->Team(a)->startPos=float3(x,100,z); if(startPosType==2) gs->Team(a)->startPos.y=-500; //show that we havent selected start pos yet } gu->myTeam=gs->players[myPlayer]->team; gu->myAllyTeam=gs->AllyTeam(gu->myTeam); for(int a=0;a<gs->activeAllyTeams;++a){ char section[50]; sprintf(section,"GAME\\ALLYTEAM%i\\",a); string s(section); startRectTop[a]=atof(file.SGetValueDef("0",s+"StartRectTop").c_str()); startRectBottom[a]=atof(file.SGetValueDef("1",s+"StartRectBottom").c_str()); startRectLeft[a]=atof(file.SGetValueDef("0",s+"StartRectLeft").c_str()); startRectRight[a]=atof(file.SGetValueDef("1",s+"StartRectRight").c_str()); int numAllies=atoi(file.SGetValueDef("0",s+"NumAllies").c_str()); for(int b=0;b<numAllies;++b){ char key[100]; sprintf(key,"GAME\\ALLYTEAM%i\\Ally%i",a,b); int other=atoi(file.SGetValueDef("0",key).c_str()); gs->SetAlly(a,other, true); } } if(startPosType==2){ for(int a=0;a<gs->activeTeams;++a) gs->Team(a)->startPos=float3(startRectLeft[gs->AllyTeam(a)]*gs->mapx*8,-500,startRectTop[gs->AllyTeam(a)]*gs->mapy*8); } int metal,energy; file.GetDef(metal,"1000","GAME\\StartMetal"); file.GetDef(energy,"1000","GAME\\StartEnergy"); for(int a=0;a<gs->activeTeams;++a){ gs->Team(a)->metal=metal; gs->Team(a)->metalIncome=metal; //for the endgame statistics gs->Team(a)->metalStorage=metal; gs->Team(a)->energy=energy; gs->Team(a)->energyIncome=energy; gs->Team(a)->energyStorage=energy; } // Read the unit restrictions int numRestrictions; file.GetDef(numRestrictions, "0", "GAME\\NumRestrictions"); for (int i = 0; i < numRestrictions; ++i) { char key[100]; sprintf(key, "GAME\\RESTRICT\\Unit%d", i); string resName = file.SGetValueDef("", key); sprintf(key, "GAME\\RESTRICT\\Limit%d", i); int resLimit; file.GetDef(resLimit, "0", key); restrictedUnits[resName] = resLimit; } return true; }
bool CPreGame::Update() { assert(good_fpu_control_registers("CPreGame::Update")); switch (state) { case UNKNOWN: logOutput.Print("Internal error in CPreGame"); return false; case WAIT_ON_ADDRESS: if (userWriting) break; if (saveAddress) configHandler.SetString("address",userInput); if(net->InitClient(userInput.c_str(),8452,0)==-1){ logOutput.Print("Client couldn't connect"); return false; } // State is never WAIT_ON_ADDRESS if gameSetup was true in our constructor, // so if it's true here, it means net->InitClient() just loaded a demo // with gameSetup. // If so, don't wait indefinitely on a script/map/mod name, but load // everything from gameSetup and switch to ALL_READY state. if(gameSetup) { CScriptHandler::SelectScript("Commanders"); SelectMap(gameSetup->mapname); SelectMod(gameSetup->baseMod); state = ALL_READY; break; } else { state = WAIT_ON_SCRIPT; // fall trough } case WAIT_ON_SCRIPT: if (showList || !server) break; mapName = CScriptHandler::Instance().chosenScript->GetMapName(); if (mapName == "") ShowMapList(); state = WAIT_ON_MAP; // fall through case WAIT_ON_MAP: if (showList || !server) break; modName = CScriptHandler::Instance().chosenScript->GetModName(); if (modName == "") ShowModList(); state = WAIT_ON_MOD; // fall through case WAIT_ON_MOD: if (showList || !server) break; state = ALL_READY; // fall through case ALL_READY: ENTER_MIXED; // Map all required archives depending on selected mod(s) vector<string> ars = archiveScanner->GetArchives(modName); if (ars.empty()) logOutput.Print("Warning: mod archive \"%s\" is missing?\n", modName.c_str()); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) if (!hpiHandler->AddArchive(*i, false)) logOutput.Print("Warning: Couldn't load archive '%s'.", i->c_str()); // Determine if the map is inside an archive, and possibly map needed archives CFileHandler* f = SAFE_NEW CFileHandler("maps/" + mapName); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(mapName); if (ars.empty()) logOutput.Print("Warning: map archive \"%s\" is missing?\n", mapName.c_str()); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { if (!hpiHandler->AddArchive(*i, false)) logOutput.Print("Warning: Couldn't load archive '%s'.", i->c_str()); } } delete f; // always load springcontent.sdz hpiHandler->AddArchive("base/springcontent.sdz", false); LoadStartPicture(); game = SAFE_NEW CGame(server, mapName, modName, infoConsole); infoConsole = 0; ENTER_UNSYNCED; pregame=0; delete this; return true; } if(!server && state != WAIT_ON_ADDRESS){ net->Update(); UpdateClientNet(); } return true; }
int main(int argc, char *argv[]) { #ifdef _WIN32 try { #endif std::cout << "If you find any errors, report them to mantis or the forums." << std::endl << std::endl; ConfigHandler::Instantiate(""); FileSystemHandler::Cleanup(); FileSystemHandler::Initialize(false); CGameServer* server = 0; CGameSetup* gameSetup = 0; if (argc > 1) { const std::string script(argv[1]); std::cout << "Loading script from file: " << script << std::endl; ClientSetup settings; CFileHandler fh(argv[1]); if (!fh.FileExists()) throw content_error("Setupscript doesn't exists in given location: "+script); std::string buf; if (!fh.LoadStringData(buf)) throw content_error("Setupscript cannot be read: "+script); settings.Init(buf); gameSetup = new CGameSetup(); // to store the gamedata inside if (!gameSetup->Init(buf)) // read the script provided by cmdline { std::cout << "Failed to load script" << std::endl; return 1; } std::cout << "Starting server..." << std::endl; // Create the server, it will run in a separate thread GameData* data = new GameData(); UnsyncedRNG rng; rng.Seed(gameSetup->gameSetupText.length()); rng.Seed(script.length()); data->SetRandomSeed(rng.RandInt()); // Use script provided hashes if they exist if (gameSetup->mapHash != 0) { data->SetMapChecksum(gameSetup->mapHash); gameSetup->LoadStartPositions(false); // reduced mode } else { data->SetMapChecksum(archiveScanner->GetMapChecksum(gameSetup->mapName)); CFileHandler* f = new CFileHandler("maps/" + gameSetup->mapName); if (!f->FileExists()) { std::vector<std::string> ars = archiveScanner->GetArchivesForMap(gameSetup->mapName); if (ars.empty()) { throw content_error("Couldn't find any archives for map '" + gameSetup->mapName + "'."); } for (std::vector<std::string>::iterator i = ars.begin(); i != ars.end(); ++i) { if (!vfsHandler->AddArchive(*i, false)) { throw content_error("Couldn't load archive '" + *i + "' for map '" + gameSetup->mapName + "'."); } } } delete f; gameSetup->LoadStartPositions(); // full mode } if (gameSetup->modHash != 0) { data->SetModChecksum(gameSetup->modHash); } else { const std::string modArchive = archiveScanner->ModNameToModArchive(gameSetup->modName); data->SetModChecksum(archiveScanner->GetModChecksum(modArchive)); } data->SetSetup(gameSetup->gameSetupText); server = new CGameServer(&settings, false, data, gameSetup); while (!server->HasFinished()) // check if still running #ifdef _WIN32 Sleep(1000); #else sleep(1); // if so, wait 1 second #endif delete server; // delete the server after usage } else { std::cout << "usage: spring-dedicated <full_path_to_script>" << std::endl; } FileSystemHandler::Cleanup(); #ifdef _WIN32 } catch (const std::exception& err) { std::cout << "Exception raised: " << err.what() << std::endl; return 1; } #endif return 0; }
CglFont::CglFont(const std::string& fontfile, int size, int _outlinewidth, float _outlineweight): fontSize(size), fontPath(fontfile), outlineWidth(_outlinewidth), outlineWeight(_outlineweight), inBeginEnd(false) { if (size<=0) size = 14; const float invSize = 1.0f / size; const float normScale = invSize / 64.0f; FT_Library library; FT_Face face; //! initialize Freetype2 library FT_Error error = FT_Init_FreeType(&library); if (error) { string msg = "FT_Init_FreeType failed:"; msg += GetFTError(error); throw std::runtime_error(msg); } //! load font via VFS CFileHandler* f = new CFileHandler(fontPath); if (!f->FileExists()) { //! check in 'fonts/', too if (fontPath.substr(0, 6) != "fonts/") { delete f; fontPath = "fonts/" + fontPath; f = new CFileHandler(fontPath); } if (!f->FileExists()) { delete f; FT_Done_FreeType(library); throw content_error("Couldn't find font '" + fontfile + "'."); } } int filesize = f->FileSize(); FT_Byte* buf = new FT_Byte[filesize]; f->Read(buf,filesize); delete f; //! create face error = FT_New_Memory_Face(library, buf, filesize, 0, &face); if (error) { FT_Done_FreeType(library); delete[] buf; string msg = fontfile + ": FT_New_Face failed: "; msg += GetFTError(error); throw content_error(msg); } //! set render size error = FT_Set_Pixel_Sizes(face, 0, size); if (error) { FT_Done_Face(face); FT_Done_FreeType(library); delete[] buf; string msg = fontfile + ": FT_Set_Pixel_Sizes failed: "; msg += GetFTError(error); throw content_error(msg); } //! setup character range charstart = 32; charend = 254; //! char 255 = colorcode chars = (charend - charstart) + 1; //! get font information fontFamily = face->family_name; fontStyle = face->style_name; //! font's descender & height (in pixels) fontDescender = normScale * FT_MulFix(face->descender, face->size->metrics.y_scale); //lineHeight = invSize * (FT_MulFix(face->height, face->size->metrics.y_scale) / 64.0f); //lineHeight = invSize * math::ceil(FT_MulFix(face->height, face->size->metrics.y_scale) / 64.0f); lineHeight = face->height / face->units_per_EM; //lineHeight = invSize * face->size->metrics.height / 64.0f; if (lineHeight<=0.0f) { lineHeight = 1.25 * invSize * (face->bbox.yMax - face->bbox.yMin); } //! used to create the glyph textureatlas CFontTextureRenderer texRenderer(outlineWidth, outlineWeight); for (unsigned int i = charstart; i <= charend; i++) { GlyphInfo* g = &glyphs[i]; //! translate WinLatin (codepage-1252) to Unicode (used by freetype) int unicode = WinLatinToUnicode(i); //! convert to an anti-aliased bitmap error = FT_Load_Char(face, unicode, FT_LOAD_RENDER); if ( error ) { continue; } FT_GlyphSlot slot = face->glyph; //! Keep sign! const float ybearing = slot->metrics.horiBearingY * normScale; const float xbearing = slot->metrics.horiBearingX * normScale; g->advance = slot->advance.x * normScale; g->height = slot->metrics.height * normScale; g->descender = ybearing - g->height; g->x0 = xbearing; g->y0 = ybearing - fontDescender; g->x1 = (xbearing + slot->metrics.width * normScale); g->y1 = g->y0 - g->height; texRenderer.AddGlyph(i, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.buffer, slot->bitmap.pitch); } //! create font atlas texture fontTexture = texRenderer.CreateTexture(); texWidth = texRenderer.texWidth; texHeight = texRenderer.texHeight; //! get glyph's uv coords in the atlas for (unsigned int i = charstart; i <= charend; i++) { texRenderer.GetGlyph(i,&glyphs[i]); } //! generate kerning tables for (unsigned int i = charstart; i <= charend; i++) { GlyphInfo& g = glyphs[i]; int unicode = WinLatinToUnicode(i); FT_UInt left_glyph = FT_Get_Char_Index(face, unicode); for (unsigned int j = 0; j <= 255; j++) { unicode = WinLatinToUnicode(j); FT_UInt right_glyph = FT_Get_Char_Index(face, unicode); FT_Vector kerning; kerning.x = kerning.y = 0.0f; FT_Get_Kerning(face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerning); g.kerning[j] = g.advance + normScale * static_cast<float>(kerning.x); } } //! initialize null char GlyphInfo& g = glyphs[0]; g.height = g.descender = g.advance = 0.0f; for (unsigned int j = 0; j <= 255; j++) { g.kerning[j] = 0.0f; } FT_Done_Face(face); FT_Done_FreeType(library); delete[] buf; textColor = white; outlineColor = darkOutline; }
bool CGameSetup::Init(char* buf, int size) { for(int a=0;a<gs->activePlayers;a++){ gs->players[a]->team=0; //needed in case one tries to spec a game with only one team } palette.Init(); gameSetupText=new char[size]; memcpy(gameSetupText,buf,size); gameSetupTextLength=size; file=new CSunParser; file->LoadBuffer(buf,size); if(!file->SectionExist("GAME")) return false; mapname=file->SGetValueDef("","GAME\\mapname"); baseMod=file->SGetValueDef("xta_se_060.sdz","GAME\\Gametype"); file->GetDef(hostip,"0","GAME\\HostIP"); file->GetDef(hostport,"0","GAME\\HostPort"); file->GetDef(maxUnits,"500","GAME\\MaxUnits"); file->GetDef(gs->gameMode,"0","GAME\\GameMode"); file->GetDef(sourceport,"0","GAME\\SourcePort"); file->GetDef(limitDgun,"0","GAME\\LimitDgun"); file->GetDef(diminishingMMs,"0","GAME\\DiminishingMMs"); demoName=file->SGetValueDef("","GAME\\Demofile"); // Determine if the map is inside an archive, and possibly map needed archives CFileHandler* f = new CFileHandler("maps\\" + mapname); if (!f->FileExists()) { vector<string> ars = archiveScanner->GetArchivesForMap(mapname); for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) { hpiHandler->AddArchive(*i, false); } } delete f; file->GetDef(myPlayer,"0","GAME\\MyPlayerNum"); gu->myPlayerNum=myPlayer; file->GetDef(numPlayers,"2","GAME\\NumPlayers"); gs->activePlayers=numPlayers; file->GetDef(gs->activeTeams,"2","GAME\\NumTeams"); file->GetDef(gs->activeAllyTeams,"2","GAME\\NumAllyTeams"); file->GetDef(startPosType,"0","GAME\\StartPosType"); if(startPosType==2){ for(int a=0;a<gs->activeTeams;++a) readyTeams[a]=false; for(int a=0;a<gs->activeTeams;++a) teamStartNum[a]=a; new CStartPosSelecter(); } else { for(int a=0;a<gs->activeTeams;++a) readyTeams[a]=true; if(startPosType==0){ //in order for(int a=0;a<gs->activeTeams;++a) teamStartNum[a]=a; } else { //random order std::multimap<int,int> startNums; for(int a=0;a<gs->activeTeams;++a) startNums.insert(pair<int,int>(gu->usRandInt(),a)); //server syncs these later int b=0; for(std::multimap<int,int>::iterator si=startNums.begin();si!=startNums.end();++si){ teamStartNum[si->second]=b; ++b; } } } for(int a=0;a<numPlayers;++a){ char section[50]; sprintf(section,"GAME\\PLAYER%i\\",a); string s(section); gs->players[a]->team=atoi(file->SGetValueDef("0",s+"team").c_str()); gs->players[a]->spectator=!!atoi(file->SGetValueDef("0",s+"spectator").c_str()); gs->players[a]->playerName=file->SGetValueDef("0",s+"name"); int fromDemo; file->GetDef(fromDemo,"0",s+"IsFromDemo"); if(fromDemo) numDemoPlayers++; } if(!demoName.empty() && myPlayer==numDemoPlayers){ hostDemo=true; } gu->spectating=gs->players[myPlayer]->spectator; CSunParser p2; p2.LoadFile(string("maps\\")+mapname.substr(0,mapname.find_last_of('.'))+".smd"); for(int a=0;a<gs->activeTeams;++a){ char section[50]; sprintf(section,"GAME\\TEAM%i\\",a); string s(section); gs->teams[a]->colorNum=atoi(file->SGetValueDef("0",s+"color").c_str()); for(int b=0;b<4;++b) gs->teams[a]->color[b]=palette.teamColor[gs->teams[a]->colorNum][b]; gs->teams[a]->handicap=atof(file->SGetValueDef("0",s+"handicap").c_str())/100+1; gs->teams[a]->leader=atoi(file->SGetValueDef("0",s+"teamleader").c_str()); gs->teams[a]->side=file->SGetValueDef("arm",s+"side").c_str(); std::transform(gs->teams[a]->side.begin(), gs->teams[a]->side.end(), gs->teams[a]->side.begin(), (int (*)(int))std::tolower); gs->team2allyteam[a]=atoi(file->SGetValueDef("0",s+"allyteam").c_str()); aiDlls[a]=file->SGetValueDef("",s+"aidll"); float x,z; char teamName[50]; sprintf(teamName,"TEAM%i",teamStartNum[a]); p2.GetDef(x,"1000",string("MAP\\")+teamName+"\\StartPosX"); p2.GetDef(z,"1000",string("MAP\\")+teamName+"\\StartPosZ"); gs->teams[a]->startPos=float3(x,100,z); if(startPosType==2) gs->teams[a]->startPos.y=-500; //show that we havent selected start pos yet } gu->myTeam=gs->players[myPlayer]->team; gu->myAllyTeam=gs->team2allyteam[gu->myTeam]; for(int a=0;a<gs->activeAllyTeams;++a){ char section[50]; sprintf(section,"GAME\\ALLYTEAM%i\\",a); string s(section); startRectTop[a]=atof(file->SGetValueDef("0",s+"StartRectTop").c_str()); startRectBottom[a]=atof(file->SGetValueDef("1",s+"StartRectBottom").c_str()); startRectLeft[a]=atof(file->SGetValueDef("0",s+"StartRectLeft").c_str()); startRectRight[a]=atof(file->SGetValueDef("1",s+"StartRectRight").c_str()); int numAllies=atoi(file->SGetValueDef("0",s+"NumAllies").c_str()); for(int b=0;b<numAllies;++b){ char key[100]; sprintf(key,"GAME\\ALLYTEAM%i\\Ally%i",a,b); int other=atoi(file->SGetValueDef("0",key).c_str()); gs->allies[a][other]=true; } } int metal,energy; file->GetDef(metal,"1000","GAME\\StartMetal"); file->GetDef(energy,"1000","GAME\\StartEnergy"); for(int a=0;a<gs->activeTeams;++a){ gs->teams[a]->metal=metal; gs->teams[a]->metalStorage=metal; gs->teams[a]->energy=energy; gs->teams[a]->energyStorage=energy; } // Read the unit restrictions int numRestrictions; file->GetDef(numRestrictions, "0", "GAME\\NumRestrictions"); for (int i = 0; i < numRestrictions; ++i) { char key[100]; sprintf(key, "GAME\\RESTRICT\\Unit%d", i); string resName = file->SGetValueDef("", key); sprintf(key, "GAME\\RESTRICT\\Limit%d", i); int resLimit; file->GetDef(resLimit, "0", key); restrictedUnits[resName] = resLimit; } return true; }
S3DModel* CAssParser::Load(const std::string& modelFilePath) { logOutput.Print (LOG_MODEL, "Loading model: %s\n", modelFilePath.c_str() ); std::string modelPath = modelFilePath.substr(0, modelFilePath.find_last_of('/')); std::string modelFileNameNoPath = modelFilePath.substr(modelPath.length()+1, modelFilePath.length()); std::string modelName = modelFileNameNoPath.substr(0, modelFileNameNoPath.find_last_of('.')); std::string modelExt = modelFileNameNoPath.substr(modelFileNameNoPath.find_last_of('.'), modelFilePath.length()); //! LOAD METADATA //! Load the lua metafile. This contains properties unique to Spring models and must return a table std::string metaFileName = modelFilePath + ".lua"; CFileHandler* metaFile = new CFileHandler(metaFileName); if (!metaFile->FileExists()) { //! Try again without the model file extension metaFileName = modelPath + '/' + modelName + ".lua"; metaFile = new CFileHandler(metaFileName); } LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP); if (!metaFileParser.Execute()) { if (!metaFile->FileExists()) { logOutput.Print(LOG_MODEL, "No meta-file '%s'. Using defaults.", metaFileName.c_str()); } else { logOutput.Print(LOG_MODEL, "ERROR in '%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str()); } } //! Get the (root-level) model table const LuaTable& metaTable = metaFileParser.GetRoot(); if (metaTable.IsValid()) logOutput.Print(LOG_MODEL, "Found valid model metadata in '%s'", metaFileName.c_str()); //! LOAD MODEL DATA //! Create a model importer instance Assimp::Importer importer; //! Create a logger for debugging model loading issues Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE); const unsigned int severity = Assimp::Logger::Debugging|Assimp::Logger::Info|Assimp::Logger::Err|Assimp::Logger::Warn; Assimp::DefaultLogger::get()->attachStream( new AssLogStream(), severity ); //! Give the importer an IO class that handles Spring's VFS importer.SetIOHandler( new AssVFSSystem() ); //! Speed-up processing by skipping things we don't need importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_CAMERAS|aiComponent_LIGHTS|aiComponent_TEXTURES|aiComponent_ANIMATIONS); #ifndef BITMAP_NO_OPENGL //! Optimize VBO-Mesh sizes/ranges GLint maxIndices = 1024; GLint maxVertices = 1024; glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxIndices); glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxVertices); //FIXME returns not optimal data, at best compute it ourself! (pre-TL cache size!) importer.SetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT, maxVertices); importer.SetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT, maxIndices/3); #endif //! Read the model file to build a scene object logOutput.Print(LOG_MODEL, "Importing model file: %s\n", modelFilePath.c_str() ); const aiScene* scene = importer.ReadFile( modelFilePath, ASS_POSTPROCESS_OPTIONS ); if (scene != NULL) { logOutput.Print(LOG_MODEL, "Processing scene for model: %s (%d meshes / %d materials / %d textures)", modelFilePath.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumTextures ); } else { logOutput.Print (LOG_MODEL, "Model Import Error: %s\n", importer.GetErrorString()); } SAssModel* model = new SAssModel; model->name = modelFilePath; model->type = MODELTYPE_ASS; model->scene = scene; //model->meta = &metaTable; //! Gather per mesh info CalculatePerMeshMinMax(model); //! Assign textures //! The S3O texture handler uses two textures. //! The first contains diffuse color (RGB) and teamcolor (A) //! The second contains glow (R), reflectivity (G) and 1-bit Alpha (A). if (metaTable.KeyExists("tex1")) { model->tex1 = metaTable.GetString("tex1", "default.png"); } else { //! Search for a texture std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + ".*"); for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { std::string texPath = std::string(*fi); model->tex1 = texPath.substr(texPath.find('/')+1, texPath.length()); break; //! there can be only one! } } if (metaTable.KeyExists("tex2")) { model->tex2 = metaTable.GetString("tex2", ""); } else { //! Search for a texture std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + "2.*"); for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) { std::string texPath = std::string(*fi); model->tex2 = texPath.substr(texPath.find('/')+1, texPath.length()); break; //! there can be only one! } } model->flipTexY = metaTable.GetBool("fliptextures", true); //! Flip texture upside down model->invertTexAlpha = metaTable.GetBool("invertteamcolor", true); //! Reverse teamcolor levels //! Load textures logOutput.Print(LOG_MODEL, "Loading textures. Tex1: '%s' Tex2: '%s'", model->tex1.c_str(), model->tex2.c_str()); texturehandlerS3O->LoadS3OTexture(model); //! Load all pieces in the model logOutput.Print(LOG_MODEL, "Loading pieces from root node '%s'", scene->mRootNode->mName.data); LoadPiece(model, scene->mRootNode, metaTable); //! Update piece hierarchy based on metadata BuildPieceHierarchy( model ); //! Simplified dimensions used for rough calculations model->radius = metaTable.GetFloat("radius", model->radius); model->height = metaTable.GetFloat("height", model->height); model->relMidPos = metaTable.GetFloat3("midpos", model->relMidPos); model->mins = metaTable.GetFloat3("mins", model->mins); model->maxs = metaTable.GetFloat3("maxs", model->maxs); //! Calculate model dimensions if not set if (!metaTable.KeyExists("mins") || !metaTable.KeyExists("maxs")) CalculateMinMax( model->rootPiece ); if (model->radius < 0.0001f) CalculateRadius( model ); if (model->height < 0.0001f) CalculateHeight( model ); //! Verbose logging of model properties logOutput.Print(LOG_MODEL_DETAIL, "model->name: %s", model->name.c_str()); logOutput.Print(LOG_MODEL_DETAIL, "model->numobjects: %d", model->numPieces); logOutput.Print(LOG_MODEL_DETAIL, "model->radius: %f", model->radius); logOutput.Print(LOG_MODEL_DETAIL, "model->height: %f", model->height); logOutput.Print(LOG_MODEL_DETAIL, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]); logOutput.Print(LOG_MODEL_DETAIL, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]); logOutput.Print (LOG_MODEL, "Model %s Imported.", model->name.c_str()); return model; }