improved friends feature

This commit is contained in:
oy 2011-06-26 17:10:13 +02:00
parent c10c7d9ac3
commit fb309436b4
28 changed files with 324 additions and 164 deletions

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Prikaži chat
Show friends
Show friends only
== Prikaži prijatelje
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Показвай чата
Show friends
Show friends only
== Покажи приятели
Show ingame HUD
@ -674,12 +674,3 @@ Strict gametype filter
##### old translations #####
Page %d of %d
== Страница %d/%d
Next
== Нататък
Prev
== Назад

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Zobrazit chat
Show friends
Show friends only
== Zobrazit přátele
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Vis chat
Show friends
Show friends only
== Vis venner
Show ingame HUD
@ -674,6 +674,3 @@ Strict gametype filter
##### old translations #####
##### translated strings #####
==

View file

@ -511,7 +511,7 @@ Shotgun
Show chat
== Laat chat zien
Show friends
Show friends only
== Laat vrienden zien
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Näytä chatti
Show friends
Show friends only
== Näytä ystävät
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Montrer le chat
Show friends
Show friends only
== Montrer les amis
Show ingame HUD

View file

@ -514,7 +514,7 @@ Shotgun
Show chat
== Chat anzeigen
Show friends
Show friends only
== Nur Freunde zeigen
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Mostra chat
Show friends
Show friends only
== Mostra amici
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Vis samtale
Show friends
Show friends only
== Vis venner
Show ingame HUD

View file

@ -612,7 +612,7 @@ Server address:
Server filter
==
Show friends
Show friends only
==
Show ingame HUD

View file

@ -1,4 +1,4 @@

##### translated strings #####
%d Bytes
@ -514,7 +514,7 @@ Shotgun
Show chat
== Mostrar conversa
Show friends
Show friends only
== Mostrar amigos
Show ingame HUD
@ -672,9 +672,5 @@ no limit
##### needs translation #####
##### old translations #####

== ## translated strings #####

View file

@ -1,3 +1,4 @@
##### translated strings #####
%d Bytes
@ -141,12 +142,12 @@ Delete
Delete demo
== Șterge demonstrația
Demofile: %s
== Fișier demo: %s
Demo details
== Detalii demo
Demofile: %s
== Fișier demo: %s
Demos
== Demo
@ -513,7 +514,7 @@ Shotgun
Show chat
== Afișare chat
Show friends
Show friends only
== Arată prietenii
Show ingame HUD

View file

@ -511,7 +511,7 @@ Shotgun
Show chat
== Показать чат
Show friends
Show friends only
== Показывать друзей
Show ingame HUD

View file

@ -612,7 +612,7 @@ Server address:
Server filter
==
Show friends
Show friends only
==
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Ukázať chat
Show friends
Show friends only
== Ukázať priateľov
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Mostrar chat
Show friends
Show friends only
== Mostrar amigos
Show ingame HUD
@ -674,12 +674,3 @@ Strict gametype filter
##### old translations #####
Page %d of %d
== Página %d de %d
Next
== Siguiente
Prev
== Anterior

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Visa chatt
Show friends
Show friends only
== Visa kompisar
Show ingame HUD

View file

@ -508,7 +508,7 @@ Shotgun
Show chat
== Sohbeti göster
Show friends
Show friends only
== Arkadaşları göster
Show ingame HUD

View file

@ -618,7 +618,7 @@ Server address:
Server filter
==
Show friends
Show friends only
==
Show ingame HUD

View file

