diff options
Diffstat (limited to 'src/engine/client/client.cpp')
| -rw-r--r-- | src/engine/client/client.cpp | 459 |
1 files changed, 187 insertions, 272 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 61a96eee..d5da647b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1,11 +1,13 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ +#include <new> #include <stdlib.h> // qsort #include <stdarg.h> #include <base/math.h> #include <base/system.h> +#include <base/tl/threading.h> #include <engine/client.h> #include <engine/config.h> @@ -26,6 +28,7 @@ #include <engine/shared/compression.h> #include <engine/shared/datafile.h> #include <engine/shared/demo.h> +#include <engine/shared/filecollection.h> #include <engine/shared/mapchecker.h> #include <engine/shared/network.h> #include <engine/shared/packer.h> @@ -33,6 +36,8 @@ #include <engine/shared/ringbuffer.h> #include <engine/shared/snapshot.h> +#include <game/version.h> + #include <mastersrv/mastersrv.h> #include <versionsrv/versionsrv.h> @@ -46,6 +51,10 @@ #include <windows.h> #endif +#include "SDL.h" +#ifdef main +#undef main +#endif void CGraph::Init(float Min, float Max) { @@ -231,185 +240,6 @@ void CSmoothTime::Update(CGraph *pGraph, int64 Target, int TimeLeft, int AdjustD } -bool CFileCollection::IsFilenameValid(const char *pFilename) -{ - if(str_length(pFilename) != m_FileDescLength+TIMESTAMP_LENGTH+m_FileExtLength || - str_comp_num(pFilename, m_aFileDesc, m_FileDescLength) || - str_comp(pFilename+m_FileDescLength+TIMESTAMP_LENGTH, m_aFileExt)) - return false; - - pFilename += m_FileDescLength; - if(pFilename[0] == '_' && - pFilename[1] >= '0' && pFilename[1] <= '9' && - pFilename[2] >= '0' && pFilename[2] <= '9' && - pFilename[3] >= '0' && pFilename[3] <= '9' && - pFilename[4] >= '0' && pFilename[4] <= '9' && - pFilename[5] == '-' && - pFilename[6] >= '0' && pFilename[6] <= '9' && - pFilename[7] >= '0' && pFilename[7] <= '9' && - pFilename[8] == '-' && - pFilename[9] >= '0' && pFilename[9] <= '9' && - pFilename[10] >= '0' && pFilename[10] <= '9' && - pFilename[11] == '_' && - pFilename[12] >= '0' && pFilename[12] <= '9' && - pFilename[13] >= '0' && pFilename[13] <= '9' && - pFilename[14] == '-' && - pFilename[15] >= '0' && pFilename[15] <= '9' && - pFilename[16] >= '0' && pFilename[16] <= '9' && - pFilename[17] == '-' && - pFilename[18] >= '0' && pFilename[18] <= '9' && - pFilename[19] >= '0' && pFilename[19] <= '9') - return true; - - return false; -} - -int64 CFileCollection::ExtractTimestamp(const char *pTimestring) -{ - int64 Timestamp = pTimestring[0]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[1]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[2]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[3]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[5]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[6]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[8]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[9]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[11]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[12]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[14]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[15]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[17]-'0'; Timestamp <<= 4; - Timestamp += pTimestring[18]-'0'; - - return Timestamp; -} - -void CFileCollection::BuildTimestring(int64 Timestamp, char *pTimestring) -{ - pTimestring[19] = 0; - pTimestring[18] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[17] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[16] = '-'; - pTimestring[15] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[14] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[13] = '-'; - pTimestring[12] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[11] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[10] = '_'; - pTimestring[9] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[8] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[7] = '-'; - pTimestring[6] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[5] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[4] = '-'; - pTimestring[3] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[2] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[1] = (Timestamp&0xF)+'0'; Timestamp >>= 4; - pTimestring[0] = (Timestamp&0xF)+'0'; -} - -void CFileCollection::Init(IStorage *pStorage, const char *pPath, const char *pFileDesc, const char *pFileExt, int MaxEntries) -{ - mem_zero(m_aTimestamps, sizeof(m_aTimestamps)); - m_NumTimestamps = 0; - m_MaxEntries = clamp(MaxEntries, 1, static_cast<int>(MAX_ENTRIES)); - str_copy(m_aFileDesc, pFileDesc, sizeof(m_aFileDesc)); - m_FileDescLength = str_length(m_aFileDesc); - str_copy(m_aFileExt, pFileExt, sizeof(m_aFileExt)); - m_FileExtLength = str_length(m_aFileExt); - str_copy(m_aPath, pPath, sizeof(m_aPath)); - m_pStorage = pStorage; - - m_pStorage->ListDirectory(IStorage::TYPE_SAVE, m_aPath, FilelistCallback, this); -} - -void CFileCollection::AddEntry(int64 Timestamp) -{ - if(m_NumTimestamps == 0) - { - // empty list - m_aTimestamps[m_NumTimestamps++] = Timestamp; - } - else - { - // remove old file - if(m_NumTimestamps == m_MaxEntries) - { - char aBuf[512]; - char aTimestring[TIMESTAMP_LENGTH]; - BuildTimestring(m_aTimestamps[0], aTimestring); - str_format(aBuf, sizeof(aBuf), "%s/%s_%s%s", m_aPath, m_aFileDesc, aTimestring, m_aFileExt); - m_pStorage->RemoveFile(aBuf, IStorage::TYPE_SAVE); - } - - // add entry to the sorted list - if(m_aTimestamps[0] > Timestamp) - { - // first entry - if(m_NumTimestamps < m_MaxEntries) - { - mem_move(m_aTimestamps+1, m_aTimestamps, m_NumTimestamps*sizeof(int64)); - m_aTimestamps[0] = Timestamp; - ++m_NumTimestamps; - } - } - else if(m_aTimestamps[m_NumTimestamps-1] <= Timestamp) - { - // last entry - if(m_NumTimestamps == m_MaxEntries) - { - mem_move(m_aTimestamps, m_aTimestamps+1, (m_NumTimestamps-1)*sizeof(int64)); - m_aTimestamps[m_NumTimestamps-1] = Timestamp; - } - else - m_aTimestamps[m_NumTimestamps++] = Timestamp; - } - else - { - // middle entry - int Left = 0, Right = m_NumTimestamps-1; - while(Right-Left > 1) - { - int Mid = (Left+Right)/2; - if(m_aTimestamps[Mid] > Timestamp) - Right = Mid; - else - Left = Mid; - } - - if(m_NumTimestamps == m_MaxEntries) - { - mem_move(m_aTimestamps, m_aTimestamps+1, (Right-1)*sizeof(int64)); - m_aTimestamps[Right-1] = Timestamp; - } - else - { - mem_move(m_aTimestamps+Right+1, m_aTimestamps+Right, (m_NumTimestamps-Right)*sizeof(int64)); - m_aTimestamps[Right] = Timestamp; - ++m_NumTimestamps; - } - } - } -} - -int CFileCollection::FilelistCallback(const char *pFilename, int IsDir, int StorageType, void *pUser) -{ - CFileCollection *pThis = static_cast<CFileCollection *>(pUser); - - // check for valid file name format - if(IsDir || !pThis->IsFilenameValid(pFilename)) - return 0; - - // extract the timestamp - int64 Timestamp = pThis->ExtractTimestamp(pFilename+pThis->m_FileDescLength+1); - - // add the entry - pThis->AddEntry(Timestamp); - - return 0; -} - - CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotDelta) { m_pEditor = 0; @@ -420,10 +250,11 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_pMap = 0; m_pConsole = 0; - m_FrameTime = 0.0001f; - m_FrameTimeLow = 1.0f; - m_FrameTimeHigh = 0.0f; - m_Frames = 0; + m_RenderFrameTime = 0.0001f; + m_RenderFrameTimeLow = 1.0f; + m_RenderFrameTimeHigh = 0.0f; + m_RenderFrames = 0; + m_LastRenderTime = time_get(); m_GameTickSpeed = SERVER_TICK_SPEED; @@ -467,6 +298,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_aServerAddressStr[0] = 0; mem_zero(m_aSnapshots, sizeof(m_aSnapshots)); + m_SnapshotStorage.Init(); m_RecivedSnapshots = 0; m_VersionInfo.m_State = CVersionInfo::STATE_INIT; @@ -536,11 +368,6 @@ void CClient::SendReady() SendMsgEx(&Msg, MSGFLAG_VITAL|MSGFLAG_FLUSH); } -bool CClient::RconAuthed() -{ - return m_RconAuthed; -} - void CClient::RconAuth(const char *pName, const char *pPassword) { if(RconAuthed()) @@ -549,6 +376,7 @@ void CClient::RconAuth(const char *pName, const char *pPassword) CMsgPacker Msg(NETMSG_RCON_AUTH); Msg.AddString(pName, 32); Msg.AddString(pPassword, 32); + Msg.AddInt(1); SendMsgEx(&Msg, MSGFLAG_VITAL); } @@ -635,6 +463,9 @@ int *CClient::GetInput(int Tick) // ------ state handling ----- void CClient::SetState(int s) { + if(m_State == IClient::STATE_QUITING) + return; + int Old = m_State; if(g_Config.m_Debug) { @@ -693,12 +524,12 @@ void CClient::Connect(const char *pAddress) ServerInfoRequest(); - if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, NETTYPE_ALL) != 0) + if(net_host_lookup(m_aServerAddressStr, &m_ServerAddress, m_NetClient.NetType()) != 0) { char aBufMsg[256]; str_format(aBufMsg, sizeof(aBufMsg), "could not find the address of %s, connecting to localhost", aBuf); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBufMsg); - net_host_lookup("localhost", &m_ServerAddress, NETTYPE_ALL); + net_host_lookup("localhost", &m_ServerAddress, m_NetClient.NetType()); } m_RconAuthed = 0; @@ -726,6 +557,8 @@ void CClient::DisconnectWithReason(const char *pReason) // m_RconAuthed = 0; + m_UseTempRconCommands = 0; + m_pConsole->DeregisterTempAll(); m_NetClient.Disconnect(pReason); SetState(IClient::STATE_OFFLINE); m_pMap->Unload(); @@ -859,13 +692,13 @@ void CClient::DebugRender() udp = 8 total = 42 */ - FrameTimeAvg = FrameTimeAvg*0.9f + m_FrameTime*0.1f; + FrameTimeAvg = FrameTimeAvg*0.9f + m_RenderFrameTime*0.1f; str_format(aBuffer, sizeof(aBuffer), "ticks: %8d %8d mem %dk %d gfxmem: %dk fps: %3d", m_CurGameTick, m_PredTick, mem_stats()->allocated/1024, mem_stats()->total_allocations, Graphics()->MemoryUsage()/1024, - (int)(1.0f/FrameTimeAvg)); + (int)(1.0f/FrameTimeAvg + 0.5f)); Graphics()->QuadsText(2, 2, 16, 1,1,1,1, aBuffer); @@ -1028,23 +861,26 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) if(m_VersionInfo.m_State == CVersionInfo::STATE_READY && net_addr_comp(&pPacket->m_Address, &m_VersionInfo.m_VersionServeraddr.m_Addr) == 0) { // version info - if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) && + if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(GAME_RELEASE_VERSION)) && mem_comp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0) { - unsigned char *pVersionData = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION); - int VersionMatch = !mem_comp(pVersionData, VERSION_DATA, sizeof(VERSION_DATA)); + char *pVersionData = (char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION); + int VersionMatch = !mem_comp(pVersionData, GAME_RELEASE_VERSION, sizeof(GAME_RELEASE_VERSION)); + + char aVersion[sizeof(GAME_RELEASE_VERSION)]; + str_copy(aVersion, pVersionData, sizeof(aVersion)); char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "version does %s (%d.%d.%d)", + str_format(aBuf, sizeof(aBuf), "version does %s (%s)", VersionMatch ? "match" : "NOT match", - pVersionData[1], pVersionData[2], pVersionData[3]); + aVersion); m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/version", aBuf); // assume version is out of date when version-data doesn't match - if (!VersionMatch) + if(!VersionMatch) { - str_format(m_aVersionStr, sizeof(m_aVersionStr), "%d.%d.%d", pVersionData[1], pVersionData[2], pVersionData[3]); + str_copy(m_aVersionStr, aVersion, sizeof(m_aVersionStr)); } // request the map version list now @@ -1143,13 +979,13 @@ void CClient::ProcessConnlessPacket(CNetChunk *pPacket) Info.m_NumPlayers < 0 || Info.m_NumPlayers > Info.m_NumClients || Info.m_MaxPlayers < 0 || Info.m_MaxPlayers > Info.m_MaxClients) return; - net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress)); + net_addr_str(&pPacket->m_Address, Info.m_aAddress, sizeof(Info.m_aAddress), true); for(int i = 0; i < Info.m_NumClients; i++) { str_copy(Info.m_aClients[i].m_aName, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aClients[i].m_aName)); str_copy(Info.m_aClients[i].m_aClan, Up.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES), sizeof(Info.m_aClients[i].m_aClan)); - Info.m_aClients[i].m_Country = GameClient()->GetCountryIndex(str_toint(Up.GetString())); + Info.m_aClients[i].m_Country = str_toint(Up.GetString()); Info.m_aClients[i].m_Score = str_toint(Up.GetString()); Info.m_aClients[i].m_Player = str_toint(Up.GetString()) != 0 ? true : false; } @@ -1313,11 +1149,31 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_PING_REPLY); SendMsgEx(&Msg, 0); } + else if(Msg == NETMSG_RCON_CMD_ADD) + { + const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC); + const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC); + const char *pParams = Unpacker.GetString(CUnpacker::SANITIZE_CC); + if(Unpacker.Error() == 0) + m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp); + } + else if(Msg == NETMSG_RCON_CMD_REM) + { + const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC); + if(Unpacker.Error() == 0) + m_pConsole->DeregisterTemp(pName); + } else if(Msg == NETMSG_RCON_AUTH_STATUS) { int Result = Unpacker.GetInt(); if(Unpacker.Error() == 0) m_RconAuthed = Result; + int Old = m_UseTempRconCommands; + m_UseTempRconCommands = Unpacker.GetInt(); + if(Unpacker.Error() != 0) + m_UseTempRconCommands = 0; + if(Old != 0 && m_UseTempRconCommands == 0) + m_pConsole->DeregisterTempAll(); } else if(Msg == NETMSG_RCON_LINE) { @@ -1718,7 +1574,6 @@ void CClient::Update() int64 PrevtickStart = (m_aSnapshots[SNAP_PREV]->m_Tick)*time_freq()/50; int PrevPredTick = (int)(PredNow*50/time_freq()); int NewPredTick = PrevPredTick+1; - static float LastPredintra = 0; m_GameIntraTick = (Now - PrevtickStart) / (float)(CurtickStart-PrevtickStart); m_GameTickTime = (Now - PrevtickStart) / (float)Freq; //(float)SERVER_TICK_SPEED); @@ -1735,15 +1590,12 @@ void CClient::Update() if(NewPredTick > m_PredTick) { - LastPredintra = m_PredIntraTick; m_PredTick = NewPredTick; Repredict = 1; // send input SendInput(); } - - LastPredintra = m_PredIntraTick; } // only do sane predictions @@ -1803,7 +1655,7 @@ void CClient::VersionUpdate() { if(m_VersionInfo.m_State == CVersionInfo::STATE_INIT) { - Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_BindAddr.type); + Engine()->HostLookup(&m_VersionInfo.m_VersionServeraddr, g_Config.m_ClVersionServer, m_NetClient.NetType()); m_VersionInfo.m_State = CVersionInfo::STATE_START; } else if(m_VersionInfo.m_State == CVersionInfo::STATE_START) @@ -1841,7 +1693,7 @@ void CClient::InitInterfaces() // fetch interfaces m_pEngine = Kernel()->RequestInterface<IEngine>(); m_pEditor = Kernel()->RequestInterface<IEditor>(); - m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>(); + //m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>(); m_pSound = Kernel()->RequestInterface<IEngineSound>(); m_pGameClient = Kernel()->RequestInterface<IGameClient>(); m_pInput = Kernel()->RequestInterface<IEngineInput>(); @@ -1856,21 +1708,49 @@ void CClient::InitInterfaces() void CClient::Run() { - int64 ReportTime = time_get(); - int64 ReportInterval = time_freq()*1; - m_LocalStartTime = time_get(); m_SnapshotParts = 0; + // init SDL + { + if(SDL_Init(0) < 0) + { + dbg_msg("client", "unable to init SDL base: %s", SDL_GetError()); + return; + } + + atexit(SDL_Quit); // ignore_convention + } + // init graphics - if(m_pGraphics->Init() != 0) - return; + { + if(g_Config.m_GfxThreaded) + m_pGraphics = CreateEngineGraphicsThreaded(); + else + m_pGraphics = CreateEngineGraphics(); + + bool RegisterFail = false; + RegisterFail = RegisterFail || !Kernel()->RegisterInterface(static_cast<IEngineGraphics*>(m_pGraphics)); // register graphics as both + RegisterFail = RegisterFail || !Kernel()->RegisterInterface(static_cast<IGraphics*>(m_pGraphics)); + + if(RegisterFail || m_pGraphics->Init() != 0) + { + dbg_msg("client", "couldn't init graphics"); + return; + } + } + + // init sound, allowed to fail + m_SoundInitFailed = Sound()->Init() != 0; // open socket { NETADDR BindAddr; - mem_zero(&BindAddr, sizeof(BindAddr)); - BindAddr.type = NETTYPE_ALL; + if(g_Config.m_Bindaddr[0] == 0 || net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) != 0) + { + mem_zero(&BindAddr, sizeof(BindAddr)); + BindAddr.type = NETTYPE_ALL; + } if(!m_NetClient.Open(BindAddr, 0)) { dbg_msg("client", "couldn't start network"); @@ -1885,19 +1765,18 @@ void CClient::Run() Input()->Init(); // start refreshing addresses while we load - MasterServer()->RefreshAddresses(m_BindAddr.type); + MasterServer()->RefreshAddresses(m_NetClient.NetType()); // init the editor m_pEditor->Init(); - // init sound, allowed to fail - m_SoundInitFailed = Sound()->Init() != 0; // load data if(!LoadData()) return; GameClient()->OnInit(); + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion()); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); @@ -1922,9 +1801,6 @@ void CClient::Run() while (1) { - int64 FrameStartTime = time_get(); - m_Frames++; - // VersionUpdate(); @@ -1974,7 +1850,10 @@ void CClient::Run() // panic quit button if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyPressed('q')) + { + Quit(); break; + } if(Input()->KeyPressed(KEY_LCTRL) && Input()->KeyPressed(KEY_LSHIFT) && Input()->KeyDown('d')) g_Config.m_Debug ^= 1; @@ -1994,39 +1873,61 @@ void CClient::Run() */ // render - if(g_Config.m_ClEditor) { - if(!m_EditorActive) + if(g_Config.m_ClEditor) { - GameClient()->OnActivateEditor(); - m_EditorActive = true; + if(!m_EditorActive) + { + GameClient()->OnActivateEditor(); + m_EditorActive = true; + } } - - Update(); - m_pEditor->UpdateAndRender(); - DebugRender(); - m_pGraphics->Swap(); - } - else - { - if(m_EditorActive) + else if(m_EditorActive) m_EditorActive = false; Update(); - - if(g_Config.m_DbgStress) + + if(!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle()) { - if((m_Frames%10) == 0) + m_RenderFrames++; + + // update frametime + int64 Now = time_get(); + m_RenderFrameTime = (Now - m_LastRenderTime) / (float)time_freq(); + if(m_RenderFrameTime < m_RenderFrameTimeLow) + m_RenderFrameTimeLow = m_RenderFrameTime; + if(m_RenderFrameTime > m_RenderFrameTimeHigh) + m_RenderFrameTimeHigh = m_RenderFrameTime; + m_FpsGraph.Add(1.0f/m_RenderFrameTime, 1,1,1); + + m_LastRenderTime = Now; + + if(g_Config.m_DbgStress) + { + if((m_RenderFrames%10) == 0) + { + if(!m_EditorActive) + Render(); + else + { + m_pEditor->UpdateAndRender(); + DebugRender(); + } + m_pGraphics->Swap(); + } + } + else { - Render(); + if(!m_EditorActive) + Render(); + else + { + m_pEditor->UpdateAndRender(); + DebugRender(); + } m_pGraphics->Swap(); } } - else - { - Render(); - m_pGraphics->Swap(); - } } AutoScreenshot_Cleanup(); @@ -2047,32 +1948,25 @@ void CClient::Run() g_Config.m_DbgHitch = 0; } + /* if(ReportTime < time_get()) { if(0 && g_Config.m_Debug) { dbg_msg("client/report", "fps=%.02f (%.02f %.02f) netstate=%d", m_Frames/(float)(ReportInterval/time_freq()), - 1.0f/m_FrameTimeHigh, - 1.0f/m_FrameTimeLow, + 1.0f/m_RenderFrameTimeHigh, + 1.0f/m_RenderFrameTimeLow, m_NetClient.State()); } - m_FrameTimeLow = 1; - m_FrameTimeHigh = 0; - m_Frames = 0; + m_RenderFrameTimeLow = 1; + m_RenderFrameTimeHigh = 0; + m_RenderFrames = 0; ReportTime += ReportInterval; - } - - // update frametime - m_FrameTime = (time_get()-FrameStartTime)/(float)time_freq(); - if(m_FrameTime < m_FrameTimeLow) - m_FrameTimeLow = m_FrameTime; - if(m_FrameTime > m_FrameTimeHigh) - m_FrameTimeHigh = m_FrameTime; + }*/ + // update local time m_LocalTime = (time_get()-m_LocalStartTime)/(float)time_freq(); - - m_FpsGraph.Add(1.0f/m_FrameTime, 1,1,1); } GameClient()->OnShutdown(); @@ -2080,6 +1974,11 @@ void CClient::Run() m_pGraphics->Shutdown(); m_pSound->Shutdown(); + + // shutdown SDL + { + SDL_Quit(); + } } @@ -2270,6 +2169,11 @@ void CClient::DemoRecorder_Stop() m_DemoRecorder.Stop(); } +void CClient::DemoRecorder_AddDemoMarker() +{ + m_DemoRecorder.AddDemoMarker(); +} + void CClient::Con_Record(IConsole::IResult *pResult, void *pUserData) { CClient *pSelf = (CClient *)pUserData; @@ -2285,6 +2189,12 @@ void CClient::Con_StopRecord(IConsole::IResult *pResult, void *pUserData) pSelf->DemoRecorder_Stop(); } +void CClient::Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData) +{ + CClient *pSelf = (CClient *)pUserData; + pSelf->DemoRecorder_AddDemoMarker(); +} + void CClient::ServerBrowserUpdate() { m_ResortServerBrowser = true; @@ -2320,9 +2230,10 @@ void CClient::RegisterCommands() m_pConsole->Register("screenshot", "", CFGFLAG_CLIENT, Con_Screenshot, this, "Take a screenshot"); m_pConsole->Register("rcon", "r", CFGFLAG_CLIENT, Con_Rcon, this, "Send specified command to rcon"); m_pConsole->Register("rcon_auth", "s", CFGFLAG_CLIENT, Con_RconAuth, this, "Authenticate to rcon"); - m_pConsole->Register("play", "r", CFGFLAG_CLIENT, Con_Play, this, "Play the file specified"); + m_pConsole->Register("play", "r", CFGFLAG_CLIENT|CFGFLAG_STORE, Con_Play, this, "Play the file specified"); m_pConsole->Register("record", "?s", CFGFLAG_CLIENT, Con_Record, this, "Record to the file"); m_pConsole->Register("stoprecord", "", CFGFLAG_CLIENT, Con_StopRecord, this, "Stop recording"); + m_pConsole->Register("add_demomarker", "", CFGFLAG_CLIENT, Con_AddDemoMarker, this, "Add demo timeline marker"); m_pConsole->Register("add_favorite", "s", CFGFLAG_CLIENT, Con_AddFavorite, this, "Add a server as a favorite"); m_pConsole->Register("remove_favorite", "s", CFGFLAG_CLIENT, Con_RemoveFavorite, this, "Remove a server from favorites"); @@ -2332,7 +2243,12 @@ void CClient::RegisterCommands() m_pConsole->Chain("br_filter_serveraddress", ConchainServerBrowserUpdate, this); } -static CClient m_Client; +static CClient *CreateClient() +{ + CClient *pClient = static_cast<CClient *>(mem_alloc(sizeof(CClient), 1)); + mem_zero(pClient, sizeof(CClient)); + return new(pClient) CClient; +} /* Server Time @@ -2347,11 +2263,13 @@ static CClient m_Client; */ #if defined(CONF_PLATFORM_MACOSX) -extern "C" int SDL_main(int argc, const char **argv) // ignore_convention +extern "C" int SDL_main(int argc, char **argv_) // ignore_convention +{ + const char **argv = const_cast<const char **>(argv_); #else int main(int argc, const char **argv) // ignore_convention -#endif { +#endif #if defined(CONF_FAMILY_WINDOWS) for(int i = 1; i < argc; i++) // ignore_convention { @@ -2363,16 +2281,16 @@ int main(int argc, const char **argv) // ignore_convention } #endif + CClient *pClient = CreateClient(); IKernel *pKernel = IKernel::Create(); - pKernel->RegisterInterface(&m_Client); - m_Client.RegisterInterfaces(); + pKernel->RegisterInterface(pClient); + pClient->RegisterInterfaces(); // create the components IEngine *pEngine = CreateEngine("Teeworlds"); IConsole *pConsole = CreateConsole(CFGFLAG_CLIENT); - IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); // ignore_convention + IStorage *pStorage = CreateStorage("Teeworlds", IStorage::STORAGETYPE_CLIENT, argc, argv); // ignore_convention IConfig *pConfig = CreateConfig(); - IEngineGraphics *pEngineGraphics = CreateEngineGraphics(); IEngineSound *pEngineSound = CreateEngineSound(); IEngineInput *pEngineInput = CreateEngineInput(); IEngineTextRender *pEngineTextRender = CreateEngineTextRender(); @@ -2386,9 +2304,6 @@ int main(int argc, const char **argv) // ignore_convention RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConsole); RegisterFail = RegisterFail || !pKernel->RegisterInterface(pConfig); - RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineGraphics*>(pEngineGraphics)); // register graphics as both - RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IGraphics*>(pEngineGraphics)); - RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<IEngineSound*>(pEngineSound)); // register as both RegisterFail = RegisterFail || !pKernel->RegisterInterface(static_cast<ISound*>(pEngineSound)); @@ -2418,12 +2333,12 @@ int main(int argc, const char **argv) // ignore_convention pEngineMasterServer->Load(); // register all console commands - m_Client.RegisterCommands(); + pClient->RegisterCommands(); pKernel->RequestInterface<IGameClient>()->OnConsoleInit(); // init client's interfaces - m_Client.InitInterfaces(); + pClient->InitInterfaces(); // execute config file pConsole->ExecuteFile("settings.cfg"); @@ -2438,11 +2353,11 @@ int main(int argc, const char **argv) // ignore_convention // restore empty config strings to their defaults pConfig->RestoreStrings(); - m_Client.Engine()->InitLogfile(); + pClient->Engine()->InitLogfile(); // run the client dbg_msg("client", "starting..."); - m_Client.Run(); + pClient->Run(); // write down the config and quit pConfig->Save(); |