void HangDetector() { while (keepRunning) { // increase multiplier during game load to prevent false positives e.g. during pathing const int hangTimeMultiplier = CrashHandler::gameLoading? 3 : 1; const spring_time hangtimeout = spring_msecs(spring_tomsecs(hangTimeout) * hangTimeMultiplier); spring_time curwdt = spring_gettime(); #if defined(USE_GML) && GML_ENABLE_SIM if (gmlMultiThreadSim) { spring_time cursimwdt = simwdt; if (spring_istime(cursimwdt) && curwdt > cursimwdt && (curwdt - cursimwdt) > hangtimeout) { HangHandler(true); simwdt = curwdt; } } #endif spring_time curdrawwdt = drawwdt; if (spring_istime(curdrawwdt) && curwdt > curdrawwdt && (curwdt - curdrawwdt) > hangtimeout) { HangHandler(false); drawwdt = curwdt; } spring_sleep(spring_secs(1)); } }
void GameParticipant::Kill(const std::string& reason, const bool flush) { if (link) { link->SendData(CBaseNetProtocol::Get().SendQuit(reason)); if (flush) // make sure the Flush() performed by Close() has any effect (forced flushes are undesirable) spring_sleep(spring_msecs(1000)); // it will cause a slight lag in the game server during kick, but not a big deal link->Close(); link.reset(); } linkData[MAX_AIS].link.reset(); #ifdef SYNCCHECK syncResponse.clear(); #endif myState = DISCONNECTED; }
bool CLoadScreen::Draw() { //! Limit the Frames Per Second to not lock a singlethreaded CPU from loading the game if (mtLoading) { spring_time now = spring_gettime(); unsigned diff_ms = spring_tomsecs(now - last_draw); static const unsigned wantedFPS = 50; static const unsigned min_frame_time = 1000 / wantedFPS; if (diff_ms < min_frame_time) { spring_time nap = spring_msecs(min_frame_time - diff_ms); spring_sleep(nap); } last_draw = now; } //! cause of `curLoadMessage` boost::recursive_mutex::scoped_lock lck(mutex); if (LuaIntro != nullptr) { LuaIntro->Update(); LuaIntro->DrawGenesis(); ClearScreen(); LuaIntro->DrawLoadScreen(); } else { ClearScreen(); float xDiv = 0.0f; float yDiv = 0.0f; const float ratioComp = globalRendering->aspectRatio / aspectRatio; if (math::fabs(ratioComp - 1.0f) < 0.01f) { //! ~= 1 //! show Load-Screen full screen //! nothing to do } else if (ratioComp > 1.0f) { //! show Load-Screen on part of the screens X-Axis only xDiv = (1.0f - (1.0f / ratioComp)) * 0.5f; } else { //! show Load-Screen on part of the screens Y-Axis only yDiv = (1.0f - ratioComp) * 0.5f; } //! Draw loading screen & print load msg. if (startupTexture) { glBindTexture(GL_TEXTURE_2D,startupTexture); glBegin(GL_QUADS); glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f + xDiv, 0.0f + yDiv); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f + xDiv, 1.0f - yDiv); glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f - xDiv, 1.0f - yDiv); glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f - xDiv, 0.0f + yDiv); glEnd(); } if (showMessages) { font->Begin(); font->SetTextColor(0.5f,0.5f,0.5f,0.9f); font->glPrint(0.1f,0.9f, globalRendering->viewSizeY / 35.0f, FONT_NORM, oldLoadMessages); font->SetTextColor(0.9f,0.9f,0.9f,0.9f); float posy = font->GetTextNumLines(oldLoadMessages) * font->GetLineHeight() * globalRendering->viewSizeY / 35.0f; font->glPrint(0.1f,0.9f - posy * globalRendering->pixelY, globalRendering->viewSizeY / 35.0f, FONT_NORM, curLoadMessage); font->End(); } } // Always render Spring's license notice font->Begin(); font->SetOutlineColor(0.0f,0.0f,0.0f,0.65f); font->SetTextColor(1.0f,1.0f,1.0f,1.0f); font->glFormat(0.5f,0.06f, globalRendering->viewSizeY / 35.0f, FONT_OUTLINE | FONT_CENTER | FONT_NORM, "Spring %s", SpringVersion::GetFull().c_str()); font->glFormat(0.5f,0.02f, globalRendering->viewSizeY / 50.0f, FONT_OUTLINE | FONT_CENTER | FONT_NORM, "This program is distributed under the GNU General Public License, see license.html for more info"); font->End(); if (!mtLoading) SDL_GL_SwapWindow(globalRendering->window); return true; }
int main(int argc, char* argv[]) { Threading::SetMainThread(); try { spring_clock::PushTickRate(); // initialize start time (can safely be done before SDL_Init // since we are not using SDL_GetTicks as our clock anymore) spring_time::setstarttime(spring_time::gettime(true)); CLogOutput::LogSystemInfo(); std::string scriptName; std::string scriptText; std::string binaryName = argv[0]; gflags::SetUsageMessage("Usage: " + binaryName + " [options] path_to_script.txt"); gflags::SetVersionString(SpringVersion::GetFull()); gflags::ParseCommandLineFlags(&argc, &argv, true); ParseCmdLine(argc, argv, scriptName); GlobalConfig::Instantiate(); FileSystemInitializer::InitializeLogOutput(); FileSystemInitializer::Initialize(); // Initialize crash reporting CrashHandler::Install(); LOG("report any errors to Mantis or the forums."); LOG("loading script from file: %s", scriptName.c_str()); // server will take ownership of these std::shared_ptr<ClientSetup> dsClientSetup(new ClientSetup()); std::shared_ptr<GameData> dsGameData(new GameData()); std::shared_ptr<CGameSetup> dsGameSetup(new CGameSetup()); CFileHandler fh(scriptName); if (!fh.FileExists()) throw content_error("script does not exist in given location: " + scriptName); if (!fh.LoadStringData(scriptText)) throw content_error("script cannot be read: " + scriptName); dsClientSetup->LoadFromStartScript(scriptText); if (!dsGameSetup->Init(scriptText)) { // read the script provided by cmdline LOG_L(L_ERROR, "failed to load script %s", scriptName.c_str()); return 1; } // Create the server, it will run in a separate thread CGlobalUnsyncedRNG rng; const unsigned sleepTime = FLAGS_sleeptime; const unsigned randSeed = time(nullptr) % ((spring_gettime().toNanoSecsi() + 1) * 9007); rng.Seed(randSeed); dsGameData->SetRandomSeed(rng.NextInt()); // Use script provided hashes if they exist if (dsGameSetup->mapHash != 0) { dsGameData->SetMapChecksum(dsGameSetup->mapHash); dsGameSetup->LoadStartPositions(false); // reduced mode } else { dsGameData->SetMapChecksum(archiveScanner->GetArchiveCompleteChecksum(dsGameSetup->mapName)); CFileHandler f("maps/" + dsGameSetup->mapName); if (!f.FileExists()) vfsHandler->AddArchiveWithDeps(dsGameSetup->mapName, false); dsGameSetup->LoadStartPositions(); // full mode } if (dsGameSetup->modHash != 0) { dsGameData->SetModChecksum(dsGameSetup->modHash); } else { const std::string& modArchive = archiveScanner->ArchiveFromName(dsGameSetup->modName); const unsigned int modCheckSum = archiveScanner->GetArchiveCompleteChecksum(modArchive); dsGameData->SetModChecksum(modCheckSum); } LOG("starting server..."); { dsGameData->SetSetupText(dsGameSetup->setupText); CGameServer server(dsClientSetup, dsGameData, dsGameSetup); while (!server.HasGameID()) { // wait until gameID has been generated or // a timeout occurs (if no clients connect) if (server.HasFinished()) break; spring_sleep(spring_secs(sleepTime)); } while (!server.HasFinished()) { static bool printData = (server.GetDemoRecorder() != nullptr); if (printData) { printData = false; const std::unique_ptr<CDemoRecorder>& demoRec = server.GetDemoRecorder(); const std::uint8_t* gameID = (demoRec->GetFileHeader()).gameID; LOG("recording demo: %s", (demoRec->GetName()).c_str()); LOG("using mod: %s", (dsGameSetup->modName).c_str()); LOG("using map: %s", (dsGameSetup->mapName).c_str()); LOG("GameID: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", gameID[0], gameID[1], gameID[2], gameID[3], gameID[4], gameID[5], gameID[6], gameID[7], gameID[8], gameID[9], gameID[10], gameID[11], gameID[12], gameID[13], gameID[14], gameID[15]); } spring_secs(sleepTime).sleep(true); } } LOG("exiting"); FileSystemInitializer::Cleanup(); GlobalConfig::Deallocate(); DataDirLocater::FreeInstance(); spring_clock::PopTickRate(); LOG("exited"); } CATCH_SPRING_ERRORS return 0; }
void sleep_spring2(int time) { spring_sleep(spring_time::fromNanoSecs(time)); }
void sleep_spring(int time) { spring_sleep(spring_msecs(time)); }