@ -1,6 +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 <base/math.h>
#include <base/system.h>
#include <engine/config.h>
#include <engine/console.h>
@ -44,12 +45,35 @@ const CFriendInfo *CFriends::GetFriend(int Index) const
return &m_aFriends[max(0, Index%m_NumFriends)];
}
bool CFriends::IsFriend(const char *pName, const char *pClan, bool PlayersOnly) const
int CFriends::GetFriendState(const char *pName, const char *pClan) const
{
int Result = FRIEND_NO;
unsigned NameHash = str_quickhash(pName);
unsigned ClanHash = str_quickhash(pClan);
for(int i = 0; i < m_NumFriends; ++i)
{
if(!str_comp(m_aFriends[i].m_aClan, pClan) &&
((!PlayersOnly && m_aFriends[i].m_aName[0] == 0) || !str_comp(m_aFriends[i].m_aName, pName)))
if(m_aFriends[i].m_ClanHash == ClanHash)
{
if(m_aFriends[i].m_aName[0] == 0)
Result = FRIEND_CLAN;
else if(m_aFriends[i].m_NameHash == NameHash)
{
Result = FRIEND_PLAYER;
break;
}
}
}
return Result;
}
bool CFriends::IsFriend(const char *pName, const char *pClan, bool PlayersOnly) const
{
unsigned NameHash = str_quickhash(pName);
unsigned ClanHash = str_quickhash(pClan);
for(int i = 0; i < m_NumFriends; ++i)
{
if(m_aFriends[i].m_ClanHash == ClanHash &&
((!PlayersOnly && m_aFriends[i].m_aName[0] == 0) || m_aFriends[i].m_NameHash == NameHash))
return true;
}
return false;
@ -61,22 +85,28 @@ void CFriends::AddFriend(const char *pName, const char *pClan)
return;
// make sure we don't have the friend already
unsigned NameHash = str_quickhash(pName);
unsigned ClanHash = str_quickhash(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))
if(m_aFriends[i].m_NameHash == NameHash && m_aFriends[i].m_ClanHash == ClanHash)
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_aFriends[m_NumFriends].m_NameHash = NameHash;
m_aFriends[m_NumFriends].m_ClanHash = ClanHash;
++m_NumFriends;
}
void CFriends::RemoveFriend(const char *pName, const char *pClan)
{
unsigned NameHash = str_quickhash(pName);
unsigned ClanHash = str_quickhash(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))
if(m_aFriends[i].m_NameHash == NameHash && m_aFriends[i].m_ClanHash == ClanHash)
{
RemoveFriend(i);
return;

View file

@ -22,6 +22,7 @@ public:
int NumFriends() const { return m_NumFriends; }
const CFriendInfo *GetFriend(int Index) const;
int GetFriendState(const char *pName, const char *pClan) const;
bool IsFriend(const char *pName, const char *pClan, bool PlayersOnly) const;
void AddFriend(const char *pName, const char *pClan);

View file

@ -144,101 +144,98 @@ void CServerBrowser::Filter()
{
int Filtered = 0;
if(g_Config.m_BrFilterFriends)
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))
{
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 ||
str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf6") == 0 ||
str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf7") == 0)
)
{
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_BrFilterGametypeStrict && g_Config.m_BrFilterGametype[0] && str_comp_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype))
Filtered = 1;
else if(!g_Config.m_BrFilterGametypeStrict && 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_SERVERNAME;
}
// match against players
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, false))
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 = 0;
MatchFound = 1;
m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_PLAYER;
break;
}
}
}
else
{
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))
// match against map
if(str_find_nocase(m_ppServerlist[i]->m_Info.m_aMap, g_Config.m_BrFilterString))
{
Filtered = 1;
MatchFound = 1;
m_ppServerlist[i]->m_Info.m_QuickSearchHit |= IServerBrowser::QUICK_MAPNAME;
}
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 ||
str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf6") == 0 ||
str_comp(m_ppServerlist[i]->m_Info.m_aMap, "ctf7") == 0)
)
{
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_BrFilterGametypeStrict && g_Config.m_BrFilterGametype[0] && str_comp_nocase(m_ppServerlist[i]->m_Info.m_aGameType, g_Config.m_BrFilterGametype))
Filtered = 1;
else if(!g_Config.m_BrFilterGametypeStrict && 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_SERVERNAME;
}
// 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;
}
}
// 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(!MatchFound)
Filtered = 1;
}
if(Filtered == 0)
m_pSortedServerlist[m_NumSortedServers++] = i;
{
// check for friend
m_ppServerlist[i]->m_Info.m_FriendState = IFriends::FRIEND_NO;
for(p = 0; p < m_ppServerlist[i]->m_Info.m_NumClients; p++)
{
m_ppServerlist[i]->m_Info.m_aClients[p].m_FriendState = m_pFriends->GetFriendState(m_ppServerlist[i]->m_Info.m_aClients[p].m_aName,
m_ppServerlist[i]->m_Info.m_aClients[p].m_aClan);
m_ppServerlist[i]->m_Info.m_FriendState = max(m_ppServerlist[i]->m_Info.m_FriendState, m_ppServerlist[i]->m_Info.m_aClients[p].m_FriendState);
}
if(!g_Config.m_BrFilterFriends || m_ppServerlist[i]->m_Info.m_FriendState != IFriends::FRIEND_NO)
m_pSortedServerlist[m_NumSortedServers++] = i;
}
}
}

