void Client::TakeMapShot(){ try{ std::string name = MapShotPath(); { std::unique_ptr<IStream> stream(FileManager::OpenForWriting(name.c_str())); try{ GameMap *map = GetWorld()->GetMap(); if(map == nullptr){ SPRaise("No map loaded"); } map->Save(stream.get()); }catch(...){ throw; } } std::string msg; msg = _Tr("Client", "Map saved: {0}", name); ShowAlert(msg, AlertType::Notice); }catch(const Exception& ex){ std::string msg; msg = _Tr("Client", "Saving map failed: "); msg += ex.GetShortMessage(); ShowAlert(msg, AlertType::Error); SPLog("Saving map failed: %s", ex.what()); }catch(const std::exception& ex){ std::string msg; msg = _Tr("Client", "Saving map failed: "); msg += ex.what(); ShowAlert(msg, AlertType::Error); SPLog("Saving map failed: %s", ex.what()); } }
SplashWindow(): window(nullptr), surface(nullptr), startupScreenRequested(false){ spades::MemoryStream stream(reinterpret_cast<const char*>(splashImage), sizeof(splashImage)); bmp.Set(spades::Bitmap::Load(&stream), false); SDL_InitSubSystem(SDL_INIT_VIDEO|SDL_INIT_TIMER); window = SDL_CreateWindow("OpenSpades Splash Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, bmp->GetWidth(), bmp->GetHeight(), SDL_WINDOW_BORDERLESS); if(window == nullptr) { SPLog("Creation of splash window failed."); return; } surface = SDL_GetWindowSurface(window); if(surface == nullptr) { SPLog("Creation of splash window surface failed."); SDL_DestroyWindow(window); return; } // put splash image auto *s = SDL_CreateRGBSurfaceFrom(bmp->GetPixels(), bmp->GetWidth(), bmp->GetHeight(), 32, bmp->GetWidth() * 4, 0xff, 0xff00, 0xff0000, 0); SDL_BlitSurface(s, nullptr, surface, nullptr); SDL_FreeSurface(s); SDL_UpdateWindowSurface(window); }
void Runner::RunProtected() { SPADES_MARK_FUNCTION(); std::string err; try{ Run(); }catch(const spades::Exception& ex){ err = ex.GetShortMessage(); SPLog("[!] Unhandled exception in SDLRunner:\n%s", ex.what()); }catch(const std::exception& ex){ err = ex.what(); SPLog("[!] Unhandled exception in SDLRunner:\n%s", ex.what()); } if(!err.empty()){ std::string msg = err; msg = _Tr("Main", "A serious error caused OpenSpades to stop working:\n\n{0}\n\nSee SystemMessages.log for more details.", msg); SDL_InitSubSystem(SDL_INIT_VIDEO); if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _Tr("Main", "OpenSpades Fatal Error").c_str(), msg.c_str(), nullptr)) { // showing dialog failed. // TODO: do appropriate action } } }
void Runner::RunProtected() { SPADES_MARK_FUNCTION(); std::string err; try{ Run(); }catch(const spades::Exception& ex){ err = ex.GetShortMessage(); SPLog("Unhandled exception in SDLRunner:\n%s", ex.what()); }catch(const std::exception& ex){ err = ex.what(); SPLog("Unhandled exception in SDLRunner:\n%s", ex.what()); } if(!err.empty()){ ErrorDialog dlg; dlg.set_modal(); dlg.result = 0; // TODO: free this buffer (just leaking) Fl_Text_Buffer *buf = new Fl_Text_Buffer; buf->append(err.c_str()); dlg.infoView->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); dlg.infoView->buffer(buf); dlg.helpView->value("See SystemMessages.log for more details."); dlg.show(); while(dlg.visible()){ Fl::wait(); } } }
GLProgram *GLProgramManager::CreateProgram(const std::string &name) { SPADES_MARK_FUNCTION(); SPLog("Loading GLSL program '%s'", name.c_str()); std::string text = FileManager::ReadAllBytes(name.c_str()); std::vector<std::string> lines = SplitIntoLines(text); GLProgram *p = new GLProgram(device, name); for (size_t i = 0; i < lines.size(); i++) { std::string text = TrimSpaces(lines[i]); if (text.empty()) break; if (text == "*shadow*") { std::vector<GLShader *> shaders = GLShadowShader::RegisterShader(this, settings, false); for (size_t i = 0; i < shaders.size(); i++) p->Attach(shaders[i]); continue; } else if (text == "*shadow-lite*") { std::vector<GLShader *> shaders = GLShadowShader::RegisterShader(this, settings, false, true); for (size_t i = 0; i < shaders.size(); i++) p->Attach(shaders[i]); continue; } else if (text == "*shadow-variance*") { std::vector<GLShader *> shaders = GLShadowShader::RegisterShader(this, settings, true); for (size_t i = 0; i < shaders.size(); i++) p->Attach(shaders[i]); continue; } else if (text == "*dlight*") { std::vector<GLShader *> shaders = GLDynamicLightShader::RegisterShader(this); for (size_t i = 0; i < shaders.size(); i++) p->Attach(shaders[i]); continue; } else if (text == "*shadowmap*") { std::vector<GLShader *> shaders = GLShadowMapShader::RegisterShader(this); for (size_t i = 0; i < shaders.size(); i++) p->Attach(shaders[i]); continue; } else if (text[0] == '*') { SPRaise("Unknown special shader: %s", text.c_str()); } else if (text[0] == '#') { continue; } GLShader *s = CreateShader(text); p->Attach(s); } Stopwatch sw; p->Link(); SPLog("Successfully linked GLSL program '%s' in %.3fms", name.c_str(), sw.GetTime() * 1000.); // p->Validate(); return p; }
ThreadQuantumSetter() { if(core_win32BeginPeriod){ timeBeginPeriod(1); SPLog("Thread quantum was modified to 1ms by timeBeginPeriod"); SPLog("(to disable this behavior, set core_win32BeginPeriod to 0)"); }else{ SPLog("Thread quantum is not modified"); SPLog("(to enable this behavior, set core_win32BeginPeriod to 1)"); } }
std::vector<std::pair<std::string, std::string>> ImportFltkPreference() { std::vector<std::pair<std::string, std::string>> ret; auto path = GetFltkPreferencePath(); SPLog("Checking for legacy preference file: %s", path.c_str()); auto *rw = SDL_RWFromFile(path.c_str(), "rb"); if(rw == nullptr) { SPLog("Legacy preference file wasn't found."); return ret; } SdlFileStream stream(rw, true); std::string text = stream.ReadAllBytes(); SPLog("Parsing %d bytes of legacy preference file", static_cast<int>(text.size())); auto lines = SplitIntoLines(text); std::string buf; auto flush = [&]{ if(buf.empty()) return; auto idx = buf.find(':'); if(idx != std::string::npos) { auto name = buf.substr(0, idx); auto value = buf.substr(idx + 1); if(name.size() > 0) ret.emplace_back(name, value); } buf.clear(); }; for(auto& line: lines) { { auto idx = line.find(';'); if(idx != std::string::npos) { line.resize(idx); } } if(line.size() == 0) continue; if(line[0] == '[') continue; // group is not used if(line[0] == '+') { // continuation buf.append(line, 1, line.size() - 1); }else{ flush(); buf = line; } } flush(); return ret; }
GLShader *GLProgramManager::CreateShader(const std::string &name) { SPADES_MARK_FUNCTION(); SPLog("Loading GLSL shader '%s'", name.c_str()); std::string text = FileManager::ReadAllBytes(name.c_str()); GLShader::Type type; if (name.find(".fs") != std::string::npos) type = GLShader::FragmentShader; else if (name.find(".vs") != std::string::npos) type = GLShader::VertexShader; else if (name.find(".gs") != std::string::npos) type = GLShader::GeometryShader; else SPRaise("Failed to determine the type of a shader: %s", name.c_str()); GLShader *s = new GLShader(device, type); std::string finalSource; if (settings.r_hdr) { finalSource += "#define USE_HDR 1\n"; finalSource += "#define LINEAR_FRAMEBUFFER 1\n"; } else { finalSource += "#define USE_HDR 0\n"; finalSource += "#define LINEAR_FRAMEBUFFER 0\n"; } if (settings.r_fogShadow) { finalSource += "#define USE_VOLUMETRIC_FOG 1\n"; } else { finalSource += "#define USE_VOLUMETRIC_FOG 0\n"; } if (settings.r_ssao) { finalSource += "#define USE_SSAO 1\n"; } else { finalSource += "#define USE_SSAO 0\n"; } finalSource += text; s->AddSource(finalSource); Stopwatch sw; s->Compile(); SPLog("Successfully compiled GLSL program '%s' in %.3fms", name.c_str(), // should this be "program" or "shader"? sw.GetTime() * 1000.); return s; }
SplashWindow(): window(nullptr), surface(nullptr), startupScreenRequested(false){ spades::MemoryStream stream(reinterpret_cast<const char*>(splashImage), sizeof(splashImage)); bmp.Set(spades::Bitmap::Load(&stream), false); SDL_InitSubSystem(SDL_INIT_VIDEO|SDL_INIT_TIMER); window = SDL_CreateWindow("OpenSpades Splash Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, bmp->GetWidth(), bmp->GetHeight(), SDL_WINDOW_BORDERLESS); if(window == nullptr) { SPLog("Creation of splash window failed."); return; } surface = SDL_GetWindowSurface(window); if(surface == nullptr) { SPLog("Creation of splash window surface failed."); SDL_DestroyWindow(window); return; } #ifdef __APPLE__ #elif __unix SDL_Surface *icon = nullptr; SDL_RWops *icon_rw = nullptr; icon_rw = SDL_RWFromConstMem(Icon, sizeof(Icon)); if (icon_rw != nullptr) { icon = IMG_LoadPNG_RW(icon_rw); SDL_FreeRW(icon_rw); } if(icon == nullptr) { std::string msg = SDL_GetError(); SPLog("Failed to load icon: %s", msg.c_str()); } else { SDL_SetWindowIcon(window, icon); SDL_FreeSurface(icon); } #endif // put splash image auto *s = SDL_CreateRGBSurfaceFrom(bmp->GetPixels(), bmp->GetWidth(), bmp->GetHeight(), 32, bmp->GetWidth() * 4, 0xff, 0xff00, 0xff0000, 0); SDL_BlitSurface(s, nullptr, surface, nullptr); SDL_FreeSurface(s); SDL_UpdateWindowSurface(window); }
static void *GPA(const char *str) { if(!alLibrary){ auto paths = spades::Split(s_alDriver, ";"); std::string errors; for (const std::string &path: paths) { auto trimmedPath = spades::TrimSpaces(path); try { alLibrary = new spades::DynamicLibrary(trimmedPath.c_str()); if (alLibrary) { SPLog("'%s' loaded", trimmedPath.c_str()); break; } } catch (const std::exception &ex) { errors += trimmedPath; errors += ":\n"; errors += ex.what(); } } if (!alLibrary) { SPRaise("Failed to load a OpenAL driver.\n%s", errors.c_str()); } } if(qalGetProcAddress){ void *v = qalGetProcAddress(str); if(v) return v; } return alLibrary->GetSymbol(str); }
Client::~Client() { SPADES_MARK_FUNCTION(); NetLog("Disconnecting"); if(logStream) { SPLog("Closing netlog"); logStream.reset(); } if(net){ SPLog("Disconnecting"); net->Disconnect(); net.reset(); } SPLog("Disconnected"); RemoveAllLocalEntities(); RemoveAllCorpses(); renderer->SetGameMap(nullptr); audioDevice->SetGameMap(nullptr); for(size_t i = 0; i < clientPlayers.size(); i++) { if(clientPlayers[i]) { clientPlayers[i]->Invalidate(); } } clientPlayers.clear(); scriptedUI->ClientDestroyed(); tcView.reset(); limbo.reset(); scoreboard.reset(); mapView.reset(); largeMapView.reset(); chatWindow.reset(); killfeedWindow.reset(); paletteView.reset(); centerMessageView.reset(); hurtRingView.reset(); designFont.Set(nullptr); textFont.Set(nullptr); bigTextFont.Set(nullptr); world.reset(); }
void CheckError(const char *source, const char *fun, int line){ ALenum e; e = qalGetError(); if(e != AL_NO_ERROR) { if(s_alErrorFatal) SPRaise("[%s:%d] : %s : OpenAL error %d: %s", source, line, fun, (int)e, DescribeError(e)); else SPLog("[%s:%d] : %s : OpenAL error %d: %s", source, line, fun, (int)e, DescribeError(e)); } }
void CheckError(void){ ALenum e; e = qalGetError(); if(e != AL_NO_ERROR) { if(s_alErrorFatal) SPRaise("OpenAL error %d: %s", (int)e, DescribeError(e)); else SPLog("OpenAL error %d: %s", (int)e, DescribeError(e)); } }
std::string MainScreen::Connect() { spades::ServerAddress host(cg_lastQuickConnectHost, (int)cg_protocolVersion == 3 ? spades::ProtocolVersion::v075 : spades::ProtocolVersion::v076); try { subview.Set(new client::Client(&*renderer, &*audioDevice, host, cg_playerName), false); }catch(const std::exception& ex) { SPLog("[!] Error while initializing a game client: %s", ex.what()); return ex.what(); } return ""; }
GLBasicShadowMapRenderer::GLBasicShadowMapRenderer(GLRenderer *r) : IGLShadowMapRenderer(r) { SPADES_MARK_FUNCTION(); device = r->GetGLDevice(); textureSize = r->GetSettings().r_shadowMapSize; if ((int)textureSize > 4096) { SPLog("r_shadowMapSize is too large; changed to 4096"); r->GetSettings().r_shadowMapSize = textureSize = 4096; } colorTexture = device->GenTexture(); device->BindTexture(IGLDevice::Texture2D, colorTexture); device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::RGB, textureSize, textureSize, 0, IGLDevice::RGB, IGLDevice::UnsignedByte, NULL); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Linear); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::ClampToEdge); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::ClampToEdge); for (int i = 0; i < NumSlices; i++) { texture[i] = device->GenTexture(); device->BindTexture(IGLDevice::Texture2D, texture[i]); device->TexImage2D(IGLDevice::Texture2D, 0, IGLDevice::DepthComponent24, textureSize, textureSize, 0, IGLDevice::DepthComponent, IGLDevice::UnsignedInt, NULL); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMagFilter, IGLDevice::Linear); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureMinFilter, IGLDevice::Linear); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapS, IGLDevice::ClampToEdge); device->TexParamater(IGLDevice::Texture2D, IGLDevice::TextureWrapT, IGLDevice::ClampToEdge); framebuffer[i] = device->GenFramebuffer(); device->BindFramebuffer(IGLDevice::Framebuffer, framebuffer[i]); device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::ColorAttachment0, IGLDevice::Texture2D, colorTexture, 0); device->FramebufferTexture2D(IGLDevice::Framebuffer, IGLDevice::DepthAttachment, IGLDevice::Texture2D, texture[i], 0); device->BindFramebuffer(IGLDevice::Framebuffer, 0); } }
static void *GPA(const char *str) { if(!alLibrary){ alLibrary = new spades::DynamicLibrary(s_alDriver.CString()); SPLog("'%s' loaded", s_alDriver.CString()); } if(qalGetProcAddress){ void *v = qalGetProcAddress(str); if(v) return v; } return alLibrary->GetSymbol(str); }
GLShader *GLProgramManager::CreateShader(const std::string &name) { SPADES_MARK_FUNCTION(); SPLog("Loading GLSL shader '%s'", name.c_str()); std::string text = FileManager::ReadAllBytes(name.c_str()); GLShader::Type type; if(name.find(".fs") != std::string::npos) type = GLShader::FragmentShader; else if(name.find(".vs") != std::string::npos) type = GLShader::VertexShader; else SPRaise("Failed to determine the type of a shader: %s", name.c_str()); GLShader *s = new GLShader(device, type); s->AddSource(text); Stopwatch sw; s->Compile(); SPLog("Successfully compiled GLSL program '%s' in %.3fms", name.c_str(), sw.GetTime() * 1000.); return s; }
void DeleteFltkPreference() { auto path = GetFltkPreferencePath(); /* #ifdef WIN32 DeleteFileW(Utf8ToWString(path.c_str()).c_str()); #else unlink(path.c_str()); #endif */ // afraid of removing the pref file completely SPLog("Moving %s to %s", path.c_str(), (path + "-old").c_str()); #ifdef WIN32 auto s = Utf8ToWString(path.c_str()); MoveFileW(s.c_str(), (s + L"-old").c_str()); #else rename(path.c_str(), (path + "-old").c_str()); #endif }
void MainScreen::RunFrame(float dt) { SPADES_MARK_FUNCTION(); if(subview){ try{ subview->RunFrame(dt); if(subview->WantsToBeClosed()) { subview->Closing(); subview = NULL; RestoreRenderer(); }else{ return; } }catch(const std::exception& ex) { SPLog("[!] Error while running a game client: %s", ex.what()); subview->Closing(); subview = NULL; RestoreRenderer(); helper->errorMessage = ex.what(); } } if(timeToStartInitialization > 100.f){ timeToStartInitialization = 0.2f; } if(timeToStartInitialization > 0.f){ DrawStartupScreen(); timeToStartInitialization -= dt; if(timeToStartInitialization <= 0.f){ // do init DoInit(); } return; } static ScriptFunction func("MainScreenUI", "void RunFrame(float)"); ScriptContextHandle c = func.Prepare(); c->SetObject(&*ui); c->SetArgFloat(0, dt); c.ExecuteChecked(); }
Internal(GLSparseShadowMapRenderer *r):renderer(r){ GLProfiler profiler(r->device, "Sparse Page Table Generation"); cameraShadowCoord = r->GetRenderer()->GetSceneDef().viewOrigin; cameraShadowCoord = (r->matrix * cameraShadowCoord).GetXYZ(); // clear group maps for(size_t x = 0; x < Tiles; x++) for(size_t y = 0; y < Tiles; y++) groupMap[x][y] = NoGroup; const std::vector<GLModelRenderer::RenderModel>& rmodels = renderer->GetRenderer()->GetModelRenderer()->models; allInstances.reserve(256); groups.reserve(64); nodes.reserve(256); for(std::vector<GLModelRenderer::RenderModel>::const_iterator it = rmodels.begin(); it != rmodels.end(); it++) { const GLModelRenderer::RenderModel& rmodel = *it; Instance inst; inst.model = rmodel.model; OBB3 modelBounds = inst.model->GetBoundingBox(); for(size_t i = 0; i < rmodel.params.size(); i++) { inst.param = &(rmodel.params[i]); if(inst.param->depthHack) continue; OBB3 instWorldBoundsOBB = inst.param->matrix * modelBounds; // w should be 1, so this should wor OBB3 instBoundsOBB = r->matrix * instWorldBoundsOBB; AABB3 instBounds = instBoundsOBB.GetBoundingAABB(); // frustrum(?) cull if(instBounds.max.x < -1.f || instBounds.max.y < -1.f || instBounds.min.x > 1.f || instBounds.min.y > 1.f) continue; inst.tile1 = ShadowMapToTileCoord(instBounds.min); inst.tile2 = ShadowMapToTileCoord(instBounds.max); inst.tile2.x++; inst.tile2.y++; if(inst.tile1.x < 0) inst.tile1.x = 0; if(inst.tile1.y < 0) inst.tile1.y = 0; if(inst.tile2.x > Tiles) inst.tile2.x = Tiles; if(inst.tile2.y > Tiles) inst.tile2.y = Tiles; if(inst.tile1.x >= inst.tile2.x) continue; if(inst.tile1.y >= inst.tile2.y) continue; size_t instId = allInstances.size(); size_t grp = RegisterGroup(inst.tile1, inst.tile2); Group& g = groups[grp]; SPAssert(g.valid); if(g.lastInstance == NoInstance) { // this is new group. g.firstInstance = instId; g.lastInstance = instId; inst.prev = NoInstance; inst.next = NoInstance; }else{ // adding this instance to the group Instance& oldLast = allInstances[g.lastInstance]; SPAssert(oldLast.next == NoInstance); oldLast.next = instId; inst.prev = g.lastInstance; inst.next = NoInstance; g.lastInstance = instId; } g.lod = std::max(g.lod, ComputeLod(instBoundsOBB.m.GetOrigin())); allInstances.push_back(inst); } } if(false){ GLProfiler profiler(r->device, "Debug Output"); SPLog("Sparse Page Table -------"); for(int y = 0; y < Tiles; y++) { char buf[Tiles + 1]; for(int x = 0; x < Tiles; x++) { size_t g = groupMap[x][y]; const char *c = "0123456789ABCDEF"; if(g == NoGroup) buf[x] = ' '; else buf[x] = c[g & 15]; } buf[Tiles] = 0; SPLog("%s", buf); } SPLog("-----------------------"); } mapSize = r_shadowMapSize; }
int main(int argc, char ** argv) { #ifdef WIN32 SetUnhandledExceptionFilter( UnhandledExceptionProc ); #endif for(int i = 1; i < argc;) { int ret = argsHandler(argc, argv, i); if(!ret) { // ignore unknown arg i++; } } if ( cg_printVersion ) { printf( "%s\n", PACKAGE_STRING ); return 0; } if ( cg_printHelp ) { printHelp( argv[0] ); return 0; } std::unique_ptr<SplashWindow> splashWindow; try{ // start recording backtrace spades::reflection::Backtrace::StartBacktrace(); SPADES_MARK_FUNCTION(); // show splash window // NOTE: splash window uses image loader, which assumes backtrace is already initialized. splashWindow.reset(new SplashWindow()); auto showSplashWindowTime = SDL_GetTicks(); auto pumpEvents = [&splashWindow] { splashWindow->PumpEvents(); }; // initialize threads spades::Thread::InitThreadSystem(); spades::DispatchQueue::GetThreadQueue()->MarkSDLVideoThread(); SPLog("Package: " PACKAGE_STRING); // setup user-specific default resource directories #ifdef WIN32 static wchar_t buf[4096]; GetModuleFileNameW(NULL, buf, 4096); std::wstring appdir = buf; appdir = appdir.substr(0, appdir.find_last_of(L'\\')+1); if(SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, buf))){ std::wstring datadir = buf; datadir += L"\\OpenSpades\\Resources"; spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(Utf8FromWString(datadir.c_str()), true)); } spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(Utf8FromWString((appdir + L"Resources").c_str()), false)); //fltk has a console window on windows (can disable while building, maybe use a builtin console for a later release?) HWND hCon = GetConsoleWindow(); if( NULL != hCon ) { setIcon( hCon ); } #elif defined(__APPLE__) std::string home = getenv("HOME"); spades::FileManager::AddFileSystem (new spades::DirectoryFileSystem("./Resources", false)); // OS X application is made of Bundle, which contains its own Resources directory. { char *baseDir = SDL_GetBasePath(); if(baseDir) { spades::FileManager::AddFileSystem (new spades::DirectoryFileSystem(baseDir, false)); SDL_free(baseDir); } } spades::FileManager::AddFileSystem (new spades::DirectoryFileSystem(home+"/Library/Application Support/OpenSpades/Resources", true)); #else std::string home = getenv("HOME"); spades::FileManager::AddFileSystem (new spades::DirectoryFileSystem("./Resources", false)); spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(CMAKE_INSTALL_PREFIX "/" OPENSPADES_INSTALL_RESOURCES, false)); std::string xdg_data_home = home+"/.local/share"; if (getenv("XDG_DATA_HOME") == NULL) { SPLog("XDG_DATA_HOME not defined. Assuming that XDG_DATA_HOME is ~/.local/share"); } else { std::string xdg_data_home = getenv("XDG_DATA_HOME"); SPLog("XDG_DATA_HOME is %s", xdg_data_home.c_str()); } struct stat info; if ( stat((xdg_data_home+"/openspades").c_str(), &info ) != 0 ) { if ( stat((home+"/.openspades").c_str(), &info ) != 0) { } else if( info.st_mode & S_IFDIR ) { SPLog("Openspades directory in XDG_DATA_HOME not found, though old directory exists. Trying to resolve compatibility problem."); if (rename( (home+"/.openspades").c_str() , (xdg_data_home+"/openspades").c_str() ) != 0) { SPLog("Failed to move old directory to new."); } else { SPLog("Successfully moved old directory."); if (mkdir((home+"/.openspades").c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) { SDL_RWops *io = SDL_RWFromFile((home+"/.openspades/CONTENT_MOVED_TO_NEW_DIR").c_str(), "wb"); if (io != NULL) { const char* text = ("Content of this directory moved to "+xdg_data_home+"/openspades").c_str(); io->write(io, text, strlen(text), 1); io->close(io); } } } } } spades::FileManager::AddFileSystem (new spades::DirectoryFileSystem(xdg_data_home+"/openspades/Resources", true)); #endif // start log output to SystemMessages.log try{ spades::StartLog(); }catch(const std::exception& ex){ SDL_InitSubSystem(SDL_INIT_VIDEO); auto msg = spades::Format("Failed to start recording log because of the following error:\n{0}\n\n" "OpenSpades will continue to run, but any critical events are not logged.", ex.what()); if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "OpenSpades Log System Failure", msg.c_str(), splashWindow->GetWindow())) { // showing dialog failed. } } SPLog("Log Started."); // load preferences. spades::Settings::GetInstance()->Load(); pumpEvents(); // dump CPU info (for debugging?) { spades::CpuID cpuid; SPLog("---- CPU Information ----"); SPLog("Vendor ID: %s", cpuid.GetVendorId().c_str()); SPLog("Brand ID: %s", cpuid.GetBrand().c_str()); SPLog("Supports MMX: %s", cpuid.Supports(spades::CpuFeature::MMX)?"YES":"NO"); SPLog("Supports SSE: %s", cpuid.Supports(spades::CpuFeature::SSE)?"YES":"NO"); SPLog("Supports SSE2: %s", cpuid.Supports(spades::CpuFeature::SSE2)?"YES":"NO"); SPLog("Supports SSE3: %s", cpuid.Supports(spades::CpuFeature::SSE3)?"YES":"NO"); SPLog("Supports SSSE3: %s", cpuid.Supports(spades::CpuFeature::SSSE3)?"YES":"NO"); SPLog("Supports FMA: %s", cpuid.Supports(spades::CpuFeature::FMA)?"YES":"NO"); SPLog("Supports AVX: %s", cpuid.Supports(spades::CpuFeature::AVX)?"YES":"NO"); SPLog("Supports AVX2: %s", cpuid.Supports(spades::CpuFeature::AVX2)?"YES":"NO"); SPLog("Supports AVX512F: %s", cpuid.Supports(spades::CpuFeature::AVX512F)?"YES":"NO"); SPLog("Supports AVX512CD: %s", cpuid.Supports(spades::CpuFeature::AVX512CD)?"YES":"NO"); SPLog("Supports AVX512ER: %s", cpuid.Supports(spades::CpuFeature::AVX512ER)?"YES":"NO"); SPLog("Supports AVX512PF: %s", cpuid.Supports(spades::CpuFeature::AVX512PF)?"YES":"NO"); SPLog("Simultaneous Multithreading: %s", cpuid.Supports(spades::CpuFeature::SimultaneousMT)?"YES":"NO"); SPLog("Misc:"); SPLog("%s", cpuid.GetMiscInfo().c_str()); SPLog("-------------------------"); } // register resource directory specified by Makefile (or something) #if defined(RESDIR_DEFINED) spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(RESDIR, false)); #endif // search current file system for .pak files { std::vector<spades::IFileSystem*> fss; std::vector<spades::IFileSystem*> fssImportant; std::vector<std::string> files = spades::FileManager::EnumFiles(""); struct Comparator { static int GetPakId(const std::string& str) { if(str.size() >= 4 && str[0] == 'p' && str[1] == 'a' && str[2] == 'k' && (str[3] >= '0' && str[3] <= '9')){ return atoi(str.c_str() + 3); }else{ return 32767; } } static bool Compare(const std::string& a, const std::string& b) { int pa = GetPakId(a); int pb = GetPakId(b); if(pa == pb){ return a < b; }else{ return pa < pb; } } }; std::sort(files.begin(), files.end(), Comparator::Compare); for(size_t i = 0; i < files.size(); i++){ std::string name = files[i]; // check extension if(name.size() < 4 || name.rfind(".pak") != name.size() - 4){ continue; } if(spades::FileManager::FileExists(name.c_str())) { spades::IStream *stream = spades::FileManager::OpenForReading(name.c_str()); spades::ZipFileSystem *fs = new spades::ZipFileSystem(stream); if(name[0] == '_' && false) { // last resort for #198 SPLog("Pak Registered: %s (marked as 'important')\n", name.c_str()); fssImportant.push_back(fs); }else{ SPLog("Pak Registered: %s\n", name.c_str()); fss.push_back(fs); } } } for(size_t i = fss.size(); i > 0; i--){ spades::FileManager::AppendFileSystem(fss[i - 1]); } for(size_t i = 0; i < fssImportant.size(); i++){ spades::FileManager::PrependFileSystem(fssImportant[i]); } } pumpEvents(); // initialize localization system SPLog("Initializing localization system"); spades::LoadCurrentLocale(); _Tr("Main", "Localization System Loaded"); pumpEvents(); // parse args // initialize AngelScript SPLog("Initializing script engine"); spades::ScriptManager::GetInstance(); pumpEvents(); ThreadQuantumSetter quantumSetter; (void)quantumSetter; // suppress "unused variable" warning SDL_InitSubSystem(SDL_INIT_VIDEO); // we want to show splash window at least for some time... pumpEvents(); auto ticks = SDL_GetTicks(); if(ticks < showSplashWindowTime + 1500) { SDL_Delay(showSplashWindowTime + 1500 - ticks); } pumpEvents(); // everything is now ready! if( !cg_autoConnect ) { if(!((int)cl_showStartupWindow != 0 || splashWindow->IsStartupScreenRequested())) { splashWindow.reset(); SPLog("Starting main screen"); spades::StartMainScreen(); }else{ splashWindow.reset(); SPLog("Starting startup window"); ::spades::gui::StartupScreen::Run(); } } else { splashWindow.reset(); spades::ServerAddress host(cg_lastQuickConnectHost.CString(), (int)cg_protocolVersion == 3 ? spades::ProtocolVersion::v075 : spades::ProtocolVersion::v076 ); spades::StartClient(host, cg_playerName); } spades::Settings::GetInstance()->Flush(); }catch(const ExitRequestException&){ // user changed his mind. }catch(const std::exception& ex) { try { splashWindow.reset(nullptr); }catch(...){ } std::string msg = ex.what(); msg = _Tr("Main", "A serious error caused OpenSpades to stop working:\n\n{0}\n\nSee SystemMessages.log for more details.", msg); SPLog("[!] Terminating due to the fatal error: %s", ex.what()); SDL_InitSubSystem(SDL_INIT_VIDEO); if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, _Tr("Main", "OpenSpades Fatal Error").c_str(), msg.c_str(), nullptr)) { // showing dialog failed. // TODO: do appropriate action } } return 0; }
void SDLAsyncRunner::RunClientLoop(client::IRenderer *renderer, client::IAudioDevice *audio) { client::AsyncRenderer *asyncRenderer = new client::AsyncRenderer(renderer, DispatchQueue::GetThreadQueue()); modState = 0; ClientThread *cliThread = new ClientThread(); cliThread->runner = this; cliThread->renderer = asyncRenderer; cliThread->audio = audio; cliThread->Start(); bool editing = false; bool absoluteMouseCoord = true; SPLog("Main event loop started"); try{ while(cliThread->IsAlive()) { modState = SDLRunner::GetModState(); if(currentView){ class SDLEventDispatch: public ConcurrentDispatch { SDLAsyncRunner *runner; SDL_Event ev; public: SDLEventDispatch(SDLAsyncRunner *runner, const SDL_Event& ev): runner(runner), ev(ev){ } virtual void Run() { View *view = runner->currentView; if(view){ runner->ProcessEvent(ev, view); } } }; SDL_Event event; if(SDL_WaitEvent(&event)){ { SDLEventDispatch *disp = new SDLEventDispatch(this, event); // FIXME: cliQueue may be deleted.. if(cliQueue){ disp->StartOn(cliQueue); disp->Release(); }else{ delete disp; } } while(SDL_PollEvent(&event)) { SDLEventDispatch *disp = new SDLEventDispatch(this, event); // FIXME: cliQueue may be deleted.. if(cliQueue){ disp->StartOn(cliQueue); disp->Release(); }else{ delete disp; } } } }else{ SDL_Event event; SDL_WaitEvent(&event); if(event.type == SDL_QUIT){ break; } } PulledState state; { AutoLocker guard(&stateMutex); state = this->state; } bool ed = state.acceptsTextInput; if(ed && !editing) { SDL_StartTextInput(); }else if(!ed && editing){ SDL_StopTextInput(); } editing = ed; if(editing){ SDL_SetTextInputRect(&state.textInputRect); } bool ab = state.needsAbsoluteMouseCoord; if(ab != absoluteMouseCoord) { absoluteMouseCoord = ab; SDL_SetRelativeMouseMode(absoluteMouseCoord?SDL_FALSE:SDL_TRUE); } DispatchQueue::GetThreadQueue()->ProcessQueue(); } }catch(const std::exception& ex){ rendererErrorOccured = true; SPLog("Renderer error:\n%s", ex.what()); cliThread->MarkForAutoDeletion(); SPLog("Main event loop terminated"); throw; } SPLog("Main event loop ended"); if(!clientError.empty()){ SPLog("Client reported an error: \n%s", clientError.c_str()); SPRaise("Client error:\n%s", clientError.c_str()); } }
void SDLRunner::RunClientLoop(spades::client::IRenderer *renderer, spades::client::IAudioDevice *audio) { { client::Client client(renderer, audio, host, playerName); Uint32 ot = SDL_GetTicks(); bool running = true; bool lastShift = false; bool lastCtrl = false; SPLog("Starting Client Loop"); while(running){ SDL_Event event; DispatchQueue::GetThreadQueue()->ProcessQueue(); Uint32 dt = SDL_GetTicks() - ot; ot += dt; if((int32_t)dt > 0) client.RunFrame((float)dt / 1000.f); if(client.WantsToBeClosed()){ client.Closing(); running = false; SPLog("Close requested by Client"); break; } int modState = GetModState(); if(modState & (KMOD_CTRL | KMOD_LCTRL | KMOD_RCTRL)){ if(!lastCtrl){ client.KeyEvent("Control", true); lastCtrl = true; } }else{ if(lastCtrl){ client.KeyEvent("Control", false); lastCtrl = false; } } if(modState & (KMOD_SHIFT | KMOD_LSHIFT | KMOD_RSHIFT)){ if(!lastShift){ client.KeyEvent("Shift", true); lastShift = true; } }else{ if(lastShift){ client.KeyEvent("Shift", false); lastShift = false; } } while(SDL_PollEvent(&event)) { ProcessEvent(event, &client); } //Fl::check(); } SPLog("Leaving Client Loop"); } }
Client::Client(IRenderer *r, IAudioDevice *audioDev, const ServerAddress& host, std::string playerName) : playerName(playerName) , logStream(nullptr) , hostname(host) , renderer(r) , audioDevice(audioDev) , time(0.f) , readyToClose(false) , worldSubFrame(0.f) , frameToRendererInit(5) , timeSinceInit(0.f) , hasLastTool(false) , lastPosSentTime(0.f) , lastAliveTime(0.f) , lastKills(0) , hasDelayedReload(false) , localFireVibrationTime(-1.f) , grenadeVibration(0.f) , scoreboardVisible(false) , flashlightOn(false) , focalLength(20.f) , targetFocalLength(20.f) , autoFocusEnabled(true) , hitFeedbackFriendly(false) , lastMyCorpse(nullptr) , nextScreenShotIndex(0) , nextMapShotIndex(0) , alertDisappearTime(-10000.f) // FIXME: preferences? , corpseSoftTimeLimit(30.f) // FIXME: this is not used , corpseSoftLimit(6) , corpseHardLimit(16) , followYaw(0.f) , followPitch(0.f) { SPADES_MARK_FUNCTION(); SPLog("Initializing..."); designFont.Set(CreateSquareDesignFont(renderer), false); textFont.Set(CreateGuiFont(renderer), false); bigTextFont.Set(CreateLargeFont(renderer), false); renderer->SetFogDistance(128.f); renderer->SetFogColor(MakeVector3(.8f, 1.f, 1.f)); chatWindow.reset(new ChatWindow(this, GetRenderer(), textFont, false)); killfeedWindow.reset(new ChatWindow(this, GetRenderer(), textFont, true)); hurtRingView.reset(new HurtRingView(this)); centerMessageView.reset(new CenterMessageView(this, bigTextFont)); mapView.reset(new MapView(this, false)); largeMapView.reset(new MapView(this, true)); scoreboard.reset(new ScoreboardView(this)); limbo.reset(new LimboView(this)); paletteView.reset(new PaletteView(this)); tcView.reset(new TCProgressView(this)); scriptedUI.Set(new ClientUI(renderer, audioDev, textFont, this), false); renderer->SetGameMap(nullptr); }
void Link(void) { SPLog("Linking with OpenGL library."); L(alEnable); L(alDisable); L(alIsEnabled); L(alGetString); L(alGetBooleanv); L(alGetIntegerv); L(alGetFloatv); L(alGetDoublev); L(alGetBoolean); L(alGetInteger); L(alGetFloat); L(alGetDouble); L(alGetError); L(alIsExtensionPresent); L(alGetProcAddress); L(alGetEnumValue); L(alListenerf); L(alListener3f); L(alListenerfv); L(alListeneri); L(alGetListenerf); L(alGetListener3f); L(alGetListenerfv); L(alGetListeneri); L(alGenSources); L(alDeleteSources); L(alIsSource); L(alSourcef); L(alSource3f); L(alSourcefv); L(alSourcei); L(alSource3i); L(alGetSourcef); L(alGetSource3f); L(alGetSourcefv); L(alGetSourcei); L(alSourcePlayv); L(alSourceStopv); L(alSourceRewindv); L(alSourcePausev); L(alSourcePlay); L(alSourceStop); L(alSourceRewind); L(alSourcePause); L(alSourceQueueBuffers); L(alSourceUnqueueBuffers); L(alGenBuffers); L(alDeleteBuffers); L(alIsBuffer); L(alBufferData); L(alGetBufferf); L(alGetBufferi); L(alDopplerFactor); L(alDopplerVelocity); L(alDistanceModel); L(alcCreateContext); L(alcMakeContextCurrent); L(alcProcessContext); L(alcSuspendContext); L(alcDestroyContext); L(alcGetCurrentContext); L(alcGetContextsDevice); L(alcOpenDevice); L(alcCloseDevice); L(alcGetError); L(alcIsExtensionPresent); L(alcGetProcAddress); L(alcGetEnumValue); L(alcGetString); L(alcGetIntegerv); }
void Client::RunFrame(float dt) { SPADES_MARK_FUNCTION(); fpsCounter.MarkFrame(); if(frameToRendererInit > 0){ // waiting for renderer initialization DrawStartupScreen(); frameToRendererInit--; if(frameToRendererInit == 0){ DoInit(); }else{ return; } } timeSinceInit += std::min(dt, .03f); // update network try{ if(net->GetStatus() == NetClientStatusConnected) net->DoEvents(0); else net->DoEvents(10); }catch(const std::exception& ex){ if(net->GetStatus() == NetClientStatusNotConnected){ SPLog("Disconnected because of error:\n%s", ex.what()); NetLog("Disconnected because of error:\n%s", ex.what()); throw; }else{ SPLog("Exception while processing network packets (ignored):\n%s", ex.what()); } } hurtRingView->Update(dt); centerMessageView->Update(dt); mapView->Update(dt); largeMapView->Update(dt); UpdateAutoFocus(dt); if(world){ UpdateWorld(dt); }else{ renderer->SetFogColor(MakeVector3(0.f, 0.f, 0.f)); } chatWindow->Update(dt); killfeedWindow->Update(dt); limbo->Update(dt); // CreateSceneDefinition also can be used for sounds SceneDefinition sceneDef = CreateSceneDefinition(); lastSceneDef = sceneDef; // Update sounds try{ audioDevice->Respatialize(sceneDef.viewOrigin, sceneDef.viewAxis[2], sceneDef.viewAxis[1]); }catch(const std::exception& ex){ SPLog("Audio subsystem returned error (ignored):\n%s", ex.what()); } // render scene DrawScene(); // draw 2d Draw2D(); // draw scripted GUI scriptedUI->RunFrame(dt); if(scriptedUI->WantsClientToBeClosed()) readyToClose = true; // Well done! renderer->FrameDone(); renderer->Flip(); // reset all "delayed actions" (in case we forget to reset these) hasDelayedReload = false; time += dt; }
/** Initiate an initialization which likely to take some time */ void Client::DoInit() { renderer->Init(); SmokeSpriteEntity::Preload(renderer); renderer->RegisterImage("Textures/Fluid.png"); renderer->RegisterImage("Textures/WaterExpl.png"); renderer->RegisterImage("Gfx/White.tga"); audioDevice->RegisterSound("Sounds/Weapons/Block/Build.wav"); audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal1.wav"); audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal2.wav"); audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal3.wav"); audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal4.wav"); audioDevice->RegisterSound("Sounds/Misc/SwitchMapZoom.wav"); audioDevice->RegisterSound("Sounds/Misc/OpenMap.wav"); audioDevice->RegisterSound("Sounds/Misc/CloseMap.wav"); audioDevice->RegisterSound("Sounds/Player/Flashlight.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep1.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep2.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep3.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep4.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep5.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep6.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep7.wav"); audioDevice->RegisterSound("Sounds/Player/Footstep8.wav"); audioDevice->RegisterSound("Sounds/Player/Wade1.wav"); audioDevice->RegisterSound("Sounds/Player/Wade2.wav"); audioDevice->RegisterSound("Sounds/Player/Wade3.wav"); audioDevice->RegisterSound("Sounds/Player/Wade4.wav"); audioDevice->RegisterSound("Sounds/Player/Wade5.wav"); audioDevice->RegisterSound("Sounds/Player/Wade6.wav"); audioDevice->RegisterSound("Sounds/Player/Wade7.wav"); audioDevice->RegisterSound("Sounds/Player/Wade8.wav"); audioDevice->RegisterSound("Sounds/Player/Run1.wav"); audioDevice->RegisterSound("Sounds/Player/Run2.wav"); audioDevice->RegisterSound("Sounds/Player/Run3.wav"); audioDevice->RegisterSound("Sounds/Player/Run4.wav"); audioDevice->RegisterSound("Sounds/Player/Run5.wav"); audioDevice->RegisterSound("Sounds/Player/Run6.wav"); audioDevice->RegisterSound("Sounds/Player/Run7.wav"); audioDevice->RegisterSound("Sounds/Player/Run8.wav"); audioDevice->RegisterSound("Sounds/Player/Run9.wav"); audioDevice->RegisterSound("Sounds/Player/Run10.wav"); audioDevice->RegisterSound("Sounds/Player/Run11.wav"); audioDevice->RegisterSound("Sounds/Player/Run12.wav"); audioDevice->RegisterSound("Sounds/Player/Jump.wav"); audioDevice->RegisterSound("Sounds/Player/Land.wav"); audioDevice->RegisterSound("Sounds/Player/WaterJump.wav"); audioDevice->RegisterSound("Sounds/Player/WaterLand.wav"); audioDevice->RegisterSound("Sounds/Weapons/SwitchLocal.wav"); audioDevice->RegisterSound("Sounds/Weapons/Switch.wav"); audioDevice->RegisterSound("Sounds/Weapons/Restock.wav"); audioDevice->RegisterSound("Sounds/Weapons/RestockLocal.wav"); audioDevice->RegisterSound("Sounds/Weapons/AimDownSightLocal.wav"); renderer->RegisterImage("Gfx/Ball.png"); renderer->RegisterModel("Models/Player/Dead.kv6"); renderer->RegisterImage("Gfx/Spotlight.tga"); renderer->RegisterImage("Gfx/Glare.tga"); renderer->RegisterModel("Models/Weapons/Spade/Spade.kv6"); renderer->RegisterModel("Models/Weapons/Block/Block2.kv6"); renderer->RegisterModel("Models/Weapons/Grenade/Grenade.kv6"); renderer->RegisterModel("Models/Weapons/SMG/Weapon.kv6"); renderer->RegisterModel("Models/Weapons/SMG/WeaponNoMagazine.kv6"); renderer->RegisterModel("Models/Weapons/SMG/Magazine.kv6"); renderer->RegisterModel("Models/Weapons/Rifle/Weapon.kv6"); renderer->RegisterModel("Models/Weapons/Rifle/WeaponNoMagazine.kv6"); renderer->RegisterModel("Models/Weapons/Rifle/Magazine.kv6"); renderer->RegisterModel("Models/Weapons/Shotgun/Weapon.kv6"); renderer->RegisterModel("Models/Weapons/Shotgun/WeaponNoPump.kv6"); renderer->RegisterModel("Models/Weapons/Shotgun/Pump.kv6"); renderer->RegisterModel("Models/Player/Arm.kv6"); renderer->RegisterModel("Models/Player/UpperArm.kv6"); renderer->RegisterModel("Models/Player/LegCrouch.kv6"); renderer->RegisterModel("Models/Player/TorsoCrouch.kv6"); renderer->RegisterModel("Models/Player/Leg.kv6"); renderer->RegisterModel("Models/Player/Torso.kv6"); renderer->RegisterModel("Models/Player/Arms.kv6"); renderer->RegisterModel("Models/Player/Head.kv6"); renderer->RegisterModel("Models/MapObjects/Intel.kv6"); renderer->RegisterModel("Models/MapObjects/CheckPoint.kv6"); renderer->RegisterImage("Gfx/Sight.tga"); renderer->RegisterImage("Gfx/Bullet/7.62mm.tga"); renderer->RegisterImage("Gfx/Bullet/9mm.tga"); renderer->RegisterImage("Gfx/Bullet/12gauge.tga"); renderer->RegisterImage("Gfx/CircleGradient.png"); renderer->RegisterImage("Gfx/HurtSprite.png"); renderer->RegisterImage("Gfx/HurtRing2.png"); audioDevice->RegisterSound("Sounds/Feedback/Chat.wav"); SPLog("Started connecting to '%s'", hostname.asString(true).c_str()); net.reset(new NetClient(this)); net->Connect(hostname); // decide log file name std::string fn = hostname.asString(false); std::string fn2; { time_t t; struct tm tm; ::time(&t); tm = *localtime(&t); char buf[256]; sprintf(buf, "%04d%02d%02d%02d%02d%02d_", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); fn2 = buf; } for(size_t i = 0; i < fn.size(); i++){ char c = fn[i]; if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { fn2 += c; }else{ fn2 += '_'; } } fn2 = "NetLogs/" + fn2 + ".log"; try{ logStream.reset(FileManager::OpenForWriting(fn2.c_str())); SPLog("Netlog Started at '%s'", fn2.c_str()); }catch(const std::exception& ex){ SPLog("Failed to open netlog file '%s' (%s)", fn2.c_str(), ex.what()); } }
~ThreadQuantumSetter() { if(core_win32BeginPeriod){ timeEndPeriod(1); SPLog("Thread quantum was restored"); } }
void Settings::Save() { SPLog("Saving preferences to " CONFIGFILE); try { std::string buffer; buffer = "# OpenSpades config file\n" "#\n" "\n"; int column = 0; auto emitContinuation = [&] { buffer += "\\\n"; column = 0; }; auto emitString = [&](const std::string& val, bool escapeColon) { std::size_t i = 0; while(i < val.size() && val[i] == ' ') { if(column > 78) { emitContinuation(); } buffer += "\\ "; column += 2; i++; } while(i < val.size()) { if(column > 78) { emitContinuation(); } unsigned char uc = static_cast<unsigned char>(val[i]); switch(val[i]) { case '\n': buffer += "\\n"; column += 2; i++; break; case '\r': buffer += "\\r"; column += 2; i++; break; case '\t': buffer += "\\t"; column += 2; i++; break; default: std::size_t utf8charsize; GetCodePointFromUTF8String(val, i, &utf8charsize); if(val[i] == '#' || // comment marker (escapeColon && val[i] == ':') || // key/value split uc < 0x20 || // control char (uc >= 0x80 && utf8charsize == 0) || // invalid UTF8 utf8charsize >= 5) { // valid UTF-8 but codepoint beyond BMP/SMP range static const char *s = "0123456789abcdef"; buffer += "\\x"; buffer += s[uc>>4]; buffer += s[uc&15]; column += 3; i++; }else{ buffer.append(val, i, utf8charsize); column += utf8charsize; i += utf8charsize; } break; } } }; for(const auto& item: items) { Item *itm = item.second; emitString(itm->name, true); buffer += ": "; column += 2; emitString(itm->string, false); buffer += "\n"; column = 0; } std::unique_ptr<IStream> s(FileManager::OpenForWriting(CONFIGFILE)); s->Write(buffer); } catch (const std::exception& ex) {
void Client::SetWorld(spades::client::World *w) { SPADES_MARK_FUNCTION(); if(world.get() == w){ return; } scriptedUI->CloseUI(); RemoveAllCorpses(); RemoveAllLocalEntities(); lastHealth = 0; lastHurtTime = -100.f; hurtRingView->ClearAll(); scoreboardVisible = false; flashlightOn = false; for(size_t i = 0; i < clientPlayers.size(); i++) { if(clientPlayers[i]) { clientPlayers[i]->Invalidate(); } } clientPlayers.clear(); if(world){ world->SetListener(nullptr); renderer->SetGameMap(nullptr); audioDevice->SetGameMap(nullptr); world = nullptr; map = nullptr; } world.reset(w); if(world){ SPLog("World set"); // initialize player view objects clientPlayers.resize(world->GetNumPlayerSlots()); for(size_t i = 0; i < world->GetNumPlayerSlots(); i++) { Player *p = world->GetPlayer(i); if(p){ clientPlayers[i] = new ClientPlayer(p, this); }else{ clientPlayers[i] = nullptr; } } world->SetListener(this); map = world->GetMap(); renderer->SetGameMap(map); audioDevice->SetGameMap(map); NetLog("------ World Loaded ------"); }else{ SPLog("World removed"); NetLog("------ World Unloaded ------"); } limbo->SetSelectedTeam(2); limbo->SetSelectedWeapon(RIFLE_WEAPON); worldSubFrame = 0.f; worldSetTime = time; inGameLimbo = false; }