From 83652c91ec44f5cda7c864a7492555c798bb7ff7 Mon Sep 17 00:00:00 2001 From: SushiTee Date: Mon, 1 Aug 2011 21:03:51 +0200 Subject: fixed a warning in client (mac) --- src/game/client/components/countryflags.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/game/client/components') diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index ef350cd7..6daf3c2e 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -94,6 +94,7 @@ void CCountryFlags::OnInit() CCountryFlag DummyEntry; DummyEntry.m_CountryCode = -1; DummyEntry.m_Texture = -1; + mem_zero(DummyEntry.m_aCountryCodeString, sizeof(DummyEntry.m_aCountryCodeString)); m_aCountryFlags.add(DummyEntry); } } -- cgit 1.4.1 From 2b2ddde04f3d61b09129f944387279906c73f6a4 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 4 Aug 2011 23:43:39 +0200 Subject: sort players in kick/move to spec vote and player options by team. Closes #809 --- src/game/client/components/menus_ingame.cpp | 34 +++++++++++++++++------------ src/game/client/gameclient.cpp | 11 ++++++++++ src/game/client/gameclient.h | 1 + 3 files changed, 32 insertions(+), 14 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 1afef922..a809aef0 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -149,7 +149,11 @@ void CMenus::RenderPlayers(CUIRect MainView) static int s_aPlayerIDs[MAX_CLIENTS][2] = {{0}}; for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i) { - if(!m_pClient->m_Snap.m_paPlayerInfos[i] || i == m_pClient->m_Snap.m_LocalClientID) + if(!m_pClient->m_Snap.m_paInfoByTeam[i]) + continue; + + int Index = m_pClient->m_Snap.m_paInfoByTeam[i]->m_ClientID; + if(Index == m_pClient->m_Snap.m_LocalClientID) continue; Options.HSplitTop(28.0f, &ButtonBar, &Options); @@ -159,7 +163,7 @@ void CMenus::RenderPlayers(CUIRect MainView) // player info Player.VSplitLeft(28.0f, &Button, &Player); - CTeeRenderInfo Info = m_pClient->m_aClients[i].m_RenderInfo; + CTeeRenderInfo Info = m_pClient->m_aClients[Index].m_RenderInfo; Info.m_Size = Button.h; RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Button.x+Button.h/2, Button.y+Button.h/2)); @@ -168,31 +172,31 @@ void CMenus::RenderPlayers(CUIRect MainView) CTextCursor Cursor; TextRender()->SetCursor(&Cursor, Player.x, Player.y, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Player.w; - TextRender()->TextEx(&Cursor, m_pClient->m_aClients[i].m_aName, -1); + TextRender()->TextEx(&Cursor, m_pClient->m_aClients[Index].m_aName, -1); TextRender()->SetCursor(&Cursor, Button.x,Button.y, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); Cursor.m_LineWidth = Button.w; - TextRender()->TextEx(&Cursor, m_pClient->m_aClients[i].m_aClan, -1); + TextRender()->TextEx(&Cursor, m_pClient->m_aClients[Index].m_aClan, -1); // ignore button ButtonBar.HMargin(2.0f, &ButtonBar); ButtonBar.VSplitLeft(Width, &Button, &ButtonBar); Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button); Button.VSplitLeft(Button.h, &Button, 0); - if(DoButton_Toggle(&s_aPlayerIDs[i][0], m_pClient->m_aClients[i].m_ChatIgnore, &Button)) - m_pClient->m_aClients[i].m_ChatIgnore ^= 1; + if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button)) + m_pClient->m_aClients[Index].m_ChatIgnore ^= 1; // friend button ButtonBar.VSplitLeft(20.0f, &Button, &ButtonBar); ButtonBar.VSplitLeft(Width, &Button, &ButtonBar); Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button); Button.VSplitLeft(Button.h, &Button, 0); - if(DoButton_Toggle(&s_aPlayerIDs[i][1], m_pClient->m_aClients[i].m_Friend, &Button)) + if(DoButton_Toggle(&s_aPlayerIDs[Index][1], m_pClient->m_aClients[Index].m_Friend, &Button)) { - if(m_pClient->m_aClients[i].m_Friend) - m_pClient->Friends()->RemoveFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan); + if(m_pClient->m_aClients[Index].m_Friend) + m_pClient->Friends()->RemoveFriend(m_pClient->m_aClients[Index].m_aName, m_pClient->m_aClients[Index].m_aClan); else - m_pClient->Friends()->AddFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan); + m_pClient->Friends()->AddFriend(m_pClient->m_aClients[Index].m_aName, m_pClient->m_aClients[Index].m_aClan); } } @@ -385,13 +389,15 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) static int aPlayerIDs[MAX_CLIENTS]; for(int i = 0; i < MAX_CLIENTS; i++) { - if(!m_pClient->m_Snap.m_paPlayerInfos[i] || i == m_pClient->m_Snap.m_LocalClientID) + if(!m_pClient->m_Snap.m_paInfoByTeam[i]) continue; - if(FilterSpectators && m_pClient->m_Snap.m_paPlayerInfos[i]->m_Team == TEAM_SPECTATORS) + + int Index = m_pClient->m_Snap.m_paInfoByTeam[i]->m_ClientID; + if(Index == m_pClient->m_Snap.m_LocalClientID || FilterSpectators && m_pClient->m_Snap.m_paInfoByTeam[i]->m_Team == TEAM_SPECTATORS) continue; - if(m_CallvoteSelectedPlayer == i) + if(m_CallvoteSelectedPlayer == Index) Selected = NumOptions; - aPlayerIDs[NumOptions++] = i; + aPlayerIDs[NumOptions++] = Index; } static int s_VoteList = 0; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 7b6b1192..d110bfe7 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -862,6 +862,17 @@ void CGameClient::OnNewSnapshot() } } } + // sort player infos by team + int Teams[3] = { TEAM_RED, TEAM_BLUE, TEAM_SPECTATORS }; + int Index = 0; + for(int Team = 0; Team < 3; ++Team) + { + for(int i = 0; i < MAX_CLIENTS && Index < MAX_CLIENTS; ++i) + { + if(m_Snap.m_paPlayerInfos[i] && m_Snap.m_paPlayerInfos[i]->m_Team == Teams[Team]) + m_Snap.m_paInfoByTeam[Index++] = m_Snap.m_paPlayerInfos[i]; + } + } CTuningParams StandardTuning; CServerInfo CurrentServerInfo; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 4783f8b4..0dff77d4 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -125,6 +125,7 @@ public: const CNetObj_PlayerInfo *m_paPlayerInfos[MAX_CLIENTS]; const CNetObj_PlayerInfo *m_paInfoByScore[MAX_CLIENTS]; + const CNetObj_PlayerInfo *m_paInfoByTeam[MAX_CLIENTS]; int m_LocalClientID; int m_NumPlayers; -- cgit 1.4.1 From c6fd4a2cc57f8d9dec7164aff98f5a73abc9698d Mon Sep 17 00:00:00 2001 From: Shereef Marzouk Date: Thu, 11 Aug 2011 10:59:14 +0200 Subject: General whitespace and tab cleanup --- src/base/system.c | 8 +- src/engine/client/sound.cpp | 60 ++++++------ src/engine/docs/client_time.txt | 2 +- src/engine/docs/prediction.txt | 2 +- src/engine/docs/server_op.txt | 4 +- src/engine/docs/snapshots.txt | 2 +- src/engine/server/server.cpp | 2 +- src/engine/serverbrowser.h | 2 +- src/engine/shared/console.cpp | 8 +- src/engine/shared/demo.cpp | 2 +- src/engine/shared/masterserver.cpp | 2 +- src/engine/shared/network_console.cpp | 6 +- src/engine/shared/network_console_conn.cpp | 2 +- src/engine/sound.h | 4 +- src/game/client/components/chat.cpp | 2 +- src/game/client/components/hud.cpp | 2 +- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus_browser.cpp | 4 +- src/game/client/components/menus_ingame.cpp | 2 +- src/game/client/components/menus_settings.cpp | 4 +- src/game/client/components/sounds.cpp | 6 +- src/game/editor/auto_map.cpp | 50 +++++----- src/game/editor/auto_map.h | 8 +- src/game/editor/editor.cpp | 130 +++++++++++++------------- src/game/editor/editor.h | 2 +- src/game/editor/layer_tiles.cpp | 4 +- src/game/editor/popups.cpp | 4 +- src/tools/dilate.cpp | 2 +- 28 files changed, 164 insertions(+), 164 deletions(-) (limited to 'src/game/client/components') diff --git a/src/base/system.c b/src/base/system.c index 466e3ca6..e451cb9a 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -1119,7 +1119,7 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a) sockaddr_len = sizeof(addr); s = accept(sock.ipv4sock, (struct sockaddr *)&addr, &sockaddr_len); - + if (s != -1) { sockaddr_to_netaddr((const struct sockaddr *)&addr, a); @@ -1135,7 +1135,7 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a) sockaddr_len = sizeof(addr); s = accept(sock.ipv6sock, (struct sockaddr *)&addr, &sockaddr_len); - + if (s != -1) { sockaddr_to_netaddr((const struct sockaddr *)&addr, a); @@ -1186,7 +1186,7 @@ int net_tcp_send(NETSOCKET sock, const void *data, int size) bytes = send((int)sock.ipv4sock, (const char*)data, size, 0); if(sock.ipv6sock >= 0) bytes = send((int)sock.ipv6sock, (const char*)data, size, 0); - + return bytes; } @@ -1198,7 +1198,7 @@ int net_tcp_recv(NETSOCKET sock, void *data, int maxsize) bytes = recv((int)sock.ipv4sock, (char*)data, maxsize, 0); if(sock.ipv6sock >= 0) bytes = recv((int)sock.ipv6sock, (char*)data, maxsize, 0); - + return bytes; } diff --git a/src/engine/client/sound.cpp b/src/engine/client/sound.cpp index aae52e32..45404d18 100644 --- a/src/engine/client/sound.cpp +++ b/src/engine/client/sound.cpp @@ -19,7 +19,7 @@ enum NUM_SAMPLES = 512, NUM_VOICES = 64, NUM_CHANNELS = 16, - + MAX_FRAMES = 1024 }; @@ -89,9 +89,9 @@ static void Mix(short *pFinalOut, unsigned Frames) // aquire lock while we are mixing lock_wait(m_SoundLock); - + MasterVol = m_SoundVolume; - + for(unsigned i = 0; i < NUM_VOICES; i++) { if(m_aVoices[i].m_pSample) @@ -103,7 +103,7 @@ static void Mix(short *pFinalOut, unsigned Frames) int Step = v->m_pSample->m_Channels; // setup input sources short *pInL = &v->m_pSample->m_pData[v->m_Tick*Step]; short *pInR = &v->m_pSample->m_pData[v->m_Tick*Step+1]; - + unsigned End = v->m_pSample->m_NumFrames-v->m_Tick; int Rvol = v->m_pChannel->m_Vol; @@ -112,7 +112,7 @@ static void Mix(short *pFinalOut, unsigned Frames) // make sure that we don't go outside the sound data if(Frames < End) End = Frames; - + // check if we have a mono sound if(v->m_pSample->m_Channels == 1) pInR = pInL; @@ -133,7 +133,7 @@ static void Mix(short *pFinalOut, unsigned Frames) Lvol = ((Range-p)*Lvol)/Range; else Rvol = ((Range-p)*Rvol)/Range; - + // falloff Lvol = (Lvol*(Range-Dist))/Range; Rvol = (Rvol*(Range-Dist))/Range; @@ -154,7 +154,7 @@ static void Mix(short *pFinalOut, unsigned Frames) pInR += Step; v->m_Tick++; } - + // free voice if not used any more if(v->m_Tick == v->m_pSample->m_NumFrames) { @@ -165,8 +165,8 @@ static void Mix(short *pFinalOut, unsigned Frames) } } } - - + + // release the lock lock_release(m_SoundLock); @@ -201,14 +201,14 @@ int CSound::Init() m_SoundEnabled = 0; m_pGraphics = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); - + SDL_AudioSpec Format; - + m_SoundLock = lock_create(); - + if(!g_Config.m_SndEnable) return 0; - + m_MixingRate = g_Config.m_SndRate; // Set 16-bit stereo audio at 22Khz @@ -229,7 +229,7 @@ int CSound::Init() dbg_msg("client/sound", "sound init successful"); SDL_PauseAudio(0); - + m_SoundEnabled = 1; Update(); // update the volume return 0; @@ -239,17 +239,17 @@ int CSound::Update() { // update volume int WantedVolume = g_Config.m_SndVolume; - + if(!m_pGraphics->WindowActive() && g_Config.m_SndNonactiveMute) WantedVolume = 0; - + if(WantedVolume != m_SoundVolume) { lock_wait(m_SoundLock); m_SoundVolume = WantedVolume; lock_release(m_SoundLock); } - + return 0; } @@ -277,7 +277,7 @@ void CSound::RateConvert(int SampleID) CSample *pSample = &m_aSamples[SampleID]; int NumFrames = 0; short *pNewData = 0; - + // make sure that we need to convert this sound if(!pSample->m_pData || pSample->m_Rate == m_MixingRate) return; @@ -285,7 +285,7 @@ void CSound::RateConvert(int SampleID) // allocate new data NumFrames = (int)((pSample->m_NumFrames/(float)pSample->m_Rate)*m_MixingRate); pNewData = (short *)mem_alloc(NumFrames*pSample->m_Channels*sizeof(short), 1); - + for(int i = 0; i < NumFrames; i++) { // resample TODO: this should be done better, like linear atleast @@ -293,7 +293,7 @@ void CSound::RateConvert(int SampleID) int f = (int)(a*pSample->m_NumFrames); if(f >= pSample->m_NumFrames) f = pSample->m_NumFrames-1; - + // set new data if(pSample->m_Channels == 1) pNewData[i] = pSample->m_pData[f]; @@ -303,7 +303,7 @@ void CSound::RateConvert(int SampleID) pNewData[i*2+1] = pSample->m_pData[f*2+1]; } } - + // free old data and apply new mem_free(pSample->m_pData); pSample->m_pData = pNewData; @@ -321,15 +321,15 @@ int CSound::LoadWV(const char *pFilename) int SampleID = -1; char aError[100]; WavpackContext *pContext; - + // don't waste memory on sound when we are stress testing if(g_Config.m_DbgStress) return -1; - + // no need to load sound when we are running with no sound if(!m_SoundEnabled) return 1; - + if(!m_pStorage) return -1; @@ -372,7 +372,7 @@ int CSound::LoadWV(const char *pFilename) dbg_msg("sound/wv", "file is %d Hz, not 44100 Hz. filename='%s'", snd->rate, filename); return -1; }*/ - + if(BitsPerSample != 16) { dbg_msg("sound/wv", "bps is %d, not 16, filname='%s'", BitsPerSample, pFilename); @@ -382,7 +382,7 @@ int CSound::LoadWV(const char *pFilename) pData = (int *)mem_alloc(4*m_aSamples*m_aChannels, 1); WavpackUnpackSamples(pContext, pData, m_aSamples); // TODO: check return value pSrc = pData; - + pSample->m_pData = (short *)mem_alloc(2*m_aSamples*m_aChannels, 1); pDst = pSample->m_pData; @@ -428,9 +428,9 @@ int CSound::Play(int ChannelID, int SampleID, int Flags, float x, float y) { int VoiceID = -1; int i; - + lock_wait(m_SoundLock); - + // search for voice for(i = 0; i < NUM_VOICES; i++) { @@ -442,7 +442,7 @@ int CSound::Play(int ChannelID, int SampleID, int Flags, float x, float y) break; } } - + // voice found, use it if(VoiceID != -1) { @@ -457,7 +457,7 @@ int CSound::Play(int ChannelID, int SampleID, int Flags, float x, float y) m_aVoices[VoiceID].m_X = (int)x; m_aVoices[VoiceID].m_Y = (int)y; } - + lock_release(m_SoundLock); return VoiceID; } diff --git a/src/engine/docs/client_time.txt b/src/engine/docs/client_time.txt index bc76f91c..0d4dd53e 100644 --- a/src/engine/docs/client_time.txt +++ b/src/engine/docs/client_time.txt @@ -6,6 +6,6 @@ predtick, predintratick prevtick tick predtick 4 8 14 |---------------------|---------------------| - 0 <- intratick -> 1 + 0 <- intratick -> 1 0 <- ticktime(in s)-> X 0 <- predintratick?-> 1 diff --git a/src/engine/docs/prediction.txt b/src/engine/docs/prediction.txt index d5771d1a..e740b1e8 100644 --- a/src/engine/docs/prediction.txt +++ b/src/engine/docs/prediction.txt @@ -8,7 +8,7 @@ Predicted input sent to the server can be retrived by calling > { > int tick; > prediction_reset(); -> +> > for(tick = client_tick()+1; tick <= client_predtick(); tick++) > { > MY_INPUT *input = (MY_INPUT *)client_get_input(); diff --git a/src/engine/docs/server_op.txt b/src/engine/docs/server_op.txt index 59181e62..c0a054c4 100644 --- a/src/engine/docs/server_op.txt +++ b/src/engine/docs/server_op.txt @@ -25,13 +25,13 @@ while running send snapshot end for end - + process new network messages end while unload map (end) - + Section: Reinit diff --git a/src/engine/docs/snapshots.txt b/src/engine/docs/snapshots.txt index 647b049a..adb84863 100644 --- a/src/engine/docs/snapshots.txt +++ b/src/engine/docs/snapshots.txt @@ -48,7 +48,7 @@ After a snapshot have been created, compression is applyed to reduce the bandwid Topic: Interval -The interval for how often a client recives a snapshot changes during the course of the connection. There are three different snapshot rates. +The interval for how often a client recives a snapshot changes during the course of the connection. There are three different snapshot rates. - *Init*. 5 snapshots per second. Used when a client is connecting and used until the client has acknowlaged a snapshot. This mechanism is used because the first snapshot because no delta compression can be done. diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 6f6d9e1c..93e96db9 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -672,7 +672,7 @@ void CServer::SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int Cli void CServer::UpdateClientRconCommands() { int ClientID = Tick() % MAX_CLIENTS; - + if(m_aClients[ClientID].m_State != CClient::STATE_EMPTY && m_aClients[ClientID].m_Authed) { int ConsoleAccessLevel = m_aClients[ClientID].m_Authed == AUTHED_ADMIN ? IConsole::ACCESS_LEVEL_ADMIN : IConsole::ACCESS_LEVEL_MOD; diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 1a49eaf0..79919b09 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -24,7 +24,7 @@ public: int m_Country; int m_Score; bool m_Player; - + int m_FriendState; }; diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index e4cb1991..de5116c1 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -665,7 +665,7 @@ void CConsole::Register(const char *pName, const char *pParams, pCommand->m_pName = pName; pCommand->m_pHelp = pHelp; pCommand->m_pParams = pParams; - + pCommand->m_Flags = Flags; pCommand->m_Temp = false; @@ -699,7 +699,7 @@ void CConsole::RegisterTemp(const char *pName, const char *pParams, int Flags, c } pCommand->m_pfnCallback = 0; - pCommand->m_pUserData = 0; + pCommand->m_pUserData = 0; pCommand->m_Flags = Flags; pCommand->m_Temp = true; @@ -729,7 +729,7 @@ void CConsole::DeregisterTemp(const char *pName) break; } } - + // add to recycle list if(pRemoved) { @@ -742,7 +742,7 @@ void CConsole::DeregisterTempAll() { // set non temp as first one for(; m_pFirstCommand && m_pFirstCommand->m_Temp; m_pFirstCommand = m_pFirstCommand->m_pNext); - + // remove temp entries from command list for(CCommand *pCommand = m_pFirstCommand; pCommand && pCommand->m_pNext; pCommand = pCommand->m_pNext) { diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 51dd51d9..2bd7c28a 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -775,7 +775,7 @@ void CDemoPlayer::GetDemoName(char *pBuffer, int BufferSize) const else if(*pFileName == '.') pEnd = pFileName; } - + int Length = pEnd > pExtractedName ? min(BufferSize, (int)(pEnd-pExtractedName+1)) : BufferSize; str_copy(pBuffer, pExtractedName, Length); } diff --git a/src/engine/shared/masterserver.cpp b/src/engine/shared/masterserver.cpp index 1271eeaf..eb63bab5 100644 --- a/src/engine/shared/masterserver.cpp +++ b/src/engine/shared/masterserver.cpp @@ -157,7 +157,7 @@ public: Added = true; break; } - + if(!Added) { for(int i = 0; i < MAX_MASTERSERVERS; ++i) diff --git a/src/engine/shared/network_console.cpp b/src/engine/shared/network_console.cpp index 13ed3751..cfa081a2 100644 --- a/src/engine/shared/network_console.cpp +++ b/src/engine/shared/network_console.cpp @@ -56,7 +56,7 @@ int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr) { char aError[256] = { 0 }; int FreeSlot = -1; - + // look for free slot or multiple client for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) { @@ -115,7 +115,7 @@ int CNetConsole::Update() } else str_format(aBuf, sizeof(aBuf), "You have been banned for life"); - + net_tcp_send(Socket, aBuf, str_length(aBuf)); net_tcp_close(Socket); } @@ -170,7 +170,7 @@ bool CNetConsole::AddBan(NETADDR Addr, int Seconds) { if(m_NumBans == MAX_BANS) return false; - + Addr.port = 0; int Index = FindBan(Addr); if(Index == -1) diff --git a/src/engine/shared/network_console_conn.cpp b/src/engine/shared/network_console_conn.cpp index 75b581fa..9bc163af 100644 --- a/src/engine/shared/network_console_conn.cpp +++ b/src/engine/shared/network_console_conn.cpp @@ -181,6 +181,6 @@ int CConsoleNetConnection::Send(const char *pLine) pData += Send; Length -= Send; } - + return 0; } diff --git a/src/engine/sound.h b/src/engine/sound.h index f55a978d..fa5bfc85 100644 --- a/src/engine/sound.h +++ b/src/engine/sound.h @@ -19,10 +19,10 @@ public: virtual bool IsSoundEnabled() = 0; virtual int LoadWV(const char *pFilename) = 0; - + virtual void SetChannel(int ChannelID, float Volume, float Panning) = 0; virtual void SetListenerPos(float x, float y) = 0; - + virtual int PlayAt(int ChannelID, int SampleID, int Flags, float x, float y) = 0; virtual int Play(int ChannelID, int SampleID, int Flags) = 0; virtual void Stop(int SampleID) = 0; diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index aba38bf6..a3bf5252 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -283,7 +283,7 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) m_aLines[m_CurrentLine].m_ClientID = ClientID; m_aLines[m_CurrentLine].m_Team = Team; m_aLines[m_CurrentLine].m_NameColor = -2; - + // check for highlighted name const char *pHL = str_find_nocase(pLine, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName); if(pHL) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 11343912..17365116 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -108,7 +108,7 @@ void CHud::RenderScoreHud() if(GameFlags&GAMEFLAG_FLAGS) { - int BlinkTimer = (m_pClient->m_FlagDropTick[t] != 0 && + int BlinkTimer = (m_pClient->m_FlagDropTick[t] != 0 && (Client()->GameTick()-m_pClient->m_FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20; if(FlagCarrier[t] == FLAG_ATSTAND || (FlagCarrier[t] == FLAG_TAKEN && ((Client()->GameTick()/BlinkTimer)&1))) { diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8f330f78..8813c667 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1108,7 +1108,7 @@ int CMenus::Render() Box.HSplitBottom(24.f, &Box, &Part); Box.HSplitBottom(20.f, &Box, 0); Box.VMargin(20.0f, &Box); - + static int ActSelection = -2; if(ActSelection == -2) ActSelection = g_Config.m_BrFilterCountryIndex; diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 8501c67d..825fe3da 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -516,7 +516,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); if (DoButton_CheckBox((char *)&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button)) g_Config.m_BrFilterPureMap ^= 1; - + ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); if (DoButton_CheckBox((char *)&g_Config.m_BrFilterGametypeStrict, Localize("Strict gametype filter"), g_Config.m_BrFilterGametypeStrict, &Button)) g_Config.m_BrFilterGametypeStrict ^= 1; @@ -563,7 +563,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) Button.HMargin(3.0f, &Button); if(DoButton_CheckBox(&g_Config.m_BrFilterCountry, Localize("Player country:"), g_Config.m_BrFilterCountry, &Button)) g_Config.m_BrFilterCountry ^= 1; - + float OldWidth = Rect.w; Rect.w = Rect.h*2; Rect.x += (OldWidth-Rect.w)/2.0f; diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index a809aef0..1afcefe5 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -391,7 +391,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) { if(!m_pClient->m_Snap.m_paInfoByTeam[i]) continue; - + int Index = m_pClient->m_Snap.m_paInfoByTeam[i]->m_ClientID; if(Index == m_pClient->m_Snap.m_LocalClientID || FilterSpectators && m_pClient->m_Snap.m_paInfoByTeam[i]->m_Team == TEAM_SPECTATORS) continue; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 51fdbd29..7692ac27 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -543,7 +543,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) WeaponSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &WeaponSettings); UiDoGetButtons(5, 12, WeaponSettings); } - + // defaults { ResetButton.HSplitTop(10.0f, 0, &ResetButton); @@ -554,7 +554,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) m_pClient->m_pBinds->SetDefaults(); } - + // voting settings { VotingSettings.VSplitLeft(10.0f, 0, &VotingSettings); diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index c4ade00e..65fb56fb 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -144,7 +144,7 @@ void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos) if(!pSet->m_NumSounds) return; - + int Flags = 0; if(Chn == CHN_MUSIC) Flags = ISound::FLAG_LOOP; @@ -170,9 +170,9 @@ void CSounds::Stop(int SetId) { if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) return; - + CDataSoundset *pSet = &g_pData->m_aSounds[SetId]; - + for(int i = 0; i < pSet->m_NumSounds; i++) Sound()->Stop(pSet->m_aSounds[i].m_Id); } diff --git a/src/game/editor/auto_map.cpp b/src/game/editor/auto_map.cpp index 528e459b..3abcf0f4 100644 --- a/src/game/editor/auto_map.cpp +++ b/src/game/editor/auto_map.cpp @@ -20,15 +20,15 @@ void CAutoMapper::Load(const char* pTileName) IOHANDLE RulesFile = m_pEditor->Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_ALL); if(!RulesFile) return; - + CLineReader LineReader; LineReader.Init(RulesFile); - + CConfiguration *pCurrentConf = 0; CIndexRule *pCurrentIndex = 0; - + char aBuf[256]; - + // read each line while(char *pLine = LineReader.Get()) { @@ -40,11 +40,11 @@ void CAutoMapper::Load(const char* pTileName) { // new configuration, get the name pLine++; - + CConfiguration NewConf; int ID = m_lConfigs.add(NewConf); pCurrentConf = &m_lConfigs[ID]; - + str_copy(pCurrentConf->m_aName, pLine, str_length(pLine)); } else @@ -54,15 +54,15 @@ void CAutoMapper::Load(const char* pTileName) // new index int ID = 0; char aFlip[128] = ""; - + sscanf(pLine, "Index %d %127s", &ID, aFlip); - + CIndexRule NewIndexRule; NewIndexRule.m_ID = ID; NewIndexRule.m_Flag = 0; NewIndexRule.m_RandomValue = 0; NewIndexRule.m_BaseTile = false; - + if(str_length(aFlip) > 0) { if(!str_comp(aFlip, "XFLIP")) @@ -70,7 +70,7 @@ void CAutoMapper::Load(const char* pTileName) else if(!str_comp(aFlip, "YFLIP")) NewIndexRule.m_Flag = TILEFLAG_HFLIP; } - + // add the index rule object and make it current int ArrayID = pCurrentConf->m_aIndexRules.add(NewIndexRule); pCurrentIndex = &pCurrentConf->m_aIndexRules[ArrayID]; @@ -85,9 +85,9 @@ void CAutoMapper::Load(const char* pTileName) char aValue[128]; int Value = CPosRule::EMPTY; bool IndexValue = false; - + sscanf(pLine, "Pos %d %d %127s", &x, &y, aValue); - + if(!str_comp(aValue, "FULL")) Value = CPosRule::FULL; else if(!str_comp_num(aValue, "INDEX", 5)) @@ -106,12 +106,12 @@ void CAutoMapper::Load(const char* pTileName) } } } - + io_close(RulesFile); - + str_format(aBuf, sizeof(aBuf),"loaded %s", aPath); m_pEditor->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "editor", aBuf); - + m_FileLoaded = true; } @@ -127,14 +127,14 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) { if(!m_FileLoaded || pLayer->m_Readonly || ConfigID < 0 || ConfigID >= m_lConfigs.size()) return; - + CConfiguration *pConf = &m_lConfigs[ConfigID]; - + if(!pConf->m_aIndexRules.size()) return; - + int BaseTile = 1; - + // find base tile if there is one for(int i = 0; i < pConf->m_aIndexRules.size(); ++i) { @@ -144,7 +144,7 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) break; } } - + // auto map ! int MaxIndex = pLayer->m_Width*pLayer->m_Height; for(int y = 0; y < pLayer->m_Height; y++) @@ -159,7 +159,7 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) if(y == 0 || y == pLayer->m_Height-1 || x == 0 || x == pLayer->m_Width-1) continue; - + for(int i = 0; i < pConf->m_aIndexRules.size(); ++i) { if(pConf->m_aIndexRules[i].m_BaseTile) @@ -170,7 +170,7 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) { CPosRule *pRule = &pConf->m_aIndexRules[i].m_aRules[j]; int CheckIndex = (y+pRule->m_Y)*pLayer->m_Width+(x+pRule->m_X); - + if(CheckIndex < 0 || CheckIndex >= MaxIndex) RespectRules = false; else @@ -184,15 +184,15 @@ void CAutoMapper::Proceed(CLayerTiles *pLayer, int ConfigID) { if(pLayer->m_pTiles[CheckIndex].m_Index > 0 && pRule->m_Value == CPosRule::EMPTY) RespectRules = false; - + if(pLayer->m_pTiles[CheckIndex].m_Index == 0 && pRule->m_Value == CPosRule::FULL) RespectRules = false; } } } - + if(RespectRules && - (pConf->m_aIndexRules[i].m_RandomValue <= 1 || (int)((float)rand() / ((float)RAND_MAX + 1) * pConf->m_aIndexRules[i].m_RandomValue) == 1)) + (pConf->m_aIndexRules[i].m_RandomValue <= 1 || (int)((float)rand() / ((float)RAND_MAX + 1) * pConf->m_aIndexRules[i].m_RandomValue) == 1)) { pTile->m_Index = pConf->m_aIndexRules[i].m_ID; pTile->m_Flags = pConf->m_aIndexRules[i].m_Flag; diff --git a/src/game/editor/auto_map.h b/src/game/editor/auto_map.h index ee570378..c5537d4f 100644 --- a/src/game/editor/auto_map.h +++ b/src/game/editor/auto_map.h @@ -11,7 +11,7 @@ class CAutoMapper int m_Y; int m_Value; bool m_IndexValue; - + enum { EMPTY=0, @@ -33,16 +33,16 @@ class CAutoMapper array m_aIndexRules; char m_aName[128]; }; - + public: CAutoMapper(class CEditor *pEditor); - + void Load(const char* pTileName); void Proceed(class CLayerTiles *pLayer, int ConfigID); int ConfigNamesNum() { return m_lConfigs.size(); } const char* GetConfigName(int Index); - + const bool IsLoaded() { return m_FileLoaded; } private: array m_lConfigs; diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 84308ab6..b7c1d0cb 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -164,7 +164,7 @@ void CEditorImage::AnalyseTileFlags() int tw = m_Width/16; // tilesizes int th = m_Height/16; if ( tw == th ) - { + { unsigned char *pPixelData = (unsigned char *)m_pData; int TileID = 0; @@ -381,8 +381,8 @@ float CEditor::UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Curre Handle.y += (pRect->h-Handle.h)*Current; // logic - float Ret = Current; - int Inside = UI()->MouseInside(&Handle); + float Ret = Current; + int Inside = UI()->MouseInside(&Handle); if(UI()->ActiveItem() == pID) { @@ -423,7 +423,7 @@ float CEditor::UiDoScrollbarV(const void *pID, const CUIRect *pRect, float Curre Slider.Margin(5.0f, &Slider); RenderTools()->DrawUIRect(&Slider, vec4(1,1,1,0.25f)*ButtonColorMul(pID), CUI::CORNER_ALL, 2.5f); - return Ret; + return Ret; } vec4 CEditor::GetButtonColor(const void *pID, int Checked) @@ -490,7 +490,7 @@ int CEditor::DoButton_File(const void *pID, const char *pText, int Checked, cons int CEditor::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { CUIRect r = *pRect; - RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f); + RenderTools()->DrawUIRect(&r, vec4(0.5f, 0.5f, 0.5f, 1.0f), CUI::CORNER_T, 3.0f); r = *pRect; r.VMargin(5.0f, &r); @@ -515,18 +515,18 @@ int CEditor::DoButton_MenuItem(const void *pID, const char *pText, int Checked, int CEditor::DoButton_Tab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip) { RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), CUI::CORNER_T, 5.0f); - CUIRect NewRect = *pRect; - NewRect.y += NewRect.h/2.0f-7.0f; - UI()->DoLabel(&NewRect, pText, 10, 0, -1); + CUIRect NewRect = *pRect; + NewRect.y += NewRect.h/2.0f-7.0f; + UI()->DoLabel(&NewRect, pText, 10, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } int CEditor::DoButton_Ex(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Flags, const char *pToolTip, int Corners, float FontSize) { RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, Checked), Corners, 3.0f); - CUIRect NewRect = *pRect; - NewRect.HMargin(NewRect.h/2.0f-FontSize/2.0f-1.0f, &NewRect); - UI()->DoLabel(&NewRect, pText, FontSize, 0, -1); + CUIRect NewRect = *pRect; + NewRect.HMargin(NewRect.h/2.0f-FontSize/2.0f-1.0f, &NewRect); + UI()->DoLabel(&NewRect, pText, FontSize, 0, -1); return DoButton_Editor_Common(pID, pText, Checked, pRect, Flags, pToolTip); } @@ -550,7 +550,7 @@ void CEditor::RenderGrid(CLayerGroup *pGroup) return; float aGroupPoints[4]; - pGroup->Mapping(aGroupPoints); + pGroup->Mapping(aGroupPoints); float w = UI()->Screen()->w; float h = UI()->Screen()->h; @@ -562,7 +562,7 @@ void CEditor::RenderGrid(CLayerGroup *pGroup) int XGridOffset = XOffset % m_GridFactor; int YGridOffset = YOffset % m_GridFactor; - Graphics()->TextureSet(-1); + Graphics()->TextureSet(-1); Graphics()->LinesBegin(); for(int i = 0; i < (int)w; i++) @@ -601,9 +601,9 @@ void CEditor::RenderBackground(CUIRect View, int Texture, float Size, float Brig int CEditor::UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip) { - // logic - static float s_Value; - int Inside = UI()->MouseInside(pRect); + // logic + static float s_Value; + int Inside = UI()->MouseInside(pRect); if(UI()->ActiveItem() == pID) { @@ -652,9 +652,9 @@ int CEditor::UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, in char aBuf[128]; str_format(aBuf, sizeof(aBuf),"%s %d", pLabel, Current); RenderTools()->DrawUIRect(pRect, GetButtonColor(pID, 0), CUI::CORNER_ALL, 5.0f); - pRect->y += pRect->h/2.0f-7.0f; - UI()->DoLabel(pRect, aBuf, 10, 0, -1); - + pRect->y += pRect->h/2.0f-7.0f; + UI()->DoLabel(pRect, aBuf, 10, 0, -1); + return Current; } @@ -713,7 +713,7 @@ void CEditor::CallbackAppendMap(const char *pFileName, int StorageType, void *pU pEditor->m_aFileName[0] = 0; else pEditor->SortImages(); - + pEditor->m_Dialog = DIALOG_NONE; } void CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUser) @@ -734,7 +734,7 @@ void CEditor::CallbackSaveMap(const char *pFileName, int StorageType, void *pUse pEditor->m_ValidSaveFilename = StorageType == IStorage::TYPE_SAVE && pEditor->m_pFileDialogPath == pEditor->m_aFileDialogCurrentFolder; pEditor->m_Map.m_Modified = false; } - + pEditor->m_Dialog = DIALOG_NONE; } @@ -742,11 +742,11 @@ void CEditor::DoToolbar(CUIRect ToolBar) { CUIRect TB_Top, TB_Bottom; CUIRect Button; - + ToolBar.HSplitTop(ToolBar.h/2.0f, &TB_Top, &TB_Bottom); - - TB_Top.HSplitBottom(2.5f, &TB_Top, 0); - TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom); + + TB_Top.HSplitBottom(2.5f, &TB_Top, 0); + TB_Bottom.HSplitTop(2.5f, 0, &TB_Bottom); // ctrl+o to open if(Input()->KeyDown('o') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) @@ -763,7 +763,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) // ctrl+s to save if(Input()->KeyDown('s') && (Input()->KeyPressed(KEY_LCTRL) || Input()->KeyPressed(KEY_RCTRL))) { - if(m_aFileName[0] && m_ValidSaveFilename) + if(m_aFileName[0] && m_ValidSaveFilename) { str_copy(m_aFileSaveName, m_aFileName, sizeof(m_aFileSaveName)); m_PopupEventType = POPEVENT_SAVE; @@ -947,13 +947,13 @@ void CEditor::DoToolbar(CUIRect ToolBar) } } } - + // tile manipulation { TB_Bottom.VSplitLeft(40.0f, &Button, &TB_Bottom); static int s_BorderBut = 0; CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); - + if(DoButton_Editor(&s_BorderBut, "Border", pT?0:-1, &Button, 0, "Adds border tiles")) { if(pT) @@ -1102,14 +1102,14 @@ void CEditor::DoQuad(CQuad *q, int Index) y = (int)((wy+(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); else y = (int)((wy-(LineDistance/2)*m_GridFactor)/(LineDistance*m_GridFactor)) * (LineDistance*m_GridFactor); - + int OldX = q->m_aPoints[4].x; int OldY = q->m_aPoints[4].y; q->m_aPoints[4].x = f2fx(x); q->m_aPoints[4].y = f2fx(y); int DiffX = q->m_aPoints[4].x - OldX; int DiffY = q->m_aPoints[4].y - OldY; - + for(int v = 0; v < 4; v++) { q->m_aPoints[v].x += DiffX; @@ -1198,7 +1198,7 @@ void CEditor::DoQuad(CQuad *q, int Index) { if(m_SelectedQuad != Index) m_SelectedPoints = 0; - m_SelectedQuad = Index; + m_SelectedQuad = Index; s_Operation = OP_CONTEXT_MENU; UI()->SetActiveItem(pID); } @@ -1295,12 +1295,12 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V) for(int m = 0; m < 4; m++) if(m_SelectedPoints&(1<m_aTexcoords[m].x += f2fx(dx*0.001f); pQuad->m_aTexcoords[(m+2)%4].x += f2fx(dx*0.001f); - + pQuad->m_aTexcoords[m].y += f2fx(dy*0.001f); pQuad->m_aTexcoords[m^1].y += f2fx(dy*0.001f); } @@ -1590,8 +1590,8 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { if(!UI()->MouseButton(0)) { - for(int k = 0; k < NumEditLayers; k++) - pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r); + for(int k = 0; k < NumEditLayers; k++) + pEditLayers[k]->FillSelection(m_Brush.IsEmpty(), m_Brush.m_lLayers[0], r); } else { @@ -1623,10 +1623,10 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) } } - + CLayerTiles *pLayer = (CLayerTiles*)GetSelectedLayerType(0, LAYERTYPE_TILES); if((Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) && pLayer) - s_Operation = OP_BRUSH_PAINT; + s_Operation = OP_BRUSH_PAINT; } if(!m_Brush.IsEmpty()) @@ -1736,7 +1736,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar) { CLayerGroup *g = m_Map.m_pGameGroup; g->MapScreen(); - + Graphics()->TextureSet(-1); Graphics()->LinesBegin(); @@ -1935,7 +1935,7 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int * if(pProps[i].m_Value < 0) str_copy(aBuf, "None", sizeof(aBuf)); else - str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Value]->m_aName); + str_format(aBuf, sizeof(aBuf),"%s", m_Map.m_lImages[pProps[i].m_Value]->m_aName); if(DoButton_Editor(&pIDs[i], aBuf, 0, &Shifter, 0, 0)) PopupSelectImageInvoke(pProps[i].m_Value, UI()->MouseX(), UI()->MouseY()); @@ -2174,8 +2174,8 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser) pEditor->SortImages(); for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i) { - if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName)) - pEditor->m_SelectedImage = i; + if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, pImg->m_aName)) + pEditor->m_SelectedImage = i; } pEditor->m_Dialog = DIALOG_NONE; } @@ -2192,8 +2192,8 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser) ExtractName(pFileName, aBuf, sizeof(aBuf)); for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i) { - if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, aBuf)) - return; + if(!str_comp(pEditor->m_Map.m_lImages[i]->m_aName, aBuf)) + return; } CEditorImage *pImg = new CEditorImage(pEditor); @@ -2319,7 +2319,7 @@ void CEditor::SortImages() gs_pSortedIndex = 0; } } - + void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View) { @@ -2750,7 +2750,7 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle str_copy(m_aFileDialogFileName, pDefaultName, sizeof(m_aFileDialogFileName)); if(pBasePath) str_copy(m_aFileDialogCurrentFolder, pBasePath, sizeof(m_aFileDialogCurrentFolder)); - + FilelistPopulate(m_FileDialogStorageType); m_Dialog = DIALOG_FILE; @@ -2770,10 +2770,10 @@ void CEditor::RenderModebar(CUIRect View) const char *pButName = m_Mode == MODE_LAYERS ? "Layers" : "Images"; if(DoButton_Tab(&s_Button, pButName, 0, &Button, 0, "Switch between images and layers managment.")) { - if(m_Mode == MODE_LAYERS) - m_Mode = MODE_IMAGES; - else - m_Mode = MODE_LAYERS; + if(m_Mode == MODE_LAYERS) + m_Mode = MODE_IMAGES; + else + m_Mode = MODE_LAYERS; } } @@ -3127,7 +3127,7 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) UI()->SetActiveItem(0); } else - { + { if(Input()->KeyPressed(KEY_LSHIFT) || Input()->KeyPressed(KEY_RSHIFT)) { if(i != 0) @@ -3482,12 +3482,12 @@ void CEditor::Reset(bool CreateDefault) m_SelectedPoints = 0; m_SelectedEnvelope = 0; m_SelectedImage = 0; - + m_WorldOffsetX = 0; m_WorldOffsetY = 0; m_EditorOffsetX = 0.0f; m_EditorOffsetY = 0.0f; - + m_WorldZoom = 1.0f; m_ZoomLevel = 200; @@ -3633,19 +3633,19 @@ void CEditor::Init() void CEditor::DoMapBorder() { - CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); - - for(int i = 0; i < pT->m_Width*2; ++i) - pT->m_pTiles[i].m_Index = 1; - - for(int i = 0; i < pT->m_Width*pT->m_Height; ++i) - { - if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3) - pT->m_pTiles[i].m_Index = 1; - } - - for(int i = (pT->m_Width*(pT->m_Height-2)); i < pT->m_Width*pT->m_Height; ++i) - pT->m_pTiles[i].m_Index = 1; + CLayerTiles *pT = (CLayerTiles *)GetSelectedLayerType(0, LAYERTYPE_TILES); + + for(int i = 0; i < pT->m_Width*2; ++i) + pT->m_pTiles[i].m_Index = 1; + + for(int i = 0; i < pT->m_Width*pT->m_Height; ++i) + { + if(i%pT->m_Width < 2 || i%pT->m_Width > pT->m_Width-3) + pT->m_pTiles[i].m_Index = 1; + } + + for(int i = (pT->m_Width*(pT->m_Height-2)); i < pT->m_Width*pT->m_Height; ++i) + pT->m_pTiles[i].m_Index = 1; } void CEditor::UpdateAndRender() diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 1a904953..db99a78c 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -713,7 +713,7 @@ public: void PopupSelectGametileOpInvoke(float x, float y); int PopupSelectGameTileOpResult(); - + void PopupSelectConfigAutoMapInvoke(float x, float y); int PopupSelectConfigAutoMapResult(); diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index eb78a23d..7532c1bd 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -363,7 +363,7 @@ void CLayerTiles::ShowInfo() int CLayerTiles::RenderProperties(CUIRect *pToolBox) { CUIRect Button; - + bool InGameGroup = !find_linear(m_pEditor->m_Map.m_pGameGroup->m_lLayers.all(), this).empty(); if(m_pEditor->m_Map.m_pGameLayer != this) { @@ -373,7 +373,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) pToolBox->HSplitBottom(12.0f, pToolBox, &Button); if(m_pEditor->DoButton_Editor(&s_AutoMapperButton, "Auto map", 0, &Button, 0, "")) m_pEditor->PopupSelectConfigAutoMapInvoke(m_pEditor->UI()->MouseX(), m_pEditor->UI()->MouseY()); - + int Result = m_pEditor->PopupSelectConfigAutoMapResult(); if(Result > -1) { diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 0d8036e3..a97146aa 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -811,7 +811,7 @@ int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View) CUIRect Button; static int s_AutoMapperConfigButtons[256]; CAutoMapper *pAutoMapper = &pEditor->m_Map.m_lImages[pLayer->m_Image]->m_AutoMapper; - + for(int i = 0; i < pAutoMapper->ConfigNamesNum(); ++i) { View.HSplitTop(2.0f, 0, &View); @@ -837,7 +837,7 @@ int CEditor::PopupSelectConfigAutoMapResult() { if(s_AutoMapConfigSelected < 0) return -1; - + int Result = s_AutoMapConfigSelected; s_AutoMapConfigSelected = -1; return Result; diff --git a/src/tools/dilate.cpp b/src/tools/dilate.cpp index eb770a90..55094a5b 100644 --- a/src/tools/dilate.cpp +++ b/src/tools/dilate.cpp @@ -96,7 +96,7 @@ int main(int argc, const char **argv) dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]); return -1; } - + for(int i = 1; i < argc; i++) DilateFile(argv[i]); return 0; -- cgit 1.4.1 From b1e7797b19ca15bd644a98492fc75f0bd73ae76d Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 19 Aug 2011 00:12:30 +0200 Subject: fixed compiling with mingw --- src/base/detect.h | 2 +- src/game/client/components/menus_ingame.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/game/client/components') diff --git a/src/base/detect.h b/src/base/detect.h index f9ca5779..f802b119 100644 --- a/src/base/detect.h +++ b/src/base/detect.h @@ -77,7 +77,7 @@ /* use gcc endianness definitions when available */ -#if defined(__GNUC__) && !defined(__APPLE__) +#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__MINGW32__) #if defined(__FreeBSD__) || defined(__OpenBSD__) #include #else diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 1afcefe5..3a4ad6f2 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -393,7 +393,7 @@ void CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators) continue; int Index = m_pClient->m_Snap.m_paInfoByTeam[i]->m_ClientID; - if(Index == m_pClient->m_Snap.m_LocalClientID || FilterSpectators && m_pClient->m_Snap.m_paInfoByTeam[i]->m_Team == TEAM_SPECTATORS) + if(Index == m_pClient->m_Snap.m_LocalClientID || (FilterSpectators && m_pClient->m_Snap.m_paInfoByTeam[i]->m_Team == TEAM_SPECTATORS)) continue; if(m_CallvoteSelectedPlayer == Index) Selected = NumOptions; -- cgit 1.4.1 From 05f77f64affc2445c7e386088e97c6411664cab3 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 30 Nov 2011 01:41:00 +0100 Subject: added caching for the play command. Closes #891 --- src/engine/client/client.cpp | 2 +- src/game/client/components/menus.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/game/client/components') diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index bec7d4d6..9f43b9ce 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2154,7 +2154,7 @@ 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_favorite", "s", CFGFLAG_CLIENT, Con_AddFavorite, this, "Add a server as a favorite"); diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 8813c667..a39139c8 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -35,11 +35,10 @@ vec4 CMenus::ms_GuiColor; vec4 CMenus::ms_ColorTabbarInactiveOutgame; vec4 CMenus::ms_ColorTabbarActiveOutgame; vec4 CMenus::ms_ColorTabbarInactive; -vec4 CMenus::ms_ColorTabbarActive; +vec4 CMenus::ms_ColorTabbarActive = vec4(0,0,0,0.5f); vec4 CMenus::ms_ColorTabbarInactiveIngame; vec4 CMenus::ms_ColorTabbarActiveIngame; - float CMenus::ms_ButtonHeight = 25.0f; float CMenus::ms_ListheaderHeight = 17.0f; float CMenus::ms_FontmodHeight = 0.8f; -- cgit 1.4.1 From df4e11dc8257e7e15ee5a3cf52b0d8743ccb18e7 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 30 Nov 2011 01:47:35 +0100 Subject: fixed fixed camera position when chatting as spectator. Closes #880 --- src/game/client/components/controls.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 81c4d5ae..dd856413 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -209,7 +209,8 @@ void CControls::OnRender() bool CControls::OnMouseMove(float x, float y) { - if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + if((m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) || + (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) return false; m_MousePos += vec2(x, y); // TODO: ugly -- cgit 1.4.1 From e411d8f5917ac3b47f6b5f10432d045dda62e814 Mon Sep 17 00:00:00 2001 From: SushiTee Date: Thu, 1 Dec 2011 18:36:51 +0100 Subject: made envelope rendering more smooth --- src/game/client/components/maplayers.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 096f9cc5..3d9c42e7 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -67,19 +67,30 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); + static int CurrentLocalTick = pInfo->m_CurrentTick; static int LastLocalTick = pInfo->m_CurrentTick; if(!pInfo->m_Paused) - Time += (pInfo->m_CurrentTick-LastLocalTick) / (float)pThis->Client()->GameTickSpeed() * pInfo->m_Speed; + { + if(CurrentLocalTick != pInfo->m_CurrentTick) + { + LastLocalTick = CurrentLocalTick; + CurrentLocalTick = pInfo->m_CurrentTick; + } - pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); + Time = mix(LastLocalTick / (float)pThis->Client()->GameTickSpeed(), + CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), + pThis->Client()->IntraGameTick()); + } - LastLocalTick = pInfo->m_CurrentTick; + pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); } else { if(pThis->m_pClient->m_Snap.m_pGameInfoObj) - Time = (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(); + Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + pThis->Client()->IntraGameTick()); pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); } } -- cgit 1.4.1 From b99ac459bea247f2a2474b345b1dd69e4bd59a69 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 4 Dec 2011 14:04:12 +0100 Subject: fixed envelope rendering when seeking in the demo player --- src/game/client/components/maplayers.cpp | 30 +++++++++++++++++++++--------- src/game/client/components/maplayers.h | 5 +++++ src/game/client/components/menus_demo.cpp | 3 +++ src/game/client/gameclient.cpp | 2 ++ src/game/client/gameclient.h | 2 ++ 5 files changed, 33 insertions(+), 9 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 3d9c42e7..48f11f26 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -22,6 +22,9 @@ CMapLayers::CMapLayers(int t) { m_Type = t; m_pLayers = 0; + m_CurrentLocalTick = 0; + m_LastLocalTick = 0; + m_EnvelopeUpdate = false; } void CMapLayers::OnInit() @@ -29,6 +32,17 @@ void CMapLayers::OnInit() m_pLayers = Layers(); } +void CMapLayers::EnvelopeUpdate() +{ + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); + m_CurrentLocalTick = pInfo->m_CurrentTick; + m_LastLocalTick = pInfo->m_CurrentTick; + m_EnvelopeUpdate = true; + } +} + void CMapLayers::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup) { @@ -67,19 +81,17 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); - static int CurrentLocalTick = pInfo->m_CurrentTick; - static int LastLocalTick = pInfo->m_CurrentTick; - - if(!pInfo->m_Paused) + + if(!pInfo->m_Paused || pThis->m_EnvelopeUpdate) { - if(CurrentLocalTick != pInfo->m_CurrentTick) + if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick) { - LastLocalTick = CurrentLocalTick; - CurrentLocalTick = pInfo->m_CurrentTick; + pThis->m_LastLocalTick = pThis->m_CurrentLocalTick; + pThis->m_CurrentLocalTick = pInfo->m_CurrentTick; } - Time = mix(LastLocalTick / (float)pThis->Client()->GameTickSpeed(), - CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), + Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), + pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), pThis->Client()->IntraGameTick()); } diff --git a/src/game/client/components/maplayers.h b/src/game/client/components/maplayers.h index 694633ee..d0efcfc7 100644 --- a/src/game/client/components/maplayers.h +++ b/src/game/client/components/maplayers.h @@ -8,6 +8,9 @@ class CMapLayers : public CComponent { CLayers *m_pLayers; // todo refactor: maybe remove it and access it through client* int m_Type; + int m_CurrentLocalTick; + int m_LastLocalTick; + bool m_EnvelopeUpdate; void MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup); static void EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser); @@ -21,6 +24,8 @@ public: CMapLayers(int Type); virtual void OnInit(); virtual void OnRender(); + + void EnvelopeUpdate(); }; #endif diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index f3a75f0c..ec3e648c 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -17,6 +17,7 @@ #include +#include "maplayers.h" #include "menus.h" int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect) @@ -117,6 +118,8 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) m_pClient->m_SuppressEvents = true; DemoPlayer()->SetPos(Amount); m_pClient->m_SuppressEvents = false; + m_pClient->m_pMapLayersBackGround->EnvelopeUpdate(); + m_pClient->m_pMapLayersForeGround->EnvelopeUpdate(); } } } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d110bfe7..2fd1c2f3 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -126,6 +126,8 @@ void CGameClient::OnConsoleInit() m_pVoting = &::gs_Voting; m_pScoreboard = &::gs_Scoreboard; m_pItems = &::gs_Items; + m_pMapLayersBackGround = &::gs_MapLayersBackGround; + m_pMapLayersForeGround = &::gs_MapLayersForeGround; // make a list of all the systems, make sure to add them in the corrent render order m_All.Add(m_pSkins); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 0dff77d4..e8c7e7bd 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -242,6 +242,8 @@ public: class CVoting *m_pVoting; class CScoreboard *m_pScoreboard; class CItems *m_pItems; + class CMapLayers *m_pMapLayersBackGround; + class CMapLayers *m_pMapLayersForeGround; }; -- cgit 1.4.1 From 873c5a77bcf5331b07ae91510492fdd07c89509c Mon Sep 17 00:00:00 2001 From: Choupom Date: Tue, 6 Sep 2011 15:27:56 +0200 Subject: some trivial fixes --- src/game/client/components/items.cpp | 18 +++++++++--------- src/game/client/components/items.h | 4 ++-- src/game/client/render.cpp | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 827b28a7..1c338994 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -17,7 +17,7 @@ void CItems::OnReset() { - ExtraProjectilesNum = 0; + m_NumExtraProjectiles = 0; } void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) @@ -310,23 +310,23 @@ void CItems::OnRender() } // render extra projectiles - for(int i = 0; i < ExtraProjectilesNum; i++) + for(int i = 0; i < m_NumExtraProjectiles; i++) { - if(aExtraProjectiles[i].m_StartTick < Client()->GameTick()) + if(m_aExtraProjectiles[i].m_StartTick < Client()->GameTick()) { - aExtraProjectiles[i] = aExtraProjectiles[ExtraProjectilesNum-1]; - ExtraProjectilesNum--; + m_aExtraProjectiles[i] = m_aExtraProjectiles[m_NumExtraProjectiles-1]; + m_NumExtraProjectiles--; } else - RenderProjectile(&aExtraProjectiles[i], 0); + RenderProjectile(&m_aExtraProjectiles[i], 0); } } void CItems::AddExtraProjectile(CNetObj_Projectile *pProj) { - if(ExtraProjectilesNum != MAX_EXTRA_PROJECTILES) + if(m_NumExtraProjectiles != MAX_EXTRA_PROJECTILES) { - aExtraProjectiles[ExtraProjectilesNum] = *pProj; - ExtraProjectilesNum++; + m_aExtraProjectiles[m_NumExtraProjectiles] = *pProj; + m_NumExtraProjectiles++; } } diff --git a/src/game/client/components/items.h b/src/game/client/components/items.h index 604c1b1c..caf6176b 100644 --- a/src/game/client/components/items.h +++ b/src/game/client/components/items.h @@ -11,8 +11,8 @@ class CItems : public CComponent MAX_EXTRA_PROJECTILES=32, }; - CNetObj_Projectile aExtraProjectiles[MAX_EXTRA_PROJECTILES]; - int ExtraProjectilesNum; + CNetObj_Projectile m_aExtraProjectiles[MAX_EXTRA_PROJECTILES]; + int m_NumExtraProjectiles; void RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID); void RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent); diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp index 93909d0c..278ed51a 100644 --- a/src/game/client/render.cpp +++ b/src/game/client/render.cpp @@ -75,7 +75,7 @@ void CRenderTools::SelectSprite(CDataSprite *pSpr, int Flags, int sx, int sy) void CRenderTools::SelectSprite(int Id, int Flags, int sx, int sy) { - if(Id < 0 || Id > g_pData->m_NumSprites) + if(Id < 0 || Id >= g_pData->m_NumSprites) return; SelectSprite(&g_pData->m_aSprites[Id], Flags, sx, sy); } -- cgit 1.4.1 From 9a03989e84c8d2719801889738c6af68864aba10 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 4 Dec 2011 14:34:27 +0100 Subject: added "Make an option for each envelope: (a) synchronized (b) starting at join" by Choupom --- src/game/client/components/maplayers.cpp | 13 +++++++++---- src/game/editor/editor.cpp | 11 +++++++++++ src/game/editor/editor.h | 2 ++ src/game/editor/io.cpp | 5 ++++- src/game/mapitems.h | 8 +++++++- 5 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 48f11f26..a1e629a6 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -99,10 +99,15 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void } else { - if(pThis->m_pClient->m_Snap.m_pGameInfoObj) - Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + if(pItem->m_Version < 2 || pItem->m_Synchronized) + { + if(pThis->m_pClient->m_Snap.m_pGameInfoObj) + Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + pThis->Client()->IntraGameTick()); + } + else + Time = pThis->Client()->LocalTime(); pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); } } diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 4f4096a9..d2a00d0d 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3179,6 +3179,17 @@ void CEditor::RenderEnvelopeEditor(CUIRect View) if(DoButton_Editor(&s_aChannelButtons[i], s_paNames[pEnvelope->m_Channels-3][i], s_ActiveChannels&Bit, &Button, 0, paDescriptions[pEnvelope->m_Channels-3][i])) s_ActiveChannels ^= Bit; } + + // sync checkbox + ToolBar.VSplitLeft(15.0f, &Button, &ToolBar); + ToolBar.VSplitLeft(12.0f, &Button, &ToolBar); + static int s_SyncButton; + if(DoButton_Editor(&s_SyncButton, pEnvelope->m_Synchronized?"X":"", 0, &Button, 0, "Enable envelope synchronization between clients")) + pEnvelope->m_Synchronized = !pEnvelope->m_Synchronized; + + ToolBar.VSplitLeft(4.0f, &Button, &ToolBar); + ToolBar.VSplitLeft(80.0f, &Button, &ToolBar); + UI()->DoLabel(&Button, "Synchronized", 10.0f, -1, -1); } float EndTime = pEnvelope->EndTime(); diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 1f09b0bc..f5d43dae 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -51,6 +51,7 @@ public: array m_lPoints; char m_aName[32]; float m_Bottom, m_Top; + bool m_Synchronized; CEnvelope(int Chan) { @@ -58,6 +59,7 @@ public: m_aName[0] = 0; m_Bottom = 0; m_Top = 0; + m_Synchronized = true; } void Resort() diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp index 68330f03..aec7231b 100644 --- a/src/game/editor/io.cpp +++ b/src/game/editor/io.cpp @@ -342,10 +342,11 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName) for(int e = 0; e < m_lEnvelopes.size(); e++) { CMapItemEnvelope Item; - Item.m_Version = 1; + Item.m_Version = CMapItemEnvelope::CURRENT_VERSION; Item.m_Channels = m_lEnvelopes[e]->m_Channels; Item.m_StartPoint = PointCount; Item.m_NumPoints = m_lEnvelopes[e]->m_lPoints.size(); + Item.m_Synchronized = m_lEnvelopes[e]->m_Synchronized; StrToInts(Item.m_aName, sizeof(Item.m_aName)/sizeof(int), m_lEnvelopes[e]->m_aName); df.AddItem(MAPITEMTYPE_ENVELOPE, e, sizeof(Item), &Item); @@ -601,6 +602,8 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag if(pItem->m_aName[0] != -1) // compatibility with old maps IntsToStr(pItem->m_aName, sizeof(pItem->m_aName)/sizeof(int), pEnv->m_aName); m_lEnvelopes.add(pEnv); + if(pItem->m_Version >= 2) + pEnv->m_Synchronized = pItem->m_Synchronized; } } } diff --git a/src/game/mapitems.h b/src/game/mapitems.h index 43005f75..bb2f4d19 100644 --- a/src/game/mapitems.h +++ b/src/game/mapitems.h @@ -178,7 +178,7 @@ struct CEnvPoint bool operator<(const CEnvPoint &Other) { return m_Time < Other.m_Time; } } ; -struct CMapItemEnvelope +struct CMapItemEnvelope_v1 { int m_Version; int m_Channels; @@ -187,4 +187,10 @@ struct CMapItemEnvelope int m_aName[8]; } ; +struct CMapItemEnvelope : public CMapItemEnvelope_v1 +{ + enum { CURRENT_VERSION=2 }; + int m_Synchronized; +}; + #endif -- cgit 1.4.1 From 713dd3bc08c0bec4b94b02f990811198f2e6c177 Mon Sep 17 00:00:00 2001 From: Choupom Date: Sun, 4 Dec 2011 18:06:48 +0100 Subject: fixed controls rendering with low ui scale --- src/game/client/components/menus_settings.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 7692ac27..c9b44567 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -504,10 +504,11 @@ void CMenus::RenderSettingsControls(CUIRect MainView) } CUIRect MovementSettings, WeaponSettings, VotingSettings, ChatSettings, MiscSettings, ResetButton; - MainView.VSplitLeft(MainView.w/2-5.0f, &MovementSettings, &VotingSettings); + MainView.VSplitMid(&MovementSettings, &VotingSettings); // movement settings { + MovementSettings.VMargin(5.0f, &MovementSettings); MovementSettings.HSplitTop(MainView.h/3+60.0f, &MovementSettings, &WeaponSettings); RenderTools()->DrawUIRect(&MovementSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); MovementSettings.Margin(10.0f, &MovementSettings); @@ -550,6 +551,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) RenderTools()->DrawUIRect(&ResetButton, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); ResetButton.HMargin(10.0f, &ResetButton); ResetButton.VMargin(30.0f, &ResetButton); + ResetButton.HSplitTop(20.0f, &ResetButton, 0); static int s_DefaultButton = 0; if(DoButton_Menu((void*)&s_DefaultButton, Localize("Reset to defaults"), 0, &ResetButton)) m_pClient->m_pBinds->SetDefaults(); @@ -557,7 +559,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) // voting settings { - VotingSettings.VSplitLeft(10.0f, 0, &VotingSettings); + VotingSettings.VMargin(5.0f, &VotingSettings); VotingSettings.HSplitTop(MainView.h/3-75.0f, &VotingSettings, &ChatSettings); RenderTools()->DrawUIRect(&VotingSettings, vec4(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f); VotingSettings.Margin(10.0f, &VotingSettings); -- cgit 1.4.1 From 6e20c32859ee4518f398a12b65586463ddeecaab Mon Sep 17 00:00:00 2001 From: oy Date: Sat, 10 Dec 2011 18:23:29 +0100 Subject: removed some resource loading spam. Closes #894 --- src/engine/client/graphics.cpp | 2 ++ src/game/client/components/countryflags.cpp | 8 ++++++-- src/game/client/components/skins.cpp | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src/game/client/components') diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index a6b1a47a..617162ae 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -381,6 +381,8 @@ int CGraphics_OpenGL::LoadTexture(const char *pFilename, int StorageType, int St ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags); mem_free(Img.m_pData); + if(ID != m_InvalidTexture && g_Config.m_Debug) + dbg_msg("graphics/texture", "loaded %s", pFilename); return ID; } diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index 6daf3c2e..c2af9a59 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "countryflags.h" @@ -72,8 +73,11 @@ void CCountryFlags::LoadCountryflagsIndexfile() str_copy(CountryFlag.m_aCountryCodeString, aOrigin, sizeof(CountryFlag.m_aCountryCodeString)); CountryFlag.m_Texture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); mem_free(Info.m_pData); - str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", aOrigin); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); + if(g_Config.m_Debug) + { + str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", aOrigin); + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); + } m_aCountryFlags.add(CountryFlag); } io_close(File); diff --git a/src/game/client/components/skins.cpp b/src/game/client/components/skins.cpp index dd38e9ea..babf49bb 100644 --- a/src/game/client/components/skins.cpp +++ b/src/game/client/components/skins.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "skins.h" @@ -103,8 +104,11 @@ int CSkins::SkinScan(const char *pName, int IsDir, int DirType, void *pUser) // set skin data str_copy(Skin.m_aName, pName, min((int)sizeof(Skin.m_aName),l-3)); - str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName); - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); + if(g_Config.m_Debug) + { + str_format(aBuf, sizeof(aBuf), "load skin %s", Skin.m_aName); + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf); + } pSelf->m_aSkins.add(Skin); return 0; -- cgit 1.4.1 From b44ee3d9755ff35a6df1358dcfe85ce681bbe081 Mon Sep 17 00:00:00 2001 From: oy Date: Thu, 29 Dec 2011 23:36:53 +0100 Subject: reworked ban system --- src/base/system.c | 22 +- src/base/system.h | 17 +- src/engine/client/client.cpp | 2 +- src/engine/client/serverbrowser.cpp | 11 +- src/engine/server/server.cpp | 331 ++++++----------- src/engine/server/server.h | 33 +- src/engine/shared/config.cpp | 7 +- src/engine/shared/console.cpp | 11 +- src/engine/shared/econ.cpp | 17 +- src/engine/shared/econ.h | 3 +- src/engine/shared/masterserver.cpp | 6 +- src/engine/shared/netban.cpp | 615 +++++++++++++++++++++++++++++++ src/engine/shared/netban.h | 184 +++++++++ src/engine/shared/network.h | 73 +--- src/engine/shared/network_console.cpp | 97 +---- src/engine/shared/network_server.cpp | 256 +------------ src/game/client/components/console.cpp | 8 +- src/game/client/components/maplayers.cpp | 7 +- src/mastersrv/mastersrv.cpp | 88 ++--- src/tools/crapnet.cpp | 4 +- src/tools/fake_server.cpp | 2 +- 21 files changed, 1060 insertions(+), 734 deletions(-) create mode 100644 src/engine/shared/netban.cpp create mode 100644 src/engine/shared/netban.h (limited to 'src/game/client/components') diff --git a/src/base/system.c b/src/base/system.c index 7b60dab5..bf06a36e 100644 --- a/src/base/system.c +++ b/src/base/system.c @@ -125,7 +125,7 @@ static IOHANDLE logfile = 0; static void logger_file(const char *line) { io_write(logfile, line, strlen(line)); - io_write(logfile, "\n", 1); + io_write_newline(logfile); io_flush(logfile); } @@ -222,8 +222,9 @@ void mem_debug_dump(IOHANDLE file) { while(header) { - str_format(buf, sizeof(buf), "%s(%d): %d\n", header->filename, header->line, header->size); + str_format(buf, sizeof(buf), "%s(%d): %d", header->filename, header->line, header->size); io_write(file, buf, strlen(buf)); + io_write_newline(file); header = header->next; } @@ -346,6 +347,15 @@ unsigned io_write(IOHANDLE io, const void *buffer, unsigned size) return fwrite(buffer, 1, size, (FILE*)io); } +unsigned io_write_newline(IOHANDLE io) +{ +#if defined(CONF_FAMILY_WINDOWS) + return fwrite("\r\n", 1, 2, (FILE*)io); +#else + return fwrite("\n", 1, 1, (FILE*)io); +#endif +} + int io_close(IOHANDLE io) { fclose((FILE*)io); @@ -585,18 +595,18 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b) return mem_comp(a, b, sizeof(NETADDR)); } -void net_addr_str(const NETADDR *addr, char *string, int max_length) +void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port) { if(addr->type == NETTYPE_IPV4) { - if(addr->port != 0) + if(add_port != 0) str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port); else str_format(string, max_length, "%d.%d.%d.%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]); } else if(addr->type == NETTYPE_IPV6) { - if(addr->port != 0) + if(add_port != 0) str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", (addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7], (addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15], @@ -1500,7 +1510,7 @@ int net_socket_read_wait(NETSOCKET sock, int time) return 0; } -unsigned time_timestamp() +int time_timestamp() { return time(0); } diff --git a/src/base/system.h b/src/base/system.h index 749668de..5060fcb0 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -239,6 +239,18 @@ unsigned io_skip(IOHANDLE io, int size); */ unsigned io_write(IOHANDLE io, const void *buffer, unsigned size); +/* + Function: io_write_newline + Writes newline to file. + + Parameters: + io - Handle to the file. + + Returns: + Number of bytes written. +*/ +unsigned io_write_newline(IOHANDLE io); + /* Function: io_seek Seeks to a specified offset in the file. @@ -425,7 +437,7 @@ int64 time_freq(); Returns: The time as a UNIX timestamp */ -unsigned time_timestamp(); +int time_timestamp(); /* Group: Network General */ typedef struct @@ -499,12 +511,13 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b); addr - Address to turn into a string. string - Buffer to fill with the string. max_length - Maximum size of the string. + add_port - add port to string or not Remarks: - The string will always be zero terminated */ -void net_addr_str(const NETADDR *addr, char *string, int max_length); +void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port); /* Function: net_addr_from_str diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 9f43b9ce..c3bd770c 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -964,7 +964,7 @@ 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++) { diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp index 98a22d75..4dda9da9 100644 --- a/src/engine/client/serverbrowser.cpp +++ b/src/engine/client/serverbrowser.cpp @@ -387,7 +387,7 @@ CServerBrowser::CServerEntry *CServerBrowser::Add(const NETADDR &Addr) pEntry->m_Info.m_NetAddr = Addr; pEntry->m_Info.m_Latency = 999; - net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress)); + net_addr_str(&Addr, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aAddress), true); str_copy(pEntry->m_Info.m_aName, pEntry->m_Info.m_aAddress, sizeof(pEntry->m_Info.m_aName)); // check if it's a favorite @@ -527,7 +527,7 @@ void CServerBrowser::RequestImpl(const NETADDR &Addr, CServerEntry *pEntry) cons if(g_Config.m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf),"requesting server info from %s", aAddrStr); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf); @@ -668,7 +668,7 @@ void CServerBrowser::AddFavorite(const NETADDR &Addr) if(g_Config.m_Debug) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "added fav, %s", aAddrStr); m_pConsole->Print(IConsole::OUTPUT_LEVEL_DEBUG, "client_srvbrowse", aBuf); @@ -722,12 +722,11 @@ void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData) { CServerBrowser *pSelf = (CServerBrowser *)pUserData; - int i; char aAddrStr[128]; char aBuffer[256]; - for(i = 0; i < pSelf->m_NumFavoriteServers; i++) + for(int i = 0; i < pSelf->m_NumFavoriteServers; i++) { - net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr)); + net_addr_str(&pSelf->m_aFavoriteServers[i], aAddrStr, sizeof(aAddrStr), true); str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr); pConfig->WriteLine(aBuffer); } diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 09891ba7..9587b94c 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -77,17 +78,6 @@ static void StrUTF8Rtrim(char *pStr) } -static int StrAllnum(const char *pStr) -{ - while(*pStr) - { - if(!(*pStr >= '0' && *pStr <= '9')) - return 0; - pStr++; - } - return 1; -} - CSnapIDPool::CSnapIDPool() { Reset(); @@ -176,6 +166,101 @@ void CSnapIDPool::FreeID(int ID) } } + +void CServerBan::Init(IConsole *pConsole, IStorage *pStorage, CServer* pServer) +{ + CNetBan::Init(pConsole, pStorage); + + m_pServer = pServer; + + // overwrites base command, todo: improve this + Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBanExt, this, "Ban player with ip/client id for x minutes for any reason"); +} + +template +int CServerBan::BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason) +{ + // validate address + if(Server()->m_RconClientID >= 0 && Server()->m_RconClientID < MAX_CLIENTS && + Server()->m_aClients[Server()->m_RconClientID].m_State != CServer::CClient::STATE_EMPTY) + { + if(NetMatch(pData, Server()->m_NetServer.ClientAddr(Server()->m_RconClientID))) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (you can't ban yourself)"); + return -1; + } + + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(i == Server()->m_RconClientID || Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY) + continue; + + if(Server()->m_aClients[i].m_Authed >= Server()->m_RconAuthLevel && NetMatch(pData, Server()->m_NetServer.ClientAddr(i))) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (command denied)"); + return -1; + } + } + } + + int Result = Ban(pBanPool, pData, Seconds, pReason); + if(Result != 0) + return Result; + + // drop banned clients + T::CDataType Data = *pData; + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(Server()->m_aClients[i].m_State == CServer::CClient::STATE_EMPTY) + continue; + + if(NetMatch(&Data, Server()->m_NetServer.ClientAddr(i))) + { + CNetHash NetHash(&Data); + char aBuf[256]; + MakeBanInfo(pBanPool->Find(&Data, &NetHash), aBuf, sizeof(aBuf), MSGTYPE_PLAYER); + Server()->m_NetServer.Drop(i, aBuf); + } + } + + return Result; +} + +int CServerBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason) +{ + return BanExt(&m_BanAddrPool, pAddr, Seconds, pReason); +} + +int CServerBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason) +{ + if(pRange->IsValid()) + return BanExt(&m_BanRangePool, pRange, Seconds, pReason); + + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)"); + return -1; +} + +void CServerBan::ConBanExt(IConsole::IResult *pResult, void *pUser) +{ + CServerBan *pThis = static_cast(pUser); + + const char *pStr = pResult->GetString(0); + int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : 30; + const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given"; + + if(StrAllnum(pStr)) + { + int ClientID = str_toint(pStr); + if(ClientID < 0 || ClientID >= MAX_CLIENTS || pThis->Server()->m_aClients[ClientID].m_State == CServer::CClient::STATE_EMPTY) + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid client id)"); + else + pThis->BanAddr(pThis->Server()->m_NetServer.ClientAddr(ClientID), Minutes*60, pReason); + } + else + ConBan(pResult, pUser); +} + + void CServer::CClient::Reset() { // reset input @@ -368,11 +453,7 @@ int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo) void CServer::GetClientAddr(int ClientID, char *pAddrStr, int Size) { if(ClientID >= 0 && ClientID < MAX_CLIENTS && m_aClients[ClientID].m_State == CClient::STATE_INGAME) - { - NETADDR Addr = m_NetServer.ClientAddr(ClientID); - Addr.port = 0; - net_addr_str(&Addr, pAddrStr, Size); - } + net_addr_str(m_NetServer.ClientAddr(ClientID), pAddrStr, Size, false); } @@ -618,9 +699,8 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) { CServer *pThis = (CServer *)pUser; - NETADDR Addr = pThis->m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pThis->m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); @@ -714,7 +794,6 @@ void CServer::UpdateClientRconCommands() void CServer::ProcessClientPacket(CNetChunk *pPacket) { int ClientID = pPacket->m_ClientID; - NETADDR Addr; CUnpacker Unpacker; Unpacker.Reset(pPacket->m_pData, pPacket->m_DataSize); @@ -793,9 +872,8 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) { if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) { - Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player is ready. ClientID=%x addr=%s", ClientID, aAddrStr); @@ -809,9 +887,8 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) { if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) { - Addr = m_NetServer.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "player has entered the game. ClientID=%x addr=%s", ClientID, aAddrStr); @@ -945,10 +1022,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) if(!g_Config.m_SvRconBantime) m_NetServer.Drop(ClientID, "Too many remote console authentication tries"); else - { - NETADDR Addr = m_NetServer.ClientAddr(ClientID); - BanAdd(Addr, g_Config.m_SvRconBantime*60, "Too many remote console authentication tries"); - } + m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), g_Config.m_SvRconBantime*60, "Too many remote console authentication tries"); } } else @@ -992,7 +1066,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } } -void CServer::SendServerInfo(NETADDR *pAddr, int Token) +void CServer::SendServerInfo(const NETADDR *pAddr, int Token) { CNetChunk Packet; CPacker p; @@ -1061,38 +1135,10 @@ void CServer::UpdateServerInfo() for(int i = 0; i < MAX_CLIENTS; ++i) { if(m_aClients[i].m_State != CClient::STATE_EMPTY) - { - NETADDR Addr = m_NetServer.ClientAddr(i); - SendServerInfo(&Addr, -1); - } + SendServerInfo(m_NetServer.ClientAddr(i), -1); } } -int CServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) -{ - Addr.port = 0; - char aAddrStr[128]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - char aBuf[256]; - if(Seconds) - str_format(aBuf, sizeof(aBuf), "banned %s for %d minutes", aAddrStr, Seconds/60); - else - str_format(aBuf, sizeof(aBuf), "banned %s for life", aAddrStr); - Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - - return m_NetServer.BanAdd(Addr, Seconds, pReason); -} - -int CServer::BanRemove(NETADDR Addr) -{ - return m_NetServer.BanRemove(Addr); -} - -int CServer::BanRemoveAll() -{ - return m_NetServer.BanRemoveAll(); -} - void CServer::PumpNetwork() { @@ -1119,6 +1165,7 @@ void CServer::PumpNetwork() ProcessClientPacket(&Packet); } + m_ServerBan.Update(); m_Econ.Update(); } @@ -1217,7 +1264,7 @@ int CServer::Run() BindAddr.port = g_Config.m_SvPort; } - if(!m_NetServer.Open(BindAddr, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0)) + if(!m_NetServer.Open(BindAddr, &m_ServerBan, g_Config.m_SvMaxClients, g_Config.m_SvMaxClientsPerIP, 0)) { dbg_msg("server", "couldn't open socket. port might already be in use"); return -1; @@ -1225,7 +1272,8 @@ int CServer::Run() m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this); - m_Econ.Init(Console()); + m_ServerBan.Init(Console(), Storage(), this); + m_Econ.Init(Console(), &m_ServerBan); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName); @@ -1388,170 +1436,23 @@ void CServer::ConKick(IConsole::IResult *pResult, void *pUser) ((CServer *)pUser)->Kick(pResult->GetInteger(0), "Kicked by console"); } -void CServer::ConBan(IConsole::IResult *pResult, void *pUser) -{ - NETADDR Addr; - CServer *pServer = (CServer *)pUser; - const char *pStr = pResult->GetString(0); - int Minutes = 30; - const char *pReason = "No reason given"; - - if(pResult->NumArguments() > 1) - Minutes = max(0, pResult->GetInteger(1)); - - if(pResult->NumArguments() > 2) - pReason = pResult->GetString(2); - - if(net_addr_from_str(&Addr, pStr) == 0) - { - if(pServer->m_RconClientID >= 0 && pServer->m_RconClientID < MAX_CLIENTS && pServer->m_aClients[pServer->m_RconClientID].m_State != CClient::STATE_EMPTY) - { - NETADDR AddrCheck = pServer->m_NetServer.ClientAddr(pServer->m_RconClientID); - Addr.port = AddrCheck.port = 0; - if(net_addr_comp(&Addr, &AddrCheck) == 0) - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban yourself"); - return; - } - - for(int i = 0; i < MAX_CLIENTS; ++i) - { - if(i == pServer->m_RconClientID) - continue; - - AddrCheck = pServer->m_NetServer.ClientAddr(i); - AddrCheck.port = 0; - if(net_addr_comp(&Addr, &AddrCheck) == 0 && pServer->m_aClients[i].m_Authed > pServer->m_RconAuthLevel) - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "ban command denied"); - return; - } - } - } - pServer->BanAdd(Addr, Minutes*60, pReason); - } - else if(StrAllnum(pStr)) - { - int ClientID = str_toint(pStr); - - if(ClientID < 0 || ClientID >= MAX_CLIENTS || pServer->m_aClients[ClientID].m_State == CClient::STATE_EMPTY) - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid client id"); - return; - } - else if(pServer->m_RconClientID == ClientID) - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "you can't ban yourself"); - return; - } - else if(pServer->m_aClients[ClientID].m_Authed > pServer->m_RconAuthLevel) - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "ban command denied"); - return; - } - - Addr = pServer->m_NetServer.ClientAddr(ClientID); - pServer->BanAdd(Addr, Minutes*60, pReason); - } - else - { - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid network address to ban"); - return; - } -} - -void CServer::ConUnban(IConsole::IResult *pResult, void *pUser) -{ - NETADDR Addr; - CServer *pServer = (CServer *)pUser; - const char *pStr = pResult->GetString(0); - - if(net_addr_from_str(&Addr, pStr) == 0 && !pServer->BanRemove(Addr)) - { - char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr); - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - } - else if(StrAllnum(pStr)) - { - int BanIndex = str_toint(pStr); - CNetServer::CBanInfo Info; - if(BanIndex < 0 || !pServer->m_NetServer.BanGet(BanIndex, &Info)) - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid ban index"); - else if(!pServer->BanRemove(Info.m_Addr)) - { - char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Info.m_Addr, aAddrStr, sizeof(aAddrStr)); - - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "unbanned %s", aAddrStr); - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); - } - } - else - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "invalid network address"); -} - -void CServer::ConUnbanAll(IConsole::IResult *pResult, void *pUser) -{ - CServer *pServer = (CServer *)pUser; - if(!pServer->BanRemoveAll()) - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "unbanned all"); -} - -void CServer::ConBans(IConsole::IResult *pResult, void *pUser) -{ - unsigned Now = time_timestamp(); - char aBuf[1024]; - char aAddrStr[NETADDR_MAXSTRSIZE]; - CServer* pServer = (CServer *)pUser; - - int Num = pServer->m_NetServer.BanNum(); - for(int i = 0; i < Num; i++) - { - CNetServer::CBanInfo Info; - pServer->m_NetServer.BanGet(i, &Info); - NETADDR Addr = Info.m_Addr; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - - if(Info.m_Expires == -1) - { - str_format(aBuf, sizeof(aBuf), "#%i %s for life", i, aAddrStr); - } - else - { - unsigned t = Info.m_Expires - Now; - str_format(aBuf, sizeof(aBuf), "#%i %s for %d minutes and %d seconds", i, aAddrStr, t/60, t%60); - } - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); - } - str_format(aBuf, sizeof(aBuf), "%d ban(s)", Num); - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); -} - void CServer::ConStatus(IConsole::IResult *pResult, void *pUser) { - int i; - NETADDR Addr; char aBuf[1024]; char aAddrStr[NETADDR_MAXSTRSIZE]; - CServer* pServer = (CServer *)pUser; + CServer* pThis = static_cast(pUser); - for(i = 0; i < MAX_CLIENTS; i++) + for(int i = 0; i < MAX_CLIENTS; i++) { - if(pServer->m_aClients[i].m_State != CClient::STATE_EMPTY) + if(pThis->m_aClients[i].m_State != CClient::STATE_EMPTY) { - Addr = pServer->m_NetServer.ClientAddr(i); - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); - if(pServer->m_aClients[i].m_State == CClient::STATE_INGAME) + net_addr_str(pThis->m_NetServer.ClientAddr(i), aAddrStr, sizeof(aAddrStr), true); + if(pThis->m_aClients[i].m_State == CClient::STATE_INGAME) str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d", i, aAddrStr, - pServer->m_aClients[i].m_aName, pServer->m_aClients[i].m_Score); + pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score); else str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr); - pServer->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } } } @@ -1664,10 +1565,6 @@ void CServer::RegisterCommands() m_pConsole = Kernel()->RequestInterface(); Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason"); - Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_STORE, ConBan, this, "Ban player with ip/id for x minutes for any reason"); - Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnban, this, "Unban ip"); - Console()->Register("unban_all", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConUnbanAll, this, "Clear all bans"); - Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_STORE, ConBans, this, "Show banlist"); Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players"); Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down"); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 4c450a48..2ff06a05 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -5,6 +5,7 @@ #include + class CSnapIDPool { enum @@ -39,6 +40,25 @@ public: void FreeID(int ID); }; + +class CServerBan : public CNetBan +{ + class CServer *m_pServer; + + template int BanExt(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason); + +public: + class CServer *Server() const { return m_pServer; } + + void Init(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer); + + int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason); + int BanRange(const CNetRange *pRange, int Seconds, const char *pReason); + + static void ConBanExt(class IConsole::IResult *pResult, void *pUser); +}; + + class CServer : public IServer { class IGameServer *m_pGameServer; @@ -114,6 +134,7 @@ public: CSnapIDPool m_IDPool; CNetServer m_NetServer; CEcon m_Econ; + CServerBan m_ServerBan; IEngineMap *m_pMap; @@ -184,13 +205,9 @@ public: void ProcessClientPacket(CNetChunk *pPacket); - void SendServerInfo(NETADDR *pAddr, int Token); + void SendServerInfo(const NETADDR *pAddr, int Token); void UpdateServerInfo(); - int BanAdd(NETADDR Addr, int Seconds, const char *pReason); - int BanRemove(NETADDR Addr); - int BanRemoveAll(); - void PumpNetwork(); char *GetMapName(); @@ -200,11 +217,7 @@ public: int Run(); static void ConKick(IConsole::IResult *pResult, void *pUser); - static void ConBan(IConsole::IResult *pResult, void *pUser); - static void ConUnban(IConsole::IResult *pResult, void *pUser); - static void ConUnbanAll(IConsole::IResult *pResult, void *pUser); - static void ConBans(IConsole::IResult *pResult, void *pUser); - static void ConStatus(IConsole::IResult *pResult, void *pUser); + static void ConStatus(IConsole::IResult *pResult, void *pUser); static void ConShutdown(IConsole::IResult *pResult, void *pUser); static void ConRecord(IConsole::IResult *pResult, void *pUser); static void ConStopRecord(IConsole::IResult *pResult, void *pUser); diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index b9aa1320..d0cb7a6b 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -111,13 +111,8 @@ public: { if(!m_ConfigFile) return; -#if defined(CONF_FAMILY_WINDOWS) - static const char Newline[] = "\r\n"; -#else - static const char Newline[] = "\n"; -#endif io_write(m_ConfigFile, pLine, str_length(pLine)); - io_write(m_ConfigFile, Newline, sizeof(Newline)-1); + io_write_newline(m_ConfigFile); } }; diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index de5116c1..1b98a158 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -658,7 +658,13 @@ void CConsole::AddCommandSorted(CCommand *pCommand) void CConsole::Register(const char *pName, const char *pParams, int Flags, FCommandCallback pfnFunc, void *pUser, const char *pHelp) { - CCommand *pCommand = new(mem_alloc(sizeof(CCommand), sizeof(void*))) CCommand; + CCommand *pCommand = FindCommand(pName, Flags); + bool DoAdd = false; + if(pCommand == 0) + { + pCommand = new(mem_alloc(sizeof(CCommand), sizeof(void*))) CCommand; + DoAdd = true; + } pCommand->m_pfnCallback = pfnFunc; pCommand->m_pUserData = pUser; @@ -669,7 +675,8 @@ void CConsole::Register(const char *pName, const char *pParams, pCommand->m_Flags = Flags; pCommand->m_Temp = false; - AddCommandSorted(pCommand); + if(DoAdd) + AddCommandSorted(pCommand); } void CConsole::RegisterTemp(const char *pName, const char *pParams, int Flags, const char *pHelp) diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp index 617cdbd6..3eaf7aac 100644 --- a/src/engine/shared/econ.cpp +++ b/src/engine/shared/econ.cpp @@ -2,14 +2,15 @@ #include #include "econ.h" +#include "netban.h" + int CEcon::NewClientCallback(int ClientID, void *pUser) { CEcon *pThis = (CEcon *)pUser; - NETADDR Addr = pThis->m_NetConsole.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[128]; str_format(aBuf, sizeof(aBuf), "client accepted. cid=%d addr=%s'", ClientID, aAddrStr); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "econ", aBuf); @@ -26,9 +27,8 @@ int CEcon::DelClientCallback(int ClientID, const char *pReason, void *pUser) { CEcon *pThis = (CEcon *)pUser; - NETADDR Addr = pThis->m_NetConsole.ClientAddr(ClientID); char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pThis->m_NetConsole.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); char aBuf[256]; str_format(aBuf, sizeof(aBuf), "client dropped. cid=%d addr=%s reason='%s'", ClientID, aAddrStr, pReason); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "econ", aBuf); @@ -52,7 +52,7 @@ void CEcon::ConchainEconOutputLevelUpdate(IConsole::IResult *pResult, void *pUse } } -void CEcon::Init(IConsole *pConsole) +void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan) { m_pConsole = pConsole; @@ -74,7 +74,7 @@ void CEcon::Init(IConsole *pConsole) BindAddr.port = g_Config.m_EcPort; } - if(m_NetConsole.Open(BindAddr, 0)) + if(m_NetConsole.Open(BindAddr, pNetBan, 0)) { m_NetConsole.SetCallbacks(NewClientCallback, DelClientCallback, this); m_Ready = true; @@ -123,10 +123,7 @@ void CEcon::Update() if(!g_Config.m_EcBantime) m_NetConsole.Drop(ClientID, "Too many authentication tries"); else - { - NETADDR Addr = m_NetConsole.ClientAddr(ClientID); - m_NetConsole.AddBan(Addr, g_Config.m_EcBantime*60); - } + m_NetConsole.NetBan()->BanAddr(m_NetConsole.ClientAddr(ClientID), g_Config.m_EcBantime*60, "Too many authentication tries"); } } } diff --git a/src/engine/shared/econ.h b/src/engine/shared/econ.h index daec34c4..ed7d929b 100644 --- a/src/engine/shared/econ.h +++ b/src/engine/shared/econ.h @@ -3,6 +3,7 @@ #include "network.h" + class CEcon { enum @@ -41,7 +42,7 @@ class CEcon public: IConsole *Console() { return m_pConsole; } - void Init(IConsole *pConsole); + void Init(IConsole *pConsole, class CNetBan *pNetBan); void Update(); void Send(int ClientID, const char *pLine); void Shutdown(); diff --git a/src/engine/shared/masterserver.cpp b/src/engine/shared/masterserver.cpp index eb63bab5..95482639 100644 --- a/src/engine/shared/masterserver.cpp +++ b/src/engine/shared/masterserver.cpp @@ -192,13 +192,13 @@ public: { char aAddrStr[NETADDR_MAXSTRSIZE]; if(m_aMasterServers[i].m_Addr.type != NETTYPE_INVALID) - net_addr_str(&m_aMasterServers[i].m_Addr, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&m_aMasterServers[i].m_Addr, aAddrStr, sizeof(aAddrStr), true); else aAddrStr[0] = 0; char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "%s %s\n", m_aMasterServers[i].m_aHostname, aAddrStr); - + str_format(aBuf, sizeof(aBuf), "%s %s", m_aMasterServers[i].m_aHostname, aAddrStr); io_write(File, aBuf, str_length(aBuf)); + io_write_newline(File); } io_close(File); diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp new file mode 100644 index 00000000..eebe7c84 --- /dev/null +++ b/src/engine/shared/netban.cpp @@ -0,0 +1,615 @@ +#include + +#include +#include +#include + +#include "netban.h" + + +bool CNetBan::StrAllnum(const char *pStr) +{ + while(*pStr) + { + if(!(*pStr >= '0' && *pStr <= '9')) + return false; + pStr++; + } + return true; +} + + +CNetBan::CNetHash::CNetHash(const NETADDR *pAddr) +{ + if(pAddr->type==NETTYPE_IPV4) + m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3])&0xFF; + else + m_Hash = (pAddr->ip[0]+pAddr->ip[1]+pAddr->ip[2]+pAddr->ip[3]+pAddr->ip[4]+pAddr->ip[5]+pAddr->ip[6]+pAddr->ip[7]+ + pAddr->ip[8]+pAddr->ip[9]+pAddr->ip[10]+pAddr->ip[11]+pAddr->ip[12]+pAddr->ip[13]+pAddr->ip[14]+pAddr->ip[15])&0xFF; + m_HashIndex = 0; +} + +CNetBan::CNetHash::CNetHash(const CNetRange *pRange) +{ + m_Hash = 0; + m_HashIndex = 0; + for(int i = 0; pRange->m_LB.ip[i] == pRange->m_UB.ip[i]; ++i) + { + m_Hash += pRange->m_LB.ip[i]; + ++m_HashIndex; + } + m_Hash &= 0xFF; +} + +int CNetBan::CNetHash::MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17]) +{ + int Length = pAddr->type==NETTYPE_IPV4 ? 4 : 16; + aHash[0].m_Hash = 0; + aHash[0].m_HashIndex = 0; + for(int i = 1, Sum = 0; i <= Length; ++i) + { + Sum += pAddr->ip[i-1]; + aHash[i].m_Hash = Sum&0xFF; + aHash[i].m_HashIndex = i%Length; + } + return Length; +} + + +template +typename CNetBan::CBan *CNetBan::CBanPool::Add(const T *pData, const CBanInfo *pInfo, const CNetHash *pNetHash) +{ + if(!m_pFirstFree) + return 0; + + // create new ban + CBan *pBan = m_pFirstFree; + pBan->m_Data = *pData; + pBan->m_Info = *pInfo; + pBan->m_NetHash = *pNetHash; + if(pBan->m_pNext) + pBan->m_pNext->m_pPrev = pBan->m_pPrev; + if(pBan->m_pPrev) + pBan->m_pPrev->m_pNext = pBan->m_pNext; + else + m_pFirstFree = pBan->m_pNext; + + // add it to the hash list + if(m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]) + m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]->m_pHashPrev = pBan; + pBan->m_pHashPrev = 0; + pBan->m_pHashNext = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; + m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash] = pBan; + + // insert it into the used list + if(m_pFirstUsed) + { + for(CBan *p = m_pFirstUsed; ; p = p->m_pNext) + { + if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires)) + { + // insert before + pBan->m_pNext = p; + pBan->m_pPrev = p->m_pPrev; + if(p->m_pPrev) + p->m_pPrev->m_pNext = pBan; + else + m_pFirstUsed = pBan; + p->m_pPrev = pBan; + break; + } + + if(!p->m_pNext) + { + // last entry + p->m_pNext = pBan; + pBan->m_pPrev = p; + pBan->m_pNext = 0; + break; + } + } + } + else + { + m_pFirstUsed = pBan; + pBan->m_pNext = pBan->m_pPrev = 0; + } + + // update ban count + ++m_CountUsed; + + return pBan; +} + +template +int CNetBan::CBanPool::Remove(CBan *pBan) +{ + if(pBan == 0) + return -1; + + // remove from hash list + if(pBan->m_pHashNext) + pBan->m_pHashNext->m_pHashPrev = pBan->m_pHashPrev; + if(pBan->m_pHashPrev) + pBan->m_pHashPrev->m_pHashNext = pBan->m_pHashNext; + else + m_paaHashList[pBan->m_NetHash.m_HashIndex][pBan->m_NetHash.m_Hash] = pBan->m_pHashNext; + pBan->m_pHashNext = pBan->m_pHashPrev = 0; + + // remove from used list + if(pBan->m_pNext) + pBan->m_pNext->m_pPrev = pBan->m_pPrev; + if(pBan->m_pPrev) + pBan->m_pPrev->m_pNext = pBan->m_pNext; + else + m_pFirstUsed = pBan->m_pNext; + + // add to recycle list + if(m_pFirstFree) + m_pFirstFree->m_pPrev = pBan; + pBan->m_pPrev = 0; + pBan->m_pNext = m_pFirstFree; + m_pFirstFree = pBan; + + // update ban count + --m_CountUsed; + + return 0; +} + +template +void CNetBan::CBanPool::Update(CBan *pBan, const CBanInfo *pInfo) +{ + pBan->m_Info = *pInfo; + + // remove from used list + if(pBan->m_pNext) + pBan->m_pNext->m_pPrev = pBan->m_pPrev; + if(pBan->m_pPrev) + pBan->m_pPrev->m_pNext = pBan->m_pNext; + else + m_pFirstUsed = pBan->m_pNext; + + // insert it into the used list + if(m_pFirstUsed) + { + for(CBan *p = m_pFirstUsed; ; p = p->m_pNext) + { + if(p->m_Info.m_Expires == CBanInfo::EXPIRES_NEVER || (pInfo->m_Expires != CBanInfo::EXPIRES_NEVER && pInfo->m_Expires <= p->m_Info.m_Expires)) + { + // insert before + pBan->m_pNext = p; + pBan->m_pPrev = p->m_pPrev; + if(p->m_pPrev) + p->m_pPrev->m_pNext = pBan; + else + m_pFirstUsed = pBan; + p->m_pPrev = pBan; + break; + } + + if(!p->m_pNext) + { + // last entry + p->m_pNext = pBan; + pBan->m_pPrev = p; + pBan->m_pNext = 0; + break; + } + } + } + else + { + m_pFirstUsed = pBan; + pBan->m_pNext = pBan->m_pPrev = 0; + } +} + +template +void CNetBan::CBanPool::Reset() +{ + mem_zero(m_paaHashList, sizeof(m_paaHashList)); + mem_zero(m_aBans, sizeof(m_aBans)); + m_pFirstUsed = 0; + m_CountUsed = 0; + + for(int i = 1; i < MAX_BANS-1; ++i) + { + m_aBans[i].m_pNext = &m_aBans[i+1]; + m_aBans[i].m_pPrev = &m_aBans[i-1]; + } + + m_aBans[0].m_pNext = &m_aBans[1]; + m_aBans[MAX_BANS-1].m_pPrev = &m_aBans[MAX_BANS-2]; + m_pFirstFree = &m_aBans[0]; +} + +template +typename CNetBan::CBan *CNetBan::CBanPool::Find(const T *pData, const CNetHash *pNetHash) const +{ + for(CBan *pBan = m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; pBan; pBan = pBan->m_pHashNext) + { + if(NetComp(&pBan->m_Data, pData) == 0) + return pBan; + } + + return 0; +} + +template +typename CNetBan::CBan *CNetBan::CBanPool::Get(int Index) const +{ + if(Index < 0 || Index >= Num()) + return 0; + + for(CNetBan::CBan *pBan = m_pFirstUsed; pBan; pBan = pBan->m_pNext, --Index) + { + if(Index == 0) + return pBan; + } + + return 0; +} + + +template +void CNetBan::MakeBanInfo(const CBan *pBan, char *pBuf, unsigned BuffSize, int Type) const +{ + if(pBan == 0) + { + if(BuffSize > 0) + pBuf[0] = 0; + return; + } + + // build type based part + char aBuf[256]; + if(Type == MSGTYPE_PLAYER) + str_copy(aBuf, "You have been banned", sizeof(aBuf)); + else + { + char aTemp[256]; + switch(Type) + { + case MSGTYPE_LIST: + str_format(aBuf, sizeof(aBuf), "%s banned", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break; + case MSGTYPE_BANADD: + str_format(aBuf, sizeof(aBuf), "banned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break; + case MSGTYPE_BANREM: + str_format(aBuf, sizeof(aBuf), "unbanned %s", NetToString(&pBan->m_Data, aTemp, sizeof(aTemp))); break; + default: + aBuf[0] = 0; + } + } + + // add info part + if(pBan->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER) + { + int Mins = ((pBan->m_Info.m_Expires-time_timestamp()) + 59) / 60; + if(Mins <= 1) + str_format(pBuf, BuffSize, "%s for 1 minute (%s)", aBuf, pBan->m_Info.m_aReason); + else + str_format(pBuf, BuffSize, "%s for %d minutes (%s)", aBuf, Mins, pBan->m_Info.m_aReason); + } + else + str_format(pBuf, BuffSize, "%s for life (%s)", aBuf, pBan->m_Info.m_aReason); +} + +template +int CNetBan::Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason) +{ + // do not ban localhost + if(NetMatch(pData, &m_LocalhostIPV4) || NetMatch(pData, &m_LocalhostIPV6)) + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (localhost)"); + return -1; + } + + int Stamp = Seconds > 0 ? time_timestamp()+Seconds : CBanInfo::EXPIRES_NEVER; + + // set up info + CBanInfo Info = {0}; + Info.m_Expires = Stamp; + str_copy(Info.m_aReason, pReason, sizeof(Info.m_aReason)); + + // check if it already exists + CNetHash NetHash(pData); + CBan *pBan = pBanPool->Find(pData, &NetHash); + if(pBan) + { + // adjust the ban + pBanPool->Update(pBan, &Info); + char aBuf[128]; + MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + return 1; + } + + // add ban and print result + pBan = pBanPool->Add(pData, &Info, &NetHash); + if(pBan) + { + char aBuf[128]; + MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANADD); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + return 0; + } + else + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (full banlist)"); + return -1; +} + +template +int CNetBan::Unban(T *pBanPool, const typename T::CDataType *pData) +{ + CNetHash NetHash(pData); + CBan *pBan = pBanPool->Find(pData, &NetHash); + if(pBan) + { + char aBuf[256]; + MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_BANREM); + pBanPool->Remove(pBan); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + return 0; + } + else + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban failed (invalid entry)"); + return -1; +} + +void CNetBan::Init(IConsole *pConsole, IStorage *pStorage) +{ + m_pConsole = pConsole; + m_pStorage = pStorage; + m_BanAddrPool.Reset(); + m_BanRangePool.Reset(); + + net_host_lookup("localhost", &m_LocalhostIPV4, NETTYPE_IPV4); + net_host_lookup("localhost", &m_LocalhostIPV6, NETTYPE_IPV6); + + Console()->Register("ban", "s?ir", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBan, this, "Ban ip for x minutes for any reason"); + Console()->Register("ban_range", "ss?ir", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBanRange, this, "Ban ip range for x minutes for any reason"); + Console()->Register("unban", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnban, this, "Unban ip/banlist entry"); + Console()->Register("unban_range", "ss", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnbanRange, this, "Unban ip range"); + Console()->Register("unban_all", "", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConUnbanAll, this, "Unban all entries"); + Console()->Register("bans", "", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBans, this, "Show banlist"); + Console()->Register("bans_save", "s", CFGFLAG_SERVER|CFGFLAG_MASTER|CFGFLAG_STORE, ConBansSave, this, "Save banlist in a file"); +} + +void CNetBan::Update() +{ + int Now = time_timestamp(); + + // remove expired bans + char aBuf[256], aNetStr[256]; + while(m_BanAddrPool.First() && m_BanAddrPool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanAddrPool.First()->m_Info.m_Expires < Now) + { + str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanAddrPool.First()->m_Data, aNetStr, sizeof(aNetStr))); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + m_BanAddrPool.Remove(m_BanAddrPool.First()); + } + while(m_BanRangePool.First() && m_BanRangePool.First()->m_Info.m_Expires != CBanInfo::EXPIRES_NEVER && m_BanRangePool.First()->m_Info.m_Expires < Now) + { + str_format(aBuf, sizeof(aBuf), "ban %s expired", NetToString(&m_BanRangePool.First()->m_Data, aNetStr, sizeof(aNetStr))); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + m_BanRangePool.Remove(m_BanRangePool.First()); + } +} + +int CNetBan::BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason) +{ + return Ban(&m_BanAddrPool, pAddr, Seconds, pReason); +} + +int CNetBan::BanRange(const CNetRange *pRange, int Seconds, const char *pReason) +{ + if(pRange->IsValid()) + return Ban(&m_BanRangePool, pRange, Seconds, pReason); + + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)"); + return -1; +} + +int CNetBan::UnbanByAddr(const NETADDR *pAddr) +{ + return Unban(&m_BanAddrPool, pAddr); +} + +int CNetBan::UnbanByRange(const CNetRange *pRange) +{ + if(pRange->IsValid()) + return Unban(&m_BanRangePool, pRange); + + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban failed (invalid range)"); + return -1; +} + +int CNetBan::UnbanByIndex(int Index) +{ + int Result; + char aBuf[256]; + CBanAddr *pBan = m_BanAddrPool.Get(Index); + if(pBan) + { + NetToString(&pBan->m_Data, aBuf, sizeof(aBuf)); + Result = m_BanAddrPool.Remove(pBan); + } + else + { + CBanRange *pBan = m_BanRangePool.Get(Index-m_BanAddrPool.Num()); + if(pBan) + { + NetToString(&pBan->m_Data, aBuf, sizeof(aBuf)); + Result = m_BanRangePool.Remove(pBan); + } + else + { + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban failed (invalid index)"); + return -1; + } + } + + char aMsg[256]; + str_format(aMsg, sizeof(aMsg), "unbanned index %i (%s)", Index, aBuf); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg); + return Result; +} + +bool CNetBan::IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const +{ + CNetHash aHash[17]; + int Length = CNetHash::MakeHashArray(pAddr, aHash); + + // check ban adresses + CBanAddr *pBan = m_BanAddrPool.Find(pAddr, &aHash[Length]); + if(pBan) + { + MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER); + return true; + } + + // check ban ranges + for(int i = Length-1; i >= 0; --i) + { + for(CBanRange *pBan = m_BanRangePool.First(&aHash[i]); pBan; pBan = pBan->m_pHashNext) + { + if(NetMatch(&pBan->m_Data, pAddr, i, Length)) + { + MakeBanInfo(pBan, pBuf, BufferSize, MSGTYPE_PLAYER); + return true; + } + } + } + + return false; +} + +void CNetBan::ConBan(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + const char *pStr = pResult->GetString(0); + int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : 30; + const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given"; + + NETADDR Addr; + if(net_addr_from_str(&Addr, pStr) == 0) + pThis->BanAddr(&Addr, Minutes*60, pReason); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid network address)"); +} + +void CNetBan::ConBanRange(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + const char *pStr1 = pResult->GetString(0); + const char *pStr2 = pResult->GetString(1); + int Minutes = pResult->NumArguments()>2 ? clamp(pResult->GetInteger(2), 0, 44640) : 30; + const char *pReason = pResult->NumArguments()>3 ? pResult->GetString(3) : "No reason given"; + + CNetRange Range; + if(net_addr_from_str(&Range.m_LB, pStr1) == 0 && net_addr_from_str(&Range.m_UB, pStr2) == 0) + pThis->BanRange(&Range, Minutes*60, pReason); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "ban error (invalid range)"); +} + +void CNetBan::ConUnban(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + const char *pStr = pResult->GetString(0); + if(StrAllnum(pStr)) + pThis->UnbanByIndex(str_toint(pStr)); + else + { + NETADDR Addr; + if(net_addr_from_str(&Addr, pStr) == 0) + pThis->UnbanByAddr(&Addr); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban error (invalid network address)"); + } +} + +void CNetBan::ConUnbanRange(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + const char *pStr1 = pResult->GetString(0); + const char *pStr2 = pResult->GetString(1); + + CNetRange Range; + if(net_addr_from_str(&Range.m_LB, pStr1) == 0 && net_addr_from_str(&Range.m_UB, pStr2) == 0) + pThis->UnbanByRange(&Range); + else + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unban error (invalid range)"); +} + +void CNetBan::ConUnbanAll(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + pThis->UnbanAll(); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", "unbanned all entries"); +} + +void CNetBan::ConBans(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + int Count = 0; + char aBuf[256], aMsg[256]; + for(CBanAddr *pBan = pThis->m_BanAddrPool.First(); pBan; pBan = pBan->m_pNext) + { + pThis->MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST); + str_format(aMsg, sizeof(aMsg), "#%i %s", Count++, aBuf); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg); + } + for(CBanRange *pBan = pThis->m_BanRangePool.First(); pBan; pBan = pBan->m_pNext) + { + pThis->MakeBanInfo(pBan, aBuf, sizeof(aBuf), MSGTYPE_LIST); + str_format(aMsg, sizeof(aMsg), "#%i %s", Count++, aBuf); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg); + } + str_format(aMsg, sizeof(aMsg), "%d %s", Count, Count==1?"ban":"bans"); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aMsg); +} + +void CNetBan::ConBansSave(IConsole::IResult *pResult, void *pUser) +{ + CNetBan *pThis = static_cast(pUser); + + char aBuf[256]; + IOHANDLE File = pThis->Storage()->OpenFile(pResult->GetString(0), IOFLAG_WRITE, IStorage::TYPE_SAVE); + if(!File) + { + str_format(aBuf, sizeof(aBuf), "failed to save banlist to '%s'", pResult->GetString(0)); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); + return; + } + + int Now = time_timestamp(); + char aAddrStr1[NETADDR_MAXSTRSIZE], aAddrStr2[NETADDR_MAXSTRSIZE]; + for(CBanAddr *pBan = pThis->m_BanAddrPool.First(); pBan; pBan = pBan->m_pNext) + { + int Min = pBan->m_Info.m_Expires>-1 ? (pBan->m_Info.m_Expires-Now+59)/60 : -1; + net_addr_str(&pBan->m_Data, aAddrStr1, sizeof(aAddrStr1), false); + str_format(aBuf, sizeof(aBuf), "ban_ip %s %i %s", aAddrStr1, Min, pBan->m_Info.m_aReason); + io_write(File, aBuf, str_length(aBuf)); + io_write_newline(File); + } + for(CBanRange *pBan = pThis->m_BanRangePool.First(); pBan; pBan = pBan->m_pNext) + { + int Min = pBan->m_Info.m_Expires>-1 ? (pBan->m_Info.m_Expires-Now+59)/60 : -1; + net_addr_str(&pBan->m_Data.m_LB, aAddrStr1, sizeof(aAddrStr1), false); + net_addr_str(&pBan->m_Data.m_UB, aAddrStr2, sizeof(aAddrStr2), false); + str_format(aBuf, sizeof(aBuf), "ban_range %s %i %s", aAddrStr1, aAddrStr2, Min, pBan->m_Info.m_aReason); + io_write(File, aBuf, str_length(aBuf)); + io_write_newline(File); + } + + io_close(File); + str_format(aBuf, sizeof(aBuf), "saved banlist to '%s'", pResult->GetString(0)); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "net_ban", aBuf); +} diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h new file mode 100644 index 00000000..a93cc797 --- /dev/null +++ b/src/engine/shared/netban.h @@ -0,0 +1,184 @@ +#ifndef ENGINE_SHARED_NETBAN_H +#define ENGINE_SHARED_NETBAN_H + +#include + + +inline int NetComp(const NETADDR *pAddr1, const NETADDR *pAddr2) +{ + return mem_comp(pAddr1, pAddr2, pAddr1->type==NETTYPE_IPV4 ? 8 : 20); +} + +class CNetRange +{ +public: + NETADDR m_LB; + NETADDR m_UB; + + bool IsValid() const { return m_LB.type == m_UB.type && NetComp(&m_LB, &m_UB) < 0; } +}; + +inline int NetComp(const CNetRange *pRange1, const CNetRange *pRange2) +{ + return NetComp(&pRange1->m_LB, &pRange2->m_LB) || NetComp(&pRange1->m_UB, &pRange2->m_UB); +} + + +class CNetBan +{ +protected: + bool NetMatch(const NETADDR *pAddr1, const NETADDR *pAddr2) const + { + return NetComp(pAddr1, pAddr2) == 0; + } + + bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr, int Start, int Length) const + { + return pRange->m_LB.type == pAddr->type && + mem_comp(&pRange->m_LB.ip[Start], &pAddr->ip[Start], Length-Start) <= 0 && mem_comp(&pRange->m_UB.ip[Start], &pAddr->ip[Start], Length-Start) >= 0; + } + + bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr) const + { + return NetMatch(pRange, pAddr, 0, pRange->m_LB.type==NETTYPE_IPV4 ? 4 : 16); + } + + const char *NetToString(const NETADDR *pData, char *pBuffer, unsigned BufferSize) const + { + char aAddrStr[NETADDR_MAXSTRSIZE]; + net_addr_str(pData, aAddrStr, sizeof(aAddrStr), false); + str_format(pBuffer, BufferSize, "'%s'", aAddrStr); + return pBuffer; + } + + const char *NetToString(const CNetRange *pData, char *pBuffer, unsigned BufferSize) const + { + char aAddrStr1[NETADDR_MAXSTRSIZE], aAddrStr2[NETADDR_MAXSTRSIZE]; + net_addr_str(&pData->m_LB, aAddrStr1, sizeof(aAddrStr1), false); + net_addr_str(&pData->m_UB, aAddrStr2, sizeof(aAddrStr2), false); + str_format(pBuffer, BufferSize, "'%s' - '%s'", aAddrStr1, aAddrStr2); + return pBuffer; + } + + // todo: move? + static bool StrAllnum(const char *pStr); + + class CNetHash + { + public: + int m_Hash; + int m_HashIndex; // matching parts for ranges, 0 for addr + + CNetHash() {} + CNetHash(const NETADDR *pAddr); + CNetHash(const CNetRange *pRange); + + static int MakeHashArray(const NETADDR *pAddr, CNetHash aHash[17]); + }; + + struct CBanInfo + { + enum + { + EXPIRES_NEVER=-1, + REASON_LENGTH=64, + }; + int m_Expires; + char m_aReason[REASON_LENGTH]; + }; + + template struct CBan + { + T m_Data; + CBanInfo m_Info; + CNetHash m_NetHash; + + // hash list + CBan *m_pHashNext; + CBan *m_pHashPrev; + + // used or free list + CBan *m_pNext; + CBan *m_pPrev; + }; + + template class CBanPool + { + public: + typedef T CDataType; + + CBan *Add(const CDataType *pData, const CBanInfo *pInfo, const CNetHash *pNetHash); + int Remove(CBan *pBan); + void Update(CBan *pBan, const CBanInfo *pInfo); + void Reset(); + + int Num() const { return m_CountUsed; } + bool IsFull() const { return m_CountUsed == MAX_BANS; } + + CBan *First() const { return m_pFirstUsed; } + CBan *First(const CNetHash *pNetHash) const { return m_paaHashList[pNetHash->m_HashIndex][pNetHash->m_Hash]; } + CBan *Find(const CDataType *pData, const CNetHash *pNetHash) const; + CBan *Get(int Index) const; + + private: + enum + { + MAX_BANS=1024, + }; + + CBan *m_paaHashList[HashCount][256]; + CBan m_aBans[MAX_BANS]; + CBan *m_pFirstFree; + CBan *m_pFirstUsed; + int m_CountUsed; + }; + + typedef CBanPool CBanAddrPool; + typedef CBanPool CBanRangePool; + typedef CBan CBanAddr; + typedef CBan CBanRange; + + template void MakeBanInfo(const CBan *pBan, char *pBuf, unsigned BuffSize, int Type) const; + template int Ban(T *pBanPool, const typename T::CDataType *pData, int Seconds, const char *pReason); + template int Unban(T *pBanPool, const typename T::CDataType *pData); + + class IConsole *m_pConsole; + class IStorage *m_pStorage; + CBanAddrPool m_BanAddrPool; + CBanRangePool m_BanRangePool; + NETADDR m_LocalhostIPV4, m_LocalhostIPV6; + +public: + enum + { + MSGTYPE_PLAYER=0, + MSGTYPE_LIST, + MSGTYPE_BANADD, + MSGTYPE_BANREM, + }; + + class IConsole *Console() const { return m_pConsole; } + class IStorage *Storage() const { return m_pStorage; } + + virtual ~CNetBan() {} + virtual void Init(class IConsole *pConsole, class IStorage *pStorage); + void Update(); + + virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason); + virtual int BanRange(const CNetRange *pRange, int Seconds, const char *pReason); + int UnbanByAddr(const NETADDR *pAddr); + int UnbanByRange(const CNetRange *pRange); + int UnbanByIndex(int Index); + void UnbanAll() { m_BanAddrPool.Reset(); m_BanRangePool.Reset(); } + bool IsBanned(const NETADDR *pAddr, char *pBuf, unsigned BufferSize) const; + + static void ConBan(class IConsole::IResult *pResult, void *pUser); + static void ConBanRange(class IConsole::IResult *pResult, void *pUser); + static void ConUnban(class IConsole::IResult *pResult, void *pUser); + static void ConUnbanRange(class IConsole::IResult *pResult, void *pUser); + static void ConUnbanAll(class IConsole::IResult *pResult, void *pUser); + static void ConBans(class IConsole::IResult *pResult, void *pUser); + static void ConBansSave(class IConsole::IResult *pResult, void *pUser); +}; + +#endif diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index ca460d67..dd43389e 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -73,8 +73,6 @@ enum NET_CTRLMSG_ACCEPT=3, NET_CTRLMSG_CLOSE=4, - NET_SERVER_MAXBANS=1024, - NET_CONN_BUFFERSIZE=1024*32, NET_ENUM_TERMINATOR @@ -182,7 +180,7 @@ public: const char *ErrorString(); void SignalResend(); int State() const { return m_State; } - NETADDR PeerAddress() const { return m_PeerAddr; } + const NETADDR *PeerAddress() const { return &m_PeerAddr; } void ResetErrorString() { m_ErrorString[0] = 0; } const char *ErrorString() const { return m_ErrorString; } @@ -214,7 +212,7 @@ public: void Disconnect(const char *pReason); int State() const { return m_State; } - NETADDR PeerAddress() const { return m_PeerAddr; } + const NETADDR *PeerAddress() const { return &m_PeerAddr; } const char *ErrorString() const { return m_aErrorString; } void Reset(); @@ -244,59 +242,29 @@ public: // server side class CNetServer { -public: - struct CBanInfo - { - NETADDR m_Addr; - int m_Expires; - char m_Reason[128]; - }; - -private: struct CSlot { public: CNetConnection m_Connection; }; - struct CBan - { - public: - CBanInfo m_Info; - - // hash list - CBan *m_pHashNext; - CBan *m_pHashPrev; - - // used or free list - CBan *m_pNext; - CBan *m_pPrev; - }; - - NETSOCKET m_Socket; + class CNetBan *m_pNetBan; CSlot m_aSlots[NET_MAX_CLIENTS]; int m_MaxClients; int m_MaxClientsPerIP; - CBan *m_aBans[256]; - CBan m_BanPool[NET_SERVER_MAXBANS]; - CBan *m_BanPool_FirstFree; - CBan *m_BanPool_FirstUsed; - NETFUNC_NEWCLIENT m_pfnNewClient; NETFUNC_DELCLIENT m_pfnDelClient; void *m_UserPtr; CNetRecvUnpacker m_RecvUnpacker; - void BanRemoveByObject(CBan *pBan); - public: int SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); // - bool Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags); + bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags); int Close(); // @@ -307,16 +275,10 @@ public: // int Drop(int ClientID, const char *pReason); - // banning - int BanAdd(NETADDR Addr, int Seconds, const char *pReason); - int BanRemove(NETADDR Addr); - int BanRemoveAll(); - int BanNum(); // caution, slow - int BanGet(int Index, CBanInfo *pInfo); // caution, slow - // status requests - NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } + const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } NETSOCKET Socket() const { return m_Socket; } + class CNetBan *NetBan() const { return m_pNetBan; } int NetType() const { return m_Socket.type; } int MaxClients() const { return m_MaxClients; } @@ -326,27 +288,13 @@ public: class CNetConsole { - enum - { - MAX_BANS=128, - }; - - int FindBan(NETADDR Addr); - void UpdateBans(); - - struct CBanEntry - { - NETADDR m_Addr; - int m_Expires; - } m_aBans[MAX_BANS]; - int m_NumBans; - struct CSlot { CConsoleNetConnection m_Connection; }; NETSOCKET m_Socket; + class CNetBan *m_pNetBan; CSlot m_aSlots[NET_MAX_CONSOLE_CLIENTS]; NETFUNC_NEWCLIENT m_pfnNewClient; @@ -359,7 +307,7 @@ public: void SetCallbacks(NETFUNC_NEWCLIENT pfnNewClient, NETFUNC_DELCLIENT pfnDelClient, void *pUser); // - bool Open(NETADDR BindAddr, int Flags); + bool Open(NETADDR BindAddr, class CNetBan *pNetBan, int Flags); int Close(); // @@ -371,10 +319,9 @@ public: int AcceptClient(NETSOCKET Socket, const NETADDR *pAddr); int Drop(int ClientID, const char *pReason); - bool AddBan(NETADDR Addr, int Seconds); - // status requests - NETADDR ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } + const NETADDR *ClientAddr(int ClientID) const { return m_aSlots[ClientID].m_Connection.PeerAddress(); } + class CNetBan *NetBan() const { return m_pNetBan; } }; diff --git a/src/engine/shared/network_console.cpp b/src/engine/shared/network_console.cpp index cfa081a2..ded83f68 100644 --- a/src/engine/shared/network_console.cpp +++ b/src/engine/shared/network_console.cpp @@ -1,15 +1,21 @@ /* (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 + +#include + +#include "netban.h" #include "network.h" -bool CNetConsole::Open(NETADDR BindAddr, int Flags) + +bool CNetConsole::Open(NETADDR BindAddr, CNetBan *pNetBan, int Flags) { // zero out the whole structure mem_zero(this, sizeof(*this)); m_Socket.type = NETTYPE_INVALID; m_Socket.ipv4sock = -1; m_Socket.ipv6sock = -1; + m_pNetBan = pNetBan; // open socket m_Socket = net_tcp_create(BindAddr); @@ -64,8 +70,7 @@ int CNetConsole::AcceptClient(NETSOCKET Socket, const NETADDR *pAddr) FreeSlot = i; if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE) { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); - if(net_addr_comp(pAddr, &PeerAddr) == 0) + if(net_addr_comp(pAddr, m_aSlots[i].m_Connection.PeerAddress()) == 0) { str_copy(aError, "only one client per IP allowed", sizeof(aError)); break; @@ -99,26 +104,16 @@ int CNetConsole::Update() if(net_tcp_accept(m_Socket, &Socket, &Addr) > 0) { - int Index = FindBan(Addr); - if(Index == -1) - AcceptClient(Socket, &Addr); - else + // check if we just should drop the packet + char aBuf[128]; + if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf))) { - char aBuf[128]; - if(m_aBans[Index].m_Expires > -1) - { - int Mins = (m_aBans[Index].m_Expires-time_timestamp()+ 59) / 60; - if(Mins <= 1) - str_format(aBuf, sizeof(aBuf), "You have been banned for 1 minute"); - else - str_format(aBuf, sizeof(aBuf), "You have been banned for %d minutes", Mins); - } - else - str_format(aBuf, sizeof(aBuf), "You have been banned for life"); - + // banned, reply with a message and drop net_tcp_send(Socket, aBuf, str_length(aBuf)); net_tcp_close(Socket); } + else + AcceptClient(Socket, &Addr); } for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) @@ -129,8 +124,6 @@ int CNetConsole::Update() Drop(i, m_aSlots[i].m_Connection.ErrorString()); } - UpdateBans(); - return 0; } @@ -155,65 +148,3 @@ int CNetConsole::Send(int ClientID, const char *pLine) else return -1; } - -int CNetConsole::FindBan(NETADDR Addr) -{ - Addr.port = 0; - for(int i = 0; i < m_NumBans; i++) - if(net_addr_comp(&m_aBans[i].m_Addr, &Addr) == 0) - return i; - - return -1; -} - -bool CNetConsole::AddBan(NETADDR Addr, int Seconds) -{ - if(m_NumBans == MAX_BANS) - return false; - - Addr.port = 0; - int Index = FindBan(Addr); - if(Index == -1) - { - Index = m_NumBans++; - m_aBans[Index].m_Addr = Addr; - } - m_aBans[Index].m_Expires = Seconds>0 ? time_timestamp()+Seconds : -1; - - for(int i = 0; i < NET_MAX_CONSOLE_CLIENTS; i++) - { - if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE) - { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); - PeerAddr.port = 0; - if(net_addr_comp(&Addr, &PeerAddr) == 0) - { - char aBuf[128]; - if(Seconds>0) - { - int Mins = (Seconds + 59) / 60; - if(Mins <= 1) - str_format(aBuf, sizeof(aBuf), "You have been banned for 1 minute"); - else - str_format(aBuf, sizeof(aBuf), "You have been banned for %d minutes", Mins); - } - else - str_format(aBuf, sizeof(aBuf), "You have been banned for life"); - Drop(i, aBuf); - } - } - } - return true; -} - -void CNetConsole::UpdateBans() -{ - int Now = time_timestamp(); - for(int i = 0; i < m_NumBans; ++i) - if(m_aBans[i].m_Expires > 0 && m_aBans[i].m_Expires < Now) - { - m_aBans[i] = m_aBans[m_NumBans-1]; - --m_NumBans; - break; - } -} diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index b4986bf0..1264a4a5 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -1,32 +1,14 @@ /* (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 -#include "network.h" -#define MACRO_LIST_LINK_FIRST(Object, First, Prev, Next) \ - { if(First) First->Prev = Object; \ - Object->Prev = (struct CBan *)0; \ - Object->Next = First; \ - First = Object; } - -#define MACRO_LIST_LINK_AFTER(Object, After, Prev, Next) \ - { Object->Prev = After; \ - Object->Next = After->Next; \ - After->Next = Object; \ - if(Object->Next) \ - Object->Next->Prev = Object; \ - } +#include -#define MACRO_LIST_UNLINK(Object, First, Prev, Next) \ - { if(Object->Next) Object->Next->Prev = Object->Prev; \ - if(Object->Prev) Object->Prev->Next = Object->Next; \ - else First = Object->Next; \ - Object->Next = 0; Object->Prev = 0; } +#include "netban.h" +#include "network.h" -#define MACRO_LIST_FIND(Start, Next, Expression) \ - { while(Start && !(Expression)) Start = Start->Next; } -bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int Flags) +bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int MaxClientsPerIP, int Flags) { // zero out the whole structure mem_zero(this, sizeof(*this)); @@ -36,6 +18,8 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int if(!m_Socket.type) return false; + m_pNetBan = pNetBan; + // clamp clients m_MaxClients = MaxClients; if(m_MaxClients > NET_MAX_CLIENTS) @@ -48,8 +32,6 @@ bool CNetServer::Open(NETADDR BindAddr, int MaxClients, int MaxClientsPerIP, int for(int i = 0; i < NET_MAX_CLIENTS; i++) m_aSlots[i].m_Connection.Init(m_Socket); - BanRemoveAll(); - return true; } @@ -85,181 +67,8 @@ int CNetServer::Drop(int ClientID, const char *pReason) return 0; } -int CNetServer::BanGet(int Index, CBanInfo *pInfo) -{ - CBan *pBan; - for(pBan = m_BanPool_FirstUsed; pBan && Index; pBan = pBan->m_pNext, Index--) - {} - - if(!pBan) - return 0; - *pInfo = pBan->m_Info; - return 1; -} - -int CNetServer::BanNum() -{ - int Count = 0; - CBan *pBan; - for(pBan = m_BanPool_FirstUsed; pBan; pBan = pBan->m_pNext) - Count++; - return Count; -} - -void CNetServer::BanRemoveByObject(CBan *pBan) -{ - int IpHash = (pBan->m_Info.m_Addr.ip[0]+pBan->m_Info.m_Addr.ip[1]+pBan->m_Info.m_Addr.ip[2]+pBan->m_Info.m_Addr.ip[3]+ - pBan->m_Info.m_Addr.ip[4]+pBan->m_Info.m_Addr.ip[5]+pBan->m_Info.m_Addr.ip[6]+pBan->m_Info.m_Addr.ip[7]+ - pBan->m_Info.m_Addr.ip[8]+pBan->m_Info.m_Addr.ip[9]+pBan->m_Info.m_Addr.ip[10]+pBan->m_Info.m_Addr.ip[11]+ - pBan->m_Info.m_Addr.ip[12]+pBan->m_Info.m_Addr.ip[13]+pBan->m_Info.m_Addr.ip[14]+pBan->m_Info.m_Addr.ip[15])&0xff; - char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&pBan->m_Info.m_Addr, aAddrStr, sizeof(aAddrStr)); - dbg_msg("netserver", "removing ban on %s", aAddrStr); - MACRO_LIST_UNLINK(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - MACRO_LIST_UNLINK(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext); - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); -} - -int CNetServer::BanRemove(NETADDR Addr) -{ - int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ - Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; - CBan *pBan = m_aBans[IpHash]; - - MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); - - if(pBan) - { - BanRemoveByObject(pBan); - return 0; - } - - return -1; -} - -int CNetServer::BanRemoveAll() -{ - // clear bans memory - mem_zero(m_aBans, sizeof(m_aBans)); - mem_zero(m_BanPool, sizeof(m_BanPool)); - m_BanPool_FirstFree = 0; - m_BanPool_FirstUsed = 0; - - // setup all pointers for bans - for(int i = 1; i < NET_SERVER_MAXBANS-1; i++) - { - m_BanPool[i].m_pNext = &m_BanPool[i+1]; - m_BanPool[i].m_pPrev = &m_BanPool[i-1]; - } - - m_BanPool[0].m_pNext = &m_BanPool[1]; - m_BanPool[NET_SERVER_MAXBANS-1].m_pPrev = &m_BanPool[NET_SERVER_MAXBANS-2]; - m_BanPool_FirstFree = &m_BanPool[0]; - - return 0; -} - -int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) -{ - int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ - Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; - int Stamp = -1; - CBan *pBan; - - // remove the port - Addr.port = 0; - - if(Seconds) - Stamp = time_timestamp() + Seconds; - - // search to see if it already exists - pBan = m_aBans[IpHash]; - MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); - if(pBan) - { - // adjust the ban - pBan->m_Info.m_Expires = Stamp; - return 0; - } - - if(!m_BanPool_FirstFree) - return -1; - - // fetch and clear the new ban - pBan = m_BanPool_FirstFree; - MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); - - // setup the ban info - pBan->m_Info.m_Expires = Stamp; - pBan->m_Info.m_Addr = Addr; - str_copy(pBan->m_Info.m_Reason, pReason, sizeof(pBan->m_Info.m_Reason)); - - // add it to the ban hash - MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext); - - // insert it into the used list - { - if(m_BanPool_FirstUsed) - { - CBan *pInsertAfter = m_BanPool_FirstUsed; - MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires); - - if(pInsertAfter) - pInsertAfter = pInsertAfter->m_pPrev; - else - { - // add to last - pInsertAfter = m_BanPool_FirstUsed; - while(pInsertAfter->m_pNext) - pInsertAfter = pInsertAfter->m_pNext; - } - - if(pInsertAfter) - { - MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext); - } - else - { - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - } - } - else - { - MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); - } - } - - // drop banned clients - { - char Buf[128]; - NETADDR BanAddr; - - if(Stamp > -1) - { - int Mins = (Seconds + 59) / 60; - if(Mins <= 1) - str_format(Buf, sizeof(Buf), "You have been banned for 1 minute (%s)", pReason); - else - str_format(Buf, sizeof(Buf), "You have been banned for %d minutes (%s)", Mins, pReason); - } - else - str_format(Buf, sizeof(Buf), "You have been banned for life (%s)", pReason); - - for(int i = 0; i < MaxClients(); i++) - { - BanAddr = m_aSlots[i].m_Connection.PeerAddress(); - BanAddr.port = 0; - - if(net_addr_comp(&Addr, &BanAddr) == 0) - Drop(i, Buf); - } - } - return 0; -} - int CNetServer::Update() { - int Now = time_timestamp(); for(int i = 0; i < MaxClients(); i++) { m_aSlots[i].m_Connection.Update(); @@ -267,13 +76,6 @@ int CNetServer::Update() Drop(i, m_aSlots[i].m_Connection.ErrorString()); } - // remove expired bans - while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires > -1 && m_BanPool_FirstUsed->m_Info.m_Expires < Now) - { - CBan *pBan = m_BanPool_FirstUsed; - BanRemoveByObject(pBan); - } - return 0; } @@ -282,8 +84,6 @@ int CNetServer::Update() */ int CNetServer::Recv(CNetChunk *pChunk) { - unsigned Now = time_timestamp(); - while(1) { NETADDR Addr; @@ -301,36 +101,12 @@ int CNetServer::Recv(CNetChunk *pChunk) if(CNetBase::UnpackPacket(m_RecvUnpacker.m_aBuffer, Bytes, &m_RecvUnpacker.m_Data) == 0) { - CBan *pBan = 0; - NETADDR BanAddr = Addr; - int IpHash = (BanAddr.ip[0]+BanAddr.ip[1]+BanAddr.ip[2]+BanAddr.ip[3]+BanAddr.ip[4]+BanAddr.ip[5]+BanAddr.ip[6]+BanAddr.ip[7]+ - BanAddr.ip[8]+BanAddr.ip[9]+BanAddr.ip[10]+BanAddr.ip[11]+BanAddr.ip[12]+BanAddr.ip[13]+BanAddr.ip[14]+BanAddr.ip[15])&0xff; - int Found = 0; - BanAddr.port = 0; - - // search a ban - for(pBan = m_aBans[IpHash]; pBan; pBan = pBan->m_pHashNext) - { - if(net_addr_comp(&pBan->m_Info.m_Addr, &BanAddr) == 0) - break; - } - // check if we just should drop the packet - if(pBan) + char aBuf[128]; + if(NetBan() && NetBan()->IsBanned(&Addr, aBuf, sizeof(aBuf))) { // banned, reply with a message - char BanStr[128]; - if(pBan->m_Info.m_Expires > -1) - { - int Mins = ((pBan->m_Info.m_Expires - Now)+59)/60; - if(Mins <= 1) - str_format(BanStr, sizeof(BanStr), "Banned for 1 minute (%s)", pBan->m_Info.m_Reason); - else - str_format(BanStr, sizeof(BanStr), "Banned for %d minutes (%s)", Mins, pBan->m_Info.m_Reason); - } - else - str_format(BanStr, sizeof(BanStr), "Banned for life (%s)", pBan->m_Info.m_Reason); - CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, BanStr, str_length(BanStr)+1); + CNetBase::SendControlMsg(m_Socket, &Addr, 0, NET_CTRLMSG_CLOSE, aBuf, str_length(aBuf)+1); continue; } @@ -348,16 +124,15 @@ int CNetServer::Recv(CNetChunk *pChunk) // TODO: check size here if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_CONTROL && m_RecvUnpacker.m_Data.m_aChunkData[0] == NET_CTRLMSG_CONNECT) { - Found = 0; + bool Found = false; // check if we already got this client for(int i = 0; i < MaxClients(); i++) { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); if(m_aSlots[i].m_Connection.State() != NET_CONNSTATE_OFFLINE && - net_addr_comp(&PeerAddr, &Addr) == 0) + net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { - Found = 1; // silent ignore.. we got this client already + Found = true; // silent ignore.. we got this client already break; } } @@ -374,7 +149,7 @@ int CNetServer::Recv(CNetChunk *pChunk) if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) continue; - OtherAddr = m_aSlots[i].m_Connection.PeerAddress(); + OtherAddr = *m_aSlots[i].m_Connection.PeerAddress(); OtherAddr.port = 0; if(!net_addr_comp(&ThisAddr, &OtherAddr)) { @@ -392,7 +167,7 @@ int CNetServer::Recv(CNetChunk *pChunk) { if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_OFFLINE) { - Found = 1; + Found = true; m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr); if(m_pfnNewClient) m_pfnNewClient(i, m_UserPtr); @@ -412,8 +187,7 @@ int CNetServer::Recv(CNetChunk *pChunk) // normal packet, find matching slot for(int i = 0; i < MaxClients(); i++) { - NETADDR PeerAddr = m_aSlots[i].m_Connection.PeerAddress(); - if(net_addr_comp(&PeerAddr, &Addr) == 0) + if(net_addr_comp(m_aSlots[i].m_Connection.PeerAddress(), &Addr) == 0) { if(m_aSlots[i].m_Connection.Feed(&m_RecvUnpacker.m_Data, &Addr)) { diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index f2e9e65d..d16d56cd 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -612,16 +612,10 @@ void CGameConsole::Dump(int Type) IOHANDLE io = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(io) { - #if defined(CONF_FAMILY_WINDOWS) - static const char Newline[] = "\r\n"; - #else - static const char Newline[] = "\n"; - #endif - for(CInstance::CBacklogEntry *pEntry = pConsole->m_Backlog.First(); pEntry; pEntry = pConsole->m_Backlog.Next(pEntry)) { io_write(io, pEntry->m_aText, str_length(pEntry->m_aText)); - io_write(io, Newline, sizeof(Newline)-1); + io_write_newline(io); } io_close(io); } diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index a1e629a6..f0460d26 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -188,16 +188,11 @@ void CMapLayers::OnRender() IOHANDLE File = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE); if(File) { - #if defined(CONF_FAMILY_WINDOWS) - static const char Newline[] = "\r\n"; - #else - static const char Newline[] = "\n"; - #endif for(int y = 0; y < pTMap->m_Height; y++) { for(int x = 0; x < pTMap->m_Width; x++) io_write(File, &(pTiles[y*pTMap->m_Width + x].m_Index), sizeof(pTiles[y*pTMap->m_Width + x].m_Index)); - io_write(File, Newline, sizeof(Newline)-1); + io_write_newline(File); } io_close(File); } diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp index 70e4aecf..632a524c 100644 --- a/src/mastersrv/mastersrv.cpp +++ b/src/mastersrv/mastersrv.cpp @@ -1,20 +1,23 @@ /* (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 -#include -#include + #include -#include #include +#include + +#include +#include +#include #include "mastersrv.h" + enum { MTU = 1400, MAX_SERVERS_PER_PACKET=75, MAX_PACKETS=16, MAX_SERVERS=MAX_SERVERS_PER_PACKET*MAX_PACKETS, - MAX_BANS=128, EXPIRE_TIME = 90 }; @@ -77,14 +80,7 @@ static CCountPacketData m_CountData; static CCountPacketData m_CountDataLegacy; -struct CBanEntry -{ - NETADDR m_Address; - int64 m_Expire; -}; - -static CBanEntry m_aBans[MAX_BANS]; -static int m_NumBans = 0; +CNetBan m_NetBan; static CNetClient m_NetChecker; // NAT/FW checker static CNetClient m_NetOp; // main @@ -217,9 +213,9 @@ void AddCheckserver(NETADDR *pInfo, NETADDR *pAlt, ServerType Type) } char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true); char aAltAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(pAlt, aAltAddrStr, sizeof(aAltAddrStr)); + net_addr_str(pAlt, aAltAddrStr, sizeof(aAltAddrStr), true); dbg_msg("mastersrv", "checking: %s (%s)", aAddrStr, aAltAddrStr); m_aCheckServers[m_NumCheckServers].m_Address = *pInfo; m_aCheckServers[m_NumCheckServers].m_AltAddress = *pAlt; @@ -237,7 +233,7 @@ void AddServer(NETADDR *pInfo, ServerType Type) if(net_addr_comp(&m_aServers[i].m_Address, pInfo) == 0) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true); dbg_msg("mastersrv", "updated: %s", aAddrStr); m_aServers[i].m_Expire = time_get()+time_freq()*EXPIRE_TIME; return; @@ -252,7 +248,7 @@ void AddServer(NETADDR *pInfo, ServerType Type) } char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr)); + net_addr_str(pInfo, aAddrStr, sizeof(aAddrStr), true); dbg_msg("mastersrv", "added: %s", aAddrStr); m_aServers[m_NumServers].m_Address = *pInfo; m_aServers[m_NumServers].m_Expire = time_get()+time_freq()*EXPIRE_TIME; @@ -271,9 +267,9 @@ void UpdateServers() if(m_aCheckServers[i].m_TryCount == 10) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&m_aCheckServers[i].m_Address, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&m_aCheckServers[i].m_Address, aAddrStr, sizeof(aAddrStr), true); char aAltAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr)); + net_addr_str(&m_aCheckServers[i].m_AltAddress, aAltAddrStr, sizeof(aAltAddrStr), true); dbg_msg("mastersrv", "check failed: %s (%s)", aAddrStr, aAltAddrStr); // FAIL!! @@ -305,7 +301,7 @@ void PurgeServers() { // remove server char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&m_aServers[i].m_Address, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&m_aServers[i].m_Address, aAddrStr, sizeof(aAddrStr), true); dbg_msg("mastersrv", "expired: %s", aAddrStr); m_aServers[i] = m_aServers[m_NumServers-1]; m_NumServers--; @@ -315,53 +311,9 @@ void PurgeServers() } } -bool CheckBan(NETADDR Addr) -{ - for(int i = 0; i < m_NumBans; i++) - { - if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0) - { - return true; - } - } - Addr.port = 0; - for(int i = 0; i < m_NumBans; i++) - { - if(net_addr_comp(&m_aBans[i].m_Address, &Addr) == 0) - { - return true; - } - } - return false; -} - -void ConAddBan(IConsole::IResult *pResult, void *pUser) -{ - if(m_NumBans == MAX_BANS) - { - dbg_msg("mastersrv", "error: banlist is full"); - return; - } - - if(net_addr_from_str(&m_aBans[m_NumBans].m_Address, pResult->GetString(0)) != 0) - { - dbg_msg("mastersrv", "error: invalid address"); - return; - } - - if(CheckBan(m_aBans[m_NumBans].m_Address)) - { - dbg_msg("mastersrv", "duplicate ban: %s", pResult->GetString(0)); - return; - } - - dbg_msg("mastersrv", "ban added: %s", pResult->GetString(0)); - m_NumBans++; -} - void ReloadBans() { - m_NumBans = 0; + m_NetBan.UnbanAll(); m_pConsole->ExecuteFile("master.cfg"); } @@ -398,7 +350,7 @@ int main(int argc, const char **argv) // ignore_convention IStorage *pStorage = CreateStorage("Teeworlds", argc, argv); m_pConsole = CreateConsole(CFGFLAG_MASTER); - m_pConsole->Register("ban", "s", CFGFLAG_MASTER, ConAddBan, 0, "Ban IP from mastersrv"); + m_NetBan.Init(m_pConsole, pStorage); bool RegisterFail = !pKernel->RegisterInterface(pStorage); RegisterFail |= !pKernel->RegisterInterface(m_pConsole); @@ -418,7 +370,8 @@ int main(int argc, const char **argv) // ignore_convention while(m_NetOp.Recv(&Packet)) { // check if the server is banned - if(CheckBan(Packet.m_Address)) continue; + if(m_NetBan.IsBanned(&Packet.m_Address, 0, 0)) + continue; if(Packet.m_DataSize == sizeof(SERVERBROWSE_HEARTBEAT)+2 && mem_comp(Packet.m_pData, SERVERBROWSE_HEARTBEAT, sizeof(SERVERBROWSE_HEARTBEAT)) == 0) @@ -519,7 +472,8 @@ int main(int argc, const char **argv) // ignore_convention while(m_NetChecker.Recv(&Packet)) { // check if the server is banned - if(CheckBan(Packet.m_Address)) continue; + if(m_NetBan.IsBanned(&Packet.m_Address, 0, 0)) + continue; if(Packet.m_DataSize == sizeof(SERVERBROWSE_FWRESPONSE) && mem_comp(Packet.m_pData, SERVERBROWSE_FWRESPONSE, sizeof(SERVERBROWSE_FWRESPONSE)) == 0) diff --git a/src/tools/crapnet.cpp b/src/tools/crapnet.cpp index 98b6c0a7..fbd20445 100644 --- a/src/tools/crapnet.cpp +++ b/src/tools/crapnet.cpp @@ -129,7 +129,7 @@ void Run(int Port, NETADDR Dest) if(m_ConfigLog) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&From, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&From, aAddrStr, sizeof(aAddrStr), true); dbg_msg("crapnet", "<< %08d %s (%d)", p->m_ID, aAddrStr, p->m_DataSize); } } @@ -193,7 +193,7 @@ void Run(int Port, NETADDR Dest) if(m_ConfigLog) { char aAddrStr[NETADDR_MAXSTRSIZE]; - net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr)); + net_addr_str(&p->m_SendTo, aAddrStr, sizeof(aAddrStr), true); dbg_msg("crapnet", ">> %08d %s (%d) %s", p->m_ID, aAddrStr, p->m_DataSize, aFlags); } diff --git a/src/tools/fake_server.cpp b/src/tools/fake_server.cpp index 68c47659..9e76b3e7 100644 --- a/src/tools/fake_server.cpp +++ b/src/tools/fake_server.cpp @@ -113,7 +113,7 @@ static int Run() int64 NextHeartBeat = 0; NETADDR BindAddr = {NETTYPE_IPV4, {0},0}; - if(!pNet->Open(BindAddr, 0, 0, 0)) + if(!pNet->Open(BindAddr, 0, 0, 0, 0)) return 0; while(1) -- cgit 1.4.1 From 8ffe5826156d07b1feb7fc58bf59a1431e01160f Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Fri, 30 Dec 2011 16:02:22 +0100 Subject: ugly incomplete hack to put the rendering into another thread so we don't have to wait for the flip --- src/base/tl/threading.h | 78 ++++++++++++++++++++++++++++ src/engine/client/client.cpp | 98 +++++++++++++++++++++++++++++++++--- src/engine/client/client.h | 6 +++ src/game/client/components/menus.cpp | 3 ++ 4 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 src/base/tl/threading.h (limited to 'src/game/client/components') diff --git a/src/base/tl/threading.h b/src/base/tl/threading.h new file mode 100644 index 00000000..66751ec4 --- /dev/null +++ b/src/base/tl/threading.h @@ -0,0 +1,78 @@ + +#pragma once + +#include "../system.h" + +inline unsigned atomic_inc(volatile unsigned *pValue) +{ + return __sync_fetch_and_add(pValue, 1); +} + +inline unsigned atomic_dec(volatile unsigned *pValue) +{ + return __sync_fetch_and_add(pValue, -1); +} + +inline unsigned atomic_compswap(volatile unsigned *pValue, unsigned comperand, unsigned value) +{ + return __sync_val_compare_and_swap(pValue, comperand, value); +} + +inline void sync_barrier() +{ + __sync_synchronize(); +} + +#include +typedef sem_t SEMAPHORE; +inline void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); } +inline void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); } +inline void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); } +inline void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); } + +class semaphore +{ + SEMAPHORE sem; +public: + semaphore() { semaphore_init(&sem); } + ~semaphore() { semaphore_destroy(&sem); } + void wait() { semaphore_wait(&sem); } + void signal() { semaphore_signal(&sem); } +}; + +class lock +{ + friend class scope_lock; + + LOCK var; + + void take() { lock_wait(var); } + void release() { lock_release(var); } + +public: + lock() + { + var = lock_create(); + } + + ~lock() + { + lock_destroy(var); + } +}; + +class scope_lock +{ + lock *var; +public: + scope_lock(lock *l) + { + var = l; + var->take(); + } + + ~scope_lock() + { + var->release(); + } +}; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 9f43b9ce..4107cd85 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -1688,17 +1689,27 @@ void CClient::InitInterfaces() m_Friends.Init(); } -void CClient::Run() -{ - int64 ReportTime = time_get(); - int64 ReportInterval = time_freq()*1; - m_LocalStartTime = time_get(); - m_SnapshotParts = 0; +enum +{ + GFXSTATE_ERROR = -1, + GFXSTATE_INIT = 0, + GFXSTATE_IDLE, + GFXSTATE_RENDERING, + GFXSTATE_SWAPPING, +}; +void CClient::GraphicsThread() +{ // init graphics if(m_pGraphics->Init() != 0) + { + m_GfxState = GFXSTATE_ERROR; + m_GfxStateSemaphore.signal(); + m_GfxState = GFXSTATE_ERROR; return; + } + // open socket { @@ -1708,6 +1719,7 @@ void CClient::Run() if(!m_NetClient.Open(BindAddr, 0)) { dbg_msg("client", "couldn't start network"); + m_GfxState = GFXSTATE_ERROR; return; } } @@ -1722,16 +1734,66 @@ void CClient::Run() MasterServer()->RefreshAddresses(m_NetClient.NetType()); // init the editor - m_pEditor->Init(); + //m_pEditor->Init(); // init sound, allowed to fail m_SoundInitFailed = Sound()->Init() != 0; // load data if(!LoadData()) + { + m_GfxState = GFXSTATE_ERROR; return; + } GameClient()->OnInit(); + + + while(1) + { + // do idle + sync_barrier(); + m_GfxState = GFXSTATE_IDLE; + m_GfxStateSemaphore.signal(); + m_GfxRenderSemaphore.wait(); + + // do render + m_GfxState = GFXSTATE_RENDERING; + m_GfxStateSemaphore.signal(); + Render(); + sync_barrier(); + + // do swap + m_GfxState = GFXSTATE_SWAPPING; + m_GfxStateSemaphore.signal(); + m_pGraphics->Swap(); + } + + // do shutdown +} + +void CClient::Run() +{ + int64 ReportTime = time_get(); + int64 ReportInterval = time_freq()*1; + + m_LocalStartTime = time_get(); + m_SnapshotParts = 0; + + m_GfxState = GFXSTATE_INIT; + thread_create(GraphicsThreadProxy, this); + + // wait for gfx to init + while(1) + { + m_GfxStateSemaphore.wait(); + if(m_GfxState == GFXSTATE_ERROR) + return; + if(m_GfxState != GFXSTATE_INIT) + break; + } + + char aBuf[256]; str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion()); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); @@ -1847,7 +1909,27 @@ void CClient::Run() m_EditorActive = false; Update(); + + + if(m_GfxState == GFXSTATE_IDLE) + { + // issue new rendering + m_GfxRenderSemaphore.signal(); + + // wait for gfx to finish rendering + while(m_GfxState != GFXSTATE_SWAPPING) + m_GfxStateSemaphore.wait(); + } + + /* + if(m_pGraphics->AsyncSwapIsDone()) + { + m_pGraphics->BeginScene(); + Render(); + m_pGraphics->EndScene(); + }*/ + /* if(g_Config.m_DbgStress) { if((m_Frames%10) == 0) @@ -1860,7 +1942,7 @@ void CClient::Run() { Render(); m_pGraphics->Swap(); - } + }*/ } AutoScreenshot_Cleanup(); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 1504a4e4..83553eb4 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -172,6 +172,12 @@ class CClient : public IClient, public CDemoPlayer::IListner class CHostLookup m_VersionServeraddr; } m_VersionInfo; + semaphore m_GfxRenderSemaphore; + semaphore m_GfxStateSemaphore; + volatile int m_GfxState; + static void GraphicsThreadProxy(void *pThis) { ((CClient*)pThis)->GraphicsThread(); } + void GraphicsThread(); + public: IEngine *Engine() { return m_pEngine; } IEngineGraphics *Graphics() { return m_pGraphics; } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index a39139c8..fc1ca2db 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -627,6 +627,9 @@ int CMenus::RenderMenubar(CUIRect r) void CMenus::RenderLoading() { + // TODO: not supported right now due to separate render thread + return; + static int64 LastLoadRender = 0; float Percent = m_LoadCurrent++/(float)m_LoadTotal; -- cgit 1.4.1 From 8e568857959291f442ba8f11abac059b6bd6a9e9 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sat, 31 Dec 2011 01:06:04 +0100 Subject: initial commit of the threaded graphics. can start game and render the gui. no textures at the moment. still waits for the swap for now --- src/engine/client/client.cpp | 93 +-- src/engine/client/graphics.cpp | 2 +- src/engine/client/graphics.h | 342 +++++++++ src/engine/client/graphics_threaded.cpp | 1225 +++++++++++++++++++++++++++++++ src/game/client/components/menus.cpp | 1 - 5 files changed, 1576 insertions(+), 87 deletions(-) create mode 100644 src/engine/client/graphics_threaded.cpp (limited to 'src/game/client/components') diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 4107cd85..bb888c60 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1689,28 +1689,21 @@ void CClient::InitInterfaces() m_Friends.Init(); } - -enum +void CClient::Run() { - GFXSTATE_ERROR = -1, - GFXSTATE_INIT = 0, - GFXSTATE_IDLE, - GFXSTATE_RENDERING, - GFXSTATE_SWAPPING, -}; + int64 ReportTime = time_get(); + int64 ReportInterval = time_freq()*1; + + m_LocalStartTime = time_get(); + m_SnapshotParts = 0; -void CClient::GraphicsThread() -{ // init graphics if(m_pGraphics->Init() != 0) { - m_GfxState = GFXSTATE_ERROR; - m_GfxStateSemaphore.signal(); - m_GfxState = GFXSTATE_ERROR; + dbg_msg("client", "couldn't init graphics"); return; } - // open socket { NETADDR BindAddr; @@ -1719,7 +1712,6 @@ void CClient::GraphicsThread() if(!m_NetClient.Open(BindAddr, 0)) { dbg_msg("client", "couldn't start network"); - m_GfxState = GFXSTATE_ERROR; return; } } @@ -1741,59 +1733,10 @@ void CClient::GraphicsThread() // load data if(!LoadData()) - { - m_GfxState = GFXSTATE_ERROR; return; - } GameClient()->OnInit(); - - while(1) - { - // do idle - sync_barrier(); - m_GfxState = GFXSTATE_IDLE; - m_GfxStateSemaphore.signal(); - m_GfxRenderSemaphore.wait(); - - // do render - m_GfxState = GFXSTATE_RENDERING; - m_GfxStateSemaphore.signal(); - Render(); - sync_barrier(); - - // do swap - m_GfxState = GFXSTATE_SWAPPING; - m_GfxStateSemaphore.signal(); - m_pGraphics->Swap(); - } - - // do shutdown -} - -void CClient::Run() -{ - int64 ReportTime = time_get(); - int64 ReportInterval = time_freq()*1; - - m_LocalStartTime = time_get(); - m_SnapshotParts = 0; - - m_GfxState = GFXSTATE_INIT; - thread_create(GraphicsThreadProxy, this); - - // wait for gfx to init - while(1) - { - m_GfxStateSemaphore.wait(); - if(m_GfxState == GFXSTATE_ERROR) - return; - if(m_GfxState != GFXSTATE_INIT) - break; - } - - char aBuf[256]; str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion()); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); @@ -1910,26 +1853,6 @@ void CClient::Run() Update(); - - if(m_GfxState == GFXSTATE_IDLE) - { - // issue new rendering - m_GfxRenderSemaphore.signal(); - - // wait for gfx to finish rendering - while(m_GfxState != GFXSTATE_SWAPPING) - m_GfxStateSemaphore.wait(); - - } - - /* - if(m_pGraphics->AsyncSwapIsDone()) - { - m_pGraphics->BeginScene(); - Render(); - m_pGraphics->EndScene(); - }*/ - /* if(g_Config.m_DbgStress) { if((m_Frames%10) == 0) @@ -1942,7 +1865,7 @@ void CClient::Run() { Render(); m_pGraphics->Swap(); - }*/ + } } AutoScreenshot_Cleanup(); diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index 617162ae..2d034f3f 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -950,4 +950,4 @@ int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes) return NumModes; } -extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); } +//extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); } diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h index 95e9769a..84142d9d 100644 --- a/src/engine/client/graphics.h +++ b/src/engine/client/graphics.h @@ -3,6 +3,348 @@ #ifndef ENGINE_CLIENT_GRAPHICS_H #define ENGINE_CLIENT_GRAPHICS_H +#include + +class CCommandBuffer +{ + class CBuffer + { + unsigned char *m_pData; + unsigned m_Size; + unsigned m_Used; + public: + CBuffer(unsigned BufferSize) + { + m_Size = BufferSize; + m_pData = new unsigned char[m_Size]; + m_Used = 0; + } + + ~CBuffer() + { + delete [] m_pData; + m_pData = 0x0; + m_Used = 0; + m_Size = 0; + } + + void Reset() + { + m_Used = 0; + } + + void *Alloc(unsigned Requested) + { + if(Requested + m_Used > m_Size) + return 0; + void *pPtr = &m_pData[m_Used]; + m_Used += Requested; + return pPtr; + } + + unsigned char *DataPtr() { return m_pData; } + unsigned DataSize() { return m_Size; } + unsigned DataUsed() { return m_Used; } + }; + + CBuffer m_CmdBuffer; + CBuffer m_DataBuffer; +public: + enum + { + // + CMD_NOP = 0, + + // + CMD_INIT, + CMD_SHUTDOWN, + + // + CMD_RUNBUFFER, + + // syncronization + CMD_SIGNAL, + + // texture commands + CMD_TEXTURE_CREATE, + CMD_TEXTURE_DESTROY, + + // rendering + CMD_CLEAR, + CMD_RENDER, + + // swap + CMD_SWAP, + }; + + enum + { + // + PRIMTYPE_INVALID = 0, + PRIMTYPE_LINES, + PRIMTYPE_QUADS, + }; + + enum + { + BLEND_NONE = 0, + BLEND_ALPHA, + BLEND_ADDITIVE, + }; + + struct SPoint { float x, y, z; }; + struct STexCoord { float u, v; }; + struct SColor { float r, g, b, a; }; + + struct SVertex + { + SPoint m_Pos; + STexCoord m_Tex; + SColor m_Color; + } ; + + struct SCommand + { + public: + SCommand(unsigned Cmd) : m_Cmd(Cmd), m_Size(0) {} + unsigned m_Cmd; + unsigned m_Size; + }; + + struct SState + { + int m_BlendMode; + int m_Texture; + SPoint m_ScreenTL; + SPoint m_ScreenBR; + + // clip + bool m_ClipEnable; + int m_ClipX; + int m_ClipY; + int m_ClipW; + int m_ClipH; + }; + + struct SCommand_Clear : public SCommand + { + SCommand_Clear() : SCommand(CMD_CLEAR) {} + SColor m_Color; + }; + + + struct SCommand_Init : public SCommand + { + SCommand_Init() : SCommand(CMD_INIT) {} + volatile int *m_pResult; + }; + + struct SCommand_RunBuffer : public SCommand + { + SCommand_RunBuffer() : SCommand(CMD_RUNBUFFER) {} + CCommandBuffer *m_pOtherBuffer; + }; + + struct SCommand_Render : public SCommand + { + SCommand_Render() : SCommand(CMD_RENDER) {} + SState m_State; + unsigned m_PrimType; + unsigned m_PrimCount; + SVertex *m_pVertices; + }; + + struct SCommand_Swap : public SCommand + { + SCommand_Swap() : SCommand(CMD_SWAP) {} + }; + + // + CCommandBuffer(unsigned CmdBufferSize, unsigned DataBufferSize) + : m_CmdBuffer(CmdBufferSize), m_DataBuffer(DataBufferSize) + { + } + + void *AllocData(unsigned WantedSize) + { + return m_DataBuffer.Alloc(WantedSize); + } + + template + void AddCommand(const T &Command) + { + SCommand *pCmd = (SCommand *)m_CmdBuffer.Alloc(sizeof(Command)); + if(!pCmd) + return; + + mem_copy(pCmd, &Command, sizeof(Command)); + pCmd->m_Size = sizeof(Command); + } + + SCommand *GetCommand(unsigned *pIndex) + { + if(*pIndex >= m_CmdBuffer.DataUsed()) + return NULL; + + SCommand *pCommand = (SCommand *)&m_CmdBuffer.DataPtr()[*pIndex]; + *pIndex += pCommand->m_Size; + return pCommand; + } + + void Reset() + { + m_CmdBuffer.Reset(); + m_DataBuffer.Reset(); + } +}; + +class ICommandProcessor +{ +public: + virtual ~ICommandProcessor() {} + virtual void RunBuffer(CCommandBuffer *pBuffer) = 0; +}; + + +class CCommandProcessorHandler +{ + ICommandProcessor *m_pProcessor; + CCommandBuffer * volatile m_pBuffer; + volatile bool m_Shutdown; + semaphore m_Activity; + semaphore m_BufferDone; + void *m_pThread; + + static void ThreadFunc(void *pUser); + +public: + CCommandProcessorHandler(); + void Start(ICommandProcessor *pProcessor); + void RunBuffer(CCommandBuffer *pBuffer); + bool IsIdle() const { return m_pBuffer == 0; } + void WaitForIdle(); +}; + +class CGraphics_Threaded : public IEngineGraphics +{ + CCommandBuffer::SState m_State; + CCommandProcessorHandler m_Handler; + + CCommandBuffer *m_apCommandBuffers[2]; + CCommandBuffer *m_pCommandBuffer; + unsigned m_CurrentCommandBuffer; + + // + class IStorage *m_pStorage; + class IConsole *m_pConsole; + + enum + { + MAX_VERTICES = 32*1024, + MAX_TEXTURES = 1024*4, + + DRAWING_QUADS=1, + DRAWING_LINES=2 + }; + + CCommandBuffer::SVertex m_aVertices[MAX_VERTICES]; + int m_NumVertices; + + CCommandBuffer::SColor m_aColor[4]; + CCommandBuffer::STexCoord m_aTexture[4]; + + bool m_RenderEnable; + + float m_Rotation; + int m_Drawing; + bool m_DoScreenshot; + char m_aScreenshotName[128]; + + int m_InvalidTexture; + + struct CTexture + { + GLuint m_Tex; + int m_MemSize; + int m_Flags; + int m_Next; + }; + + CTexture m_aTextures[MAX_TEXTURES]; + int m_FirstFreeTexture; + int m_TextureMemoryUsage; + + void Flush(); + void AddVertices(int Count); + void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints); + + static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp); + static unsigned char *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData); +public: + CGraphics_Threaded(); + + virtual void ClipEnable(int x, int y, int w, int h); + virtual void ClipDisable(); + + virtual void BlendNone(); + virtual void BlendNormal(); + virtual void BlendAdditive(); + + virtual int MemoryUsage() const; + + virtual void MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY); + virtual void GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY); + + virtual void LinesBegin(); + virtual void LinesEnd(); + virtual void LinesDraw(const CLineItem *pArray, int Num); + + virtual int UnloadTexture(int Index); + virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags); + + // simple uncompressed RGBA loaders + virtual int LoadTexture(const char *pFilename, int StorageType, int StoreFormat, int Flags); + virtual int LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType); + + void ScreenshotDirect(const char *pFilename); + + virtual void TextureSet(int TextureID); + + virtual void Clear(float r, float g, float b); + + virtual void QuadsBegin(); + virtual void QuadsEnd(); + virtual void QuadsSetRotation(float Angle); + + virtual void SetColorVertex(const CColorVertex *pArray, int Num); + virtual void SetColor(float r, float g, float b, float a); + + virtual void QuadsSetSubset(float TlU, float TlV, float BrU, float BrV); + virtual void QuadsSetSubsetFree( + float x0, float y0, float x1, float y1, + float x2, float y2, float x3, float y3); + + virtual void QuadsDraw(CQuadItem *pArray, int Num); + virtual void QuadsDrawTL(const CQuadItem *pArray, int Num); + virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num); + virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText); + + virtual void Minimize(); + virtual void Maximize(); + + virtual int WindowActive(); + virtual int WindowOpen(); + + virtual bool Init(); + virtual void Shutdown(); + + virtual void TakeScreenshot(const char *pFilename); + virtual void Swap(); + + virtual int GetVideoModes(CVideoMode *pModes, int MaxModes); + +}; + class CGraphics_OpenGL : public IEngineGraphics { protected: diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp new file mode 100644 index 00000000..c227dbd5 --- /dev/null +++ b/src/engine/client/graphics_threaded.cpp @@ -0,0 +1,1225 @@ +/* (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 +#include + +#include "SDL.h" +#include "SDL_opengl.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include // cosf, sinf + +#include "graphics.h" + + +static CVideoMode g_aFakeModes[] = { + {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8}, + {720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8}, + {1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8}, + {1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8}, + {1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8}, + {1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8}, + {1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8}, + {1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8}, + {1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8}, + {2048,1536,8,8,8}, + + {320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5}, + {720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5}, + {1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5}, + {1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5}, + {1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5}, + {1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5}, + {1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5}, + {1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5}, + {1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5}, + {2048,1536,5,6,5} +}; + + +class CCommandProcessorFragment_OpenGL +{ +public: + void SetState(const CCommandBuffer::SState &State) + { + // blend + switch(State.m_BlendMode) + { + case CCommandBuffer::BLEND_NONE: + glDisable(GL_BLEND); + break; + case CCommandBuffer::BLEND_ALPHA: + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case CCommandBuffer::BLEND_ADDITIVE: + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + break; + default: + dbg_msg("render", "unknown blendmode %d\n", State.m_BlendMode); + }; + + // clip + /*if(State.m_ClipEnable) + { + glScissor(State.m_ClipX, State.m_ClipY+State.m_ClipH, State.m_ClipW, State.m_ClipH); + glEnable(GL_SCISSOR_TEST); + } + else*/ + glDisable(GL_SCISSOR_TEST); + + // texture + glDisable(GL_TEXTURE_2D); + + // screen mapping + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(State.m_ScreenTL.x, State.m_ScreenBR.x, State.m_ScreenBR.y, State.m_ScreenTL.y, 1.0f, 10.f); + + } + + bool RunCommand(const CCommandBuffer::SCommand * pBaseCommand) + { + + switch(pBaseCommand->m_Cmd) + { + case CCommandBuffer::CMD_TEXTURE_CREATE: + break; + case CCommandBuffer::CMD_TEXTURE_DESTROY: + break; + case CCommandBuffer::CMD_CLEAR: + { + const CCommandBuffer::SCommand_Clear *pCommand = (CCommandBuffer::SCommand_Clear *)pBaseCommand; + glClearColor(pCommand->m_Color.r, pCommand->m_Color.g, pCommand->m_Color.b, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } break; + case CCommandBuffer::CMD_RENDER: + { + const CCommandBuffer::SCommand_Render *pCommand = (CCommandBuffer::SCommand_Render *)pBaseCommand; + SetState(pCommand->m_State); + + glVertexPointer(3, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices); + glTexCoordPointer(2, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*3); + glColorPointer(4, GL_FLOAT, sizeof(CCommandBuffer::SVertex), (char*)pCommand->m_pVertices + sizeof(float)*5); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + switch(pCommand->m_PrimType) + { + case CCommandBuffer::PRIMTYPE_QUADS: + glDrawArrays(GL_QUADS, 0, pCommand->m_PrimCount*4); + break; + case CCommandBuffer::PRIMTYPE_LINES: + glDrawArrays(GL_LINES, 0, pCommand->m_PrimCount*2); + break; + default: + dbg_msg("render", "unknown primtype %d\n", pCommand->m_Cmd); + }; + } break; + default: + return false; + break; + } + + return true; + } +}; + +class CCommandProcessorFragment_SDL +{ + // SDL stuff + SDL_Surface *m_pScreenSurface; + + int m_ScreenWidth; + int m_ScreenHeight; + + int TryInit() + { + m_ScreenWidth = g_Config.m_GfxScreenWidth; + m_ScreenHeight = g_Config.m_GfxScreenHeight; + + const SDL_VideoInfo *pInfo = SDL_GetVideoInfo(); + SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + + // set flags + int Flags = SDL_OPENGL; + if(g_Config.m_DbgResizable) + Flags |= SDL_RESIZABLE; + + if(pInfo->hw_available) // ignore_convention + Flags |= SDL_HWSURFACE; + else + Flags |= SDL_SWSURFACE; + + if(pInfo->blit_hw) // ignore_convention + Flags |= SDL_HWACCEL; + + if(g_Config.m_GfxFullscreen) + Flags |= SDL_FULLSCREEN; + + // set gl attributes + if(g_Config.m_GfxFsaaSamples) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, g_Config.m_GfxFsaaSamples); + } + else + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + } + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, g_Config.m_GfxVsync); + + // set caption + SDL_WM_SetCaption("Teeworlds", "Teeworlds"); + + // create window + m_pScreenSurface = SDL_SetVideoMode(m_ScreenWidth, m_ScreenHeight, 0, Flags); + if(m_pScreenSurface == NULL) + { + dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError()); + return -1; + } + + return 0; + } + + + int InitWindow() + { + if(TryInit() == 0) + return 0; + + // try disabling fsaa + while(g_Config.m_GfxFsaaSamples) + { + g_Config.m_GfxFsaaSamples--; + + if(g_Config.m_GfxFsaaSamples) + dbg_msg("gfx", "lowering FSAA to %d and trying again", g_Config.m_GfxFsaaSamples); + else + dbg_msg("gfx", "disabling FSAA and trying again"); + + if(TryInit() == 0) + return 0; + } + + // try lowering the resolution + if(g_Config.m_GfxScreenWidth != 640 || g_Config.m_GfxScreenHeight != 480) + { + dbg_msg("gfx", "setting resolution to 640x480 and trying again"); + g_Config.m_GfxScreenWidth = 640; + g_Config.m_GfxScreenHeight = 480; + + if(TryInit() == 0) + return 0; + } + + dbg_msg("gfx", "out of ideas. failed to init graphics"); + + return -1; + } + + int Init() + { + { + int Systems = SDL_INIT_VIDEO; + + if(g_Config.m_SndEnable) + Systems |= SDL_INIT_AUDIO; + + if(g_Config.m_ClEventthread) + Systems |= SDL_INIT_EVENTTHREAD; + + if(SDL_Init(Systems) < 0) + { + dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError()); + return -1; + } + } + + atexit(SDL_Quit); // ignore_convention + + #ifdef CONF_FAMILY_WINDOWS + if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention + putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention + #endif + + if(InitWindow() != 0) + return -1; + + SDL_ShowCursor(0); + + // set some default settings + glEnable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glAlphaFunc(GL_GREATER, 0); + glEnable(GL_ALPHA_TEST); + glDepthMask(0); + + return 0; + } + + +public: + CCommandProcessorFragment_SDL() + { + m_pScreenSurface = 0x0; + } + + bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand) + { + + switch(pBaseCommand->m_Cmd) + { + case CCommandBuffer::CMD_NOP: + break; + case CCommandBuffer::CMD_INIT: + { + const CCommandBuffer::SCommand_Init *pCommand = (CCommandBuffer::SCommand_Init *)pBaseCommand; + *pCommand->m_pResult = Init(); + } break; + case CCommandBuffer::CMD_SHUTDOWN: + break; + case CCommandBuffer::CMD_SWAP: + { + SDL_GL_SwapBuffers(); + } break; + default: + return false; + break; + } + + return true; + } +}; + + +class CCommandProcessor_SDL_OpenGL : public ICommandProcessor +{ + CCommandProcessorFragment_OpenGL m_OpenGL; + CCommandProcessorFragment_SDL m_SDL; + public: + virtual void RunBuffer(CCommandBuffer *pBuffer) + { + unsigned CmdIndex = 0; + while(1) + { + CCommandBuffer::SCommand * const pBaseCommand = pBuffer->GetCommand(&CmdIndex); + if(pBaseCommand == 0x0) + break; + + if(m_OpenGL.RunCommand(pBaseCommand)) + continue; + + if(m_SDL.RunCommand(pBaseCommand)) + continue; + + dbg_msg("graphics", "unknown command %d", pBaseCommand->m_Cmd); + } + } +}; + +void CCommandProcessorHandler::ThreadFunc(void *pUser) +{ + CCommandProcessorHandler *pThis = (CCommandProcessorHandler *)pUser; + + while(!pThis->m_Shutdown) + { + pThis->m_Activity.wait(); + if(pThis->m_pBuffer) + { + pThis->m_pProcessor->RunBuffer(pThis->m_pBuffer); + sync_barrier(); + pThis->m_pBuffer = 0x0; + pThis->m_BufferDone.signal(); + } + } +} + +CCommandProcessorHandler::CCommandProcessorHandler() +{ + m_pBuffer = 0x0; + m_pProcessor = 0x0; + m_pThread = 0x0; +} + +void CCommandProcessorHandler::Start(ICommandProcessor *pProcessor) +{ + m_Shutdown = false; + m_pProcessor = pProcessor; + m_pThread = thread_create(ThreadFunc, this); + m_BufferDone.signal(); +} + +void CCommandProcessorHandler::RunBuffer(CCommandBuffer *pBuffer) +{ + WaitForIdle(); + m_pBuffer = pBuffer; + m_Activity.signal(); +} + +void CCommandProcessorHandler::WaitForIdle() +{ + while(m_pBuffer != 0x0) + m_BufferDone.wait(); +} + + +/* +void RenderThread() +{ + .wait() + if(m_pCommandBuffer) + RunBuffer(m_pCommandBuffer); + // reset buffer? + m_pCommandBuffer = 0; +}*/ + +void CGraphics_Threaded::Flush() +{ + if(m_NumVertices == 0) + return; + + int NumVerts = m_NumVertices; + m_NumVertices = 0; + + CCommandBuffer::SCommand_Render Cmd; + Cmd.m_State = m_State; + + if(m_Drawing == DRAWING_QUADS) + { + Cmd.m_PrimType = CCommandBuffer::PRIMTYPE_QUADS; + Cmd.m_PrimCount = NumVerts/4; + } + else if(m_Drawing == DRAWING_LINES) + { + Cmd.m_PrimType = CCommandBuffer::PRIMTYPE_LINES; + Cmd.m_PrimCount = NumVerts/2; + } + else + return; + + Cmd.m_pVertices = (CCommandBuffer::SVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::SVertex)*NumVerts); + if(Cmd.m_pVertices == 0x0) + return; + + mem_copy(Cmd.m_pVertices, m_aVertices, sizeof(CCommandBuffer::SVertex)*NumVerts); + m_pCommandBuffer->AddCommand(Cmd); +} + +void CGraphics_Threaded::AddVertices(int Count) +{ + m_NumVertices += Count; + if((m_NumVertices + Count) >= MAX_VERTICES) + Flush(); +} + +void CGraphics_Threaded::Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints) +{ + float c = cosf(m_Rotation); + float s = sinf(m_Rotation); + float x, y; + int i; + + for(i = 0; i < 4; i++) + { + x = pPoints[i].m_Pos.x - rCenter.x; + y = pPoints[i].m_Pos.y - rCenter.y; + pPoints[i].m_Pos.x = x * c - y * s + rCenter.x; + pPoints[i].m_Pos.y = x * s + y * c + rCenter.y; + } +} + +unsigned char CGraphics_Threaded::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp) +{ + int Value = 0; + for(int x = 0; x < ScaleW; x++) + for(int y = 0; y < ScaleH; y++) + Value += pData[((v+y)*w+(u+x))*Bpp+Offset]; + return Value/(ScaleW*ScaleH); +} + +unsigned char *CGraphics_Threaded::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData) +{ + unsigned char *pTmpData; + int ScaleW = Width/NewWidth; + int ScaleH = Height/NewHeight; + + int Bpp = 3; + if(Format == CImageInfo::FORMAT_RGBA) + Bpp = 4; + + pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1); + + int c = 0; + for(int y = 0; y < NewHeight; y++) + for(int x = 0; x < NewWidth; x++, c++) + { + pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp); + pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp); + pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp); + if(Bpp == 4) + pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp); + } + + return pTmpData; +} + +CGraphics_Threaded::CGraphics_Threaded() +{ + m_State.m_ScreenTL.x = 0; + m_State.m_ScreenTL.y = 0; + m_State.m_ScreenBR.x = 0; + m_State.m_ScreenBR.y = 0; + m_State.m_ClipEnable = false; + m_State.m_ClipX = 0; + m_State.m_ClipY = 0; + m_State.m_ClipW = 0; + m_State.m_ClipH = 0; + m_State.m_Texture = -1; + m_State.m_BlendMode = CCommandBuffer::BLEND_NONE; + + + + m_NumVertices = 0; + + m_ScreenWidth = -1; + m_ScreenHeight = -1; + + m_Rotation = 0; + m_Drawing = 0; + m_InvalidTexture = 0; + + m_TextureMemoryUsage = 0; + + m_RenderEnable = true; + m_DoScreenshot = false; +} + +void CGraphics_Threaded::ClipEnable(int x, int y, int w, int h) +{ + if(x < 0) + w += x; + if(y < 0) + h += y; + + x = clamp(x, 0, ScreenWidth()); + y = clamp(y, 0, ScreenHeight()); + w = clamp(w, 0, ScreenWidth()-x); + h = clamp(h, 0, ScreenHeight()-y); + + m_State.m_ClipEnable = true; + m_State.m_ClipX = x; + m_State.m_ClipY = ScreenHeight()-(y+h); + m_State.m_ClipW = w; + m_State.m_ClipH = h; +} + +void CGraphics_Threaded::ClipDisable() +{ + m_State.m_ClipEnable = false; +} + +void CGraphics_Threaded::BlendNone() +{ + m_State.m_BlendMode = CCommandBuffer::BLEND_NONE; +} + +void CGraphics_Threaded::BlendNormal() +{ + m_State.m_BlendMode = CCommandBuffer::BLEND_ALPHA; +} + +void CGraphics_Threaded::BlendAdditive() +{ + m_State.m_BlendMode = CCommandBuffer::BLEND_ADDITIVE; +} + +int CGraphics_Threaded::MemoryUsage() const +{ + return m_TextureMemoryUsage; +} + +void CGraphics_Threaded::MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY) +{ + m_State.m_ScreenTL.x = TopLeftX; + m_State.m_ScreenTL.y = TopLeftY; + m_State.m_ScreenBR.x = BottomRightX; + m_State.m_ScreenBR.y = BottomRightY; +} + +void CGraphics_Threaded::GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBottomRightX, float *pBottomRightY) +{ + *pTopLeftX = m_State.m_ScreenTL.x; + *pTopLeftY = m_State.m_ScreenTL.y; + *pBottomRightX = m_State.m_ScreenBR.x; + *pBottomRightY = m_State.m_ScreenBR.y; +} + +void CGraphics_Threaded::LinesBegin() +{ + dbg_assert(m_Drawing == 0, "called Graphics()->LinesBegin twice"); + m_Drawing = DRAWING_LINES; + SetColor(1,1,1,1); +} + +void CGraphics_Threaded::LinesEnd() +{ + dbg_assert(m_Drawing == DRAWING_LINES, "called Graphics()->LinesEnd without begin"); + Flush(); + m_Drawing = 0; +} + +void CGraphics_Threaded::LinesDraw(const CLineItem *pArray, int Num) +{ + dbg_assert(m_Drawing == DRAWING_LINES, "called Graphics()->LinesDraw without begin"); + + for(int i = 0; i < Num; ++i) + { + m_aVertices[m_NumVertices + 2*i].m_Pos.x = pArray[i].m_X0; + m_aVertices[m_NumVertices + 2*i].m_Pos.y = pArray[i].m_Y0; + m_aVertices[m_NumVertices + 2*i].m_Tex = m_aTexture[0]; + m_aVertices[m_NumVertices + 2*i].m_Color = m_aColor[0]; + + m_aVertices[m_NumVertices + 2*i + 1].m_Pos.x = pArray[i].m_X1; + m_aVertices[m_NumVertices + 2*i + 1].m_Pos.y = pArray[i].m_Y1; + m_aVertices[m_NumVertices + 2*i + 1].m_Tex = m_aTexture[1]; + m_aVertices[m_NumVertices + 2*i + 1].m_Color = m_aColor[1]; + } + + AddVertices(2*Num); +} + +int CGraphics_Threaded::UnloadTexture(int Index) +{ + return 0; + if(Index == m_InvalidTexture) + return 0; + + if(Index < 0) + return 0; + + glDeleteTextures(1, &m_aTextures[Index].m_Tex); + m_aTextures[Index].m_Next = m_FirstFreeTexture; + m_TextureMemoryUsage -= m_aTextures[Index].m_MemSize; + m_FirstFreeTexture = Index; + return 0; +} + + +int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) +{ + return 0; + + int Mipmap = 1; + unsigned char *pTexData = (unsigned char *)pData; + unsigned char *pTmpData = 0; + int Oglformat = 0; + int StoreOglformat = 0; + int Tex = 0; + + // don't waste memory on texture if we are stress testing + if(g_Config.m_DbgStress) + return m_InvalidTexture; + + // grab texture + Tex = m_FirstFreeTexture; + m_FirstFreeTexture = m_aTextures[Tex].m_Next; + m_aTextures[Tex].m_Next = -1; + + // resample if needed + if(!(Flags&TEXLOAD_NORESAMPLE) && (Format == CImageInfo::FORMAT_RGBA || Format == CImageInfo::FORMAT_RGB)) + { + if(Width > GL_MAX_TEXTURE_SIZE || Height > GL_MAX_TEXTURE_SIZE) + { + int NewWidth = min(Width, GL_MAX_TEXTURE_SIZE); + int NewHeight = min(Height, GL_MAX_TEXTURE_SIZE); + pTmpData = Rescale(Width, Height, NewWidth, NewHeight, Format, pTexData); + pTexData = pTmpData; + Width = NewWidth; + Height = NewHeight; + } + else if(Width > 16 && Height > 16 && g_Config.m_GfxTextureQuality == 0) + { + pTmpData = Rescale(Width, Height, Width/2, Height/2, Format, pTexData); + pTexData = pTmpData; + Width /= 2; + Height /= 2; + } + } + + Oglformat = GL_RGBA; + if(Format == CImageInfo::FORMAT_RGB) + Oglformat = GL_RGB; + else if(Format == CImageInfo::FORMAT_ALPHA) + Oglformat = GL_ALPHA; + + // upload texture + if(g_Config.m_GfxTextureCompression) + { + StoreOglformat = GL_COMPRESSED_RGBA_ARB; + if(StoreFormat == CImageInfo::FORMAT_RGB) + StoreOglformat = GL_COMPRESSED_RGB_ARB; + else if(StoreFormat == CImageInfo::FORMAT_ALPHA) + StoreOglformat = GL_COMPRESSED_ALPHA_ARB; + } + else + { + StoreOglformat = GL_RGBA; + if(StoreFormat == CImageInfo::FORMAT_RGB) + StoreOglformat = GL_RGB; + else if(StoreFormat == CImageInfo::FORMAT_ALPHA) + StoreOglformat = GL_ALPHA; + } + + glGenTextures(1, &m_aTextures[Tex].m_Tex); + glBindTexture(GL_TEXTURE_2D, m_aTextures[Tex].m_Tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); + + // calculate memory usage + { + int PixelSize = 4; + if(StoreFormat == CImageInfo::FORMAT_RGB) + PixelSize = 3; + else if(StoreFormat == CImageInfo::FORMAT_ALPHA) + PixelSize = 1; + + m_aTextures[Tex].m_MemSize = Width*Height*PixelSize; + if(Mipmap) + { + while(Width > 2 && Height > 2) + { + Width>>=1; + Height>>=1; + m_aTextures[Tex].m_MemSize += Width*Height*PixelSize; + } + } + } + + m_TextureMemoryUsage += m_aTextures[Tex].m_MemSize; + mem_free(pTmpData); + return Tex; +} + +// simple uncompressed RGBA loaders +int CGraphics_Threaded::LoadTexture(const char *pFilename, int StorageType, int StoreFormat, int Flags) +{ + return 0; + + int l = str_length(pFilename); + int ID; + CImageInfo Img; + + if(l < 3) + return -1; + if(LoadPNG(&Img, pFilename, StorageType)) + { + if (StoreFormat == CImageInfo::FORMAT_AUTO) + StoreFormat = Img.m_Format; + + ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags); + mem_free(Img.m_pData); + if(ID != m_InvalidTexture && g_Config.m_Debug) + dbg_msg("graphics/texture", "loaded %s", pFilename); + return ID; + } + + return m_InvalidTexture; +} + +int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int StorageType) +{ + return 0; + + char aCompleteFilename[512]; + unsigned char *pBuffer; + png_t Png; // ignore_convention + + // open file for reading + png_init(0,0); // ignore_convention + + IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_READ, StorageType, aCompleteFilename, sizeof(aCompleteFilename)); + if(File) + io_close(File); + else + { + dbg_msg("game/png", "failed to open file. filename='%s'", pFilename); + return 0; + } + + int Error = png_open_file(&Png, aCompleteFilename); // ignore_convention + if(Error != PNG_NO_ERROR) + { + dbg_msg("game/png", "failed to open file. filename='%s'", aCompleteFilename); + if(Error != PNG_FILE_ERROR) + png_close_file(&Png); // ignore_convention + return 0; + } + + if(Png.depth != 8 || (Png.color_type != PNG_TRUECOLOR && Png.color_type != PNG_TRUECOLOR_ALPHA)) // ignore_convention + { + dbg_msg("game/png", "invalid format. filename='%s'", aCompleteFilename); + png_close_file(&Png); // ignore_convention + return 0; + } + + pBuffer = (unsigned char *)mem_alloc(Png.width * Png.height * Png.bpp, 1); // ignore_convention + png_get_data(&Png, pBuffer); // ignore_convention + png_close_file(&Png); // ignore_convention + + pImg->m_Width = Png.width; // ignore_convention + pImg->m_Height = Png.height; // ignore_convention + if(Png.color_type == PNG_TRUECOLOR) // ignore_convention + pImg->m_Format = CImageInfo::FORMAT_RGB; + else if(Png.color_type == PNG_TRUECOLOR_ALPHA) // ignore_convention + pImg->m_Format = CImageInfo::FORMAT_RGBA; + pImg->m_pData = pBuffer; + return 1; +} + +void CGraphics_Threaded::ScreenshotDirect(const char *pFilename) +{ + // fetch image data + int y; + int w = m_ScreenWidth; + int h = m_ScreenHeight; + unsigned char *pPixelData = (unsigned char *)mem_alloc(w*(h+1)*3, 1); + unsigned char *pTempRow = pPixelData+w*h*3; + GLint Alignment; + glGetIntegerv(GL_PACK_ALIGNMENT, &Alignment); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData); + glPixelStorei(GL_PACK_ALIGNMENT, Alignment); + + // flip the pixel because opengl works from bottom left corner + for(y = 0; y < h/2; y++) + { + mem_copy(pTempRow, pPixelData+y*w*3, w*3); + mem_copy(pPixelData+y*w*3, pPixelData+(h-y-1)*w*3, w*3); + mem_copy(pPixelData+(h-y-1)*w*3, pTempRow,w*3); + } + + // find filename + { + char aWholePath[1024]; + png_t Png; // ignore_convention + + IOHANDLE File = m_pStorage->OpenFile(pFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE, aWholePath, sizeof(aWholePath)); + if(File) + io_close(File); + + // save png + char aBuf[256]; + str_format(aBuf, sizeof(aBuf), "saved screenshot to '%s'", aWholePath); + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf); + png_open_file_write(&Png, aWholePath); // ignore_convention + png_set_data(&Png, w, h, 8, PNG_TRUECOLOR, (unsigned char *)pPixelData); // ignore_convention + png_close_file(&Png); // ignore_convention + } + + // clean up + mem_free(pPixelData); +} + +void CGraphics_Threaded::TextureSet(int TextureID) +{ + return; + + dbg_assert(m_Drawing == 0, "called Graphics()->TextureSet within begin"); + if(TextureID == -1) + { + glDisable(GL_TEXTURE_2D); + } + else + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_aTextures[TextureID].m_Tex); + } +} + +void CGraphics_Threaded::Clear(float r, float g, float b) +{ + CCommandBuffer::SCommand_Clear Cmd; + Cmd.m_Color.r = r; + Cmd.m_Color.g = g; + Cmd.m_Color.b = b; + Cmd.m_Color.a = 0; + m_pCommandBuffer->AddCommand(Cmd); +} + +void CGraphics_Threaded::QuadsBegin() +{ + dbg_assert(m_Drawing == 0, "called Graphics()->QuadsBegin twice"); + m_Drawing = DRAWING_QUADS; + + QuadsSetSubset(0,0,1,1); + QuadsSetRotation(0); + SetColor(1,1,1,1); +} + +void CGraphics_Threaded::QuadsEnd() +{ + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsEnd without begin"); + Flush(); + m_Drawing = 0; +} + +void CGraphics_Threaded::QuadsSetRotation(float Angle) +{ + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetRotation without begin"); + m_Rotation = Angle; +} + +void CGraphics_Threaded::SetColorVertex(const CColorVertex *pArray, int Num) +{ + dbg_assert(m_Drawing != 0, "called Graphics()->SetColorVertex without begin"); + + for(int i = 0; i < Num; ++i) + { + m_aColor[pArray[i].m_Index].r = pArray[i].m_R; + m_aColor[pArray[i].m_Index].g = pArray[i].m_G; + m_aColor[pArray[i].m_Index].b = pArray[i].m_B; + m_aColor[pArray[i].m_Index].a = pArray[i].m_A; + } +} + +void CGraphics_Threaded::SetColor(float r, float g, float b, float a) +{ + dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin"); + CColorVertex Array[4] = { + CColorVertex(0, r, g, b, a), + CColorVertex(1, r, g, b, a), + CColorVertex(2, r, g, b, a), + CColorVertex(3, r, g, b, a)}; + SetColorVertex(Array, 4); +} + +void CGraphics_Threaded::QuadsSetSubset(float TlU, float TlV, float BrU, float BrV) +{ + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin"); + + m_aTexture[0].u = TlU; m_aTexture[1].u = BrU; + m_aTexture[0].v = TlV; m_aTexture[1].v = TlV; + + m_aTexture[3].u = TlU; m_aTexture[2].u = BrU; + m_aTexture[3].v = BrV; m_aTexture[2].v = BrV; +} + +void CGraphics_Threaded::QuadsSetSubsetFree( + float x0, float y0, float x1, float y1, + float x2, float y2, float x3, float y3) +{ + m_aTexture[0].u = x0; m_aTexture[0].v = y0; + m_aTexture[1].u = x1; m_aTexture[1].v = y1; + m_aTexture[2].u = x2; m_aTexture[2].v = y2; + m_aTexture[3].u = x3; m_aTexture[3].v = y3; +} + +void CGraphics_Threaded::QuadsDraw(CQuadItem *pArray, int Num) +{ + for(int i = 0; i < Num; ++i) + { + pArray[i].m_X -= pArray[i].m_Width/2; + pArray[i].m_Y -= pArray[i].m_Height/2; + } + + QuadsDrawTL(pArray, Num); +} + +void CGraphics_Threaded::QuadsDrawTL(const CQuadItem *pArray, int Num) +{ + CCommandBuffer::SPoint Center; + Center.z = 0; + + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawTL without begin"); + + for(int i = 0; i < Num; ++i) + { + m_aVertices[m_NumVertices + 4*i].m_Pos.x = pArray[i].m_X; + m_aVertices[m_NumVertices + 4*i].m_Pos.y = pArray[i].m_Y; + m_aVertices[m_NumVertices + 4*i].m_Tex = m_aTexture[0]; + m_aVertices[m_NumVertices + 4*i].m_Color = m_aColor[0]; + + m_aVertices[m_NumVertices + 4*i + 1].m_Pos.x = pArray[i].m_X + pArray[i].m_Width; + m_aVertices[m_NumVertices + 4*i + 1].m_Pos.y = pArray[i].m_Y; + m_aVertices[m_NumVertices + 4*i + 1].m_Tex = m_aTexture[1]; + m_aVertices[m_NumVertices + 4*i + 1].m_Color = m_aColor[1]; + + m_aVertices[m_NumVertices + 4*i + 2].m_Pos.x = pArray[i].m_X + pArray[i].m_Width; + m_aVertices[m_NumVertices + 4*i + 2].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height; + m_aVertices[m_NumVertices + 4*i + 2].m_Tex = m_aTexture[2]; + m_aVertices[m_NumVertices + 4*i + 2].m_Color = m_aColor[2]; + + m_aVertices[m_NumVertices + 4*i + 3].m_Pos.x = pArray[i].m_X; + m_aVertices[m_NumVertices + 4*i + 3].m_Pos.y = pArray[i].m_Y + pArray[i].m_Height; + m_aVertices[m_NumVertices + 4*i + 3].m_Tex = m_aTexture[3]; + m_aVertices[m_NumVertices + 4*i + 3].m_Color = m_aColor[3]; + + if(m_Rotation != 0) + { + Center.x = pArray[i].m_X + pArray[i].m_Width/2; + Center.y = pArray[i].m_Y + pArray[i].m_Height/2; + + Rotate4(Center, &m_aVertices[m_NumVertices + 4*i]); + } + } + + AddVertices(4*Num); +} + +void CGraphics_Threaded::QuadsDrawFreeform(const CFreeformItem *pArray, int Num) +{ + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawFreeform without begin"); + + for(int i = 0; i < Num; ++i) + { + m_aVertices[m_NumVertices + 4*i].m_Pos.x = pArray[i].m_X0; + m_aVertices[m_NumVertices + 4*i].m_Pos.y = pArray[i].m_Y0; + m_aVertices[m_NumVertices + 4*i].m_Tex = m_aTexture[0]; + m_aVertices[m_NumVertices + 4*i].m_Color = m_aColor[0]; + + m_aVertices[m_NumVertices + 4*i + 1].m_Pos.x = pArray[i].m_X1; + m_aVertices[m_NumVertices + 4*i + 1].m_Pos.y = pArray[i].m_Y1; + m_aVertices[m_NumVertices + 4*i + 1].m_Tex = m_aTexture[1]; + m_aVertices[m_NumVertices + 4*i + 1].m_Color = m_aColor[1]; + + m_aVertices[m_NumVertices + 4*i + 2].m_Pos.x = pArray[i].m_X3; + m_aVertices[m_NumVertices + 4*i + 2].m_Pos.y = pArray[i].m_Y3; + m_aVertices[m_NumVertices + 4*i + 2].m_Tex = m_aTexture[3]; + m_aVertices[m_NumVertices + 4*i + 2].m_Color = m_aColor[3]; + + m_aVertices[m_NumVertices + 4*i + 3].m_Pos.x = pArray[i].m_X2; + m_aVertices[m_NumVertices + 4*i + 3].m_Pos.y = pArray[i].m_Y2; + m_aVertices[m_NumVertices + 4*i + 3].m_Tex = m_aTexture[2]; + m_aVertices[m_NumVertices + 4*i + 3].m_Color = m_aColor[2]; + } + + AddVertices(4*Num); +} + +void CGraphics_Threaded::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText) +{ + float StartX = x; + + QuadsBegin(); + SetColor(r,g,b,a); + + while(*pText) + { + char c = *pText; + pText++; + + if(c == '\n') + { + x = StartX; + y += Size; + } + else + { + QuadsSetSubset( + (c%16)/16.0f, + (c/16)/16.0f, + (c%16)/16.0f+1.0f/16.0f, + (c/16)/16.0f+1.0f/16.0f); + + CQuadItem QuadItem(x, y, Size, Size); + QuadsDrawTL(&QuadItem, 1); + x += Size/2; + } + } + + QuadsEnd(); +} + +bool CGraphics_Threaded::Init() +{ + // fetch pointers + m_pStorage = Kernel()->RequestInterface(); + m_pConsole = Kernel()->RequestInterface(); + + // Set all z to -5.0f + for(int i = 0; i < MAX_VERTICES; i++) + m_aVertices[i].m_Pos.z = -5.0f; + + // init textures + m_FirstFreeTexture = 0; + for(int i = 0; i < MAX_TEXTURES; i++) + m_aTextures[i].m_Next = i+1; + m_aTextures[MAX_TEXTURES-1].m_Next = -1; + + // start the command processor + ICommandProcessor *pProcessor = new CCommandProcessor_SDL_OpenGL; + m_Handler.Start(pProcessor); + + // create command buffers + m_apCommandBuffers[0] = new CCommandBuffer(1024*512, 1024*1024); + m_apCommandBuffers[1] = new CCommandBuffer(1024*512, 1024*1024); + m_pCommandBuffer = m_apCommandBuffers[0]; + + // issue init command + m_pCommandBuffer->Reset(); + volatile int Result; + CCommandBuffer::SCommand_Init Cmd; + Cmd.m_pResult = &Result; + m_pCommandBuffer->AddCommand(Cmd); + m_Handler.RunBuffer(m_pCommandBuffer); + m_Handler.WaitForIdle(); + + + if(Result == 0) + { + // create null texture, will get id=0 + static const unsigned char aNullTextureData[] = { + 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, + 0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, + 0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, + }; + + m_InvalidTexture = LoadTextureRaw(4,4,CImageInfo::FORMAT_RGBA,aNullTextureData,CImageInfo::FORMAT_RGBA,TEXLOAD_NORESAMPLE); + } + + return Result; +} + +void CGraphics_Threaded::Shutdown() +{ + // TODO: SDL, is this correct? + SDL_Quit(); +} + +void CGraphics_Threaded::Minimize() +{ + SDL_WM_IconifyWindow(); +} + +void CGraphics_Threaded::Maximize() +{ + // TODO: SDL +} + +int CGraphics_Threaded::WindowActive() +{ + return SDL_GetAppState()&SDL_APPINPUTFOCUS; +} + +int CGraphics_Threaded::WindowOpen() +{ + return SDL_GetAppState()&SDL_APPACTIVE; + +} + +void CGraphics_Threaded::TakeScreenshot(const char *pFilename) +{ + // TODO: screenshot support + return; + /* + char aDate[20]; + str_timestamp(aDate, sizeof(aDate)); + str_format(m_aScreenshotName, sizeof(m_aScreenshotName), "screenshots/%s_%s.png", pFilename?pFilename:"screenshot", aDate); + m_DoScreenshot = true; + */ +} + +void CGraphics_Threaded::Swap() +{ + if(0) { + CCommandBuffer::SCommand_Clear Cmd; + Cmd.m_Color.r = 1.0f; + Cmd.m_Color.g = 0.0f; + Cmd.m_Color.b = 0.0f; + Cmd.m_Color.a = 0.0f; + m_pCommandBuffer->AddCommand(Cmd); + } + + CCommandBuffer::SCommand_Swap Cmd; + m_pCommandBuffer->AddCommand(Cmd); + + m_Handler.RunBuffer(m_pCommandBuffer); + m_Handler.WaitForIdle(); + m_pCommandBuffer->Reset(); + + // TODO: screenshot support + /* + if(m_DoScreenshot) + { + ScreenshotDirect(m_aScreenshotName); + m_DoScreenshot = false; + }*/ + + //SDL_GL_SwapBuffers(); + + //if(g_Config.m_GfxFinish) + // glFinish(); +} + + +int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes) +{ + // TODO: fix support for video modes, using fake modes for now + //int NumModes = sizeof(g_aFakeModes)/sizeof(CVideoMode); + //SDL_Rect **ppModes; + + //if(g_Config.m_GfxDisplayAllModes) + { + int Count = sizeof(g_aFakeModes)/sizeof(CVideoMode); + mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes)); + if(MaxModes < Count) + Count = MaxModes; + return Count; + } + + // TODO: fix this code on osx or windows + /* + + ppModes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN); + if(ppModes == NULL) + { + // no modes + NumModes = 0; + } + else if(ppModes == (SDL_Rect**)-1) + { + // all modes + } + else + { + NumModes = 0; + for(int i = 0; ppModes[i]; ++i) + { + if(NumModes == MaxModes) + break; + pModes[NumModes].m_Width = ppModes[i]->w; + pModes[NumModes].m_Height = ppModes[i]->h; + pModes[NumModes].m_Red = 8; + pModes[NumModes].m_Green = 8; + pModes[NumModes].m_Blue = 8; + NumModes++; + } + } + + return NumModes;*/ +} + + +extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_Threaded(); } diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index fc1ca2db..0e61ec6e 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -628,7 +628,6 @@ int CMenus::RenderMenubar(CUIRect r) void CMenus::RenderLoading() { // TODO: not supported right now due to separate render thread - return; static int64 LastLoadRender = 0; float Percent = m_LoadCurrent++/(float)m_LoadTotal; -- cgit 1.4.1 From 4e923442e48bd78617061afe9da0ed5bf5d1fa02 Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sat, 31 Dec 2011 10:15:54 +0100 Subject: fixed the broken damage indicators --- src/game/client/components/damageind.cpp | 17 ++++++++++------- src/game/client/components/damageind.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index cba47666..9be6722a 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -38,7 +38,7 @@ void CDamageInd::Create(vec2 Pos, vec2 Dir) if (i) { i->m_Pos = Pos; - i->m_Life = 0.75f; + i->m_StartTime = Client()->LocalTime(); i->m_Dir = Dir*-1; i->m_StartAngle = (( (float)rand()/(float)RAND_MAX) - 1.0f) * 2.0f * pi; } @@ -46,19 +46,19 @@ void CDamageInd::Create(vec2 Pos, vec2 Dir) void CDamageInd::OnRender() { + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); for(int i = 0; i < m_NumItems;) { - vec2 Pos = mix(m_aItems[i].m_Pos+m_aItems[i].m_Dir*75.0f, m_aItems[i].m_Pos, clamp((m_aItems[i].m_Life-0.60f)/0.15f, 0.0f, 1.0f)); - - m_aItems[i].m_Life -= Client()->FrameTime(); - if(m_aItems[i].m_Life < 0.0f) + float Life = 0.75f - (Client()->LocalTime() - m_aItems[i].m_StartTime); + if(Life < 0.0f) DestroyI(&m_aItems[i]); else { - Graphics()->SetColor(1.0f,1.0f,1.0f, m_aItems[i].m_Life/0.1f); - Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + m_aItems[i].m_Life * 2.0f); + vec2 Pos = mix(m_aItems[i].m_Pos+m_aItems[i].m_Dir*75.0f, m_aItems[i].m_Pos, clamp((Life-0.60f)/0.15f, 0.0f, 1.0f)); + Graphics()->SetColor(1.0f,1.0f,1.0f, Life/0.1f); + Graphics()->QuadsSetRotation(m_aItems[i].m_StartAngle + Life * 2.0f); RenderTools()->SelectSprite(SPRITE_STAR1); RenderTools()->DrawSprite(Pos.x, Pos.y, 48.0f); i++; @@ -66,3 +66,6 @@ void CDamageInd::OnRender() } Graphics()->QuadsEnd(); } + + + diff --git a/src/game/client/components/damageind.h b/src/game/client/components/damageind.h index 2f89e422..4a5975a8 100644 --- a/src/game/client/components/damageind.h +++ b/src/game/client/components/damageind.h @@ -12,7 +12,7 @@ class CDamageInd : public CComponent { vec2 m_Pos; vec2 m_Dir; - float m_Life; + float m_StartTime; float m_StartAngle; }; -- cgit 1.4.1 From c1942ca6cbafb605e3ebc8e8cfabf982144f388f Mon Sep 17 00:00:00 2001 From: Magnus Auvinen Date: Sun, 1 Jan 2012 13:38:46 +0100 Subject: fixed the render frame time and cleaned up some more code --- src/engine/client.h | 4 +- src/engine/client/client.cpp | 60 ++++++++------- src/engine/client/client.h | 9 ++- src/engine/client/graphics_threaded.cpp | 132 +------------------------------- src/engine/client/graphics_threaded.h | 10 +++ src/game/client/components/hud.cpp | 2 +- src/game/client/components/items.cpp | 3 - 7 files changed, 54 insertions(+), 166 deletions(-) (limited to 'src/game/client/components') diff --git a/src/engine/client.h b/src/engine/client.h index 966e8f61..e9076b76 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -23,7 +23,7 @@ protected: float m_PredIntraTick; float m_LocalTime; - float m_FrameTime; + float m_RenderFrameTime; int m_GameTickSpeed; public: @@ -68,7 +68,7 @@ public: inline int GameTickSpeed() const { return m_GameTickSpeed; } // other time access - inline float FrameTime() const { return m_FrameTime; } + inline float RenderFrameTime() const { return m_RenderFrameTime; } inline float LocalTime() const { return m_LocalTime; } // actions diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b54b9084..b7244db4 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -244,10 +244,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; @@ -681,13 +682,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); @@ -1691,9 +1692,6 @@ void CClient::InitInterfaces() void CClient::Run() { - int64 ReportTime = time_get(); - int64 ReportInterval = time_freq()*1; - m_LocalStartTime = time_get(); m_SnapshotParts = 0; @@ -1772,9 +1770,6 @@ void CClient::Run() while (1) { - int64 FrameStartTime = time_get(); - m_Frames++; - // VersionUpdate(); @@ -1866,9 +1861,22 @@ void CClient::Run() if(!g_Config.m_GfxAsyncRender || m_pGraphics->IsIdle()) { + 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_Frames%10) == 0) + if((m_RenderFrames%10) == 0) { Render(); m_pGraphics->Swap(); @@ -1879,6 +1887,9 @@ void CClient::Run() Render(); m_pGraphics->Swap(); } + + + } } @@ -1900,32 +1911,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(); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 83553eb4..1849830c 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -84,9 +84,12 @@ class CClient : public IClient, public CDemoPlayer::IListner int64 m_LocalStartTime; int m_DebugFont; - float m_FrameTimeLow; - float m_FrameTimeHigh; - int m_Frames; + + int64 m_LastRenderTime; + float m_RenderFrameTimeLow; + float m_RenderFrameTimeHigh; + int m_RenderFrames; + NETADDR m_ServerAddress; int m_WindowMustRefocus; int m_SnapCrcErrors; diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index febb3b28..694ecc71 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -230,130 +230,6 @@ class CCommandProcessorFragment_SDL // SDL stuff SDL_Surface *m_pScreenSurface; bool m_SystemInited; - /* - int TryInit() - { - const SDL_VideoInfo *pInfo = SDL_GetVideoInfo(); - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); - - // set flags - int Flags = SDL_OPENGL; - if(g_Config.m_DbgResizable) - Flags |= SDL_RESIZABLE; - - if(pInfo->hw_available) // ignore_convention - Flags |= SDL_HWSURFACE; - else - Flags |= SDL_SWSURFACE; - - if(pInfo->blit_hw) // ignore_convention - Flags |= SDL_HWACCEL; - - if(g_Config.m_GfxFullscreen) - Flags |= SDL_FULLSCREEN; - - // set gl attributes - if(g_Config.m_GfxFsaaSamples) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, g_Config.m_GfxFsaaSamples); - } - else - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - } - - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, g_Config.m_GfxVsync); - - // set caption - SDL_WM_SetCaption("Teeworlds", "Teeworlds"); - - // create window - m_pScreenSurface = SDL_SetVideoMode(g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight, 0, Flags); - if(m_pScreenSurface == NULL) - { - dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError()); - return -1; - } - - return 0; - } - - - int InitWindow() - { - if(TryInit() == 0) - return 0; - - // try disabling fsaa - while(g_Config.m_GfxFsaaSamples) - { - g_Config.m_GfxFsaaSamples--; - - if(g_Config.m_GfxFsaaSamples) - dbg_msg("gfx", "lowering FSAA to %d and trying again", g_Config.m_GfxFsaaSamples); - else - dbg_msg("gfx", "disabling FSAA and trying again"); - - if(TryInit() == 0) - return 0; - } - - // try lowering the resolution - if(g_Config.m_GfxScreenWidth != 640 || g_Config.m_GfxScreenHeight != 480) - { - dbg_msg("gfx", "setting resolution to 640x480 and trying again"); - g_Config.m_GfxScreenWidth = 640; - g_Config.m_GfxScreenHeight = 480; - - if(TryInit() == 0) - return 0; - } - - dbg_msg("gfx", "out of ideas. failed to init graphics"); - - return -1; - } - - int Init() - { - { - int Systems = SDL_INIT_VIDEO; - - if(g_Config.m_SndEnable) - Systems |= SDL_INIT_AUDIO; - - if(g_Config.m_ClEventthread) - Systems |= SDL_INIT_EVENTTHREAD; - - if(SDL_Init(Systems) < 0) - { - dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError()); - return -1; - } - } - - - if(InitWindow() != 0) - return -1; - - SDL_ShowCursor(0); - - // set some default settings - glEnable(GL_BLEND); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glAlphaFunc(GL_GREATER, 0); - glEnable(GL_ALPHA_TEST); - glDepthMask(0); - - return 0; - }*/ void Cmd_Init(const CCommandBuffer::SCommand_Init *pCommand) { @@ -445,14 +321,11 @@ class CCommandProcessorFragment_SDL dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError()); *pCommand->m_pResult = -1; } - - - //*pCommand->m_pResult = Init(); } void Cmd_Shutdown(const CCommandBuffer::SCommand_Shutdown *pCommand) { - + SDL_Quit(); } void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand) @@ -1312,7 +1185,8 @@ bool CGraphics_Threaded::Init() void CGraphics_Threaded::Shutdown() { // TODO: SDL, is this correct? - SDL_Quit(); + + // } void CGraphics_Threaded::Minimize() diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h index 54455d6d..1ea84ea9 100644 --- a/src/engine/client/graphics_threaded.h +++ b/src/engine/client/graphics_threaded.h @@ -78,6 +78,9 @@ public: // swap CMD_SWAP, + + // + CMD_SCREENSHOT, }; enum @@ -192,6 +195,13 @@ public: SVertex *m_pVertices; }; + struct SCommand_Screenshot : public SCommand + { + SCommand_Screenshot() : SCommand(CMD_SCREENSHOT) {} + + CImageInfo *m_pImage; // processor will fill this out + }; + struct SCommand_Swap : public SCommand { SCommand_Swap() : SCommand(CMD_SWAP) {} diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 17365116..df3afdea 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -248,7 +248,7 @@ void CHud::RenderFps() if(g_Config.m_ClShowfps) { // calculate avg. fps - float FPS = 1.0f / Client()->FrameTime(); + float FPS = 1.0f / Client()->RenderFrameTime(); m_AverageFPS = (m_AverageFPS*(1.0f-(1.0f/m_AverageFPS))) + (FPS*(1.0f/m_AverageFPS)); char Buf[512]; str_format(Buf, sizeof(Buf), "%d", (int)m_AverageFPS); diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 1c338994..9f787a4b 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -22,7 +22,6 @@ void CItems::OnReset() void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) { - // get positions float Curvature = 0; float Speed = 0; @@ -64,7 +63,6 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); - m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { @@ -85,7 +83,6 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) else { m_pClient->m_pEffects->BulletTrail(Pos); - m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(length(Vel) > 0.00001f) Graphics()->QuadsSetRotation(GetAngle(Vel)); -- cgit 1.4.1 From b592d7a591f32ecdc2c91a79b76c58f77a2b5fee Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 6 Jan 2012 19:38:40 +0100 Subject: cleaned up playing of global sounds --- src/game/client/components/chat.cpp | 6 +-- src/game/client/components/effects.cpp | 6 +-- src/game/client/components/menus.cpp | 2 +- src/game/client/components/menus_settings.cpp | 4 +- src/game/client/components/players.cpp | 2 +- src/game/client/components/sounds.cpp | 65 ++++++++++++++++++--------- src/game/client/components/sounds.h | 5 ++- src/game/client/gameclient.cpp | 4 +- 8 files changed, 61 insertions(+), 33 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index a3bf5252..a89d2b7e 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -323,11 +323,11 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) // play sound if(ClientID == -1) - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0, vec2(0,0)); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); else if(Highlighted) - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0, vec2(0.0f, 0.0f)); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); else - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0, vec2(0,0)); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); } void CChat::OnRender() diff --git a/src/game/client/components/effects.cpp b/src/game/client/components/effects.cpp index 8554b7ba..933e7fe6 100644 --- a/src/game/client/components/effects.cpp +++ b/src/game/client/components/effects.cpp @@ -44,7 +44,7 @@ void CEffects::AirJump(vec2 Pos) p.m_Pos = Pos + vec2(6.0f, 16.0f); m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); - m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, Pos); + m_pClient->m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_AIRJUMP, 1.0f, Pos); } void CEffects::DamageIndicator(vec2 Pos, vec2 Dir) @@ -147,7 +147,7 @@ void CEffects::PlayerSpawn(vec2 Pos) m_pClient->m_pParticles->Add(CParticles::GROUP_GENERAL, &p); } - m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, Pos); + m_pClient->m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_SPAWN, 1.0f, Pos); } void CEffects::PlayerDeath(vec2 Pos, int ClientID) @@ -242,7 +242,7 @@ void CEffects::HammerHit(vec2 Pos) p.m_EndSize = 0; p.m_Rot = frandom()*pi*2; m_pClient->m_pParticles->Add(CParticles::GROUP_EXPLOSIONS, &p); - m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, Pos); + m_pClient->m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_HAMMER_HIT, 1.0f, Pos); } void CEffects::OnRender() diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0e61ec6e..a2ccfba4 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1404,7 +1404,7 @@ void CMenus::OnStateChange(int NewState, int OldState) if(NewState == IClient::STATE_OFFLINE) { if(OldState >= IClient::STATE_ONLINE) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f, vec2(0, 0)); + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); m_Popup = POPUP_NONE; if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) { diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index c9b44567..de4b10bd 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -763,7 +763,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) if(g_Config.m_SndEnable) { if(g_Config.m_SndMusic) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f, vec2(0, 0)); + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); } else m_pClient->m_pSounds->Stop(SOUND_MENU); @@ -778,7 +778,7 @@ void CMenus::RenderSettingsSound(CUIRect MainView) { g_Config.m_SndMusic ^= 1; if(g_Config.m_SndMusic) - m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f, vec2(0, 0)); + m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); else m_pClient->m_pSounds->Stop(SOUND_MENU); } diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 6811c2ad..2ce73384 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -347,7 +347,7 @@ void CPlayers::RenderPlayer( static int64 SkidSoundTime = 0; if(time_get()-SkidSoundTime > time_freq()/10) { - m_pClient->m_pSounds->Play(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position); + m_pClient->m_pSounds->PlayAt(CSounds::CHN_WORLD, SOUND_PLAYER_SKID, 0.25f, Position); SkidSoundTime = time_get(); } diff --git a/src/game/client/components/sounds.cpp b/src/game/client/components/sounds.cpp index 65fb56fb..be63415c 100644 --- a/src/game/client/components/sounds.cpp +++ b/src/game/client/components/sounds.cpp @@ -34,6 +34,30 @@ static int LoadSoundsThread(void *pUser) return 0; } + +int CSounds::GetSampleId(int SetId) +{ + if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + return -1; + + CDataSoundset *pSet = &g_pData->m_aSounds[SetId]; + if(!pSet->m_NumSounds) + return -1; + + if(pSet->m_NumSounds == 1) + return pSet->m_aSounds[0].m_Id; + + // return random one + int Id; + do + { + Id = rand() % pSet->m_NumSounds; + } + while(Id == pSet->m_Last); + pSet->m_Last = Id; + return pSet->m_aSounds[Id].m_Id; +} + void CSounds::OnInit() { // setup sound channels @@ -98,7 +122,7 @@ void CSounds::OnRender() int64 Now = time_get(); if(m_QueueWaitTime <= Now) { - Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f, vec2(0,0)); + Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f); m_QueueWaitTime = Now+time_freq()*3/10; // wait 300ms before playing the next one if(--m_QueuePos > 0) mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(QueueEntry)); @@ -132,38 +156,39 @@ void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos) Msg.m_SoundID = SetId; Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD); - Play(Chn, SetId, Vol, Pos); + Play(Chn, SetId, Vol); } -void CSounds::Play(int Chn, int SetId, float Vol, vec2 Pos) +void CSounds::Play(int Chn, int SetId, float Vol) { - if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || (Chn == CHN_MUSIC && !g_Config.m_SndMusic) || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds) + if(Chn == CHN_MUSIC && !g_Config.m_SndMusic) return; - CDataSoundset *pSet = &g_pData->m_aSounds[SetId]; - - if(!pSet->m_NumSounds) + int SampleId = GetSampleId(SetId); + if(SampleId == -1) return; int Flags = 0; if(Chn == CHN_MUSIC) Flags = ISound::FLAG_LOOP; - if(pSet->m_NumSounds == 1) - { - Sound()->PlayAt(Chn, pSet->m_aSounds[0].m_Id, Flags, Pos.x, Pos.y); + Sound()->Play(Chn, SampleId, Flags); +} + +void CSounds::PlayAt(int Chn, int SetId, float Vol, vec2 Pos) +{ + if(Chn == CHN_MUSIC && !g_Config.m_SndMusic) + return; + + int SampleId = GetSampleId(SetId); + if(SampleId == -1) return; - } - // play a random one - int Id; - do - { - Id = rand() % pSet->m_NumSounds; - } - while(Id == pSet->m_Last); - Sound()->PlayAt(Chn, pSet->m_aSounds[Id].m_Id, Flags, Pos.x, Pos.y); - pSet->m_Last = Id; + int Flags = 0; + if(Chn == CHN_MUSIC) + Flags = ISound::FLAG_LOOP; + + Sound()->PlayAt(Chn, SampleId, Flags, Pos.x, Pos.y); } void CSounds::Stop(int SetId) diff --git a/src/game/client/components/sounds.h b/src/game/client/components/sounds.h index ab9cc8e6..9d647398 100644 --- a/src/game/client/components/sounds.h +++ b/src/game/client/components/sounds.h @@ -19,6 +19,8 @@ class CSounds : public CComponent int64 m_QueueWaitTime; class CJob m_SoundJob; bool m_WaitForSoundJob; + + int GetSampleId(int SetId); public: // sound channels @@ -37,7 +39,8 @@ public: void ClearQueue(); void Enqueue(int Channel, int SetId); - void Play(int Channel, int SetId, float Vol, vec2 Pos); + void Play(int Channel, int SetId, float Vol); + void PlayAt(int Channel, int SetId, float Vol, vec2 Pos); void PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos); void Stop(int SetId); }; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 6bcf21de..6e94c830 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -551,7 +551,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker) pMsg->m_SoundID == SOUND_CTF_GRAB_PL) g_GameClient.m_pSounds->Enqueue(CSounds::CHN_GLOBAL, pMsg->m_SoundID); else - g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_SoundID, 1.0f, vec2(0,0)); + g_GameClient.m_pSounds->Play(CSounds::CHN_GLOBAL, pMsg->m_SoundID, 1.0f); } } @@ -626,7 +626,7 @@ void CGameClient::ProcessEvents() else if(Item.m_Type == NETEVENTTYPE_SOUNDWORLD) { CNetEvent_SoundWorld *ev = (CNetEvent_SoundWorld *)pData; - g_GameClient.m_pSounds->Play(CSounds::CHN_WORLD, ev->m_SoundID, 1.0f, vec2(ev->m_X, ev->m_Y)); + g_GameClient.m_pSounds->PlayAt(CSounds::CHN_WORLD, ev->m_SoundID, 1.0f, vec2(ev->m_X, ev->m_Y)); } } } -- cgit 1.4.1 From f3ebfae18e409e48b6553019788fbf4818f40eee Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 6 Jan 2012 19:47:49 +0100 Subject: drop multiple chat sounds that are played within 300ms. Closes #440 --- src/game/client/components/chat.cpp | 28 +++++++++++++++++++++++++--- src/game/client/components/chat.h | 6 ++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index a89d2b7e..591dccc6 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -41,6 +41,9 @@ void CChat::OnReset() m_PlaceholderOffset = 0; m_PlaceholderLength = 0; m_pHistoryEntry = 0x0; + + for(int i = 0; i < CHAT_NUM; ++i) + m_aLastSoundPlayed[i] = -1; } void CChat::OnRelease() @@ -322,12 +325,31 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) } // play sound + int64 Now = time_get(); if(ClientID == -1) - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); + { + if(Now-m_aLastSoundPlayed[CHAT_SERVER] >= time_freq()*3/10) + { + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_SERVER, 0); + m_aLastSoundPlayed[CHAT_SERVER] = Now; + } + } else if(Highlighted) - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); + { + if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) + { + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); + m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; + } + } else - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); + { + if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10) + { + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); + m_aLastSoundPlayed[CHAT_CLIENT] = Now; + } + } } void CChat::OnRender() diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index 60e18387..f007f314 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -36,6 +36,11 @@ class CChat : public CComponent MODE_NONE=0, MODE_ALL, MODE_TEAM, + + CHAT_SERVER=0, + CHAT_HIGHLIGHT, + CHAT_CLIENT, + CHAT_NUM, }; int m_Mode; @@ -49,6 +54,7 @@ class CChat : public CComponent int m_PlaceholderLength; char *m_pHistoryEntry; TStaticRingBuffer m_History; + int64 m_aLastSoundPlayed[CHAT_NUM]; static void ConSay(IConsole::IResult *pResult, void *pUserData); static void ConSayTeam(IConsole::IResult *pResult, void *pUserData); -- cgit 1.4.1 From 27852934693bc8e3192bd06378095e457d436e71 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 6 Jan 2012 20:03:57 +0100 Subject: don't start playing the music again if we're quitting --- src/engine/client/client.cpp | 6 ++++++ src/game/client/components/menus.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/game/client/components') diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 34923f28..8faf1e41 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -461,6 +461,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) { @@ -1842,7 +1845,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; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index a2ccfba4..15837efc 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1403,7 +1403,7 @@ void CMenus::OnStateChange(int NewState, int OldState) if(NewState == IClient::STATE_OFFLINE) { - if(OldState >= IClient::STATE_ONLINE) + if(OldState >= IClient::STATE_ONLINE && NewState < IClient::STATE_QUITING) m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f); m_Popup = POPUP_NONE; if(Client()->ErrorString() && Client()->ErrorString()[0] != 0) -- cgit 1.4.1 From 6649d651a8fcb170ccfd53c30d1f3c55d86b9767 Mon Sep 17 00:00:00 2001 From: oy Date: Fri, 6 Jan 2012 20:06:13 +0100 Subject: switched client and highlight chat sound. Closes #630 --- src/game/client/components/chat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index 591dccc6..ea80c54a 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -338,7 +338,7 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(Now-m_aLastSoundPlayed[CHAT_HIGHLIGHT] >= time_freq()*3/10) { - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); m_aLastSoundPlayed[CHAT_HIGHLIGHT] = Now; } } @@ -346,7 +346,7 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(Now-m_aLastSoundPlayed[CHAT_CLIENT] >= time_freq()*3/10) { - m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_CLIENT, 0); + m_pClient->m_pSounds->Play(CSounds::CHN_GUI, SOUND_CHAT_HIGHLIGHT, 0); m_aLastSoundPlayed[CHAT_CLIENT] = Now; } } -- cgit 1.4.1 From 535324d6ed365d32c14e46f6a9f058edf99c4fd0 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 8 Jan 2012 00:20:02 +0100 Subject: added an entry for the kill command to the controls menu. Closes #652 --- data/languages/belarusian.txt | 3 ++ data/languages/bosnian.txt | 3 ++ data/languages/brazilian_portuguese.txt | 3 ++ data/languages/bulgarian.txt | 3 ++ data/languages/czech.txt | 3 ++ data/languages/danish.txt | 40 +++++++++++++------------ data/languages/dutch.txt | 3 ++ data/languages/finnish.txt | 3 ++ data/languages/french.txt | 3 ++ data/languages/german.txt | 3 ++ data/languages/hungarian.txt | 3 ++ data/languages/italian.txt | 3 ++ data/languages/norwegian.txt | 3 ++ data/languages/polish.txt | 3 ++ data/languages/portuguese.txt | 3 ++ data/languages/romanian.txt | 3 ++ data/languages/russian.txt | 5 ++++ data/languages/serbian.txt | 4 +++ data/languages/slovak.txt | 3 ++ data/languages/spanish.txt | 3 ++ data/languages/swedish.txt | 3 ++ data/languages/turkish.txt | 42 +++++++++++++++------------ data/languages/ukrainian.txt | 3 ++ src/game/client/components/menus_settings.cpp | 5 ++-- 24 files changed, 114 insertions(+), 39 deletions(-) (limited to 'src/game/client/components') diff --git a/data/languages/belarusian.txt b/data/languages/belarusian.txt index 672995c0..88e8f414 100644 --- a/data/languages/belarusian.txt +++ b/data/languages/belarusian.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 4888db6a..ce82a3a2 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/brazilian_portuguese.txt b/data/languages/brazilian_portuguese.txt index a83a0d05..5bebe251 100644 --- a/data/languages/brazilian_portuguese.txt +++ b/data/languages/brazilian_portuguese.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/bulgarian.txt b/data/languages/bulgarian.txt index 38df7891..5bcee12b 100644 --- a/data/languages/bulgarian.txt +++ b/data/languages/bulgarian.txt @@ -672,6 +672,9 @@ no limit ##### needs translation ##### +Respawn +== + Spectate previous == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index 5d50f47a..8b53ff6f 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/danish.txt b/data/languages/danish.txt index d8d0e706..646d8a33 100644 --- a/data/languages/danish.txt +++ b/data/languages/danish.txt @@ -1,3 +1,4 @@ + ##### translated strings ##### %d Bytes @@ -144,6 +145,9 @@ Delete demo Demo details == Demoinformation +Demofile: %s +== Demo fil: %s + Demos == Demoer @@ -387,9 +391,15 @@ Pistol Play == Spil +Play background music +== Spil baggrunds musik + Player == Spiller +Player country: +== Spillernes land: + Player options == Spillermuligheder @@ -537,6 +547,12 @@ Sound volume Spectate == Kig på +Spectate next +== Kig på næste + +Spectate previous +== Kig på forrige + Spectator mode == Tilskuer mode @@ -552,6 +568,9 @@ Standard map Stop record == Stop optagelse +Strict gametype filter +== Streng spiltype filter + Sudden Death == Sudden Death @@ -654,25 +673,10 @@ Your skin no limit == Ingen grænse -Demofile: %s -== Demo fil: %s - -Play background music -== Spil baggrunds musik - -Player country: -== Spillernes land: - -Spectate next -== Kig på næste - -Spectate previous -== Kig på forrige - -Strict gametype filter -== Streng spiltype filter - ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 4375f784..30733489 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index 77ce6cf7..587af4d8 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/french.txt b/data/languages/french.txt index 5ea3b935..a2947bf8 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/german.txt b/data/languages/german.txt index 17720d60..8110cd2f 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/hungarian.txt b/data/languages/hungarian.txt index 49f3116a..d265dabc 100644 --- a/data/languages/hungarian.txt +++ b/data/languages/hungarian.txt @@ -666,6 +666,9 @@ Play background music Player country: == +Respawn +== + Spectate next == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index d566da49..4fecf787 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations #####  diff --git a/data/languages/norwegian.txt b/data/languages/norwegian.txt index db362e93..09bb30b9 100644 --- a/data/languages/norwegian.txt +++ b/data/languages/norwegian.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/polish.txt b/data/languages/polish.txt index e955e1e6..bc21c6f7 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### utracić swojej pracy! diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index e3c7c6cb..4f1ca5d5 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index e38faadb..dede932e 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/russian.txt b/data/languages/russian.txt index 93a32912..549c2880 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -1,3 +1,4 @@ + ##### translated strings ##### %d Bytes @@ -674,4 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### + diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 58525494..40ba2db1 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -1,3 +1,4 @@ + ##### translated strings ##### %d Bytes @@ -674,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/slovak.txt b/data/languages/slovak.txt index 48816234..d8b190b3 100644 --- a/data/languages/slovak.txt +++ b/data/languages/slovak.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt index 5348d16a..ff47f3bb 100644 --- a/data/languages/spanish.txt +++ b/data/languages/spanish.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 7f48d95d..944a9146 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -675,5 +675,8 @@ no limit ##### needs translation ##### +Respawn +== + ##### old translations ##### diff --git a/data/languages/turkish.txt b/data/languages/turkish.txt index 55b2c191..9b2a9711 100644 --- a/data/languages/turkish.txt +++ b/data/languages/turkish.txt @@ -1,4 +1,4 @@ - + ##### translated strings ##### %d Bytes @@ -145,6 +145,9 @@ Delete demo Demo details == Demo ayrıntıları +Demofile: %s +== Demo dosyası + Demos == Demolar @@ -200,7 +203,7 @@ Folder == Dosya Force vote -== Oylamayı zorla +== Oylamayı zorla Free-View == Serbest Görüntü @@ -388,6 +391,9 @@ Pistol Play == Oynat +Play background music +== Arkaplan müziğini çal + Player == Oyuncu @@ -538,6 +544,12 @@ Sound volume Spectate == İzle +Spectate next +== Sıradakini izle + +Spectate previous +== Öncekini izle + Spectator mode == İzleyici modu @@ -553,6 +565,9 @@ Standard map Stop record == Kaydı durdur +Strict gametype filter +== Sıkı oyun türü filtresi + Sudden Death == Ani ölüm @@ -655,27 +670,16 @@ Your skin no limit == limit yok -Demofile: %s -== Demo dosyası - -Play background music -== Arkaplan müziğini çal - -Player country: -== Oyuncu ülkesi +##### needs translation ##### Player country: == -Spectate next -== Sıradakini izle - -Spectate previous -== Öncekini izle - -Strict gametype filter -== Sıkı oyun türü filtresi +Respawn +== -#### needs translation ##### ##### old translations ##### + +== ## translated strings ##### + diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index 93566829..97f5ca48 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -615,6 +615,9 @@ Rename Rename demo == +Respawn +== + Server address: == diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index de4b10bd..c7a76cea 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -446,13 +446,14 @@ static CKeyInfo gs_aKeys[] = { "Remote console", "toggle_remote_console", 0 }, { "Screenshot", "screenshot", 0 }, { "Scoreboard", "+scoreboard", 0 }, + { "Respawn", "kill", 0 }, }; /* This is for scripts/update_localization.py to work, don't remove! Localize("Move left");Localize("Move right");Localize("Jump");Localize("Fire");Localize("Hook");Localize("Hammer"); Localize("Pistol");Localize("Shotgun");Localize("Grenade");Localize("Rifle");Localize("Next weapon");Localize("Prev. weapon"); Localize("Vote yes");Localize("Vote no");Localize("Chat");Localize("Team chat");Localize("Show chat");Localize("Emoticon"); - Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console");Localize("Screenshot");Localize("Scoreboard"); + Localize("Spectator mode");Localize("Spectate next");Localize("Spectate previous");Localize("Console");Localize("Remote console");Localize("Screenshot");Localize("Scoreboard");Localize("Respawn"); */ const int g_KeyCount = sizeof(gs_aKeys) / sizeof(CKeyInfo); @@ -592,7 +593,7 @@ void CMenus::RenderSettingsControls(CUIRect MainView) TextRender()->Text(0, MiscSettings.x, MiscSettings.y, 14.0f*UI()->Scale(), Localize("Miscellaneous"), -1); MiscSettings.HSplitTop(14.0f+5.0f+10.0f, 0, &MiscSettings); - UiDoGetButtons(17, 25, MiscSettings); + UiDoGetButtons(17, 26, MiscSettings); } } -- cgit 1.4.1 From 3811476c6e69824a6a67b913961c4ab4716eda20 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 8 Jan 2012 15:44:49 +0100 Subject: removed multiple updating of the renderinfo for ninjas. Closes #855 --- src/game/client/components/players.cpp | 74 +++++++++++++--------------------- src/game/client/components/players.h | 1 + 2 files changed, 28 insertions(+), 47 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 2ce73384..53bf5489 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -95,30 +95,7 @@ void CPlayers::RenderHook( Player = *pPlayerChar; CNetObj_PlayerInfo pInfo = *pPlayerInfo; - CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientID].m_RenderInfo; - - // check for teamplay modes - bool IsTeamplay = false; - if(m_pClient->m_Snap.m_pGameInfoObj) - IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; - - // check for ninja - if (Player.m_Weapon == WEAPON_NINJA) - { - // change the skin for the player to the ninja - int Skin = m_pClient->m_pSkins->Find("x_ninja"); - if(Skin != -1) - { - if(IsTeamplay) - RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; - else - { - RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; - RenderInfo.m_ColorBody = vec4(1,1,1,1); - RenderInfo.m_ColorFeet = vec4(1,1,1,1); - } - } - } + CTeeRenderInfo RenderInfo = m_aRenderInfo[pInfo.m_ClientID]; float IntraTick = Client()->IntraGameTick(); @@ -218,31 +195,9 @@ void CPlayers::RenderPlayer( Player = *pPlayerChar; CNetObj_PlayerInfo pInfo = *pPlayerInfo; - CTeeRenderInfo RenderInfo = m_pClient->m_aClients[pInfo.m_ClientID].m_RenderInfo; + CTeeRenderInfo RenderInfo = m_aRenderInfo[pInfo.m_ClientID]; - // check for teamplay modes - bool IsTeamplay = false; bool NewTick = m_pClient->m_NewTick; - if(m_pClient->m_Snap.m_pGameInfoObj) - IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; - - // check for ninja - if (Player.m_Weapon == WEAPON_NINJA) - { - // change the skin for the player to the ninja - int Skin = m_pClient->m_pSkins->Find("x_ninja"); - if(Skin != -1) - { - if(IsTeamplay) - RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; - else - { - RenderInfo.m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; - RenderInfo.m_ColorBody = vec4(1,1,1,1); - RenderInfo.m_ColorFeet = vec4(1,1,1,1); - } - } - } // set size RenderInfo.m_Size = 64.0f; @@ -546,6 +501,31 @@ void CPlayers::RenderPlayer( void CPlayers::OnRender() { + // update RenderInfo for ninja + bool IsTeamplay = false; + if(m_pClient->m_Snap.m_pGameInfoObj) + IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; + for(int i = 0; i < MAX_CLIENTS; ++i) + { + m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; + if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA) + { + // change the skin for the player to the ninja + int Skin = m_pClient->m_pSkins->Find("x_ninja"); + if(Skin != -1) + { + if(IsTeamplay) + m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; + else + { + m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; + m_aRenderInfo[i].m_ColorBody = vec4(1,1,1,1); + m_aRenderInfo[i].m_ColorFeet = vec4(1,1,1,1); + } + } + } + } + // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { diff --git a/src/game/client/components/players.h b/src/game/client/components/players.h index cedad0ff..9f23a0e6 100644 --- a/src/game/client/components/players.h +++ b/src/game/client/components/players.h @@ -6,6 +6,7 @@ class CPlayers : public CComponent { + CTeeRenderInfo m_aRenderInfo[MAX_CLIENTS]; void RenderHand(class CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset); void RenderPlayer( const CNetObj_Character *pPrevChar, -- cgit 1.4.1 From e960cbdff3bea74edfbca157679dcf65359e0739 Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 8 Jan 2012 18:16:38 +0100 Subject: added a config to display the code string of a country flag instead of the image. Closes #897 --- src/engine/shared/config_variables.h | 1 + src/game/client/components/countryflags.cpp | 46 ++++++++++++++++++++++----- src/game/client/components/countryflags.h | 2 +- src/game/client/components/menus.cpp | 8 ++--- src/game/client/components/menus_browser.cpp | 16 +++------- src/game/client/components/menus_settings.cpp | 18 ++++------- src/game/client/components/scoreboard.cpp | 9 ++---- 7 files changed, 55 insertions(+), 45 deletions(-) (limited to 'src/game/client/components') diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index dfeeeaf6..ac913162 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -17,6 +17,7 @@ MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_CLIE MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "") MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "") +MACRO_CONFIG_INT(ClLoadCountryFlags, cl_load_country_flags, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Load and show country flags") MACRO_CONFIG_INT(ClAutoDemoRecord, cl_auto_demo_record, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Automatically record demos") MACRO_CONFIG_INT(ClAutoDemoMax, cl_auto_demo_max, 10, 0, 1000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Maximum number of automatically recorded demos (0 = no limit)") diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index c2af9a59..e62f4e51 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -57,22 +58,30 @@ void CCountryFlags::LoadCountryflagsIndexfile() // load the graphic file char aBuf[128]; - str_format(aBuf, sizeof(aBuf), "countryflags/%s.png", aOrigin); CImageInfo Info; - if(!Graphics()->LoadPNG(&Info, aBuf, IStorage::TYPE_ALL)) + if(g_Config.m_ClLoadCountryFlags) { - char aMsg[128]; - str_format(aMsg, sizeof(aMsg), "failed to load '%s'", aBuf); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aMsg); - continue; + str_format(aBuf, sizeof(aBuf), "countryflags/%s.png", aOrigin); + if(!Graphics()->LoadPNG(&Info, aBuf, IStorage::TYPE_ALL)) + { + char aMsg[128]; + str_format(aMsg, sizeof(aMsg), "failed to load '%s'", aBuf); + Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aMsg); + continue; + } } // add entry CCountryFlag CountryFlag; CountryFlag.m_CountryCode = CountryCode; str_copy(CountryFlag.m_aCountryCodeString, aOrigin, sizeof(CountryFlag.m_aCountryCodeString)); - CountryFlag.m_Texture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); - mem_free(Info.m_pData); + if(g_Config.m_ClLoadCountryFlags) + { + CountryFlag.m_Texture = Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0); + mem_free(Info.m_pData); + } + else + CountryFlag.m_Texture = -1; if(g_Config.m_Debug) { str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", aOrigin); @@ -117,3 +126,24 @@ const CCountryFlags::CCountryFlag *CCountryFlags::GetByIndex(int Index) const { return &m_aCountryFlags[max(0, Index%m_aCountryFlags.size())]; } + +void CCountryFlags::Render(int CountryCode, const vec4 *pColor, float x, float y, float w, float h) +{ + const CCountryFlag *pFlag = GetByCountryCode(CountryCode); + if(pFlag->m_Texture != -1) + { + Graphics()->TextureSet(pFlag->m_Texture); + Graphics()->QuadsBegin(); + Graphics()->SetColor(pColor->r, pColor->g, pColor->b, pColor->a); + IGraphics::CQuadItem QuadItem(x, y, w, h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } + else + { + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, x, y, 10.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); + Cursor.m_LineWidth = w; + TextRender()->TextEx(&Cursor, pFlag->m_aCountryCodeString, -1); + } +} diff --git a/src/game/client/components/countryflags.h b/src/game/client/components/countryflags.h index ad24a762..df934821 100644 --- a/src/game/client/components/countryflags.h +++ b/src/game/client/components/countryflags.h @@ -23,7 +23,7 @@ public: int Num() const; const CCountryFlag *GetByCountryCode(int CountryCode) const; const CCountryFlag *GetByIndex(int Index) const; - //int Find(int CountryCode) const; + void Render(int CountryCode, const vec4 *pColor, float x, float y, float w, float h); private: enum diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 15837efc..5ef6b1ae 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -1132,12 +1132,8 @@ int CMenus::Render() float OldWidth = Item.m_Rect.w; Item.m_Rect.w = Item.m_Rect.h*2; Item.m_Rect.x += (OldWidth-Item.m_Rect.w)/ 2.0f; - Graphics()->TextureSet(pEntry->m_Texture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); + m_pClient->m_pCountryFlags->Render(pEntry->m_CountryCode, &Color, Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h); UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); } } diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 825fe3da..a9c434b3 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -567,12 +567,8 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) float OldWidth = Rect.w; Rect.w = Rect.h*2; Rect.x += (OldWidth-Rect.w)/2.0f; - Graphics()->TextureSet(m_pClient->m_pCountryFlags->GetByCountryCode(g_Config.m_BrFilterCountryIndex)->m_Texture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, g_Config.m_BrFilterCountry?1.0f: 0.5f); - IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + vec4 Color(1.0f, 1.0f, 1.0f, g_Config.m_BrFilterCountry?1.0f: 0.5f); + m_pClient->m_pCountryFlags->Render(g_Config.m_BrFilterCountryIndex, &Color, Rect.x, Rect.y, Rect.w, Rect.h); if(g_Config.m_BrFilterCountry && UI()->DoButtonLogic(&g_Config.m_BrFilterCountryIndex, "", 0, &Rect)) m_Popup = POPUP_COUNTRY; @@ -766,12 +762,8 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) TextRender()->TextEx(&Cursor, pClan, -1); // flag - Graphics()->TextureSet(m_pClient->m_pCountryFlags->GetByCountryCode(pSelectedServer->m_aClients[i].m_Country)->m_Texture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f); - IGraphics::CQuadItem QuadItem(Flag.x, Flag.y, Flag.w, Flag.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + vec4 Color(1.0f, 1.0f, 1.0f, 0.5f); + m_pClient->m_pCountryFlags->Render(pSelectedServer->m_aClients[i].m_Country, &Color, Flag.x, Flag.y, Flag.w, Flag.h); } } } diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index c7a76cea..ea4fee90 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -221,13 +221,10 @@ void CMenus::RenderSettingsPlayer(CUIRect MainView) float OldWidth = Item.m_Rect.w; Item.m_Rect.w = Item.m_Rect.h*2; Item.m_Rect.x += (OldWidth-Item.m_Rect.w)/ 2.0f; - Graphics()->TextureSet(pEntry->m_Texture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); - IGraphics::CQuadItem QuadItem(Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); - UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); + vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); + m_pClient->m_pCountryFlags->Render(pEntry->m_CountryCode, &Color, Item.m_Rect.x, Item.m_Rect.y, Item.m_Rect.w, Item.m_Rect.h); + if(pEntry->m_Texture != -1) + UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, 0); } } @@ -920,11 +917,8 @@ void CMenus::RenderLanguageSelection(CUIRect MainView) Item.m_Rect.VSplitLeft(Item.m_Rect.h*2.0f, &Rect, &Item.m_Rect); Rect.VMargin(6.0f, &Rect); Rect.HMargin(3.0f, &Rect); - Graphics()->TextureSet(m_pClient->m_pCountryFlags->GetByCountryCode(r.front().m_CountryCode)->m_Texture); - Graphics()->QuadsBegin(); - IGraphics::CQuadItem QuadItem(Rect.x, Rect.y, Rect.w, Rect.h); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + vec4 Color(1.0f, 1.0f, 1.0f, 1.0f); + m_pClient->m_pCountryFlags->Render(r.front().m_CountryCode, &Color, Rect.x, Rect.y, Rect.w, Rect.h); Item.m_Rect.HSplitTop(2.0f, 0, &Item.m_Rect); UI()->DoLabelScaled(&Item.m_Rect, r.front().m_Name, 16.0f, -1); } diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index ae11c7ea..935f7bad 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -273,12 +273,9 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch TextRender()->TextEx(&Cursor, m_pClient->m_aClients[pInfo->m_ClientID].m_aClan, -1); // country flag - Graphics()->TextureSet(m_pClient->m_pCountryFlags->GetByCountryCode(m_pClient->m_aClients[pInfo->m_ClientID].m_Country)->m_Texture); - Graphics()->QuadsBegin(); - Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f); - IGraphics::CQuadItem QuadItem(CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f); - Graphics()->QuadsDrawTL(&QuadItem, 1); - Graphics()->QuadsEnd(); + vec4 Color(1.0f, 1.0f, 1.0f, 0.5f); + m_pClient->m_pCountryFlags->Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color, + CountryOffset, y+(Spacing+TeeSizeMod*5.0f)/2.0f, CountryLength, LineHeight-Spacing-TeeSizeMod*5.0f); // ping str_format(aBuf, sizeof(aBuf), "%d", clamp(pInfo->m_Latency, 0, 1000)); -- cgit 1.4.1 From 526262ea55c3fccb659533d5270e30a3c6eb9da4 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 9 Jan 2012 00:23:58 +0100 Subject: increased the size of emoticons in the selector. Closes #625 --- src/game/client/components/emoticon.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/emoticon.cpp b/src/game/client/components/emoticon.cpp index b2f48b80..9e2a80cf 100644 --- a/src/game/client/components/emoticon.cpp +++ b/src/game/client/components/emoticon.cpp @@ -111,14 +111,14 @@ void CEmoticon::OnRender() m_WasActive = true; - if (length(m_SelectorMouse) > 140) - m_SelectorMouse = normalize(m_SelectorMouse) * 140; + if (length(m_SelectorMouse) > 170.0f) + m_SelectorMouse = normalize(m_SelectorMouse) * 170.0f; float SelectedAngle = GetAngle(m_SelectorMouse) + 2*pi/24; if (SelectedAngle < 0) SelectedAngle += 2*pi; - if (length(m_SelectorMouse) > 100) + if (length(m_SelectorMouse) > 110.0f) m_SelectedEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTICONS); CUIRect Screen = *UI()->Screen(); @@ -130,7 +130,7 @@ void CEmoticon::OnRender() Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); - DrawCircle(Screen.w/2, Screen.h/2, 160, 64); + DrawCircle(Screen.w/2, Screen.h/2, 190.0f, 64); Graphics()->QuadsEnd(); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); @@ -144,10 +144,10 @@ void CEmoticon::OnRender() bool Selected = m_SelectedEmote == i; - float Size = Selected ? 80 : 32; + float Size = Selected ? 80.0f : 50.0f; - float NudgeX = 120 * cosf(Angle); - float NudgeY = 120 * sinf(Angle); + float NudgeX = 150.0f * cosf(Angle); + float NudgeY = 150.0f * sinf(Angle); RenderTools()->SelectSprite(SPRITE_OOP + i); IGraphics::CQuadItem QuadItem(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY, Size, Size); Graphics()->QuadsDraw(&QuadItem, 1); -- cgit 1.4.1 From 7c300ccc7b3b4139219282acc4f18aad5ad438e9 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 9 Jan 2012 00:28:42 +0100 Subject: added player names to dm score hud and repositioned the player name in team games. Closes #871 --- src/game/client/components/hud.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index df3afdea..c8e0a903 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -78,6 +78,7 @@ void CHud::RenderScoreHud() { int GameFlags = m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags; float Whole = 300*Graphics()->ScreenAspect(); + float StartY = 229.0f; if(GameFlags&GAMEFLAG_TEAMS && m_pClient->m_Snap.m_pGameDataObj) { @@ -100,11 +101,11 @@ void CHud::RenderScoreHud() Graphics()->SetColor(1.0f, 0.0f, 0.0f, 0.25f); else Graphics()->SetColor(0.0f, 0.0f, 1.0f, 0.25f); - RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L); + RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split, StartY+t*20, ScoreWidthMax+ImageSize+2*Split, 18.0f, 5.0f, CUI::CORNER_L); Graphics()->QuadsEnd(); // draw score - TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScoreTeam[t], -1); + TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreTeamWidth[t])/2-Split, StartY+t*20, 14.0f, aScoreTeam[t], -1); if(GameFlags&GAMEFLAG_FLAGS) { @@ -117,7 +118,7 @@ void CHud::RenderScoreHud() Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(t==0?SPRITE_FLAG_RED:SPRITE_FLAG_BLUE); - IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, 246.0f+t*20, ImageSize/2, ImageSize); + IGraphics::CQuadItem QuadItem(Whole-ScoreWidthMax-ImageSize, StartY+1.0f+t*20, ImageSize/2, ImageSize); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); } @@ -126,16 +127,17 @@ void CHud::RenderScoreHud() // draw name of the flag holder int ID = FlagCarrier[t]%MAX_CLIENTS; const char *pName = m_pClient->m_aClients[ID].m_aName; - float w = TextRender()->TextWidth(0, 10.0f, pName, -1); - TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-3*Split-w, 247.0f+t*20, 10.0f, pName, -1); + float w = TextRender()->TextWidth(0, 8.0f, pName, -1); + TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split), StartY+(t+1)*20.0f-3.0f, 8.0f, pName, -1); // draw tee of the flag holder CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo; Info.m_Size = 18.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), - vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20)); + vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); } } + StartY += 8.0f; } } else @@ -191,25 +193,33 @@ void CHud::RenderScoreHud() Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.25f); else Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.25f); - RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, 245.0f+t*20, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f, 5.0f, CUI::CORNER_L); + RenderTools()->DrawRoundRectExt(Whole-ScoreWidthMax-ImageSize-2*Split-PosSize, StartY+t*20, ScoreWidthMax+ImageSize+2*Split+PosSize, 18.0f, 5.0f, CUI::CORNER_L); Graphics()->QuadsEnd(); // draw score - TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, 245.0f+t*20, 14.0f, aScore[t], -1); + TextRender()->Text(0, Whole-ScoreWidthMax+(ScoreWidthMax-aScoreWidth[t])/2-Split, StartY+t*20, 14.0f, aScore[t], -1); - // draw tee if(apPlayerInfo[t]) { - CTeeRenderInfo Info = m_pClient->m_aClients[apPlayerInfo[t]->m_ClientID].m_RenderInfo; + // draw name + int ID = apPlayerInfo[t]->m_ClientID; + const char *pName = m_pClient->m_aClients[ID].m_aName; + float w = TextRender()->TextWidth(0, 8.0f, pName, -1); + TextRender()->Text(0, min(Whole-w-1.0f, Whole-ScoreWidthMax-ImageSize-2*Split-PosSize), StartY+(t+1)*20.0f-3.0f, 8.0f, pName, -1); + + // draw tee + CTeeRenderInfo Info = m_pClient->m_aClients[ID].m_RenderInfo; Info.m_Size = 18.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), - vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, 246.0f+Info.m_Size/2+t*20)); + vec2(Whole-ScoreWidthMax-Info.m_Size/2-Split, StartY+1.0f+Info.m_Size/2+t*20)); } // draw position char aBuf[32]; str_format(aBuf, sizeof(aBuf), "%d.", aPos[t]); - TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, 247.0f+t*20, 10.0f, aBuf, -1); + TextRender()->Text(0, Whole-ScoreWidthMax-ImageSize-Split-PosSize, StartY+2.0f+t*20, 10.0f, aBuf, -1); + + StartY += 8.0f; } } } -- cgit 1.4.1 From e97cfaecad4f55f329ce92e31f68df0786c599de Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 9 Jan 2012 23:13:51 +0100 Subject: buffered chat input. Closes #916 --- src/game/client/components/chat.cpp | 45 ++++++++++++++++++++++++++++--------- src/game/client/components/chat.h | 12 ++++++++-- 2 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index ea80c54a..a0eeb0b3 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -41,9 +41,11 @@ void CChat::OnReset() m_PlaceholderOffset = 0; m_PlaceholderLength = 0; m_pHistoryEntry = 0x0; + m_PendingChatCounter = 0; + m_LastChatSend = 0; for(int i = 0; i < CHAT_NUM; ++i) - m_aLastSoundPlayed[i] = -1; + m_aLastSoundPlayed[i] = 0; } void CChat::OnRelease() @@ -110,9 +112,13 @@ bool CChat::OnInput(IInput::CEvent Event) { if(m_Input.GetString()[0]) { - Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString()); - char *pEntry = m_History.Allocate(m_Input.GetLength()+1); - mem_copy(pEntry, m_Input.GetString(), m_Input.GetLength()+1); + if(m_LastChatSend+time_freq() < time_get()) + Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString()); + else + ++m_PendingChatCounter; + CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength()); + pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1; + mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1); } m_pHistoryEntry = 0x0; m_Mode = MODE_NONE; @@ -202,26 +208,26 @@ bool CChat::OnInput(IInput::CEvent Event) } if(Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_UP) { - if (m_pHistoryEntry) + if(m_pHistoryEntry) { - char *pTest = m_History.Prev(m_pHistoryEntry); + CHistoryEntry *pTest = m_History.Prev(m_pHistoryEntry); - if (pTest) + if(pTest) m_pHistoryEntry = pTest; } else m_pHistoryEntry = m_History.Last(); - if (m_pHistoryEntry) - m_Input.Set(m_pHistoryEntry); + if(m_pHistoryEntry) + m_Input.Set(m_pHistoryEntry->m_aText); } else if (Event.m_Flags&IInput::FLAG_PRESS && Event.m_Key == KEY_DOWN) { - if (m_pHistoryEntry) + if(m_pHistoryEntry) m_pHistoryEntry = m_History.Next(m_pHistoryEntry); if (m_pHistoryEntry) - m_Input.Set(m_pHistoryEntry); + m_Input.Set(m_pHistoryEntry->m_aText); else m_Input.Clear(); } @@ -354,6 +360,21 @@ void CChat::AddLine(int ClientID, int Team, const char *pLine) void CChat::OnRender() { + // send pending chat messages + if(m_PendingChatCounter > 0 && m_LastChatSend+time_freq() < time_get()) + { + CHistoryEntry *pEntry = m_History.Last(); + for(int i = m_PendingChatCounter-1; pEntry; --i, pEntry = m_History.Prev(pEntry)) + { + if(i == 0) + { + Say(pEntry->m_Team, pEntry->m_aText); + break; + } + } + --m_PendingChatCounter; + } + float Width = 300.0f*Graphics()->ScreenAspect(); Graphics()->MapScreen(0.0f, 0.0f, Width, 300.0f); float x = 5.0f; @@ -479,6 +500,8 @@ void CChat::OnRender() void CChat::Say(int Team, const char *pLine) { + m_LastChatSend = time_get(); + // send chat message CNetMsg_Cl_Say Msg; Msg.m_Team = Team; diff --git a/src/game/client/components/chat.h b/src/game/client/components/chat.h index f007f314..09519516 100644 --- a/src/game/client/components/chat.h +++ b/src/game/client/components/chat.h @@ -52,8 +52,16 @@ class CChat : public CComponent char m_aCompletionBuffer[256]; int m_PlaceholderOffset; int m_PlaceholderLength; - char *m_pHistoryEntry; - TStaticRingBuffer m_History; + + struct CHistoryEntry + { + int m_Team; + char m_aText[1]; + }; + CHistoryEntry *m_pHistoryEntry; + TStaticRingBuffer m_History; + int m_PendingChatCounter; + int64 m_LastChatSend; int64 m_aLastSoundPlayed[CHAT_NUM]; static void ConSay(IConsole::IResult *pResult, void *pUserData); -- cgit 1.4.1 From 3e918075df63245bbc117c7dace711fb3e619003 Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 9 Jan 2012 23:29:15 +0100 Subject: added an option to show only chat messages from friends --- src/game/client/components/chat.cpp | 3 ++- src/game/client/components/menus_settings.cpp | 6 ++++++ src/game/variables.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp index a0eeb0b3..340b9da1 100644 --- a/src/game/client/components/chat.cpp +++ b/src/game/client/components/chat.cpp @@ -266,7 +266,8 @@ void CChat::OnMessage(int MsgType, void *pRawMsg) void CChat::AddLine(int ClientID, int Team, const char *pLine) { if(ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client - m_pClient->m_aClients[ClientID].m_ChatIgnore)) + m_pClient->m_aClients[ClientID].m_ChatIgnore || + (m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend))) return; bool Highlighted = false; diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index ea4fee90..553195b1 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -96,6 +96,12 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView) if(DoButton_CheckBox(&g_Config.m_ClShowhud, Localize("Show ingame HUD"), g_Config.m_ClShowhud, &Button)) g_Config.m_ClShowhud ^= 1; + // chat messages + Left.HSplitTop(5.0f, 0, &Left); + Left.HSplitTop(20.0f, &Button, &Left); + if(DoButton_CheckBox(&g_Config.m_ClShowChatFriends, Localize("Show only chat messages from friends"), g_Config.m_ClShowChatFriends, &Button)) + g_Config.m_ClShowChatFriends ^= 1; + // name plates Right.HSplitTop(20.0f, &Button, &Right); if(DoButton_CheckBox(&g_Config.m_ClNameplates, Localize("Show name plates"), g_Config.m_ClNameplates, &Button)) diff --git a/src/game/variables.h b/src/game/variables.h index 4faa109d..e57a0954 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -14,6 +14,7 @@ MACRO_CONFIG_INT(ClNameplatesSize, cl_nameplates_size, 50, 0, 100, CFGFLAG_CLIEN MACRO_CONFIG_INT(ClAutoswitchWeapons, cl_autoswitch_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Auto switch weapon on pickup") MACRO_CONFIG_INT(ClShowhud, cl_showhud, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame HUD") +MACRO_CONFIG_INT(ClShowChatFriends, cl_show_chat_friends, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show only chat messages from friends") MACRO_CONFIG_INT(ClShowfps, cl_showfps, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame FPS counter") MACRO_CONFIG_INT(ClAirjumpindicator, cl_airjumpindicator, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "") -- cgit 1.4.1 From 9251796c3a8e3f31f9aa52ef84b9e0ce475d2f9b Mon Sep 17 00:00:00 2001 From: oy Date: Mon, 9 Jan 2012 23:43:53 +0100 Subject: fixed rendering on pause/specific speed for damage indicators and muzzle in the demo player --- src/game/client/components/damageind.cpp | 13 ++++++++++++- src/game/client/components/players.cpp | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index 9be6722a..e2da21e1 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -1,5 +1,6 @@ /* (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 #include #include #include @@ -46,11 +47,20 @@ void CDamageInd::Create(vec2 Pos, vec2 Dir) void CDamageInd::OnRender() { - Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); + static float s_LastLocalTime = Client()->LocalTime(); for(int i = 0; i < m_NumItems;) { + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); + if(pInfo->m_Paused) + m_aItems[i].m_StartTime += Client()->LocalTime()-s_LastLocalTime; + else + m_aItems[i].m_StartTime += (Client()->LocalTime()-s_LastLocalTime)*(1.0f-pInfo->m_Speed); + } + float Life = 0.75f - (Client()->LocalTime() - m_aItems[i].m_StartTime); if(Life < 0.0f) DestroyI(&m_aItems[i]); @@ -64,6 +74,7 @@ void CDamageInd::OnRender() i++; } } + s_LastLocalTime = Client()->LocalTime(); Graphics()->QuadsEnd(); } diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 53bf5489..c53a1977 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -415,6 +415,15 @@ void CPlayers::RenderPlayer( } int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; + if(Client()->State() == IClient::STATE_DEMOPLAYBACK) + { + static int s_LastIteX = IteX; + const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); + if(pInfo->m_Paused) + IteX = s_LastIteX; + else + s_LastIteX = IteX; + } if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) { float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety; -- cgit 1.4.1 From dfe91338f03534a6c8ed596f16742e7a1617d78e Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 10 Jan 2012 00:49:31 +0100 Subject: added pause command. Closes #15 --- src/game/client/components/controls.cpp | 2 +- src/game/client/components/damageind.cpp | 5 ++++ src/game/client/components/items.cpp | 45 ++++++++++++++++---------------- src/game/client/components/maplayers.cpp | 22 +++++++++------- src/game/client/components/particles.cpp | 10 ++++++- src/game/client/components/players.cpp | 31 ++++++++++++++++++---- src/game/server/entities/character.cpp | 14 ++++++++++ src/game/server/entities/character.h | 1 + src/game/server/entities/flag.cpp | 7 +++++ src/game/server/entities/flag.h | 1 + src/game/server/entities/laser.cpp | 5 ++++ src/game/server/entities/laser.h | 1 + src/game/server/entities/pickup.cpp | 6 +++++ src/game/server/entities/pickup.h | 1 + src/game/server/entities/projectile.cpp | 5 ++++ src/game/server/entities/projectile.h | 1 + src/game/server/entity.h | 6 +++++ src/game/server/gamecontext.cpp | 11 ++++++++ src/game/server/gamecontext.h | 1 + src/game/server/gamecontroller.cpp | 6 ++++- src/game/server/gamecontroller.h | 1 + src/game/server/gameworld.cpp | 11 ++++++++ src/game/server/player.cpp | 41 ++++++++++++++++++----------- 23 files changed, 180 insertions(+), 54 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index dd856413..c0790799 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -199,7 +199,7 @@ int CControls::SnapInput(int *pData) void CControls::OnRender() { // update target pos - if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED || m_pClient->m_Snap.m_SpecInfo.m_Active)) + if(m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active) m_TargetPos = m_pClient->m_LocalCharacterPos + m_MousePos; else if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_UsePosition) m_TargetPos = m_pClient->m_Snap.m_SpecInfo.m_Position + m_MousePos; diff --git a/src/game/client/components/damageind.cpp b/src/game/client/components/damageind.cpp index e2da21e1..0f521753 100644 --- a/src/game/client/components/damageind.cpp +++ b/src/game/client/components/damageind.cpp @@ -60,6 +60,11 @@ void CDamageInd::OnRender() else m_aItems[i].m_StartTime += (Client()->LocalTime()-s_LastLocalTime)*(1.0f-pInfo->m_Speed); } + else + { + if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + m_aItems[i].m_StartTime += Client()->LocalTime()-s_LastLocalTime; + } float Life = 0.75f - (Client()->LocalTime() - m_aItems[i].m_StartTime); if(Life < 0.0f) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 9f787a4b..e1032a51 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -41,7 +41,10 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) Speed = m_pClient->m_Tuning.m_GunSpeed; } - float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + static float s_LastGameTickTime = Client()->GameTickTime(); + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + s_LastGameTickTime = Client()->GameTickTime(); + float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) return; // projectile havn't been shot yet @@ -63,22 +66,23 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); + static float s_Time = 0.0f; + static float s_LastLocalTime = Client()->LocalTime(); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - static float Time = 0; - static float LastLocalTime = Client()->LocalTime(); - if(!pInfo->m_Paused) - Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; - - Graphics()->QuadsSetRotation(Time*pi*2*2 + ItemID); - - LastLocalTime = Client()->LocalTime(); + s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed; } else - Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemID); + { + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + s_Time += Client()->LocalTime()-s_LastLocalTime; + } + + Graphics()->QuadsSetRotation(s_Time*pi*2*2 + ItemID); + s_LastLocalTime = Client()->LocalTime(); } else { @@ -130,26 +134,23 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu Graphics()->QuadsSetRotation(Angle); + static float s_Time = 0.0f; + static float s_LastLocalTime = Client()->LocalTime(); float Offset = Pos.y/32.0f + Pos.x/32.0f; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); - static float Time = 0; - static float LastLocalTime = Client()->LocalTime(); - if(!pInfo->m_Paused) - Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; - - Pos.x += cosf(Time*2.0f+Offset)*2.5f; - Pos.y += sinf(Time*2.0f+Offset)*2.5f; - - LastLocalTime = Client()->LocalTime(); + s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed; } else { - Pos.x += cosf(Client()->LocalTime()*2.0f+Offset)*2.5f; - Pos.y += sinf(Client()->LocalTime()*2.0f+Offset)*2.5f; - } + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + s_Time += Client()->LocalTime()-s_LastLocalTime; + } + Pos.x += cosf(s_Time*2.0f+Offset)*2.5f; + Pos.y += sinf(s_Time*2.0f+Offset)*2.5f; + s_LastLocalTime = Client()->LocalTime(); RenderTools()->DrawSprite(Pos.x, Pos.y, Size); Graphics()->QuadsEnd(); } diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index f0460d26..db74b165 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -77,7 +77,8 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0); - static float Time = 0; + static float s_Time = 0.0f; + static float s_LastLocalTime = pThis->Client()->LocalTime(); if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo(); @@ -90,25 +91,28 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void pThis->m_CurrentLocalTick = pInfo->m_CurrentTick; } - Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), + s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), pThis->Client()->IntraGameTick()); } - pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); + pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); } else { - if(pItem->m_Version < 2 || pItem->m_Synchronized) + if(pThis->m_pClient->m_Snap.m_pGameInfoObj && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) { - if(pThis->m_pClient->m_Snap.m_pGameInfoObj) - Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + if(pItem->m_Version < 2 || pItem->m_Synchronized) + { + s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), pThis->Client()->IntraGameTick()); + } + else + s_Time += pThis->Client()->LocalTime()-s_LastLocalTime; } - else - Time = pThis->Client()->LocalTime(); - pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, Time+TimeOffset, pChannels); + pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); + s_LastLocalTime = pThis->Client()->LocalTime(); } } diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index c4583cb1..66a62f1c 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -43,6 +43,11 @@ void CParticles::Add(int Group, CParticle *pPart) if(pInfo->m_Paused) return; } + else + { + if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + return; + } if (m_FirstFree == -1) return; @@ -142,7 +147,10 @@ void CParticles::OnRender() Update((float)((t-LastTime)/(double)time_freq())*pInfo->m_Speed); } else - Update((float)((t-LastTime)/(double)time_freq())); + { + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + Update((float)((t-LastTime)/(double)time_freq())); + } LastTime = t; } diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index c53a1977..2eddd8a9 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -285,14 +285,17 @@ void CPlayers::RenderPlayer( else if(!WantOtherDir) State.Add(&g_pData->m_aAnimations[ANIM_WALK], WalkTime, 1.0f); + static float s_LastGameTickTime = Client()->GameTickTime(); + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + s_LastGameTickTime = Client()->GameTickTime(); if (Player.m_Weapon == WEAPON_HAMMER) { - float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; State.Add(&g_pData->m_aAnimations[ANIM_HAMMER_SWING], clamp(ct*5.0f,0.0f,1.0f), 1.0f); } if (Player.m_Weapon == WEAPON_NINJA) { - float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + float ct = (Client()->PrevGameTick()-Player.m_AttackTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; State.Add(&g_pData->m_aAnimations[ANIM_NINJA_SWING], clamp(ct*2.0f,0.0f,1.0f), 1.0f); } @@ -364,15 +367,22 @@ void CPlayers::RenderPlayer( if ((Client()->GameTick()-Player.m_AttackTick) <= (SERVER_TICK_SPEED / 6) && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles) { int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; + static int s_LastIteX = IteX; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { - static int s_LastIteX = IteX; const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(pInfo->m_Paused) IteX = s_LastIteX; else s_LastIteX = IteX; } + else + { + if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + IteX = s_LastIteX; + else + s_LastIteX = IteX; + } if(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) { vec2 Dir = vec2(pPlayerChar->m_X,pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y); @@ -393,7 +403,11 @@ void CPlayers::RenderPlayer( { // TODO: should be an animation Recoil = 0; - float a = (Client()->GameTick()-Player.m_AttackTick+IntraTick)/5.0f; + static float s_LastIntraTick = IntraTick; + if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) + s_LastIntraTick = IntraTick; + + float a = (Client()->GameTick()-Player.m_AttackTick+s_LastIntraTick)/5.0f; if(a < 1) Recoil = sinf(a*pi); p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir*Recoil*10.0f; @@ -415,15 +429,22 @@ void CPlayers::RenderPlayer( } int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; + static int s_LastIteX = IteX; if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { - static int s_LastIteX = IteX; const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(pInfo->m_Paused) IteX = s_LastIteX; else s_LastIteX = IteX; } + else + { + if(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED) + IteX = s_LastIteX; + else + s_LastIteX = IteX; + } if (Alpha > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) { float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety; diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 5e8c29b6..1c76f655 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -657,6 +657,20 @@ void CCharacter::TickDefered() } } +void CCharacter::TickPaused() +{ + ++m_AttackTick; + ++m_DamageTakenTick; + ++m_Ninja.m_ActivationTick; + ++m_ReckoningTick; + if(m_LastAction != -1) + ++m_LastAction; + if(m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart > -1) + ++m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart; + if(m_EmoteStop > -1) + ++m_EmoteStop; +} + bool CCharacter::IncreaseHealth(int Amount) { if(m_Health >= 10) diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h index 02a779bb..aa127979 100644 --- a/src/game/server/entities/character.h +++ b/src/game/server/entities/character.h @@ -30,6 +30,7 @@ public: virtual void Destroy(); virtual void Tick(); virtual void TickDefered(); + virtual void TickPaused(); virtual void Snap(int SnappingClient); bool IsGrounded(); diff --git a/src/game/server/entities/flag.cpp b/src/game/server/entities/flag.cpp index d279e4df..558ee154 100644 --- a/src/game/server/entities/flag.cpp +++ b/src/game/server/entities/flag.cpp @@ -23,6 +23,13 @@ void CFlag::Reset() m_GrabTick = 0; } +void CFlag::TickPaused() +{ + ++m_DropTick; + if(m_GrabTick) + ++m_GrabTick; +} + void CFlag::Snap(int SnappingClient) { if(NetworkClipped(SnappingClient)) diff --git a/src/game/server/entities/flag.h b/src/game/server/entities/flag.h index 2f91bc02..be22d32b 100644 --- a/src/game/server/entities/flag.h +++ b/src/game/server/entities/flag.h @@ -21,6 +21,7 @@ public: CFlag(CGameWorld *pGameWorld, int Team); virtual void Reset(); + virtual void TickPaused(); virtual void Snap(int SnappingClient); }; diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 7278995f..eb40c4e1 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -91,6 +91,11 @@ void CLaser::Tick() DoBounce(); } +void CLaser::TickPaused() +{ + ++m_EvalTick; +} + void CLaser::Snap(int SnappingClient) { if(NetworkClipped(SnappingClient)) diff --git a/src/game/server/entities/laser.h b/src/game/server/entities/laser.h index 1d7fa227..8ae6f792 100644 --- a/src/game/server/entities/laser.h +++ b/src/game/server/entities/laser.h @@ -12,6 +12,7 @@ public: virtual void Reset(); virtual void Tick(); + virtual void TickPaused(); virtual void Snap(int SnappingClient); protected: diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index ba26d85b..1aff5750 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -117,6 +117,12 @@ void CPickup::Tick() } } +void CPickup::TickPaused() +{ + if(m_SpawnTick != -1) + ++m_SpawnTick; +} + void CPickup::Snap(int SnappingClient) { if(m_SpawnTick != -1 || NetworkClipped(SnappingClient)) diff --git a/src/game/server/entities/pickup.h b/src/game/server/entities/pickup.h index 77347de2..fe45b5ae 100644 --- a/src/game/server/entities/pickup.h +++ b/src/game/server/entities/pickup.h @@ -14,6 +14,7 @@ public: virtual void Reset(); virtual void Tick(); + virtual void TickPaused(); virtual void Snap(int SnappingClient); private: diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 2baa24b1..e89e0e6f 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -82,6 +82,11 @@ void CProjectile::Tick() } } +void CProjectile::TickPaused() +{ + ++m_StartTick; +} + void CProjectile::FillInfo(CNetObj_Projectile *pProj) { pProj->m_X = (int)m_Pos.x; diff --git a/src/game/server/entities/projectile.h b/src/game/server/entities/projectile.h index 5df04bcd..7b5c5e0e 100644 --- a/src/game/server/entities/projectile.h +++ b/src/game/server/entities/projectile.h @@ -14,6 +14,7 @@ public: virtual void Reset(); virtual void Tick(); + virtual void TickPaused(); virtual void Snap(int SnappingClient); private: diff --git a/src/game/server/entity.h b/src/game/server/entity.h index b9b33eb7..0f838730 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -105,6 +105,12 @@ public: */ virtual void TickDefered() {} + /* + Function: TickPaused + Called when the game is paused, to freeze the state and position of the entity. + */ + virtual void TickPaused() {} + /* Function: snap Called when a new snapshot is being generated for a specific diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index fdd78f60..87b9b3b7 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -1036,6 +1036,16 @@ void CGameContext::ConTuneDump(IConsole::IResult *pResult, void *pUserData) } } +void CGameContext::ConPause(IConsole::IResult *pResult, void *pUserData) +{ + CGameContext *pSelf = (CGameContext *)pUserData; + + if(pSelf->m_pController->IsGameOver()) + return; + + pSelf->m_World.m_Paused ^= 1; +} + void CGameContext::ConChangeMap(IConsole::IResult *pResult, void *pUserData) { CGameContext *pSelf = (CGameContext *)pUserData; @@ -1409,6 +1419,7 @@ void CGameContext::OnConsoleInit() Console()->Register("tune_reset", "", CFGFLAG_SERVER, ConTuneReset, this, "Reset tuning"); Console()->Register("tune_dump", "", CFGFLAG_SERVER, ConTuneDump, this, "Dump tuning"); + Console()->Register("pause", "", CFGFLAG_SERVER, ConPause, this, "Pause/unpause game"); Console()->Register("change_map", "?r", CFGFLAG_SERVER|CFGFLAG_STORE, ConChangeMap, this, "Change map"); Console()->Register("restart", "?i", CFGFLAG_SERVER|CFGFLAG_STORE, ConRestart, this, "Restart in x seconds (0 = abort)"); Console()->Register("broadcast", "r", CFGFLAG_SERVER, ConBroadcast, this, "Broadcast message"); diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index 559d1c0d..2ffb0ab4 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -48,6 +48,7 @@ class CGameContext : public IGameServer static void ConTuneParam(IConsole::IResult *pResult, void *pUserData); static void ConTuneReset(IConsole::IResult *pResult, void *pUserData); static void ConTuneDump(IConsole::IResult *pResult, void *pUserData); + static void ConPause(IConsole::IResult *pResult, void *pUserData); static void ConChangeMap(IConsole::IResult *pResult, void *pUserData); static void ConRestart(IConsole::IResult *pResult, void *pUserData); static void ConBroadcast(IConsole::IResult *pResult, void *pUserData); diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index 181e5052..7001ca32 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -430,8 +430,12 @@ void IGameController::Tick() } } + // game is Paused + if(GameServer()->m_World.m_Paused) + ++m_RoundStartTick; + // do team-balancing - if (IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) + if(IsTeamplay() && m_UnbalancedTick != -1 && Server()->Tick() > m_UnbalancedTick+g_Config.m_SvTeambalanceTime*Server()->TickSpeed()*60) { GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "Balancing teams"); diff --git a/src/game/server/gamecontroller.h b/src/game/server/gamecontroller.h index 4706df48..1675fe35 100644 --- a/src/game/server/gamecontroller.h +++ b/src/game/server/gamecontroller.h @@ -64,6 +64,7 @@ public: const char *m_pGameType; bool IsTeamplay() const; + bool IsGameOver() const { return m_GameOverTick != -1; } IGameController(class CGameContext *pGameServer); virtual ~IGameController(); diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 89f4808d..d803ae67 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -173,6 +173,17 @@ void CGameWorld::Tick() pEnt = m_pNextTraverseEntity; } } + else + { + // update all objects + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->TickPaused(); + pEnt = m_pNextTraverseEntity; + } + } RemoveEntities(); } diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index df9727a9..75c2c1c6 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -60,26 +60,37 @@ void CPlayer::Tick() } } - if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW) - m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f)); + if(!GameServer()->m_World.m_Paused) + { + if(!m_pCharacter && m_Team == TEAM_SPECTATORS && m_SpectatorID == SPEC_FREEVIEW) + m_ViewPos -= vec2(clamp(m_ViewPos.x-m_LatestActivity.m_TargetX, -500.0f, 500.0f), clamp(m_ViewPos.y-m_LatestActivity.m_TargetY, -400.0f, 400.0f)); - if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick()) - m_Spawning = true; + if(!m_pCharacter && m_DieTick+Server()->TickSpeed()*3 <= Server()->Tick()) + m_Spawning = true; - if(m_pCharacter) - { - if(m_pCharacter->IsAlive()) - { - m_ViewPos = m_pCharacter->m_Pos; - } - else + if(m_pCharacter) { - delete m_pCharacter; - m_pCharacter = 0; + if(m_pCharacter->IsAlive()) + { + m_ViewPos = m_pCharacter->m_Pos; + } + else + { + delete m_pCharacter; + m_pCharacter = 0; + } } + else if(m_Spawning && m_RespawnTick <= Server()->Tick()) + TryRespawn(); } - else if(m_Spawning && m_RespawnTick <= Server()->Tick()) - TryRespawn(); + else + { + ++m_RespawnTick; + ++m_DieTick; + ++m_ScoreStartTick; + ++m_LastActionTick; + ++m_TeamChangeTick; + } } void CPlayer::PostTick() -- cgit 1.4.1 From 4efd65359e1073b673f8f5b16bb48f3a0754a4b9 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 10 Jan 2012 22:40:48 +0100 Subject: show notification when game is paused --- data/languages/belarusian.txt | 3 +++ data/languages/bosnian.txt | 3 +++ data/languages/brazilian_portuguese.txt | 3 +++ data/languages/bulgarian.txt | 3 +++ data/languages/czech.txt | 3 +++ data/languages/danish.txt | 3 +++ data/languages/dutch.txt | 3 +++ data/languages/finnish.txt | 3 +++ data/languages/french.txt | 3 +++ data/languages/german.txt | 3 +++ data/languages/hungarian.txt | 3 +++ data/languages/italian.txt | 3 +++ data/languages/norwegian.txt | 3 +++ data/languages/polish.txt | 3 +++ data/languages/portuguese.txt | 3 +++ data/languages/romanian.txt | 3 +++ data/languages/russian.txt | 3 +++ data/languages/serbian.txt | 3 +++ data/languages/slovak.txt | 3 +++ data/languages/spanish.txt | 3 +++ data/languages/swedish.txt | 3 +++ data/languages/turkish.txt | 3 +++ data/languages/ukrainian.txt | 3 +++ src/game/client/components/hud.cpp | 13 +++++++++++++ src/game/client/components/hud.h | 1 + 25 files changed, 83 insertions(+) (limited to 'src/game/client/components') diff --git a/data/languages/belarusian.txt b/data/languages/belarusian.txt index 9bceccaa..47f3aa8a 100644 --- a/data/languages/belarusian.txt +++ b/data/languages/belarusian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index d6f06d26..85f2e0c6 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/brazilian_portuguese.txt b/data/languages/brazilian_portuguese.txt index 19e85dff..5bb3f730 100644 --- a/data/languages/brazilian_portuguese.txt +++ b/data/languages/brazilian_portuguese.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/bulgarian.txt b/data/languages/bulgarian.txt index 079dfa4a..83c674b9 100644 --- a/data/languages/bulgarian.txt +++ b/data/languages/bulgarian.txt @@ -672,6 +672,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index 0a273fe3..dd18d676 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/danish.txt b/data/languages/danish.txt index 95483954..6f82249e 100644 --- a/data/languages/danish.txt +++ b/data/languages/danish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 92a57dd8..11e5559f 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index 772eb852..f9586c11 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/french.txt b/data/languages/french.txt index 5f20a3bb..846f4ed4 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/german.txt b/data/languages/german.txt index b6bc5a26..a04e2bde 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/hungarian.txt b/data/languages/hungarian.txt index a9bfa978..97001d17 100644 --- a/data/languages/hungarian.txt +++ b/data/languages/hungarian.txt @@ -660,6 +660,9 @@ no limit Demofile: %s == +Game paused +== + Play background music == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index d34e3338..5187985d 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/norwegian.txt b/data/languages/norwegian.txt index a8ede600..3f284814 100644 --- a/data/languages/norwegian.txt +++ b/data/languages/norwegian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/polish.txt b/data/languages/polish.txt index fabde4c9..67d63d7c 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index 307458ac..e99e063e 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index 224540cb..73328399 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/russian.txt b/data/languages/russian.txt index f2142028..067a205a 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 228d58e0..0abc7031 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/slovak.txt b/data/languages/slovak.txt index a3e4180e..e22d5d21 100644 --- a/data/languages/slovak.txt +++ b/data/languages/slovak.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt index 3b19e994..de2ca3a6 100644 --- a/data/languages/spanish.txt +++ b/data/languages/spanish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index b7ce150c..23e42d94 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -675,6 +675,9 @@ no limit ##### needs translation ##### +Game paused +== + Respawn == diff --git a/data/languages/turkish.txt b/data/languages/turkish.txt index 135bc6d9..2273c23d 100644 --- a/data/languages/turkish.txt +++ b/data/languages/turkish.txt @@ -672,6 +672,9 @@ no limit ##### needs translation ##### +Game paused +== + Player country: == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index 7944e183..aaf4a4cc 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -558,6 +558,9 @@ Free-View Friends == +Game paused +== + Kick player == diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index c8e0a903..6881728c 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -59,6 +59,18 @@ void CHud::RenderGameTimer() } } +void CHud::RenderPauseNotification() +{ + if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED && + !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)) + { + const char *pText = Localize("Game paused"); + float FontSize = 20.0f; + float w = TextRender()->TextWidth(0, FontSize,pText, -1); + TextRender()->Text(0, 150.0f*Graphics()->ScreenAspect()+-w/2.0f, 50.0f, FontSize, pText, -1); + } +} + void CHud::RenderSuddenDeath() { if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_SUDDENDEATH) @@ -450,6 +462,7 @@ void CHud::OnRender() } RenderGameTimer(); + RenderPauseNotification(); RenderSuddenDeath(); RenderScoreHud(); RenderWarmupTimer(); diff --git a/src/game/client/components/hud.h b/src/game/client/components/hud.h index f0250c7b..34720854 100644 --- a/src/game/client/components/hud.h +++ b/src/game/client/components/hud.h @@ -17,6 +17,7 @@ class CHud : public CComponent void RenderVoting(); void RenderHealthAndAmmo(const CNetObj_Character *pCharacter); void RenderGameTimer(); + void RenderPauseNotification(); void RenderSuddenDeath(); void RenderScoreHud(); void RenderSpectatorHud(); -- cgit 1.4.1 From e8f9145a0dc097e7c1752f586049fd489a96d984 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 10 Jan 2012 23:03:23 +0100 Subject: deactivate player ignore setting if show just friends chat is active and player isn't a friend --- src/game/client/components/menus.cpp | 8 +++++--- src/game/client/components/menus.h | 2 +- src/game/client/components/menus_ingame.cpp | 9 ++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 5ef6b1ae..d27307f4 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -94,14 +94,16 @@ int CMenus::DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect) return 0; } -int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect) +int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIBUTTONS].m_Id); Graphics()->QuadsBegin(); + if(!Active) + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f); RenderTools()->SelectSprite(Checked?SPRITE_GUIBUTTON_ON:SPRITE_GUIBUTTON_OFF); IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); Graphics()->QuadsDrawTL(&QuadItem, 1); - if((UI()->HotItem() == pID)) + if(UI()->HotItem() == pID && Active) { RenderTools()->SelectSprite(SPRITE_GUIBUTTON_HOVER); IGraphics::CQuadItem QuadItem(pRect->x, pRect->y, pRect->w, pRect->h); @@ -109,7 +111,7 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect) } Graphics()->QuadsEnd(); - return UI()->DoButtonLogic(pID, "", Checked, pRect); + return Active ? UI()->DoButtonLogic(pID, "", Checked, pRect) : 0; } int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 585fb91f..0125278c 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -40,7 +40,7 @@ class CMenus : public CComponent int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect); int DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners); - int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect); + int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active); int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect); int DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners); diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 3a4ad6f2..a9cf35e9 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -183,15 +183,18 @@ void CMenus::RenderPlayers(CUIRect MainView) ButtonBar.VSplitLeft(Width, &Button, &ButtonBar); Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button); Button.VSplitLeft(Button.h, &Button, 0); - if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button)) - m_pClient->m_aClients[Index].m_ChatIgnore ^= 1; + if(&g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend) + DoButton_Toggle(&s_aPlayerIDs[Index][0], 1, &Button, false); + else + if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button, true)) + m_pClient->m_aClients[Index].m_ChatIgnore ^= 1; // friend button ButtonBar.VSplitLeft(20.0f, &Button, &ButtonBar); ButtonBar.VSplitLeft(Width, &Button, &ButtonBar); Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button); Button.VSplitLeft(Button.h, &Button, 0); - if(DoButton_Toggle(&s_aPlayerIDs[Index][1], m_pClient->m_aClients[Index].m_Friend, &Button)) + if(DoButton_Toggle(&s_aPlayerIDs[Index][1], m_pClient->m_aClients[Index].m_Friend, &Button, true)) { if(m_pClient->m_aClients[Index].m_Friend) m_pClient->Friends()->RemoveFriend(m_pClient->m_aClients[Index].m_aName, m_pClient->m_aClients[Index].m_aClan); -- cgit 1.4.1 From fa81141110ad46fc65860091c065bb932916fef4 Mon Sep 17 00:00:00 2001 From: oy Date: Tue, 10 Jan 2012 23:13:19 +0100 Subject: added demo markers by Choupom. Closes #837 --- src/engine/client/client.cpp | 12 +++++++ src/engine/client/client.h | 2 ++ src/engine/demo.h | 12 ++++++- src/engine/shared/demo.cpp | 53 ++++++++++++++++++++++++++++++- src/engine/shared/demo.h | 5 ++- src/game/client/components/menus_demo.cpp | 17 ++++++++-- src/game/client/ui.cpp | 5 +++ src/game/client/ui.h | 1 + 8 files changed, 102 insertions(+), 5 deletions(-) (limited to 'src/game/client/components') diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index b115a9ac..d5da647b 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -2169,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; @@ -2184,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; @@ -2222,6 +2233,7 @@ void CClient::RegisterCommands() 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"); diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 1849830c..d958b49a 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -289,6 +289,7 @@ public: static void Con_Play(IConsole::IResult *pResult, void *pUserData); static void Con_Record(IConsole::IResult *pResult, void *pUserData); static void Con_StopRecord(IConsole::IResult *pResult, void *pUserData); + static void Con_AddDemoMarker(IConsole::IResult *pResult, void *pUserData); static void ConchainServerBrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); void RegisterCommands(); @@ -297,6 +298,7 @@ public: void DemoRecorder_Start(const char *pFilename, bool WithTimestamp); void DemoRecorder_HandleAutoStart(); void DemoRecorder_Stop(); + void DemoRecorder_AddDemoMarker(); void AutoScreenshot_Start(); void AutoScreenshot_Cleanup(); diff --git a/src/engine/demo.h b/src/engine/demo.h index a9e4f700..7b7365c7 100644 --- a/src/engine/demo.h +++ b/src/engine/demo.h @@ -5,6 +5,11 @@ #include "kernel.h" +enum +{ + MAX_TIMELINE_MARKERS=64 +}; + struct CDemoHeader { unsigned char m_aMarker[7]; @@ -16,6 +21,8 @@ struct CDemoHeader char m_aType[8]; char m_aLength[4]; char m_aTimestamp[20]; + char m_aNumTimelineMarkers[4]; + char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][4]; }; class IDemoPlayer : public IInterface @@ -31,6 +38,9 @@ public: int m_FirstTick; int m_CurrentTick; int m_LastTick; + + int m_NumTimelineMarkers; + int m_aTimelineMarkers[MAX_TIMELINE_MARKERS]; }; enum @@ -42,7 +52,7 @@ public: ~IDemoPlayer() {} virtual void SetSpeed(float Speed) = 0; - virtual int SetPos(float Precent) = 0; + virtual int SetPos(float Percent) = 0; virtual void Pause() = 0; virtual void Unpause() = 0; virtual const CInfo *BaseInfo() const = 0; diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp index 2bd7c28a..37c82cce 100644 --- a/src/engine/shared/demo.cpp +++ b/src/engine/shared/demo.cpp @@ -13,8 +13,9 @@ #include "snapshot.h" static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0}; -static const unsigned char gs_ActVersion = 3; +static const unsigned char gs_ActVersion = 4; static const int gs_LengthOffset = 152; +static const int gs_NumMarkersOffset = 176; CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta) @@ -89,6 +90,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con str_copy(Header.m_aType, pType, sizeof(Header.m_aType)); // Header.m_Length - add this on stop str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp)); + // Header.m_aNumTimelineMarkers - add this on stop + // Header.m_aTimelineMarkers - add this on stop io_write(DemoFile, &Header, sizeof(Header)); // write map data @@ -105,6 +108,7 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con m_LastKeyFrame = -1; m_LastTickMarker = -1; m_FirstTick = -1; + m_NumTimelineMarkers = 0; char aBuf[256]; str_format(aBuf, sizeof(aBuf), "Recording to '%s'", pFilename); @@ -266,6 +270,25 @@ int CDemoRecorder::Stop() aLength[3] = (DemoLength)&0xff; io_write(m_File, aLength, sizeof(aLength)); + // add the timeline markers to the header + io_seek(m_File, gs_NumMarkersOffset, IOSEEK_START); + char aNumMarkers[4]; + aNumMarkers[0] = (m_NumTimelineMarkers>>24)&0xff; + aNumMarkers[1] = (m_NumTimelineMarkers>>16)&0xff; + aNumMarkers[2] = (m_NumTimelineMarkers>>8)&0xff; + aNumMarkers[3] = (m_NumTimelineMarkers)&0xff; + io_write(m_File, aNumMarkers, sizeof(aNumMarkers)); + for(int i = 0; i < m_NumTimelineMarkers; i++) + { + int Marker = m_aTimelineMarkers[i]; + char aMarker[4]; + aMarker[0] = (Marker>>24)&0xff; + aMarker[1] = (Marker>>16)&0xff; + aMarker[2] = (Marker>>8)&0xff; + aMarker[3] = (Marker)&0xff; + io_write(m_File, aMarker, sizeof(aMarker)); + } + io_close(m_File); m_File = 0; m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Stopped recording"); @@ -273,6 +296,24 @@ int CDemoRecorder::Stop() return 0; } +void CDemoRecorder::AddDemoMarker() +{ + if(m_LastTickMarker < 0 || m_NumTimelineMarkers >= MAX_TIMELINE_MARKERS) + return; + + // not more than 1 marker in a second + if(m_NumTimelineMarkers > 0) + { + int Diff = m_LastTickMarker - m_aTimelineMarkers[m_NumTimelineMarkers-1]; + if(Diff < SERVER_TICK_SPEED*1.0f) + return; + } + + m_aTimelineMarkers[m_NumTimelineMarkers++] = m_LastTickMarker; + + m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "demo_recorder", "Added timeline marker"); +} + CDemoPlayer::CDemoPlayer(class CSnapshotDelta *pSnapshotDelta) @@ -622,6 +663,16 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const mem_free(pMapData); } + // get timeline markers + int Num = ((m_Info.m_Header.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_Header.m_aNumTimelineMarkers[1]<<16)&0xFF0000) | + ((m_Info.m_Header.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_Header.m_aNumTimelineMarkers[3]&0xFF); + m_Info.m_Info.m_NumTimelineMarkers = Num; + for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++) + { + char *pTimelineMarker = m_Info.m_Header.m_aTimelineMarkers[i]; + m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) | + ((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF); + } // scan the file for interessting points ScanFile(); diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h index f4ac5685..760e7256 100644 --- a/src/engine/shared/demo.h +++ b/src/engine/shared/demo.h @@ -17,6 +17,8 @@ class CDemoRecorder : public IDemoRecorder int m_FirstTick; unsigned char m_aLastSnapshotData[CSnapshot::MAX_SIZE]; class CSnapshotDelta *m_pSnapshotDelta; + int m_NumTimelineMarkers; + int m_aTimelineMarkers[MAX_TIMELINE_MARKERS]; void WriteTickMarker(int Tick, int Keyframe); void Write(int Type, const void *pData, int Size); @@ -25,6 +27,7 @@ public: int Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetversion, const char *pMap, unsigned MapCrc, const char *pType); int Stop(); + void AddDemoMarker(); void RecordSnapshot(int Tick, const void *pData, int Size); void RecordMessage(const void *pData, int Size); @@ -108,7 +111,7 @@ public: void Unpause(); int Stop(); void SetSpeed(float Speed); - int SetPos(float Precent); + int SetPos(float Percent); const CInfo *BaseInfo() const { return &m_Info.m_Info; } void GetDemoName(char *pBuffer, int BufferSize) const; bool GetDemoInfo(class IStorage *pStorage, const char *pFilename, int StorageType, CDemoHeader *pDemoHeader) const; diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp index ec3e648c..40a9e5b5 100644 --- a/src/game/client/components/menus_demo.cpp +++ b/src/game/client/components/menus_demo.cpp @@ -86,15 +86,28 @@ void CMenus::RenderDemoPlayer(CUIRect MainView) void *id = &s_SeekBarID; char aBuffer[128]; + // draw seek bar RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f); + // draw filled bar float Amount = CurrentTick/(float)TotalTicks; - CUIRect FilledBar = SeekBar; FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount; - RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f); + // draw markers + for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++) + { + float Ratio = (pInfo->m_aTimelineMarkers[i]-pInfo->m_FirstTick) / (float)TotalTicks; + Graphics()->TextureSet(-1); + Graphics()->QuadsBegin(); + Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + IGraphics::CQuadItem QuadItem(SeekBar.x + (SeekBar.w-10.0f)*Ratio, SeekBar.y, UI()->PixelSize(), SeekBar.h); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + } + + // draw time str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d", CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60, TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60); diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index 00a30c15..c5219575 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -74,6 +74,11 @@ CUIRect *CUI::Screen() return &m_Screen; } +float CUI::PixelSize() +{ + return Screen()->w/Graphics()->ScreenWidth(); +} + void CUI::SetScale(float s) { g_Config.m_UiScale = (int)(s*100.0f); diff --git a/src/game/client/ui.h b/src/game/client/ui.h index 7cd78d6f..daba5d51 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -82,6 +82,7 @@ public: void ConvertMouseMove(float *x, float *y); CUIRect *Screen(); + float PixelSize(); void ClipEnable(const CUIRect *pRect); void ClipDisable(); -- cgit 1.4.1 From c045071b40a635e3178ba8d55369eb01ba13102e Mon Sep 17 00:00:00 2001 From: oy Date: Sun, 5 Feb 2012 15:53:22 +0100 Subject: always show default country flag on invalid country index --- src/game/client/components/countryflags.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/game/client/components') diff --git a/src/game/client/components/countryflags.cpp b/src/game/client/components/countryflags.cpp index e62f4e51..b63b126f 100644 --- a/src/game/client/components/countryflags.cpp +++ b/src/game/client/components/countryflags.cpp @@ -87,13 +87,28 @@ void CCountryFlags::LoadCountryflagsIndexfile() str_format(aBuf, sizeof(aBuf), "loaded country flag '%s'", aOrigin); Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "countryflags", aBuf); } - m_aCountryFlags.add(CountryFlag); + m_aCountryFlags.add_unsorted(CountryFlag); } io_close(File); + m_aCountryFlags.sort_range(); - mem_zero(m_CodeIndexLUT, sizeof(m_CodeIndexLUT)); + // find index of default item + int DefaultIndex = 0, Index = 0; + for(sorted_array::range r = m_aCountryFlags.all(); !r.empty(); r.pop_front(), ++Index) + if(r.front().m_CountryCode == -1) + { + DefaultIndex = Index; + break; + } + + // init LUT + if(DefaultIndex != 0) + for(int i = 0; i < CODE_RANGE; ++i) + m_CodeIndexLUT[i] = DefaultIndex; + else + mem_zero(m_CodeIndexLUT, sizeof(m_CodeIndexLUT)); for(int i = 0; i < m_aCountryFlags.size(); ++i) - m_CodeIndexLUT[max(0, (m_aCountryFlags[i].m_CountryCode-CODE_LB)%CODE_RANGE)] = i+1; + m_CodeIndexLUT[max(0, (m_aCountryFlags[i].m_CountryCode-CODE_LB)%CODE_RANGE)] = i; } void CCountryFlags::OnInit() @@ -119,7 +134,7 @@ int CCountryFlags::Num() const const CCountryFlags::CCountryFlag *CCountryFlags::GetByCountryCode(int CountryCode) const { - return GetByIndex(m_CodeIndexLUT[max(0, (CountryCode-CODE_LB)%CODE_RANGE)]-1); + return GetByIndex(m_CodeIndexLUT[max(0, (CountryCode-CODE_LB)%CODE_RANGE)]); } const CCountryFlags::CCountryFlag *CCountryFlags::GetByIndex(int Index) const -- cgit 1.4.1