View file

@ -11,6 +11,8 @@ struct CFriendInfo
{
char m_aName[MAX_NAME_LENGTH];
char m_aClan[MAX_CLAN_LENGTH];
unsigned m_NameHash;
unsigned m_ClanHash;
};
class IFriends : public IInterface
@ -19,6 +21,10 @@ class IFriends : public IInterface
public:
enum
{
FRIEND_NO=0,
FRIEND_CLAN,
FRIEND_PLAYER,
MAX_FRIENDS=128,
};
@ -26,11 +32,11 @@ public:
virtual int NumFriends() const = 0;
virtual const CFriendInfo *GetFriend(int Index) const = 0;
virtual int GetFriendState(const char *pName, const char *pClan) const = 0;
virtual bool IsFriend(const char *pName, const char *pClan, bool PlayersOnly) 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

View file

@ -24,7 +24,9 @@ public:
int m_Country;
int m_Score;
bool m_Player;
} ;
int m_FriendState;
};
int m_SortedIndex;
int m_ServerIndex;
@ -32,6 +34,7 @@ public:
NETADDR m_NetAddr;
int m_QuickSearchHit;
int m_FriendState;
int m_MaxClients;
int m_NumClients;

View file

@ -734,6 +734,8 @@ void CMenus::OnInit()
Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this);
Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this);
Console()->Chain("add_friend", ConchainFriendlistUpdate, this);
Console()->Chain("remove_friend", ConchainFriendlistUpdate, this);
// setup load amount
m_LoadCurrent = 0;
@ -1205,7 +1207,9 @@ int CMenus::Render()
// remove friend
if(m_FriendlistSelectedIndex >= 0)
{
m_pClient->Friends()->RemoveFriend(m_FriendlistSelectedIndex);
m_pClient->Friends()->RemoveFriend(m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aName,
m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aClan);
FriendlistOnUpdate();
Client()->ServerBrowserUpdate();
}
}

View file

@ -7,6 +7,7 @@
#include <base/tl/sorted_array.h>
#include <engine/demo.h>
#include <engine/friends.h>
#include <game/voting.h>
#include <game/client/component.h>
@ -202,8 +203,34 @@ class CMenus : public CComponent
void DemolistPopulate();
static int DemolistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser);
// friends
struct CFriendItem
{
const CFriendInfo *m_pFriendInfo;
int m_NumFound;
bool operator<(const CFriendItem &Other)
{
if(m_NumFound && !Other.m_NumFound)
return true;
else if(!m_NumFound && Other.m_NumFound)
return false;
else
{
int Result = str_comp(m_pFriendInfo->m_aName, Other.m_pFriendInfo->m_aName);
if(Result)
return Result < 0;
else
return str_comp(m_pFriendInfo->m_aClan, Other.m_pFriendInfo->m_aClan) < 0;
}
}
};
sorted_array<CFriendItem> m_lFriends;
int m_FriendlistSelectedIndex;
void FriendlistOnUpdate();
// found in menus.cpp
int Render();
//void render_background();
@ -225,11 +252,13 @@ class CMenus : public CComponent
// found in menus_browser.cpp
int m_SelectedIndex;
int m_ScrollOffset;
void RenderServerbrowserServerList(CUIRect View);
void RenderServerbrowserServerDetail(CUIRect View);
void RenderServerbrowserFilters(CUIRect View);
void RenderServerbrowserFriends(CUIRect View);
void RenderServerbrowser(CUIRect MainView);
static void ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
// found in menus_settings.cpp

View file

