From 816f1a5a018613029b2386d61a83ce7469ed2343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sun, 17 Sep 2023 21:10:01 +0200 Subject: [PATCH] Fix memory leak of server browser entry UI elements New UI elements were being created for every server info after refreshing the server list. At the same time, old UI elements were not being deleted when the server info objects are deleted. The use of `mutable` for this purpose was also rather unclean. Now, a separate `std::vector` of UI elements is kept for all server browser entries, instead of associating the UI elements directly with the server info. --- src/engine/serverbrowser.h | 2 - src/game/client/components/menus.h | 1 + src/game/client/components/menus_browser.cpp | 42 +++++++++++--------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/engine/serverbrowser.h b/src/engine/serverbrowser.h index 0edee8c7b..82382983f 100644 --- a/src/engine/serverbrowser.h +++ b/src/engine/serverbrowser.h @@ -94,8 +94,6 @@ public: CClient m_aClients[SERVERINFO_MAX_CLIENTS]; int m_NumFilteredPlayers; - mutable CUIElement *m_pUIElement; - static int EstimateLatency(int Loc1, int Loc2); static bool ParseLocation(int *pResult, const char *pString); void InfoToString(char *pBuffer, int BufferSize) const; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 51bc1210b..c4d55fa97 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -452,6 +452,7 @@ protected: // found in menus_browser.cpp int m_SelectedIndex; bool m_ServerBrowserShouldRevealSelection; + std::vector m_vpServerBrowserUiElements; void RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemActivated); void RenderServerbrowserStatusBox(CUIRect StatusBox, bool WasListboxItemActivated); void Connect(const char *pAddress); diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp index b2a0cd23b..bc37373c0 100644 --- a/src/game/client/components/menus_browser.cpp +++ b/src/game/client/components/menus_browser.cpp @@ -230,14 +230,18 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct TextRender()->SetFontPreset(EFontPreset::DEFAULT_FONT); }; + if(m_vpServerBrowserUiElements.size() < (size_t)NumServers) + m_vpServerBrowserUiElements.resize(NumServers, nullptr); + for(int i = 0; i < NumServers; i++) { const CServerInfo *pItem = ServerBrowser()->SortedGet(i); - if(pItem->m_pUIElement == nullptr) + if(m_vpServerBrowserUiElements[i] == nullptr) { - pItem->m_pUIElement = UI()->GetNewUIElement(NUM_UI_ELEMS); + m_vpServerBrowserUiElements[i] = UI()->GetNewUIElement(NUM_UI_ELEMS); } + CUIElement *pUiElement = m_vpServerBrowserUiElements[i]; const CListboxItem ListItem = s_ListBox.DoNextItem(pItem, str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0); if(ListItem.m_Selected) @@ -281,22 +285,22 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct { if(pItem->m_Flags & SERVER_FLAG_PASSWORD) { - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_LOCK_ICON), &Button, ColorRGBA(0.75f, 0.75f, 0.75f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_LOCK, TEXTALIGN_MC); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_LOCK_ICON), &Button, ColorRGBA(0.75f, 0.75f, 0.75f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_LOCK, TEXTALIGN_MC); } } else if(ID == COL_FLAG_FAV) { if(pItem->m_Favorite != TRISTATE::NONE) { - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_FAVORITE_ICON), &Button, ColorRGBA(0.94f, 0.4f, 0.4f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_HEART, TEXTALIGN_MC); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_FAVORITE_ICON), &Button, ColorRGBA(0.94f, 0.4f, 0.4f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_HEART, TEXTALIGN_MC); } } else if(ID == COL_FLAG_OFFICIAL) { if(pItem->m_Official && g_Config.m_UiPage != PAGE_DDNET && g_Config.m_UiPage != PAGE_KOG) { - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_OFFICIAL_ICON_1), &Button, ColorRGBA(0.4f, 0.7f, 0.94f, 1.0f), ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f), FONT_ICON_CERTIFICATE, TEXTALIGN_MC); - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_OFFICIAL_ICON_2), &Button, ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), FONT_ICON_CHECK, TEXTALIGN_MC, true); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_OFFICIAL_ICON_1), &Button, ColorRGBA(0.4f, 0.7f, 0.94f, 1.0f), ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f), FONT_ICON_CERTIFICATE, TEXTALIGN_MC); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_OFFICIAL_ICON_2), &Button, ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), FONT_ICON_CHECK, TEXTALIGN_MC, true); } } else if(ID == COL_NAME) @@ -308,14 +312,14 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct bool Printed = false; if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit & IServerBrowser::QUICK_SERVERNAME)) Printed = PrintHighlighted(pItem->m_aName, [&](const char *pFilteredStr, const int FilterLen) { - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_NAME_1), &Button, pItem->m_aName, FontSize, TEXTALIGN_ML, Props, (int)(pFilteredStr - pItem->m_aName)); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_NAME_1), &Button, pItem->m_aName, FontSize, TEXTALIGN_ML, Props, (int)(pFilteredStr - pItem->m_aName)); TextRender()->TextColor(gs_HighlightedTextColor); - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_NAME_2), &Button, pFilteredStr, FontSize, TEXTALIGN_ML, Props, FilterLen, &pItem->m_pUIElement->Rect(UI_ELEM_NAME_1)->m_Cursor); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_NAME_2), &Button, pFilteredStr, FontSize, TEXTALIGN_ML, Props, FilterLen, &pUiElement->Rect(UI_ELEM_NAME_1)->m_Cursor); TextRender()->TextColor(TextRender()->DefaultTextColor()); - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_NAME_3), &Button, pFilteredStr + FilterLen, FontSize, TEXTALIGN_ML, Props, -1, &pItem->m_pUIElement->Rect(UI_ELEM_NAME_2)->m_Cursor); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_NAME_3), &Button, pFilteredStr + FilterLen, FontSize, TEXTALIGN_ML, Props, -1, &pUiElement->Rect(UI_ELEM_NAME_2)->m_Cursor); }); if(!Printed) - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_NAME_1), &Button, pItem->m_aName, FontSize, TEXTALIGN_ML, Props); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_NAME_1), &Button, pItem->m_aName, FontSize, TEXTALIGN_ML, Props); } else if(ID == COL_GAMETYPE) { @@ -327,7 +331,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct { TextRender()->TextColor(GetGametypeTextColor(pItem->m_aGameType)); } - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_GAMETYPE), &Button, pItem->m_aGameType, FontSize, TEXTALIGN_ML, Props); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_GAMETYPE), &Button, pItem->m_aGameType, FontSize, TEXTALIGN_ML, Props); TextRender()->TextColor(TextRender()->DefaultTextColor()); } else if(ID == COL_MAP) @@ -340,7 +344,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct if(g_Config.m_BrIndicateFinished && pItem->m_HasRank == 1) { Icon.Margin(2.0f, &Icon); - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_FINISH_ICON), &Icon, TextRender()->DefaultTextColor(), TextRender()->DefaultTextOutlineColor(), FONT_ICON_FLAG_CHECKERED, TEXTALIGN_MC); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_FINISH_ICON), &Icon, TextRender()->DefaultTextColor(), TextRender()->DefaultTextOutlineColor(), FONT_ICON_FLAG_CHECKERED, TEXTALIGN_MC); } } @@ -351,14 +355,14 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct bool Printed = false; if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit & IServerBrowser::QUICK_MAPNAME)) Printed = PrintHighlighted(pItem->m_aMap, [&](const char *pFilteredStr, const int FilterLen) { - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_MAP_1), &Button, pItem->m_aMap, FontSize, TEXTALIGN_ML, Props, (int)(pFilteredStr - pItem->m_aMap)); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_MAP_1), &Button, pItem->m_aMap, FontSize, TEXTALIGN_ML, Props, (int)(pFilteredStr - pItem->m_aMap)); TextRender()->TextColor(gs_HighlightedTextColor); - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_MAP_2), &Button, pFilteredStr, FontSize, TEXTALIGN_ML, Props, FilterLen, &pItem->m_pUIElement->Rect(UI_ELEM_MAP_1)->m_Cursor); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_MAP_2), &Button, pFilteredStr, FontSize, TEXTALIGN_ML, Props, FilterLen, &pUiElement->Rect(UI_ELEM_MAP_1)->m_Cursor); TextRender()->TextColor(TextRender()->DefaultTextColor()); - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_MAP_3), &Button, pFilteredStr + FilterLen, FontSize, TEXTALIGN_ML, Props, -1, &pItem->m_pUIElement->Rect(UI_ELEM_MAP_2)->m_Cursor); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_MAP_3), &Button, pFilteredStr + FilterLen, FontSize, TEXTALIGN_ML, Props, -1, &pUiElement->Rect(UI_ELEM_MAP_2)->m_Cursor); }); if(!Printed) - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_MAP_1), &Button, pItem->m_aMap, FontSize, TEXTALIGN_ML, Props); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_MAP_1), &Button, pItem->m_aMap, FontSize, TEXTALIGN_ML, Props); } else if(ID == COL_PLAYERS) { @@ -368,7 +372,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct CUIRect Icon; Button.VSplitRight(50.0f, &Icon, &Button); Icon.Margin(2.0f, &Icon); - RenderBrowserIcons(*pItem->m_pUIElement->Rect(UI_ELEM_FRIEND_ICON), &Icon, ColorRGBA(0.94f, 0.4f, 0.4f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_HEART, TEXTALIGN_MC); + RenderBrowserIcons(*pUiElement->Rect(UI_ELEM_FRIEND_ICON), &Icon, ColorRGBA(0.94f, 0.4f, 0.4f, 1.0f), TextRender()->DefaultTextOutlineColor(), FONT_ICON_HEART, TEXTALIGN_MC); if(FriendsOnServer > 1) { str_from_int(FriendsOnServer, aTemp); @@ -383,7 +387,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct { TextRender()->TextColor(gs_HighlightedTextColor); } - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_PLAYERS), &Button, aTemp, FontSize, TEXTALIGN_MR); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_PLAYERS), &Button, aTemp, FontSize, TEXTALIGN_MR); TextRender()->TextColor(TextRender()->DefaultTextColor()); } else if(ID == COL_PING) @@ -394,7 +398,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View, bool &WasListboxItemAct { TextRender()->TextColor(GetPingTextColor(pItem->m_Latency)); } - UI()->DoLabelStreamed(*pItem->m_pUIElement->Rect(UI_ELEM_PING), &Button, aTemp, FontSize, TEXTALIGN_MR); + UI()->DoLabelStreamed(*pUiElement->Rect(UI_ELEM_PING), &Button, aTemp, FontSize, TEXTALIGN_MR); TextRender()->TextColor(TextRender()->DefaultTextColor()); } }