From ae325c873f64603f3957b3ded623a67088752ba8 Mon Sep 17 00:00:00 2001 From: oy Date: Wed, 23 Mar 2011 13:06:35 +0100 Subject: added friends feature. Closes #24 --- data/languages/bosnian.txt | 27 +++++ data/languages/czech.txt | 27 +++++ data/languages/dutch.txt | 27 +++++ data/languages/finnish.txt | 27 +++++ data/languages/french.txt | 27 +++++ data/languages/german.txt | 27 +++++ data/languages/italian.txt | 27 +++++ data/languages/polish.txt | 27 +++++ data/languages/portuguese.txt | 27 +++++ data/languages/romanian.txt | 27 +++++ data/languages/russian.txt | 27 +++++ data/languages/serbian.txt | 27 +++++ data/languages/spanish.txt | 27 +++++ data/languages/swedish.txt | 27 +++++ data/languages/ukrainian.txt | 27 +++++ src/engine/client/client.cpp | 3 + src/engine/client/client.h | 1 + src/engine/client/friends.cpp | 130 +++++++++++++++++++++ src/engine/client/friends.h | 32 ++++++ src/engine/client/srvbrowse.cpp | 162 +++++++++++++++------------ src/engine/client/srvbrowse.h | 1 + src/engine/friends.h | 36 ++++++ src/engine/shared/config_variables.h | 1 + src/game/client/components/menus.cpp | 44 +++++++- src/game/client/components/menus.h | 4 + src/game/client/components/menus_browser.cpp | 111 ++++++++++++++++-- src/game/client/components/menus_ingame.cpp | 17 ++- src/game/client/gameclient.cpp | 11 ++ src/game/client/gameclient.h | 3 + src/game/variables.h | 2 +- 30 files changed, 878 insertions(+), 85 deletions(-) create mode 100644 src/engine/client/friends.cpp create mode 100644 src/engine/client/friends.h create mode 100644 src/engine/friends.h diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 86585c25..e5a7819c 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -519,6 +519,12 @@ Your skin -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -540,6 +546,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -561,6 +576,9 @@ Next Page %d of %d == +Player options +== + Prev == @@ -570,6 +588,12 @@ REC %3d:%02d Reason: == +Remove +== + +Remove friend +== + Rename == @@ -582,6 +606,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index 3846f22f..ff4c9bf8 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -459,9 +459,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -507,6 +513,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -543,6 +558,9 @@ Page %d of %d Parent Folder == +Player options +== + Please balance teams! == @@ -558,6 +576,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -573,6 +597,9 @@ Server filter Show chat == +Show friends +== + Size: == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index bec75c5d..d4268591 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -543,6 +543,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -564,6 +570,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -582,9 +597,18 @@ Next Page %d of %d == +Player options +== + Prev == +Remove +== + +Remove friend +== + Rename == @@ -597,6 +621,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index a5ba9bd7..265fc40c 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -483,9 +483,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -519,6 +525,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -555,6 +570,9 @@ Page %d of %d Parent Folder == +Player options +== + Prev == @@ -567,6 +585,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -579,6 +603,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/french.txt b/data/languages/french.txt index 2bb74231..46c6e8e8 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -531,6 +531,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -552,6 +558,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -573,9 +588,18 @@ Next Page %d of %d == +Player options +== + Prev == +Remove +== + +Remove friend +== + Rename == @@ -588,6 +612,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/german.txt b/data/languages/german.txt index 540fa399..ad0bb571 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -543,6 +543,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -564,6 +570,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -582,9 +597,18 @@ Next Page %d of %d == +Player options +== + Prev == +Remove +== + +Remove friend +== + Rename == @@ -597,6 +621,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index 6fd6a9f6..05e4306b 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -525,6 +525,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -546,6 +552,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -570,12 +585,21 @@ Next Page %d of %d == +Player options +== + Prev == REC %3d:%02d == +Remove +== + +Remove friend +== + Rename == @@ -588,6 +612,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 1270fe65..a75e5836 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -486,9 +486,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -522,6 +528,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -555,6 +570,9 @@ Page %d of %d Parent Folder == +Player options +== + Prev == @@ -567,6 +585,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -579,6 +603,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index 4231ef27..ec911ef0 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -480,9 +480,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -519,6 +525,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -555,6 +570,9 @@ Page %d of %d Parent Folder == +Player options +== + Prev == @@ -567,6 +585,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -579,6 +603,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index c059809d..90e7e17c 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -543,6 +543,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -564,6 +570,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -582,9 +597,18 @@ Next Page %d of %d == +Player options +== + Prev == +Remove +== + +Remove friend +== + Rename == @@ -597,6 +621,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/russian.txt b/data/languages/russian.txt index d976de91..6f33cca0 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -489,9 +489,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -525,6 +531,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -558,6 +573,9 @@ Page %d of %d Parent Folder == +Player options +== + Prev == @@ -567,6 +585,12 @@ REC %3d:%02d Record demo == +Remove +== + +Remove friend +== + Rename == @@ -579,6 +603,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index 21607a5d..a3537e5a 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -483,9 +483,15 @@ Your skin -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -519,6 +525,15 @@ Folder Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -555,6 +570,9 @@ Page %d of %d Parent Folder == +Player options +== + Prev == @@ -567,6 +585,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -579,6 +603,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/spanish.txt b/data/languages/spanish.txt index 0c0339ef..8ceb991a 100644 --- a/data/languages/spanish.txt +++ b/data/languages/spanish.txt @@ -543,6 +543,12 @@ no limit -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Clan == @@ -564,6 +570,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -582,9 +597,18 @@ Next Page %d of %d == +Player options +== + Prev == +Remove +== + +Remove friend +== + Rename == @@ -597,6 +621,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index b3ec1c32..d45eda0d 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -453,9 +453,15 @@ You must restart the game for all settings to take effect. -Page %d- == +Add Friend +== + Are you sure that you want to delete the demo? == +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -504,6 +510,15 @@ Force vote Free-View == +Friend +== + +Friends +== + +Ignore +== + Invalid Demo == @@ -540,6 +555,9 @@ Page %d of %d Parent Folder == +Player options +== + Please balance teams! == @@ -555,6 +573,12 @@ Reason: Record demo == +Remove +== + +Remove friend +== + Rename == @@ -570,6 +594,9 @@ Server filter Show chat == +Show friends +== + Size: == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index af94f4c3..93b4742e 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -507,6 +507,12 @@ Your skin -Page %d- == +Add Friend +== + +Are you sure that you want to remove the player from your friends list? +== + Automatically record demos == @@ -537,6 +543,15 @@ Demo details Free-View == +Friend +== + +Friends +== + +Ignore +== + Length: == @@ -567,12 +582,21 @@ Page %d of %d Parent Folder == +Player options +== + Prev == REC %3d:%02d == +Remove +== + +Remove friend +== + Rename == @@ -585,6 +609,9 @@ Server address: Server filter == +Show friends +== + Size: == diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index cb477304..3131afc1 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -36,6 +36,7 @@ #include #include +#include "friends.h" #include "srvbrowse.h" #include "client.h" @@ -1806,6 +1807,7 @@ void CClient::RegisterInterfaces() Kernel()->RegisterInterface(static_cast(&m_DemoRecorder)); Kernel()->RegisterInterface(static_cast(&m_DemoPlayer)); Kernel()->RegisterInterface(static_cast(&m_ServerBrowser)); + Kernel()->RegisterInterface(static_cast(&m_Friends)); } void CClient::InitInterfaces() @@ -1823,6 +1825,7 @@ void CClient::InitInterfaces() // m_ServerBrowser.SetBaseInfo(&m_NetClient, m_pGameClient->NetVersion()); + m_Friends.Init(); } void CClient::Run() diff --git a/src/engine/client/client.h b/src/engine/client/client.h index b5be566b..31364cd2 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -105,6 +105,7 @@ class CClient : public IClient, public CDemoPlayer::IListner class CDemoPlayer m_DemoPlayer; class CDemoRecorder m_DemoRecorder; class CServerBrowser m_ServerBrowser; + class CFriends m_Friends; char m_aServerAddressStr[256]; diff --git a/src/engine/client/friends.cpp b/src/engine/client/friends.cpp new file mode 100644 index 00000000..26d70892 --- /dev/null +++ b/src/engine/client/friends.cpp @@ -0,0 +1,130 @@ +/* (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 "friends.h" + +CFriends::CFriends() +{ + mem_zero(m_aFriends, sizeof(m_aFriends)); +} + +void CFriends::ConAddFriend(IConsole::IResult *pResult, void *pUserData) +{ + CFriends *pSelf = (CFriends *)pUserData; + pSelf->AddFriend(pResult->GetString(0), pResult->GetString(1)); +} + +void CFriends::ConRemoveFriend(IConsole::IResult *pResult, void *pUserData) +{ + CFriends *pSelf = (CFriends *)pUserData; + pSelf->RemoveFriend(pResult->GetString(0), pResult->GetString(1)); +} + +void CFriends::Init() +{ + IConfig *pConfig = Kernel()->RequestInterface(); + if(pConfig) + pConfig->RegisterCallback(ConfigSaveCallback, this); + + IConsole *pConsole = Kernel()->RequestInterface(); + if(pConsole) + { + pConsole->Register("add_friend", "ss", CFGFLAG_CLIENT, ConAddFriend, this, "Add a friend"); + pConsole->Register("remove_Friend", "ss", CFGFLAG_CLIENT, ConRemoveFriend, this, "Remove a friend"); + } +} + +const CFriendInfo *CFriends::GetFriend(int Index) const +{ + return &m_aFriends[max(0, Index%m_NumFriends)]; +} + +bool CFriends::IsFriend(const char *pName, const char *pClan) const +{ + for(int i = 0; i < m_NumFriends; ++i) + { + if(!str_comp(m_aFriends[i].m_aName, pName) && !str_comp(m_aFriends[i].m_aClan, pClan)) + return true; + } + return false; +} + +void CFriends::AddFriend(const char *pName, const char *pClan) +{ + if(m_NumFriends == MAX_FRIENDS) + return; + + // make sure we don't have the friend already + for(int i = 0; i < m_NumFriends; ++i) + { + if(!str_comp(m_aFriends[i].m_aName, pName) && !str_comp(m_aFriends[i].m_aClan, pClan)) + return; + } + + str_copy(m_aFriends[m_NumFriends].m_aName, pName, sizeof(m_aFriends[m_NumFriends].m_aName)); + str_copy(m_aFriends[m_NumFriends].m_aClan, pClan, sizeof(m_aFriends[m_NumFriends].m_aClan)); + ++m_NumFriends; +} + +void CFriends::RemoveFriend(const char *pName, const char *pClan) +{ + for(int i = 0; i < m_NumFriends; ++i) + { + if(!str_comp(m_aFriends[i].m_aName, pName) && !str_comp(m_aFriends[i].m_aClan, pClan)) + { + RemoveFriend(i); + return; + } + } +} + +void CFriends::RemoveFriend(int Index) +{ + if(Index >= 0 && Index < m_NumFriends) + { + mem_move(&m_aFriends[Index], &m_aFriends[Index+1], sizeof(CFriendInfo)*(m_NumFriends-(Index+1))); + --m_NumFriends; + } + return; +} + +void CFriends::ConfigSaveCallback(IConfig *pConfig, void *pUserData) +{ + CFriends *pSelf = (CFriends *)pUserData; + char aBuf[128]; + const char *pEnd = aBuf+sizeof(aBuf)-4; + for(int i = 0; i < pSelf->m_NumFriends; ++i) + { + str_copy(aBuf, "add_friend ", sizeof(aBuf)); + + const char *pSrc = pSelf->m_aFriends[i].m_aName; + char *pDst = aBuf+str_length(aBuf); + *pDst++ = '"'; + while(*pSrc && pDst < pEnd) + { + if(*pSrc == '"' || *pSrc == '\\') // escape \ and " + *pDst++ = '\\'; + *pDst++ = *pSrc++; + } + *pDst++ = '"'; + *pDst++ = ' '; + + pSrc = pSelf->m_aFriends[i].m_aClan; + *pDst++ = '"'; + while(*pSrc && pDst < pEnd) + { + if(*pSrc == '"' || *pSrc == '\\') // escape \ and " + *pDst++ = '\\'; + *pDst++ = *pSrc++; + } + *pDst++ = '"'; + *pDst++ = 0; + + pConfig->WriteLine(aBuf); + } +} diff --git a/src/engine/client/friends.h b/src/engine/client/friends.h new file mode 100644 index 00000000..e046fc20 --- /dev/null +++ b/src/engine/client/friends.h @@ -0,0 +1,32 @@ +/* (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. */ +#ifndef ENGINE_CLIENT_FRIENDS_H +#define ENGINE_CLIENT_FRIENDS_H + +#include + +class CFriends : public IFriends +{ + CFriendInfo m_aFriends[MAX_FRIENDS]; + int m_NumFriends; + + static void ConAddFriend(IConsole::IResult *pResult, void *pUserData); + static void ConRemoveFriend(IConsole::IResult *pResult, void *pUserData); + + static void ConfigSaveCallback(IConfig *pConfig, void *pUserData); + +public: + CFriends(); + + void Init(); + + int NumFriends() const { return m_NumFriends; } + const CFriendInfo *GetFriend(int Index) const; + bool IsFriend(const char *pName, const char *pClan) const; + + void AddFriend(const char *pName, const char *pClan); + void RemoveFriend(const char *pName, const char *pClan); + void RemoveFriend(int Index); +}; + +#endif diff --git a/src/engine/client/srvbrowse.cpp b/src/engine/client/srvbrowse.cpp index b7c20ae4..be14eaa2 100644 --- a/src/engine/client/srvbrowse.cpp +++ b/src/engine/client/srvbrowse.cpp @@ -4,14 +4,16 @@ #include #include -#include -#include + #include #include +#include +#include -#include -#include #include +#include +#include +#include #include @@ -65,6 +67,7 @@ void CServerBrowser::SetBaseInfo(class CNetClient *pClient, const char *pNetVers str_copy(m_aNetVersion, pNetVersion, sizeof(m_aNetVersion)); m_pMasterServer = Kernel()->RequestInterface(); m_pConsole = Kernel()->RequestInterface(); + m_pFriends = Kernel()->RequestInterface(); IConfig *pConfig = Kernel()->RequestInterface(); if(pConfig) pConfig->RegisterCallback(ConfigSaveCallback, this); @@ -140,79 +143,95 @@ void CServerBrowser::Filter() for(i = 0; i < m_NumServers; i++) { int Filtered = 0; + bool FoundFriend = false; - if(g_Config.m_BrFilterEmpty && ((g_Config.m_BrFilterSpectators && m_ppServerlist[i]->m_Info.m_NumPlayers == 0) || m_ppServerlist[i]->m_Info.m_NumClients == 0)) - Filtered = 1; - else if(g_Config.m_BrFilterFull && ((g_Config.m_BrFilterSpectators && m_ppServerlist[i]->m_Info.m_NumPlayers == m_ppServerlist[i]->m_Info.m_MaxPlayers) || - m_ppServerlist[i]->m_Info.m_NumClients == m_ppServerlist[i]->m_Info.m_MaxClients)) - Filtered = 1; - else if(g_Config.m_BrFilterPw && m_ppServerlist[i]->m_Info.m_Flags&SERVER_FLAG_PASSWORD) - Filtered = 1; - else if(g_Config.m_BrFilterPure && - (str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "DM") != 0 && - str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "TDM") != 0 && - str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "CTF") != 0)) + if(g_Config.m_BrFilterFriends) { - Filtered = 1; - } - else if(g_Config.m_BrFilterPureMap && - !(str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm1") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm2") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm6") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm7") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm8") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm9") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf1") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf2") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf3") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf4") == 0 || - str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf5") == 0) - ) - { - Filtered = 1; + for(p = 0; p < m_ppServerlist[i]->m_Info.m_NumClients; p++) + { + if(m_pFriends->IsFriend(m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan)) + { + FoundFriend = true; + break; + } + } } - else if(g_Config.m_BrFilterPing < m_ppServerlist[i]->m_Info.m_Latency) - Filtered = 1; - else if(g_Config.m_BrFilterCompatversion && str_comp_num(m_ppServerlist[i]->m_Info.m_aVersion, m_aNetVersion, 3) != 0) - Filtered = 1; - else if(g_Config.m_BrFilterServerAddress[0] && !str_find_nocase(m_ppServerlist[i]->m_Info.m_aAddress, g_Config.m_BrFilterServerAddress)) - Filtered = 1; - else if(g_Config.m_BrFilterGametype[0] && !str_find_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype)) - Filtered = 1; - else if(g_Config.m_BrFilterString[0] != 0) - { - int MatchFound = 0; - - m_ppServerlist[i]->m_Info.m_QuickSearchHit = 0; - // match against server name - if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aName, g_Config.m_BrFilterString)) + if(!FoundFriend) + { + if(g_Config.m_BrFilterEmpty && ((g_Config.m_BrFilterSpectators && m_ppServerlist[i]->m_Info.m_NumPlayers == 0) || m_ppServerlist[i]->m_Info.m_NumClients == 0)) + Filtered = 1; + else if(g_Config.m_BrFilterFull && ((g_Config.m_BrFilterSpectators && m_ppServerlist[i]->m_Info.m_NumPlayers == m_ppServerlist[i]->m_Info.m_MaxPlayers) || + m_ppServerlist[i]->m_Info.m_NumClients == m_ppServerlist[i]->m_Info.m_MaxClients)) + Filtered = 1; + else if(g_Config.m_BrFilterPw && m_ppServerlist[i]->m_Info.m_Flags&SERVER_FLAG_PASSWORD) + Filtered = 1; + else if(g_Config.m_BrFilterPure && + (str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "DM") != 0 && + str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "TDM") != 0 && + str_comp(m_ppServerlist[i]->m_Info.m_aGameType, "CTF") != 0)) { - MatchFound = 1; - m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_SERVERNAME; + Filtered = 1; } - - // match against players - for(p = 0; p < m_ppServerlist[i]->m_Info.m_NumPlayers; p++) + else if(g_Config.m_BrFilterPureMap && + !(str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm1") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm2") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm6") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm7") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm8") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "dm9") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf1") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf2") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf3") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf4") == 0 || + str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf5") == 0) + ) { - if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, g_Config.m_BrFilterString) || - str_find_nocase(m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, g_Config.m_BrFilterString)) + Filtered = 1; + } + else if(g_Config.m_BrFilterPing < m_ppServerlist[i]->m_Info.m_Latency) + Filtered = 1; + else if(g_Config.m_BrFilterCompatversion && str_comp_num(m_ppServerlist[i]->m_Info.m_aVersion, m_aNetVersion, 3) != 0) + Filtered = 1; + else if(g_Config.m_BrFilterServerAddress[0] && !str_find_nocase(m_ppServerlist[i]->m_Info.m_aAddress, g_Config.m_BrFilterServerAddress)) + Filtered = 1; + else if(g_Config.m_BrFilterGametype[0] && !str_find_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype)) + Filtered = 1; + else if(g_Config.m_BrFilterString[0] != 0) + { + int MatchFound = 0; + + m_ppServerlist[i]->m_Info.m_QuickSearchHit = 0; + + // match against server name + if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aName, g_Config.m_BrFilterString)) { MatchFound = 1; - m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYER; - break; + m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_SERVERNAME; } - } - // match against map - if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aMap, g_Config.m_BrFilterString)) - { - MatchFound = 1; - m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME; - } + // match against players + for(p = 0; p < m_ppServerlist[i]->m_Info.m_NumClients; p++) + { + if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aClients[p].m_aName, g_Config.m_BrFilterString) || + str_find_nocase(m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan, g_Config.m_BrFilterString)) + { + MatchFound = 1; + m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYER; + break; + } + } - if(!MatchFound) - Filtered = 1; + // match against map + if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aMap, g_Config.m_BrFilterString)) + { + MatchFound = 1; + m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME; + } + + if(!MatchFound) + Filtered = 1; + } } if(Filtered == 0) @@ -226,12 +245,13 @@ int CServerBrowser::SortHash() const i |= g_Config.m_BrFilterEmpty<<4; i |= g_Config.m_BrFilterFull<<5; i |= g_Config.m_BrFilterSpectators<<6; - i |= g_Config.m_BrFilterPw<<7; - i |= g_Config.m_BrSortOrder<<8; - i |= g_Config.m_BrFilterCompatversion<<9; - i |= g_Config.m_BrFilterPure<<10; - i |= g_Config.m_BrFilterPureMap<<11; - i |= g_Config.m_BrFilterPing<<17; + i |= g_Config.m_BrFilterFriends<<7; + i |= g_Config.m_BrFilterPw<<8; + i |= g_Config.m_BrSortOrder<<9; + i |= g_Config.m_BrFilterCompatversion<<10; + i |= g_Config.m_BrFilterPure<<11; + i |= g_Config.m_BrFilterPureMap<<12; + i |= g_Config.m_BrFilterPing<<18; return i; } diff --git a/src/engine/client/srvbrowse.h b/src/engine/client/srvbrowse.h index b3d0f9ed..876627bf 100644 --- a/src/engine/client/srvbrowse.h +++ b/src/engine/client/srvbrowse.h @@ -55,6 +55,7 @@ private: CNetClient *m_pNetClient; IMasterServer *m_pMasterServer; class IConsole *m_pConsole; + class IFriends *m_pFriends; char m_aNetVersion[128]; CHeap m_ServerlistHeap; diff --git a/src/engine/friends.h b/src/engine/friends.h new file mode 100644 index 00000000..d0b9e97b --- /dev/null +++ b/src/engine/friends.h @@ -0,0 +1,36 @@ +/* (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. */ +#ifndef ENGINE_FRIENDS_H +#define ENGINE_FRIENDS_H + +#include + +#include "kernel.h" + +struct CFriendInfo +{ + char m_aName[MAX_NAME_LENGTH]; + char m_aClan[MAX_CLAN_LENGTH]; +}; + +class IFriends : public IInterface +{ + MACRO_INTERFACE("friends", 0) +public: + enum + { + MAX_FRIENDS=128, + }; + + virtual void Init() = 0; + + virtual int NumFriends() const = 0; + virtual const CFriendInfo *GetFriend(int Index) const = 0; + virtual bool IsFriend(const char *pName, const char *pClan) const = 0; + + virtual void AddFriend(const char *pName, const char *pClan) = 0; + virtual void RemoveFriend(const char *pName, const char *pClan) = 0; + virtual void RemoveFriend(int Index) = 0; +}; + +#endif diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index b95839ba..0e3dc8e3 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -31,6 +31,7 @@ MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "", CFGFLAG_SAVE|CFGFLAG_ MACRO_CONFIG_INT(BrFilterFull, br_filter_full, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out full server in browser") MACRO_CONFIG_INT(BrFilterEmpty, br_filter_empty, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out empty server in browser") MACRO_CONFIG_INT(BrFilterSpectators, br_filter_spectators, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out spectators from player numbers") +MACRO_CONFIG_INT(BrFilterFriends, br_filter_friends, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Do not filter out servers with friends") MACRO_CONFIG_INT(BrFilterPw, br_filter_pw, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out password protected servers in browser") MACRO_CONFIG_INT(BrFilterPing, br_filter_ping, 999, 0, 999, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ping to filter by in the server browser") MACRO_CONFIG_STR(BrFilterGametype, br_filter_gametype, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Game types to filter") diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index cd8b7760..7264e412 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -6,10 +6,9 @@ #include #include -#include "menus.h" -#include "skins.h" - +#include #include +#include #include #include #include @@ -26,6 +25,9 @@ #include #include +#include "menus.h" +#include "skins.h" + vec4 CMenus::ms_GuiColor; vec4 CMenus::ms_ColorTabbarInactiveOutgame; vec4 CMenus::ms_ColorTabbarActiveOutgame; @@ -64,6 +66,8 @@ CMenus::CMenus() str_copy(m_aCurrentDemoFolder, "demos", sizeof(m_aCurrentDemoFolder)); m_aCallvoteReason[0] = 0; + + m_FriendlistSelectedIndex = -1; } vec4 CMenus::ButtonColorMul(const void *pID) @@ -873,6 +877,12 @@ int CMenus::Render() pExtraText = ""; ExtraAlign = -1; } + else if(m_Popup == POPUP_REMOVE_FRIEND) + { + pTitle = Localize("Remove friend"); + pExtraText = Localize("Are you sure that you want to remove the player from your friends list?"); + ExtraAlign = -1; + } else if(m_Popup == POPUP_SOUNDERROR) { pTitle = Localize("Sound error"); @@ -1145,6 +1155,34 @@ int CMenus::Render() static float Offset = 0.0f; DoEditBox(&Offset, &TextBox, m_aCurrentDemoFile, sizeof(m_aCurrentDemoFile), 12.0f, &Offset); } + else if(m_Popup == POPUP_REMOVE_FRIEND) + { + CUIRect Yes, No; + Box.HSplitBottom(20.f, &Box, &Part); + Box.HSplitBottom(24.f, &Box, &Part); + Part.VMargin(80.0f, &Part); + + Part.VSplitMid(&No, &Yes); + + Yes.VMargin(20.0f, &Yes); + No.VMargin(20.0f, &No); + + static int s_ButtonAbort = 0; + if(DoButton_Menu(&s_ButtonAbort, Localize("No"), 0, &No) || m_EscapePressed) + m_Popup = POPUP_NONE; + + static int s_ButtonTryAgain = 0; + if(DoButton_Menu(&s_ButtonTryAgain, Localize("Yes"), 0, &Yes) || m_EnterPressed) + { + m_Popup = POPUP_NONE; + // remove friend + if(m_FriendlistSelectedIndex >= 0) + { + m_pClient->Friends()->RemoveFriend(m_FriendlistSelectedIndex); + Client()->ServerBrowserUpdate(); + } + } + } else if(m_Popup == POPUP_FIRST_LAUNCH) { CUIRect Label, TextBox; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index e8236f59..3cdfe3f0 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -101,6 +101,7 @@ class CMenus : public CComponent POPUP_LANGUAGE, POPUP_DELETE_DEMO, POPUP_RENAME_DEMO, + POPUP_REMOVE_FRIEND, POPUP_SOUNDERROR, POPUP_PASSWORD, POPUP_QUIT, @@ -198,6 +199,8 @@ class CMenus : public CComponent void DemolistOnUpdate(bool Reset); void DemolistPopulate(); static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser); + + int m_FriendlistSelectedIndex; // found in menus.cpp int Render(); @@ -222,6 +225,7 @@ class CMenus : public CComponent void RenderServerbrowserServerList(CUIRect View); void RenderServerbrowserServerDetail(CUIRect View); void RenderServerbrowserFilters(CUIRect View); + void RenderServerbrowserFriends(CUIRect View); void RenderServerbrowser(CUIRect MainView); static void ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index 952d596d..01772935 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -1,5 +1,7 @@ /* (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 @@ -435,7 +437,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) { CUIRect ServerFilter = View, FilterHeader; const float FontSize = 12.0f; - ServerFilter.HSplitBottom(5.0f, &ServerFilter, 0); + ServerFilter.HSplitBottom(42.5f, &ServerFilter, 0); // server filter ServerFilter.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFilter); @@ -460,6 +462,10 @@ void CMenus::RenderServerbrowserFilters(CUIRect View) if (DoButton_CheckBox(&g_Config.m_BrFilterFull, Localize("Server not full"), g_Config.m_BrFilterFull, &Button)) g_Config.m_BrFilterFull ^= 1; + ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); + if (DoButton_CheckBox(&g_Config.m_BrFilterFriends, Localize("Show friends"), g_Config.m_BrFilterFriends, &Button)) + g_Config.m_BrFilterFriends ^= 1; + ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter); if (DoButton_CheckBox(&g_Config.m_BrFilterPw, Localize("No password"), g_Config.m_BrFilterPw, &Button)) g_Config.m_BrFilterPw ^= 1; @@ -536,8 +542,8 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex); // split off a piece to use for scoreboard - ServerDetails.HSplitTop(100.0f, &ServerDetails, &ServerScoreBoard); - ServerDetails.HSplitBottom(5.0f, &ServerDetails, 0x0); + ServerDetails.HSplitTop(90.0f, &ServerDetails, &ServerScoreBoard); + ServerDetails.HSplitBottom(2.5f, &ServerDetails, 0x0); // server details CTextCursor Cursor; @@ -605,7 +611,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) } // server scoreboard - ServerScoreBoard.HSplitBottom(10.0f, &ServerScoreBoard, 0x0); + ServerScoreBoard.HSplitBottom(20.0f, &ServerScoreBoard, 0x0); ServerScoreBoard.HSplitTop(ms_ListheaderHeight, &ServerHeader, &ServerScoreBoard); RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); RenderTools()->DrawUIRect(&ServerScoreBoard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f); @@ -689,6 +695,88 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View) } } +void CMenus::RenderServerbrowserFriends(CUIRect View) +{ + CUIRect ServerFriends = View, FilterHeader; + const float FontSize = 12.0f; + + // header + ServerFriends.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFriends); + RenderTools()->DrawUIRect(&FilterHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f); + RenderTools()->DrawUIRect(&ServerFriends, vec4(0,0,0,0.15f), 0, 4.0f); + UI()->DoLabelScaled(&FilterHeader, Localize("Friends"), FontSize+2.0f, 0); + CUIRect Button, List; + + ServerFriends.VSplitLeft(5.0f, 0, &ServerFriends); + ServerFriends.Margin(3.0f, &ServerFriends); + ServerFriends.VMargin(5.0f, &ServerFriends); + ServerFriends.HSplitBottom(100.0f, &List, &ServerFriends); + + // friends list(remove friend) + static int s_FriendList = 0; + static float s_ScrollValue = 0; + UiDoListboxStart(&s_FriendList, &List, 40.0f, "", "", m_pClient->Friends()->NumFriends(), 1, m_FriendlistSelectedIndex, s_ScrollValue); + + for(int i = 0; i < m_pClient->Friends()->NumFriends(); ++i) + { + const CFriendInfo *pFriend = m_pClient->Friends()->GetFriend(i); + CListboxItem Item = UiDoListboxNextItem(pFriend); + + if(Item.m_Visible) + { + Item.m_Rect.Margin(2.5f, &Item.m_Rect); + RenderTools()->DrawUIRect(&Item.m_Rect, vec4(1.0f, 1.0f, 1.0f, 0.1f), CUI::CORNER_ALL, 4.0f); + Item.m_Rect.Margin(2.5f, &Item.m_Rect); + Item.m_Rect.HSplitTop(14.0f, &Item.m_Rect, &Button); + UI()->DoLabelScaled(&Item.m_Rect, pFriend->m_aName, FontSize, -1); + UI()->DoLabelScaled(&Button, pFriend->m_aClan, FontSize, -1); + } + } + + m_FriendlistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, 0); + + ServerFriends.HSplitTop(2.5f, 0, &ServerFriends); + ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends); + if(m_FriendlistSelectedIndex != -1) + { + static int s_RemoveButton = 0; + if(DoButton_Menu(&s_RemoveButton, Localize("Remove"), 0, &Button)) + m_Popup = POPUP_REMOVE_FRIEND; + } + + // add friend + if(m_pClient->Friends()->NumFriends() < IFriends::MAX_FRIENDS) + { + ServerFriends.HSplitTop(10.0f, 0, &ServerFriends); + ServerFriends.HSplitTop(19.0f, &Button, &ServerFriends); + char aBuf[64]; + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name")); + UI()->DoLabelScaled(&Button, aBuf, FontSize, -1); + Button.VSplitLeft(80.0f, 0, &Button); + static char s_aName[MAX_NAME_LENGTH] = {0}; + static float s_OffsetName = 0.0f; + DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), FontSize, &s_OffsetName); + + ServerFriends.HSplitTop(3.0f, 0, &ServerFriends); + ServerFriends.HSplitTop(19.0f, &Button, &ServerFriends); + str_format(aBuf, sizeof(aBuf), "%s:", Localize("Clan")); + UI()->DoLabelScaled(&Button, aBuf, FontSize, -1); + Button.VSplitLeft(80.0f, 0, &Button); + static char s_aClan[MAX_CLAN_LENGTH] = {0}; + static float s_OffsetClan = 0.0f; + DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), FontSize, &s_OffsetClan); + + ServerFriends.HSplitTop(3.0f, 0, &ServerFriends); + ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends); + static int s_RemoveButton = 0; + if(DoButton_Menu(&s_RemoveButton, Localize("Add Friend"), 0, &Button)) + { + m_pClient->Friends()->AddFriend(s_aName, s_aClan); + Client()->ServerBrowserUpdate(); + } + } +} + void CMenus::RenderServerbrowser(CUIRect MainView) { /* @@ -723,11 +811,13 @@ void CMenus::RenderServerbrowser(CUIRect MainView) // tab bar { - CUIRect TabButton0, TabButton1; + CUIRect TabButton0, TabButton1, TabButton2; TabBar.HSplitTop(5.0f, 0, &TabBar); TabBar.HSplitTop(20.0f, &TabButton0, &TabBar); - TabBar.HSplitTop(5.0f, 0, &TabBar); - TabBar.HSplitTop(20.0f, &TabButton1, 0); + TabBar.HSplitTop(2.5f, 0, &TabBar); + TabBar.HSplitTop(20.0f, &TabButton1, &TabBar); + TabBar.HSplitTop(2.5f, 0, &TabBar); + TabBar.HSplitTop(20.0f, &TabButton2, 0); vec4 Active = ms_ColorTabbarActive; vec4 InActive = ms_ColorTabbarInactive; ms_ColorTabbarActive = vec4(0.0f, 0.0f, 0.0f, 0.3f); @@ -741,6 +831,10 @@ void CMenus::RenderServerbrowser(CUIRect MainView) if (DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage==1, &TabButton1, CUI::CORNER_L)) ToolboxPage = 1; + static int s_FriendsTab = 0; + if (DoButton_MenuTab(&s_FriendsTab, Localize("Friends"), ToolboxPage==2, &TabButton2, CUI::CORNER_L)) + ToolboxPage = 2; + ms_ColorTabbarActive = Active; ms_ColorTabbarInactive = InActive; g_Config.m_UiToolboxPage = ToolboxPage; @@ -755,7 +849,8 @@ void CMenus::RenderServerbrowser(CUIRect MainView) RenderServerbrowserFilters(ToolBox); else if(ToolboxPage == 1) RenderServerbrowserServerDetail(ToolBox); - + else if(ToolboxPage == 2) + RenderServerbrowserFriends(ToolBox); } // status box diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp index 2e7c33e8..184a9768 100644 --- a/src/game/client/components/menus_ingame.cpp +++ b/src/game/client/components/menus_ingame.cpp @@ -2,7 +2,9 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include +#include #include +#include #include #include #include @@ -113,7 +115,7 @@ void CMenus::RenderGame(CUIRect MainView) UI()->DoLabelScaled(&Button, Localize("Player options"), 34.0f, -1); CUIRect Player; - static int s_aPlayerIDs[MAX_CLIENTS] = {0}; + static int s_aPlayerIDs[MAX_CLIENTS][2] = {0}; for(int i = 0; i < MAX_CLIENTS; ++i) { if(!m_pClient->m_Snap.m_paPlayerInfos[i] || i == m_pClient->m_Snap.m_LocalClientID) @@ -142,8 +144,19 @@ void CMenus::RenderGame(CUIRect MainView) // ignore button ButtonBar.VSplitMid(&Button, &ButtonBar); Button.VSplitRight(10.0f, &Button, 0); - if(DoButton_CheckBox(&s_aPlayerIDs[i], Localize("Ignore"), m_pClient->m_aClients[i].m_ChatIgnore, &Button)) + if(DoButton_CheckBox(&s_aPlayerIDs[i][0], Localize("Ignore"), m_pClient->m_aClients[i].m_ChatIgnore, &Button)) m_pClient->m_aClients[i].m_ChatIgnore ^= 1; + + // friend button + ButtonBar.VSplitMid(&Button, &ButtonBar); + Button.VSplitLeft(10.0f, 0, &Button); + if(DoButton_CheckBox(&s_aPlayerIDs[i][1], Localize("Friend"), m_pClient->m_aClients[i].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); + else + m_pClient->Friends()->AddFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan); + } } /* diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 9f0898fc..21180b40 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -2,6 +2,7 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include #include +#include #include #include #include @@ -115,6 +116,7 @@ void CGameClient::OnConsoleInit() m_pDemoRecorder = Kernel()->RequestInterface(); m_pServerBrowser = Kernel()->RequestInterface(); m_pEditor = Kernel()->RequestInterface(); + m_pFriends = Kernel()->RequestInterface(); // setup pointers m_pBinds = &::gs_Binds; @@ -834,6 +836,15 @@ void CGameClient::OnNewSnapshot() m_aClients[i].Reset(); } + // update friend state + for(int i = 0; i < MAX_CLIENTS; ++i) + { + if(i == m_Snap.m_LocalClientID || !m_Snap.m_paPlayerInfos[i] || !Friends()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan)) + m_aClients[i].m_Friend = false; + else + m_aClients[i].m_Friend = true; + } + // sort player infos by score mem_copy(m_Snap.m_paInfoByScore, m_Snap.m_paPlayerInfos, sizeof(m_Snap.m_paInfoByScore)); for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 22caa740..5a045708 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -43,6 +43,7 @@ class CGameClient : public IGameClient class IDemoRecorder *m_pDemoRecorder; class IServerBrowser *m_pServerBrowser; class IEditor *m_pEditor; + class IFriends *m_pFriends; CLayers m_Layers; class CCollision m_Collision; @@ -80,6 +81,7 @@ public: class CLayers *Layers() { return &m_Layers; }; class CCollision *Collision() { return &m_Collision; }; class IEditor *Editor() { return m_pEditor; } + class IFriends *Friends() { return m_pFriends; } int NetobjNumCorrections() { return m_NetObjHandler.NumObjCorrections(); } const char *NetobjCorrectedOn() { return m_NetObjHandler.CorrectedObjOn(); } @@ -178,6 +180,7 @@ public: float m_Angle; bool m_Active; bool m_ChatIgnore; + bool m_Friend; void UpdateRenderInfo(); void Reset(); diff --git a/src/game/variables.h b/src/game/variables.h index c1d18c00..a0ac64c4 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -40,7 +40,7 @@ MACRO_CONFIG_INT(PlayerColorFeet, player_color_feet, 65408, 0, 0xFFFFFF, CFGFLAG MACRO_CONFIG_STR(PlayerSkin, player_skin, 24, "default", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Player skin") MACRO_CONFIG_INT(UiPage, ui_page, 5, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface page") -MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page") +MACRO_CONFIG_INT(UiToolboxPage, ui_toolbox_page, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Toolbox page") MACRO_CONFIG_STR(UiServerAddress, ui_server_address, 25, "localhost:8303", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface server address") MACRO_CONFIG_INT(UiScale, ui_scale, 100, 50, 150, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Interface scale") -- cgit 1.4.1