@ -154,6 +154,11 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
int ScrollNum = NumServers-Num+1;
if(ScrollNum > 0)
{
if(m_ScrollOffset)
{
s_ScrollValue = (float)(m_ScrollOffset)/ScrollNum;
m_ScrollOffset = 0;
}
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP) && UI()->MouseInside(&View))
s_ScrollValue -= 3.0f/ScrollNum;
if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN) && UI()->MouseInside(&View))
@ -213,16 +218,14 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
m_SelectedIndex = -1;
for (int i = 0; i < NumServers; i++)
{
const CServerInfo *pItem = ServerBrowser()->SortedGet(i);
NumPlayers += pItem->m_NumPlayers;
}
// reset friend counter
for(int i = 0; i < m_lFriends.size(); m_lFriends[i++].m_NumFound = 0);
for (int i = 0; i < NumServers; i++)
{
int ItemIndex = i;
const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
NumPlayers += pItem->m_NumPlayers;
CUIRect Row;
CUIRect SelectHitBox;
@ -234,6 +237,28 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
if(Selected)
m_SelectedIndex = i;
// update friend counter
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
for(int j = 0; j < pItem->m_NumClients; ++j)
{
if(pItem->m_aClients[j].m_FriendState != IFriends::FRIEND_NO)
{
unsigned NameHash = str_quickhash(pItem->m_aClients[j].m_aName);
unsigned ClanHash = str_quickhash(pItem->m_aClients[j].m_aClan);
for(int f = 0; f < m_lFriends.size(); ++f)
{
if(ClanHash == m_lFriends[f].m_pFriendInfo->m_ClanHash &&
(!m_lFriends[f].m_pFriendInfo->m_aName[0] || NameHash == m_lFriends[f].m_pFriendInfo->m_NameHash))
{
m_lFriends[f].m_NumFound++;
break;
}
}
}
}
}
// make sure that only those in view can be selected
if(Row.y+Row.h > OriginalView.y && Row.y < OriginalView.y+OriginalView.h)
{
@ -353,6 +378,15 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
}
else if(ID == COL_PLAYERS)
{
CUIRect Icon;
Button.VMargin(4.0f, &Button);
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
Button.VSplitLeft(Button.h, &Icon, &Button);
Icon.Margin(2.0f, &Icon);
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_HEART, &Icon);
}
if(g_Config.m_BrFilterSpectators)
str_format(aTemp, sizeof(aTemp), "%i/%i", pItem->m_NumPlayers, pItem->m_MaxPlayers);
else
@ -463,7 +497,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
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))
if (DoButton_CheckBox(&g_Config.m_BrFilterFriends, Localize("Show friends only"), g_Config.m_BrFilterFriends, &Button))
g_Config.m_BrFilterFriends ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
@ -622,14 +656,26 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
RenderTools()->DrawUIRect(&ServerScoreBoard, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
UI()->DoLabelScaled(&ServerHeader, Localize("Scoreboard"), FontSize+2.0f, 0);
if (pSelectedServer)
if(pSelectedServer)
{
ServerScoreBoard.Margin(3.0f, &ServerScoreBoard);
for (int i = 0; i < pSelectedServer->m_NumClients; i++)
{
CUIRect Name, Clan, Score, Flag;
ServerScoreBoard.HSplitTop(25.0f, &Name, &ServerScoreBoard);
RenderTools()->DrawUIRect(&Name, vec4(1,1,1,(i%2+1)*0.05f), CUI::CORNER_ALL, 4.0f);
if(UI()->DoButtonLogic(&pSelectedServer->m_aClients[i], "", 0, &Name))
{
if(pSelectedServer->m_aClients[i].m_FriendState == IFriends::FRIEND_PLAYER)
m_pClient->Friends()->RemoveFriend(pSelectedServer->m_aClients[i].m_aName, pSelectedServer->m_aClients[i].m_aClan);
else
m_pClient->Friends()->AddFriend(pSelectedServer->m_aClients[i].m_aName, pSelectedServer->m_aClients[i].m_aClan);
FriendlistOnUpdate();
Client()->ServerBrowserUpdate();
}
vec4 Colour = pSelectedServer->m_aClients[i].m_FriendState == IFriends::FRIEND_NO ? vec4(1.0f, 1.0f, 1.0f, (i%2+1)*0.05f) :
vec4(0.5f, 1.0f, 0.5f, 0.15f+(i%2+1)*0.05f);
RenderTools()->DrawUIRect(&Name, Colour, CUI::CORNER_ALL, 4.0f);
Name.VSplitLeft(5.0f, 0, &Name);
Name.VSplitLeft(30.0f, &Score, &Name);
Name.VSplitRight(34.0f, &Name, &Flag);
@ -701,45 +747,102 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
}
}
void CMenus::FriendlistOnUpdate()
{
m_lFriends.clear();
for(int i = 0; i < m_pClient->Friends()->NumFriends(); ++i)
{
CFriendItem Item;
Item.m_pFriendInfo = m_pClient->Friends()->GetFriend(i);
Item.m_NumFound = 0;
m_lFriends.add_unsorted(Item);
}
m_lFriends.sort_range();
}
void CMenus::RenderServerbrowserFriends(CUIRect View)
{
static int s_Inited = 0;
if(!s_Inited)
{
FriendlistOnUpdate();
s_Inited = 1;
}
CUIRect ServerFriends = View, FilterHeader;
const float FontSize = 12.0f;
const float FontSize = 10.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);
UI()->DoLabelScaled(&FilterHeader, Localize("Friends"), FontSize+4.0f, 0);
CUIRect Button, List;
ServerFriends.VSplitLeft(5.0f, 0, &ServerFriends);
ServerFriends.Margin(3.0f, &ServerFriends);
ServerFriends.VMargin(5.0f, &ServerFriends);
ServerFriends.VMargin(3.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);
UiDoListboxStart(&m_lFriends, &List, 30.0f, "", "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue);
for(int i = 0; i < m_pClient->Friends()->NumFriends(); ++i)
m_lFriends.sort_range();
for(int i = 0; i < m_lFriends.size(); ++i)
{
const CFriendInfo *pFriend = m_pClient->Friends()->GetFriend(i);
CListboxItem Item = UiDoListboxNextItem(pFriend);
CListboxItem Item = UiDoListboxNextItem(&m_lFriends[i]);
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);
Item.m_Rect.Margin(1.5f, &Item.m_Rect);
CUIRect OnState;
Item.m_Rect.VSplitRight(30.0f, &Item.m_Rect, &OnState);
RenderTools()->DrawUIRect(&Item.m_Rect, vec4(1.0f, 1.0f, 1.0f, 0.1f), CUI::CORNER_L, 4.0f);
Item.m_Rect.VMargin(2.5f, &Item.m_Rect);
Item.m_Rect.HSplitTop(12.0f, &Item.m_Rect, &Button);
UI()->DoLabelScaled(&Item.m_Rect, m_lFriends[i].m_pFriendInfo->m_aName, FontSize, -1);
UI()->DoLabelScaled(&Button, m_lFriends[i].m_pFriendInfo->m_aClan, FontSize, -1);
RenderTools()->DrawUIRect(&OnState, m_lFriends[i].m_NumFound ? vec4(0.0f, 1.0f, 0.0f, 0.25f) : vec4(1.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_R, 4.0f);
OnState.HMargin((OnState.h-FontSize)/3, &OnState);
OnState.VMargin(5.0f, &OnState);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%i", m_lFriends[i].m_NumFound);
UI()->DoLabelScaled(&OnState, aBuf, FontSize+2, 1);
}
}
m_FriendlistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, 0);
bool Activated = false;
m_FriendlistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated);
// activate found server with friend
if(Activated && !m_EnterPressed && m_lFriends[m_FriendlistSelectedIndex].m_NumFound)
{
bool Found = false;
int NumServers = ServerBrowser()->NumSortedServers();
for (int i = 0; i < NumServers && !Found; i++)
{
int ItemIndex = m_SelectedIndex != -1 ? (m_SelectedIndex+i+1)%NumServers : i;
const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
for(int j = 0; j < pItem->m_NumClients && !Found; ++j)
{
if(pItem->m_aClients[j].m_FriendState != IFriends::FRIEND_NO &&
str_quickhash(pItem->m_aClients[j].m_aClan) == m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_ClanHash &&
(!m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aName[0] ||
str_quickhash(pItem->m_aClients[j].m_aName) == m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_NameHash))
{
str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
m_ScrollOffset = ItemIndex;
m_SelectedIndex = ItemIndex;
Found = true;
}
}
}
}
}
ServerFriends.HSplitTop(2.5f, 0, &ServerFriends);
ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends);
@ -774,10 +877,11 @@ void CMenus::RenderServerbrowserFriends(CUIRect View)
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))
static int s_AddButton = 0;
if(DoButton_Menu(&s_AddButton, Localize("Add Friend"), 0, &Button))
{
m_pClient->Friends()->AddFriend(s_aName, s_aClan);
FriendlistOnUpdate();
Client()->ServerBrowserUpdate();
}
}
@ -916,6 +1020,16 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
}
}
void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments() == 2 && ((CMenus *)pUserData)->Client()->State() == IClient::STATE_OFFLINE)
{
((CMenus *)pUserData)->FriendlistOnUpdate();
((CMenus *)pUserData)->Client()->ServerBrowserUpdate();
}
}
void CMenus::ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);